From 5be0efc872d35415cb4ab3c69a0d29f2c3fd03f4 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Thu, 8 Sep 2022 10:48:20 -0400 Subject: [PATCH 001/221] WIP: Added solid query primitives --- .../solid-query/src/QueryClientProvider.tsx | 64 ++++++++++ packages/solid-query/src/createBaseQuery.ts | 76 ++++++++++++ packages/solid-query/src/createMutation.ts | 116 ++++++++++++++++++ packages/solid-query/src/createQuery.ts | 69 +++++++++++ packages/solid-query/src/index.ts | 6 + packages/solid-query/src/types.ts | 100 +++++++++++++++ packages/solid-query/src/useIsFetching.ts | 39 ++++++ packages/solid-query/src/useIsMutating.ts | 43 +++++++ packages/solid-query/src/utils.ts | 39 ++++++ 9 files changed, 552 insertions(+) create mode 100644 packages/solid-query/src/QueryClientProvider.tsx create mode 100644 packages/solid-query/src/createBaseQuery.ts create mode 100644 packages/solid-query/src/createMutation.ts create mode 100644 packages/solid-query/src/createQuery.ts create mode 100644 packages/solid-query/src/index.ts create mode 100644 packages/solid-query/src/types.ts create mode 100644 packages/solid-query/src/useIsFetching.ts create mode 100644 packages/solid-query/src/useIsMutating.ts create mode 100644 packages/solid-query/src/utils.ts diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx new file mode 100644 index 00000000000..c2fa3ff4fa7 --- /dev/null +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -0,0 +1,64 @@ +import type { QueryClient } from "@tanstack/query-core"; +import { Component, Context, createContext, useContext, JSX, onMount, onCleanup } from "solid-js"; +import { ContextOptions } from "./types"; + +declare global { + interface Window { + SolidQueryClientContext?: Context + } +} + +export const QueryClientContext = createContext(); +export const QueryClientSharingContext = createContext(false) + +interface Props { + client: QueryClient; + children: JSX.Element; +} + +// Simple Query Client Context Provider +export const QueryClientProvider: Component = (props) => { + if (!props.client) { + throw new Error("No queryClient found."); + } + + onMount(() => props.client.mount()); + onCleanup(() => props.client.unmount()); + + return ( + + {props.children} + + ); +}; + +function getQueryClientContext( + context: Context | undefined, + contextSharing: boolean +) { + if (context) { + return context; + } + + if (contextSharing && typeof window !== 'undefined') { + if (!window.SolidQueryClientContext) { + window.SolidQueryClientContext = QueryClientContext; + } + + return window.SolidQueryClientContext + } + + return QueryClientContext +} + +export const useQueryClient = ({ context }: ContextOptions = {}) => { + const queryClient = useContext( + getQueryClientContext(context, useContext(QueryClientSharingContext)) + ); + + if (!queryClient) { + throw new Error('No QueryClient set, use QueryClientProvider to set one'); + } + + return queryClient; +}; diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts new file mode 100644 index 00000000000..43d7b7b1a65 --- /dev/null +++ b/packages/solid-query/src/createBaseQuery.ts @@ -0,0 +1,76 @@ +import { QueryObserver } from '@tanstack/query-core' +import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' +import { CreateBaseQueryOptions } from './types' +import { useQueryClient } from "./QueryClientProvider"; +import { onMount, onCleanup, createComputed, createResource, createEffect, batch } from 'solid-js'; +import { createStore } from 'solid-js/store'; + +// Base Query Function that is used to create the query. +export function createBaseQuery< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey extends QueryKey +>( + options: CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey + >, + Observer: typeof QueryObserver +): QueryObserverResult { + + const queryClient = useQueryClient(); + + const defaultedOptions = queryClient.defaultQueryOptions(options) + defaultedOptions._optimisticResults = 'optimistic'; + const observer = new QueryObserver(queryClient, defaultedOptions); + + const [state, setState] = createStore>( + // @ts-ignore + observer.getOptimisticResult(defaultedOptions), + ); + + const [ dataResource, { refetch } ] = createResource(() => { + return new Promise((resolve, reject) => { + if (state.isSuccess) resolve(state.data) + if (state.isError && !state.isFetching) { + throw state.error + } + }) + }); + + observer.updateResult(); + + const unsubscribe = observer.subscribe((result) => { + const reconciledResult = result; + // @ts-ignore + setState(reconciledResult); + refetch(); + }); + + onCleanup(() => unsubscribe()); + + onMount(() => { + observer.setOptions(defaultedOptions, { listeners: false }); + }); + + createComputed(() => { + const defaultedOptions = queryClient.defaultQueryOptions(options) + observer.setOptions(defaultedOptions) + }) + + const handler = { + get(target: QueryObserverResult, prop: (keyof QueryObserverResult)): any { + if (prop === 'data') { + return dataResource(); + } + return Reflect.get(target, prop); + } + } + + return new Proxy(state, handler) as QueryObserverResult; +} \ No newline at end of file diff --git a/packages/solid-query/src/createMutation.ts b/packages/solid-query/src/createMutation.ts new file mode 100644 index 00000000000..2a4b8d65ce6 --- /dev/null +++ b/packages/solid-query/src/createMutation.ts @@ -0,0 +1,116 @@ +import { + parseMutationArgs, + MutationObserver, + MutationFunction, + MutationKey, +} from '@tanstack/query-core' +import { useQueryClient } from './QueryClientProvider' +import { + CreateMutateFunction, + CreateMutationOptions, + CreateMutationResult, +} from './types' +import { createComputed, onCleanup } from 'solid-js' +import { createStore } from 'solid-js/store'; + +// HOOK +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + options: CreateMutationOptions, +): CreateMutationResult +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + mutationFn: MutationFunction, + options?: Omit< + CreateMutationOptions, + 'mutationFn' + >, +): CreateMutationResult +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + mutationKey: MutationKey, + options?: Omit< + CreateMutationOptions, + 'mutationKey' + >, +): CreateMutationResult +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + mutationKey: MutationKey, + mutationFn?: MutationFunction, + options?: Omit< + CreateMutationOptions, + 'mutationKey' | 'mutationFn' + >, +): CreateMutationResult +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + arg1: + | MutationKey + | MutationFunction + | CreateMutationOptions, + arg2?: + | MutationFunction + | CreateMutationOptions, + arg3?: CreateMutationOptions, +): CreateMutationResult { + const [options, setOptions] = createStore(parseMutationArgs(arg1, arg2, arg3)) + const queryClient = useQueryClient({ context: options.context }) + + const observer = new MutationObserver( + queryClient, + options, + ) + + const mutate: CreateMutateFunction = + (variables, mutateOptions) => { + observer.mutate(variables, mutateOptions).catch(noop) + } + + const [state, setState] = createStore>({ + ...observer.getCurrentResult(), + mutate, + mutateAsync: observer.getCurrentResult().mutate + }) + + createComputed(() => { + const newParsedOptions = parseMutationArgs(arg1, arg2, arg3) + setOptions(newParsedOptions) + observer.setOptions(newParsedOptions) + }) + + const unsubscribe = observer.subscribe((result) => { + setState({ + ...result, + mutate, + mutateAsync: result.mutate + }) + }) + + onCleanup(unsubscribe) + + return state +} + +// eslint-disable-next-line @typescript-eslint/no-empty-function +function noop() {} \ No newline at end of file diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts new file mode 100644 index 00000000000..11ec78c5500 --- /dev/null +++ b/packages/solid-query/src/createQuery.ts @@ -0,0 +1,69 @@ +import { QueryObserver, QueryFunction } from '@tanstack/query-core'; +import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store'; +import { parseQueryArgs } from './utils' +import { createBaseQuery } from './createBaseQuery'; + +// There are several ways to create a query. +// 1. createQuery(options: CreateQueryOptions) +// 2. createQuery(querykey: () => Serializable[], options: CreateQueryOptions) +// 3. createQuery(querykey: () => Serializable[], queryFunc: Fetcher Function, options: CreateQueryOptions) +// 4. The fourth overload is a combination of all three function params +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +>( + options: CreateQueryOptions +): CreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +>( + queryKey: SolidQueryKey, + options?: Omit< + CreateQueryOptions, + 'queryKey' + > +): CreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +>( + queryKey: TQueryKey, + queryFn: QueryFunction>, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' + > +): CreateQueryResult +export function createQuery< + TQueryFnData, + TError, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +>( + arg1: TQueryKey | CreateQueryOptions, + arg2?: + | QueryFunction> + | CreateQueryOptions, + arg3?: CreateQueryOptions +): CreateQueryResult { + // The parseQuery Args functions helps normalize the arguments into the correct form. + // Whatever the parameters are, they are normalized into the correct form. + const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)) + + // Watch for changes in the options and update the parsed options. + createComputed(() => { + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) + + return createBaseQuery(parsedOptions, QueryObserver); +} diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts new file mode 100644 index 00000000000..524f1f01acd --- /dev/null +++ b/packages/solid-query/src/index.ts @@ -0,0 +1,6 @@ +export * from './createQuery' +export * from './QueryClientProvider' +export * from './createMutation' +export * from './useIsMutating' +export * from './useIsFetching' +export { QueryClient } from '@tanstack/query-core' \ No newline at end of file diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts new file mode 100644 index 00000000000..59bc9262077 --- /dev/null +++ b/packages/solid-query/src/types.ts @@ -0,0 +1,100 @@ +import type { Context, Accessor } from "solid-js"; +import type { + QueryClient, + QueryKey, + QueryObserverOptions, + QueryObserverResult, + MutateFunction, + MutationObserverOptions, + MutationObserverResult +} from '@tanstack/query-core' + +export interface ContextOptions { + /** + * Use this to pass your React Query context. Otherwise, `defaultContext` will be used. + */ + context?: Context +} + +export type SolidQueryKey = () => readonly unknown[]; + +export interface CreateBaseQueryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey +> extends ContextOptions, + QueryObserverOptions {} + +export interface CreateQueryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +> extends CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + ReturnType +> {} + +export type CreateBaseQueryResult< + TData = unknown, + TError = unknown +> = QueryObserverResult + +export type CreateQueryResult< + TData = unknown, + TError = unknown +> = CreateBaseQueryResult + + + +export interface CreateMutationOptions< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +> extends ContextOptions, + Omit< + MutationObserverOptions, + '_defaulted' | 'variables' + > {} + +export type CreateMutateFunction< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +> = ( + ...args: Parameters> +) => void + + +export type CreateMutateAsyncFunction< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +> = MutateFunction + +type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } + +export type CreateBaseMutationResult< + TData = unknown, + TError = unknown, + TVariables = unknown, + TContext = unknown, +> = Override< + MutationObserverResult, + { mutate: CreateMutateFunction } +> & { mutateAsync: CreateMutateAsyncFunction } + +export type CreateMutationResult< + TData = unknown, + TError = unknown, + TVariables = unknown, + TContext = unknown, +> = CreateBaseMutationResult \ No newline at end of file diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts new file mode 100644 index 00000000000..12d58ff1ab9 --- /dev/null +++ b/packages/solid-query/src/useIsFetching.ts @@ -0,0 +1,39 @@ +import { + QueryKey, + notifyManager, + parseFilterArgs, + QueryFilters, +} from '@tanstack/query-core' + +import { ContextOptions } from './types' +import { useQueryClient } from './QueryClientProvider' +import { Accessor, createSignal, onCleanup } from 'solid-js' +interface Options extends ContextOptions {} + +export function useIsFetching(filters?: QueryFilters, options?: Options): Accessor +export function useIsFetching( + queryKey?: QueryKey, + filters?: QueryFilters, + options?: Options, +): Accessor +export function useIsFetching( + arg1?: QueryKey | QueryFilters, + arg2?: QueryFilters | Options, + arg3?: Options, +): Accessor { + const [filters, options = {}] = parseFilterArgs(arg1, arg2, arg3) + const queryClient = useQueryClient({ context: options.context }) + const queryCache = queryClient.getQueryCache() + + const [fetches, setFetches] = createSignal(queryClient.isFetching(filters)) + + const unsubscribe = queryCache.subscribe((result) => { + setFetches(queryClient.isFetching(filters)) + }) + + onCleanup(() => { + unsubscribe() + }) + + return fetches +} \ No newline at end of file diff --git a/packages/solid-query/src/useIsMutating.ts b/packages/solid-query/src/useIsMutating.ts new file mode 100644 index 00000000000..92d1a9e997f --- /dev/null +++ b/packages/solid-query/src/useIsMutating.ts @@ -0,0 +1,43 @@ +import { + notifyManager, + MutationKey, + MutationFilters, + parseMutationFilterArgs, +} from '@tanstack/query-core' +import { ContextOptions } from './types' +import { useQueryClient } from './QueryClientProvider' +import { Accessor, createSignal, onCleanup } from 'solid-js' + +interface Options extends ContextOptions {} + +export function useIsMutating( + filters?: MutationFilters, + options?: Options, +): Accessor +export function useIsMutating( + mutationKey?: MutationKey, + filters?: Omit, + options?: Options, +): Accessor +export function useIsMutating( + arg1?: MutationKey | MutationFilters, + arg2?: Omit | Options, + arg3?: Options, +): Accessor { + const [filters, options = {}] = parseMutationFilterArgs(arg1, arg2, arg3) + + const queryClient = useQueryClient({ context: options.context }) + const mutationCache = queryClient.getMutationCache() + + const [mutations, setMutations] = createSignal(queryClient.isMutating(filters)) + + const unsubscribe = mutationCache.subscribe((result) => { + setMutations(queryClient.isMutating(filters)) + }) + + onCleanup(() => { + unsubscribe() + }) + + return mutations +} \ No newline at end of file diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts new file mode 100644 index 00000000000..83aa9db1d6d --- /dev/null +++ b/packages/solid-query/src/utils.ts @@ -0,0 +1,39 @@ + +import { CreateQueryOptions, SolidQueryKey } from './types' +import { QueryFunction } from '@tanstack/query-core' + +export function isQueryKey(value: unknown): value is SolidQueryKey { + return typeof value === 'function' +} + +// The parseQuery Args functions helps normalize the arguments into the correct form. +// Whatever the parameters are, they are normalized into the correct form. +export function parseQueryArgs< + TQueryFnData, + TError, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey, +>( + arg1: TQueryKey | CreateQueryOptions, + arg2?: + | QueryFunction> + | CreateQueryOptions, + arg3?: CreateQueryOptions +): CreateQueryOptions { + if(!isQueryKey(arg1)) { + const { queryKey: solidKey, ...opts } = arg1 as any + if (solidKey) { + return { + ...opts, + queryKey: solidKey(), + } + } + return arg1 + } + + if (typeof arg2 === 'function') { + return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any + } + + return { ...arg2, queryKey: arg1() } as any +} \ No newline at end of file From d0c974f47fd095900e9cb865d03aded1f0df0e79 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Thu, 8 Sep 2022 11:32:22 -0400 Subject: [PATCH 002/221] Remove updateresults call --- packages/solid-query/src/createBaseQuery.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 43d7b7b1a65..a825c66b85c 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -43,8 +43,6 @@ export function createBaseQuery< }) }); - observer.updateResult(); - const unsubscribe = observer.subscribe((result) => { const reconciledResult = result; // @ts-ignore From 1aa75bf1ed98acfe0efc3730e52d8365c5366d75 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 12:05:50 -0400 Subject: [PATCH 003/221] add test support and query client provider tests --- jest.config.ts | 3 +- package-lock.json | 568 ++++++++++++++++-- package.json | 8 +- packages/solid-query/.eslintrc | 9 + packages/solid-query/package.json | 44 ++ .../__tests__/QueryClientProvider.test.tsx | 271 +++++++++ packages/solid-query/src/__tests__/utils.ts | 5 + packages/solid-query/tsconfig.json | 11 + tsconfig.base.json | 3 +- tsconfig.json | 3 +- 10 files changed, 880 insertions(+), 45 deletions(-) create mode 100644 packages/solid-query/.eslintrc create mode 100644 packages/solid-query/package.json create mode 100644 packages/solid-query/src/__tests__/QueryClientProvider.test.tsx create mode 100644 packages/solid-query/src/__tests__/utils.ts create mode 100644 packages/solid-query/tsconfig.json diff --git a/jest.config.ts b/jest.config.ts index 508d426f734..444d590c6e1 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -24,7 +24,7 @@ const moduleNameMapper = { module.exports = { collectCoverage: true, coverageReporters: ['json', 'lcov', 'text', 'clover', 'text-summary'], - projects: packages.map((d) => ({ + projects: packages.map((d: string) => ({ displayName: d, clearMocks: true, testEnvironment: 'jsdom', @@ -34,5 +34,6 @@ module.exports = { printBasicPrototype: false, }, moduleNameMapper, + preset: d.includes("solid") ? 'solid-jest/preset/browser' : undefined, })), } diff --git a/package-lock.json b/package-lock.json index 6aa1a2e2b67..2e91ecd746f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "./packages/react-query", "./packages/react-query-devtools", "./packages/react-query-persist-client", + "./packages/solid-query", "./examples/react/auto-refetching", "./examples/react/basic", "./examples/react/basic-graphql-request", @@ -57,6 +58,7 @@ "axios": "^0.26.1", "babel-eslint": "^10.1.0", "babel-plugin-transform-async-to-promises": "^0.8.18", + "babel-preset-solid": "^1.5.4", "bundlewatch": "^0.3.2", "concurrently": "^7.1.0", "current-git-branch": "^1.1.0", @@ -89,7 +91,9 @@ "rollup-plugin-svelte": "^7.1.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-visualizer": "^5.6.0", - "solid-js": "^1.3.15", + "solid-jest": "^0.2.0", + "solid-js": "^1.5.4", + "solid-testing-library": "^0.3.0", "stream-to-array": "^2.3.0", "svelte": "^3.48.0", "ts-node": "^10.7.0", @@ -103,7 +107,7 @@ "license": "MIT", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "isomorphic-unfetch": "3.0.0", "next": "12.2.2", @@ -123,7 +127,7 @@ "version": "0.0.1", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "react": "^18.0.0", "react-dom": "^18.0.0" @@ -138,7 +142,7 @@ "version": "0.0.1", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "graphql": "^15.3.0", "graphql-request": "^3.1.0", "react": "^18.0.0", @@ -268,7 +272,7 @@ "dependencies": { "@tanstack/query-sync-storage-persister": "4.3.0-beta.4", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@tanstack/react-query-persist-client": "4.3.0-beta.4", "axios": "^0.26.1", "broadcast-channel": "^3.4.1", @@ -484,7 +488,7 @@ "version": "0.0.1", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.26.1", "react": "^18.0.0", "react-dom": "^18.0.0" @@ -628,7 +632,7 @@ "license": "MIT", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "isomorphic-unfetch": "3.0.0", "next": "12.2.2", @@ -650,7 +654,7 @@ "license": "MIT", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "ky": "^0.23.0", "ky-universal": "^0.8.2", "next": "12.2.2", @@ -668,7 +672,7 @@ "@tanstack/query-sync-storage-persister": "4.3.0-beta.4", "@tanstack/react-location": "^3.7.0", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@tanstack/react-query-persist-client": "4.3.0-beta.4", "ky": "^0.30.0", "msw": "^0.39.2", @@ -825,7 +829,7 @@ "license": "MIT", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@types/node": "14.14.14", "@types/react": "^18.0.15", "axios": "^0.21.1", @@ -853,7 +857,7 @@ "license": "MIT", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "isomorphic-unfetch": "3.0.0", "next": "12.2.2", @@ -873,7 +877,7 @@ "version": "0.0.1", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "react": "^18.0.0", "react-dom": "^18.0.0" }, @@ -1001,7 +1005,7 @@ "license": "MIT", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "isomorphic-unfetch": "3.0.0", "next": "12.2.2", @@ -1024,7 +1028,7 @@ "@react-navigation/native": "^6.0.2", "@react-navigation/stack": "^6.0.2", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "expo": "~43.0.2", "expo-constants": "~12.1.3", "expo-status-bar": "~1.1.0", @@ -1120,7 +1124,7 @@ "dependencies": { "@material-ui/core": "^4.9.7", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "react": "^18.0.0", "react-dom": "^18.0.0", "react-router": "^5.1.2", @@ -1249,7 +1253,7 @@ "version": "0.0.1", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.26.1", "react": "^18.0.0", "react-dom": "^18.0.0" @@ -1378,7 +1382,7 @@ "dependencies": { "@material-ui/core": "^4.9.7", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "react": "^18.0.0", "react-dom": "^18.0.0", "react-router": "^5.1.2", @@ -1507,7 +1511,7 @@ "version": "1.0.0", "dependencies": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "react": "^18.0.0", "react-dom": "^18.0.0", @@ -10755,6 +10759,10 @@ "resolved": "packages/react-query-persist-client", "link": true }, + "node_modules/@tanstack/solid-query": { + "resolved": "packages/solid-query", + "link": true + }, "node_modules/@testing-library/dom": { "version": "8.14.0", "dev": true, @@ -12908,6 +12916,39 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, "node_modules/babel-plugin-macros": { "version": "2.8.0", "license": "MIT", @@ -13470,6 +13511,18 @@ "node": ">=0.10.0" } }, + "node_modules/babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "dependencies": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/babel-runtime": { "version": "6.26.0", "license": "MIT", @@ -16704,6 +16757,22 @@ "node": ">=6.9.0" } }, + "node_modules/enhanced-resolve-jest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve-jest/-/enhanced-resolve-jest-1.1.0.tgz", + "integrity": "sha512-GM7yVsiLIaunYkCqnGRPO4kQbT6hPSgkyOFKTseWboPMjZ2tlpQYh2ttLuE8ORkR72Wb1f9SJBbnPu0AjcTzgg==", + "dev": true, + "dependencies": { + "enhanced-resolve": "^4.1.0", + "tslib": "^1.10.0" + } + }, + "node_modules/enhanced-resolve-jest/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/enhanced-resolve/node_modules/memory-fs": { "version": "0.5.0", "license": "MIT", @@ -38656,10 +38725,190 @@ "node": ">= 6" } }, + "node_modules/solid-jest": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/solid-jest/-/solid-jest-0.2.0.tgz", + "integrity": "sha512-1ILtAj+z6bh1vTvaDlcT8501vmkzkVZMk2aiexJy+XWTZ+sb9B7IWedvWadIhOwwL97fiW4eMmN6SrbaHjn12A==", + "dev": true, + "dependencies": { + "@babel/preset-env": "^7.13.9", + "babel-jest": "^27.0.0", + "enhanced-resolve-jest": "^1.1.0" + }, + "peerDependencies": { + "babel-preset-solid": "^1.0.0" + } + }, "node_modules/solid-js": { - "version": "1.4.7", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "dependencies": { + "csstype": "^3.1.0" + } + }, + "node_modules/solid-testing-library": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/solid-testing-library/-/solid-testing-library-0.3.0.tgz", + "integrity": "sha512-6NWVbySNVzyReBm2N6p3eF8bzxRZXHZTAmPix4vFWYol16QWVjNQsEUxvr+ZOutb0yuMZmNuGx3b6WIJYmjwMQ==", "dev": true, - "license": "MIT" + "dependencies": { + "@testing-library/dom": "^7.29.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "solid-js": ">=1.0.0" + } + }, + "node_modules/solid-testing-library/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/solid-testing-library/node_modules/@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/solid-testing-library/node_modules/@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/solid-testing-library/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/solid-testing-library/node_modules/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/solid-testing-library/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/solid-testing-library/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/solid-testing-library/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/solid-testing-library/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/solid-testing-library/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/solid-testing-library/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/solid-testing-library/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/source-list-map": { "version": "2.0.1", @@ -42690,7 +42939,7 @@ }, "packages/react-query-devtools": { "name": "@tanstack/react-query-devtools", - "version": "4.3.0-beta.5", + "version": "4.3.0-beta.7", "license": "MIT", "dependencies": { "@tanstack/match-sorter-utils": "^8.1.1", @@ -42721,6 +42970,33 @@ "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } + }, + "packages/solid-query": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "devDependencies": { + "@types/jscodeshift": "^0.11.3", + "jscodeshift": "^0.13.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "packages/solid-query/node_modules/@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } } }, "dependencies": { @@ -48544,7 +48820,7 @@ "version": "file:examples/react/basic", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@vitejs/plugin-react": "^2.0.0", "axios": "^0.21.1", "react": "^18.0.0", @@ -48624,7 +48900,7 @@ "version": "file:examples/react/basic-graphql-request", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@vitejs/plugin-react": "^2.0.0", "graphql": "^15.3.0", "graphql-request": "^3.1.0", @@ -48703,7 +48979,7 @@ "@rescripts/rescript-use-eslint-config": "^0.0.9", "@tanstack/query-sync-storage-persister": "4.3.0-beta.4", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@tanstack/react-query-persist-client": "4.3.0-beta.4", "@types/react": "^17.0.3", "@types/react-dom": "^17.0.3", @@ -48758,7 +49034,7 @@ "version": "file:examples/react/default-query-function", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@vitejs/plugin-react": "^2.0.0", "axios": "^0.26.1", "react": "^18.0.0", @@ -48832,7 +49108,7 @@ "version": "file:examples/react/load-more-infinite-scroll", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "isomorphic-unfetch": "3.0.0", "next": "12.2.2", @@ -48853,7 +49129,7 @@ "version": "file:examples/react/nextjs", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "ky": "^0.23.0", "ky-universal": "^0.8.2", "next": "12.2.2", @@ -48869,7 +49145,7 @@ "@tanstack/query-sync-storage-persister": "4.3.0-beta.4", "@tanstack/react-location": "^3.7.0", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@tanstack/react-query-persist-client": "4.3.0-beta.4", "@vitejs/plugin-react": "^2.0.0", "ky": "^0.30.0", @@ -48949,7 +49225,7 @@ "version": "file:examples/react/optimistic-updates-typescript", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@types/node": "14.14.14", "@types/react": "^18.0.15", "axios": "^0.21.1", @@ -48975,7 +49251,7 @@ "version": "file:examples/react/pagination", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "isomorphic-unfetch": "3.0.0", "next": "12.2.2", @@ -48995,7 +49271,7 @@ "version": "file:examples/react/playground", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@vitejs/plugin-react": "^2.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", @@ -49068,7 +49344,7 @@ "version": "file:examples/react/prefetching", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "isomorphic-unfetch": "3.0.0", "next": "12.2.2", @@ -49094,7 +49370,7 @@ "@react-navigation/native": "^6.0.2", "@react-navigation/stack": "^6.0.2", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@types/react-native": "~0.64.3", "babel-plugin-module-resolver": "^4.1.0", "eslint": "^7.32.0", @@ -49155,7 +49431,7 @@ "version": "file:examples/react/auto-refetching", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "axios": "^0.21.1", "isomorphic-unfetch": "3.0.0", "next": "12.2.2", @@ -49176,7 +49452,7 @@ "requires": { "@material-ui/core": "^4.9.7", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@vitejs/plugin-react": "^2.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", @@ -49251,7 +49527,7 @@ "version": "file:examples/react/simple", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@vitejs/plugin-react": "^2.0.0", "axios": "^0.26.1", "react": "^18.0.0", @@ -49326,7 +49602,7 @@ "requires": { "@material-ui/core": "^4.9.7", "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@vitejs/plugin-react": "^2.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", @@ -49401,7 +49677,7 @@ "version": "file:examples/react/suspense", "requires": { "@tanstack/react-query": "4.3.0-beta.4", - "@tanstack/react-query-devtools": "4.3.0-beta.5", + "@tanstack/react-query-devtools": "4.3.0-beta.7", "@vitejs/plugin-react": "^2.0.0", "axios": "^0.21.1", "react": "^18.0.0", @@ -49525,6 +49801,21 @@ "@tanstack/react-query": "4.3.0-beta.4" } }, + "@tanstack/solid-query": { + "version": "file:packages/solid-query", + "requires": { + "@tanstack/query-core": "4.2.3", + "@types/jscodeshift": "^0.11.3", + "jscodeshift": "^0.13.1" + }, + "dependencies": { + "@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + } + } + }, "@testing-library/dom": { "version": "8.14.0", "dev": true, @@ -50972,6 +51263,35 @@ "@types/babel__traverse": "^7.0.6" } }, + "babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + } + } + }, "babel-plugin-macros": { "version": "2.8.0", "requires": { @@ -51380,6 +51700,15 @@ } } }, + "babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "requires": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + } + }, "babel-runtime": { "version": "6.26.0", "requires": { @@ -53575,6 +53904,24 @@ } } }, + "enhanced-resolve-jest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve-jest/-/enhanced-resolve-jest-1.1.0.tgz", + "integrity": "sha512-GM7yVsiLIaunYkCqnGRPO4kQbT6hPSgkyOFKTseWboPMjZ2tlpQYh2ttLuE8ORkR72Wb1f9SJBbnPu0AjcTzgg==", + "dev": true, + "requires": { + "enhanced-resolve": "^4.1.0", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, "enquirer": { "version": "2.3.6", "requires": { @@ -68390,9 +68737,150 @@ "socks": "^2.3.3" } }, + "solid-jest": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/solid-jest/-/solid-jest-0.2.0.tgz", + "integrity": "sha512-1ILtAj+z6bh1vTvaDlcT8501vmkzkVZMk2aiexJy+XWTZ+sb9B7IWedvWadIhOwwL97fiW4eMmN6SrbaHjn12A==", + "dev": true, + "requires": { + "@babel/preset-env": "^7.13.9", + "babel-jest": "^27.0.0", + "enhanced-resolve-jest": "^1.1.0" + } + }, "solid-js": { - "version": "1.4.7", - "dev": true + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "requires": { + "csstype": "^3.1.0" + } + }, + "solid-testing-library": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/solid-testing-library/-/solid-testing-library-0.3.0.tgz", + "integrity": "sha512-6NWVbySNVzyReBm2N6p3eF8bzxRZXHZTAmPix4vFWYol16QWVjNQsEUxvr+ZOutb0yuMZmNuGx3b6WIJYmjwMQ==", + "dev": true, + "requires": { + "@testing-library/dom": "^7.29.4" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, "source-list-map": { "version": "2.0.1" diff --git a/package.json b/package.json index 0fcbb3ef4d5..d4cd42b82bd 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "./packages/react-query", "./packages/react-query-devtools", "./packages/react-query-persist-client", + "./packages/solid-query", "./examples/react/auto-refetching", "./examples/react/basic", "./examples/react/basic-graphql-request", @@ -66,8 +67,8 @@ "@rollup/plugin-replace": "^4.0.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.0.0", - "@testing-library/react-hooks": "^7.0.2", "@testing-library/react-17": "npm:@testing-library/react@12.1.4", + "@testing-library/react-hooks": "^7.0.2", "@tsconfig/svelte": "^3.0.0", "@types/jest": "^26.0.4", "@types/luxon": "^2.3.1", @@ -79,6 +80,7 @@ "axios": "^0.26.1", "babel-eslint": "^10.1.0", "babel-plugin-transform-async-to-promises": "^0.8.18", + "babel-preset-solid": "^1.5.4", "bundlewatch": "^0.3.2", "concurrently": "^7.1.0", "current-git-branch": "^1.1.0", @@ -111,7 +113,9 @@ "rollup-plugin-svelte": "^7.1.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-visualizer": "^5.6.0", - "solid-js": "^1.3.15", + "solid-jest": "^0.2.0", + "solid-js": "^1.5.4", + "solid-testing-library": "^0.3.0", "stream-to-array": "^2.3.0", "svelte": "^3.48.0", "ts-node": "^10.7.0", diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc new file mode 100644 index 00000000000..df08b8b4dbd --- /dev/null +++ b/packages/solid-query/.eslintrc @@ -0,0 +1,9 @@ +{ + "parserOptions": { + "project": "./tsconfig.json", + "sourceType": "module" + }, + "rules": { + "react/react-in-jsx-scope": "off" + } +} \ No newline at end of file diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json new file mode 100644 index 00000000000..abedd50c244 --- /dev/null +++ b/packages/solid-query/package.json @@ -0,0 +1,44 @@ +{ + "name": "@tanstack/solid-query", + "version": "4.2.3", + "description": "Hooks for managing, caching and syncing asynchronous and remote data in Solid", + "author": "tannerlinsley", + "license": "MIT", + "repository": "tanstack/query", + "homepage": "https://tanstack.com/query", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "module": "build/esm/index.js", + "main": "build/cjs/solid-query/src/index.js", + "browser": "build/umd/index.production.js", + "types": "build/types/packages/solid-query/src/index.d.ts", + "sideEffects": [], + "scripts": { + "test:codemods": "../../node_modules/.bin/jest --config codemods/jest.config.js", + "test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src", + "test:jest": "yarn test:codemods && ../../node_modules/.bin/jest --config jest.config.js", + "test:jest:dev": "yarn test:jest --watch", + "compile": "../../node_modules/.bin/tsc -p tsconfig.json --noEmit --emitDeclarationOnly false" + }, + "files": [ + "build/*", + "src", + "codemods", + "!codemods/jest.config.js", + "!codemods/**/__testfixtures__", + "!codemods/**/__tests__" + ], + "devDependencies": { + "@types/jscodeshift": "^0.11.3", + "jscodeshift": "^0.13.1" + }, + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + }, + "peerDependenciesMeta": {} +} \ No newline at end of file diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx new file mode 100644 index 00000000000..dbdf2707e36 --- /dev/null +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -0,0 +1,271 @@ +import { Context, createContext, useContext } from 'solid-js' +import { render, screen, waitFor } from 'solid-testing-library' +import { queryKey } from './utils' + +import { QueryCache } from '@tanstack/query-core' +import { renderToString } from 'solid-js/web' +import { + createQuery, + QueryClient, + QueryClientProvider, + useQueryClient, +} from '..' +import { createQueryClient, sleep } from '../../../../tests/utils' + +describe('QueryClientProvider', () => { + test('sets a specific cache for all queries to use', async () => { + const key = queryKey() + + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + function Page() { + const query = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + return ( +
+

{query.data}

+
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => { + return screen.getByText('test') + }) + + expect(queryCache.find(key())).toBeDefined() + }) + + test('allows multiple caches to be partitioned', async () => { + const key1 = queryKey() + const key2 = queryKey() + + const queryCache1 = new QueryCache() + const queryCache2 = new QueryCache() + + const queryClient1 = createQueryClient({ queryCache: queryCache1 }) + const queryClient2 = createQueryClient({ queryCache: queryCache2 }) + + function Page1() { + const query = createQuery(key1, async () => { + await sleep(10) + return 'test1' + }) + + return ( +
+

{query.data}

+
+ ) + } + function Page2() { + const query = createQuery(key2, async () => { + await sleep(10) + return 'test2' + }) + + return ( +
+

{query.data}

+
+ ) + } + + render(() => ( + <> + + + + + + + + )) + + await waitFor(() => screen.getByText('test1')) + await waitFor(() => screen.getByText('test2')) + + expect(queryCache1.find(key1())).toBeDefined() + expect(queryCache1.find(key2())).not.toBeDefined() + expect(queryCache2.find(key1())).not.toBeDefined() + expect(queryCache2.find(key2())).toBeDefined() + }) + + test("uses defaultOptions for queries when they don't provide their own config", async () => { + const key = queryKey() + + const queryCache = new QueryCache() + const queryClient = createQueryClient({ + queryCache, + defaultOptions: { + queries: { + cacheTime: Infinity, + }, + }, + }) + + function Page() { + const query = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + return ( +
+

{query.data}

+
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('test')) + + expect(queryCache.find(key())).toBeDefined() + expect(queryCache.find(key())?.options.cacheTime).toBe(Infinity) + }) + + describe('with custom context', () => { + it('uses the correct context', async () => { + const key = queryKey() + + const contextOuter = createContext(undefined) + const contextInner = createContext(undefined) + + const queryCacheOuter = new QueryCache() + const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) + + const queryCacheInner = new QueryCache() + const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) + + const queryCacheInnerInner = new QueryCache() + const queryClientInnerInner = new QueryClient({ + queryCache: queryCacheInnerInner, + }) + + function Page() { + const queryOuter = createQuery(key, async () => 'testOuter', { + context: contextOuter, + }) + const queryInner = createQuery(key, async () => 'testInner', { + context: contextInner, + }) + const queryInnerInner = createQuery(key, async () => 'testInnerInner') + + return ( +
+

+ {queryOuter.data} {queryInner.data} {queryInnerInner.data} +

+
+ ) + } + + // contextSharing should be ignored when passing a custom context. + const contextSharing = true + + render(() => ( + + + + + + + + )) + + await waitFor(() => + screen.getByText('testOuter testInner testInnerInner'), + ) + }) + }) + + describe('useQueryClient', () => { + test('should throw an error if no query client has been set', () => { + const consoleMock = jest + .spyOn(console, 'error') + .mockImplementation(() => undefined) + + function Page() { + useQueryClient() + return null + } + + expect(() => render(() => )).toThrow( + 'No QueryClient set, use QueryClientProvider to set one', + ) + + consoleMock.mockRestore() + }) + + test('should use window to get the context when contextSharing is true', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + let queryClientFromHook: QueryClient | undefined + let queryClientFromWindow: QueryClient | undefined + + function Page() { + queryClientFromHook = useQueryClient() + queryClientFromWindow = useContext( + window.SolidQueryClientContext as Context, + ) + return null + } + + render(() => ( + + + + )) + + expect(queryClientFromHook).toEqual(queryClient) + expect(queryClientFromWindow).toEqual(queryClient) + }) + + test('should not use window to get the context when contextSharing is true and window does not exist', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + // Mock a non web browser environment + const windowSpy = jest + .spyOn(window, 'window', 'get') + .mockImplementation(undefined) + + let queryClientFromHook: QueryClient | undefined + + function Page() { + queryClientFromHook = useQueryClient() + return null + } + + // TODO(lukemurray): this test doesn't pass because the page function is + // never called. I'm not sure why. + renderToString(() => ( + + + + )) + + expect(queryClientFromHook).toEqual(queryClient) + + windowSpy.mockRestore() + }) + }) +}) diff --git a/packages/solid-query/src/__tests__/utils.ts b/packages/solid-query/src/__tests__/utils.ts new file mode 100644 index 00000000000..c6bbb39643a --- /dev/null +++ b/packages/solid-query/src/__tests__/utils.ts @@ -0,0 +1,5 @@ +let queryKeyCount = 0 +export function queryKey(): () => Array { + const localQueryKeyCount = queryKeyCount++ + return () => [`query_${localQueryKeyCount}`] +} diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json new file mode 100644 index 00000000000..f8c5b4861ac --- /dev/null +++ b/packages/solid-query/tsconfig.json @@ -0,0 +1,11 @@ +{ + "composite": true, + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./build/types", + "jsx": "preserve", + "jsxImportSource": "solid-js", + }, + "files": ["src/index.ts"], + "include": ["src"] +} \ No newline at end of file diff --git a/tsconfig.base.json b/tsconfig.base.json index c3524d13868..c8845b11ec4 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -32,7 +32,8 @@ "@tanstack/react-query-devtools": ["packages/react-query-devtools/src"], "@tanstack/react-query-persist-client": [ "packages/react-query-persist-client/src" - ] + ], + "@tanstack/solid-query": ["packages/solid-query/src"], } } } diff --git a/tsconfig.json b/tsconfig.json index c397b08ace7..a6f9a8a2b7a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,7 @@ { "path": "packages/query-sync-storage-persister" }, { "path": "packages/react-query" }, { "path": "packages/react-query-devtools" }, - { "path": "packages/react-query-persist-client" } + { "path": "packages/react-query-persist-client" }, + { "path": "packages/solid-query" }, ] } From 8bf5b6f3b5a0c3d3497516d0897e662481aaa03f Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 18:33:32 -0400 Subject: [PATCH 004/221] add exports to match react query exports --- packages/solid-query/src/index.ts | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 524f1f01acd..cfa7a6a7705 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -1,6 +1,26 @@ -export * from './createQuery' -export * from './QueryClientProvider' -export * from './createMutation' -export * from './useIsMutating' -export * from './useIsFetching' -export { QueryClient } from '@tanstack/query-core' \ No newline at end of file +// Re-export core +export * from '@tanstack/query-core' + +// Solid Query +export * from "./types" +// export { useQueries } from './useQueries' +// export type { QueriesResults, QueriesOptions } from './useQueries' +export { createQuery } from './createQuery' +export { + QueryClientContext as defaultContext, + QueryClientProvider, + useQueryClient, +} from './QueryClientProvider' +// export type { QueryClientProviderProps } from './QueryClientProvider' +// export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' +// export { useHydrate, Hydrate } from './Hydrate' +// export type { HydrateProps } from './Hydrate' +// export { +// QueryErrorResetBoundary, +// useQueryErrorResetBoundary, +// } from './QueryErrorResetBoundary' +export { useIsFetching } from './useIsFetching' +export { useIsMutating } from './useIsMutating' +export { createMutation } from './createMutation' +// export { useInfiniteQuery } from './useInfiniteQuery' +// export { useIsRestoring, IsRestoringProvider } from './isRestoring' From 1e399184a9d24c2fbaa192dcac4822e257b83f92 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 18:56:56 -0400 Subject: [PATCH 005/221] reformat with prettier --- .../solid-query/src/QueryClientProvider.tsx | 48 ++++++++------ packages/solid-query/src/createBaseQuery.ts | 63 +++++++++++-------- packages/solid-query/src/createMutation.ts | 22 ++++--- packages/solid-query/src/createQuery.ts | 28 +++++---- packages/solid-query/src/index.ts | 2 +- packages/solid-query/src/types.ts | 57 +++++++++-------- packages/solid-query/src/useIsFetching.ts | 7 ++- packages/solid-query/src/useIsMutating.ts | 8 ++- packages/solid-query/src/utils.ts | 15 +++-- 9 files changed, 138 insertions(+), 112 deletions(-) diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index c2fa3ff4fa7..0d049fdad7e 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -1,6 +1,14 @@ -import type { QueryClient } from "@tanstack/query-core"; -import { Component, Context, createContext, useContext, JSX, onMount, onCleanup } from "solid-js"; -import { ContextOptions } from "./types"; +import type { QueryClient } from '@tanstack/query-core' +import { + Component, + Context, + createContext, + useContext, + JSX, + onMount, + onCleanup, +} from 'solid-js' +import { ContextOptions } from './types' declare global { interface Window { @@ -8,41 +16,41 @@ declare global { } } -export const QueryClientContext = createContext(); +export const QueryClientContext = createContext() export const QueryClientSharingContext = createContext(false) interface Props { - client: QueryClient; - children: JSX.Element; + client: QueryClient + children: JSX.Element } // Simple Query Client Context Provider export const QueryClientProvider: Component = (props) => { if (!props.client) { - throw new Error("No queryClient found."); + throw new Error('No queryClient found.') } - onMount(() => props.client.mount()); - onCleanup(() => props.client.unmount()); + onMount(() => props.client.mount()) + onCleanup(() => props.client.unmount()) return ( {props.children} - ); -}; + ) +} function getQueryClientContext( context: Context | undefined, - contextSharing: boolean + contextSharing: boolean, ) { if (context) { - return context; + return context } if (contextSharing && typeof window !== 'undefined') { if (!window.SolidQueryClientContext) { - window.SolidQueryClientContext = QueryClientContext; + window.SolidQueryClientContext = QueryClientContext } return window.SolidQueryClientContext @@ -53,12 +61,12 @@ function getQueryClientContext( export const useQueryClient = ({ context }: ContextOptions = {}) => { const queryClient = useContext( - getQueryClientContext(context, useContext(QueryClientSharingContext)) - ); + getQueryClientContext(context, useContext(QueryClientSharingContext)), + ) if (!queryClient) { - throw new Error('No QueryClient set, use QueryClientProvider to set one'); + throw new Error('No QueryClient set, use QueryClientProvider to set one') } - - return queryClient; -}; + + return queryClient +} diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index a825c66b85c..c3a2695bef3 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -1,9 +1,16 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' -import { CreateBaseQueryOptions } from './types' -import { useQueryClient } from "./QueryClientProvider"; -import { onMount, onCleanup, createComputed, createResource, createEffect, batch } from 'solid-js'; -import { createStore } from 'solid-js/store'; +import { CreateBaseQueryOptions } from './types' +import { useQueryClient } from './QueryClientProvider' +import { + onMount, + onCleanup, + createComputed, + createResource, + createEffect, + batch, +} from 'solid-js' +import { createStore } from 'solid-js/store' // Base Query Function that is used to create the query. export function createBaseQuery< @@ -11,7 +18,7 @@ export function createBaseQuery< TError, TData, TQueryData, - TQueryKey extends QueryKey + TQueryKey extends QueryKey, >( options: CreateBaseQueryOptions< TQueryFnData, @@ -20,41 +27,40 @@ export function createBaseQuery< TQueryData, TQueryKey >, - Observer: typeof QueryObserver + Observer: typeof QueryObserver, ): QueryObserverResult { - - const queryClient = useQueryClient(); + const queryClient = useQueryClient() const defaultedOptions = queryClient.defaultQueryOptions(options) - defaultedOptions._optimisticResults = 'optimistic'; - const observer = new QueryObserver(queryClient, defaultedOptions); + defaultedOptions._optimisticResults = 'optimistic' + const observer = new QueryObserver(queryClient, defaultedOptions) const [state, setState] = createStore>( // @ts-ignore observer.getOptimisticResult(defaultedOptions), - ); + ) - const [ dataResource, { refetch } ] = createResource(() => { + const [dataResource, { refetch }] = createResource(() => { return new Promise((resolve, reject) => { if (state.isSuccess) resolve(state.data) - if (state.isError && !state.isFetching) { + if (state.isError && !state.isFetching) { throw state.error } }) - }); + }) const unsubscribe = observer.subscribe((result) => { - const reconciledResult = result; + const reconciledResult = result // @ts-ignore - setState(reconciledResult); - refetch(); - }); + setState(reconciledResult) + refetch() + }) - onCleanup(() => unsubscribe()); + onCleanup(() => unsubscribe()) onMount(() => { - observer.setOptions(defaultedOptions, { listeners: false }); - }); + observer.setOptions(defaultedOptions, { listeners: false }) + }) createComputed(() => { const defaultedOptions = queryClient.defaultQueryOptions(options) @@ -62,13 +68,16 @@ export function createBaseQuery< }) const handler = { - get(target: QueryObserverResult, prop: (keyof QueryObserverResult)): any { + get( + target: QueryObserverResult, + prop: keyof QueryObserverResult, + ): any { if (prop === 'data') { - return dataResource(); + return dataResource() } - return Reflect.get(target, prop); - } + return Reflect.get(target, prop) + }, } - return new Proxy(state, handler) as QueryObserverResult; -} \ No newline at end of file + return new Proxy(state, handler) as QueryObserverResult +} diff --git a/packages/solid-query/src/createMutation.ts b/packages/solid-query/src/createMutation.ts index 2a4b8d65ce6..5214da550c1 100644 --- a/packages/solid-query/src/createMutation.ts +++ b/packages/solid-query/src/createMutation.ts @@ -11,7 +11,7 @@ import { CreateMutationResult, } from './types' import { createComputed, onCleanup } from 'solid-js' -import { createStore } from 'solid-js/store'; +import { createStore } from 'solid-js/store' // HOOK export function createMutation< @@ -82,17 +82,21 @@ export function createMutation< options, ) - const mutate: CreateMutateFunction = - (variables, mutateOptions) => { + const mutate: CreateMutateFunction = ( + variables, + mutateOptions, + ) => { observer.mutate(variables, mutateOptions).catch(noop) } - - const [state, setState] = createStore>({ + + const [state, setState] = createStore< + CreateMutationResult + >({ ...observer.getCurrentResult(), mutate, - mutateAsync: observer.getCurrentResult().mutate + mutateAsync: observer.getCurrentResult().mutate, }) - + createComputed(() => { const newParsedOptions = parseMutationArgs(arg1, arg2, arg3) setOptions(newParsedOptions) @@ -103,7 +107,7 @@ export function createMutation< setState({ ...result, mutate, - mutateAsync: result.mutate + mutateAsync: result.mutate, }) }) @@ -113,4 +117,4 @@ export function createMutation< } // eslint-disable-next-line @typescript-eslint/no-empty-function -function noop() {} \ No newline at end of file +function noop() {} diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index 11ec78c5500..b6594e9bcd0 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,9 +1,9 @@ -import { QueryObserver, QueryFunction } from '@tanstack/query-core'; +import { QueryObserver, QueryFunction } from '@tanstack/query-core' import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' import { createComputed } from 'solid-js' -import { createStore } from 'solid-js/store'; +import { createStore } from 'solid-js/store' import { parseQueryArgs } from './utils' -import { createBaseQuery } from './createBaseQuery'; +import { createBaseQuery } from './createBaseQuery' // There are several ways to create a query. // 1. createQuery(options: CreateQueryOptions) @@ -14,50 +14,52 @@ export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( - options: CreateQueryOptions + options: CreateQueryOptions, ): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( queryKey: SolidQueryKey, options?: Omit< CreateQueryOptions, 'queryKey' - > + >, ): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, 'queryKey' | 'queryFn' - > + >, ): CreateQueryResult export function createQuery< TQueryFnData, TError, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( arg1: TQueryKey | CreateQueryOptions, arg2?: | QueryFunction> | CreateQueryOptions, - arg3?: CreateQueryOptions + arg3?: CreateQueryOptions, ): CreateQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)) + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { @@ -65,5 +67,5 @@ export function createQuery< setParsedOptions(newParsedOptions) }) - return createBaseQuery(parsedOptions, QueryObserver); + return createBaseQuery(parsedOptions, QueryObserver) } diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index cfa7a6a7705..d11b5f5de9a 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -2,7 +2,7 @@ export * from '@tanstack/query-core' // Solid Query -export * from "./types" +export * from './types' // export { useQueries } from './useQueries' // export type { QueriesResults, QueriesOptions } from './useQueries' export { createQuery } from './createQuery' diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 59bc9262077..348af8ae5cf 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,12 +1,12 @@ -import type { Context, Accessor } from "solid-js"; -import type { - QueryClient, - QueryKey, - QueryObserverOptions, - QueryObserverResult, - MutateFunction, +import type { Context, Accessor } from 'solid-js' +import type { + QueryClient, + QueryKey, + QueryObserverOptions, + QueryObserverResult, + MutateFunction, MutationObserverOptions, - MutationObserverResult + MutationObserverResult, } from '@tanstack/query-core' export interface ContextOptions { @@ -16,14 +16,14 @@ export interface ContextOptions { context?: Context } -export type SolidQueryKey = () => readonly unknown[]; +export type SolidQueryKey = () => readonly unknown[] export interface CreateBaseQueryOptions< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryData = TQueryFnData, - TQueryKey extends QueryKey = QueryKey + TQueryKey extends QueryKey = QueryKey, > extends ContextOptions, QueryObserverOptions {} @@ -31,37 +31,35 @@ export interface CreateQueryOptions< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, > extends CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - ReturnType -> {} + TQueryFnData, + TError, + TData, + TQueryFnData, + ReturnType + > {} export type CreateBaseQueryResult< TData = unknown, - TError = unknown + TError = unknown, > = QueryObserverResult export type CreateQueryResult< TData = unknown, - TError = unknown + TError = unknown, > = CreateBaseQueryResult - - export interface CreateMutationOptions< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, > extends ContextOptions, - Omit< - MutationObserverOptions, - '_defaulted' | 'variables' - > {} + Omit< + MutationObserverOptions, + '_defaulted' | 'variables' + > {} export type CreateMutateFunction< TData = unknown, @@ -72,7 +70,6 @@ export type CreateMutateFunction< ...args: Parameters> ) => void - export type CreateMutateAsyncFunction< TData = unknown, TError = unknown, @@ -90,11 +87,13 @@ export type CreateBaseMutationResult< > = Override< MutationObserverResult, { mutate: CreateMutateFunction } -> & { mutateAsync: CreateMutateAsyncFunction } - +> & { + mutateAsync: CreateMutateAsyncFunction +} + export type CreateMutationResult< TData = unknown, TError = unknown, TVariables = unknown, TContext = unknown, -> = CreateBaseMutationResult \ No newline at end of file +> = CreateBaseMutationResult diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index 12d58ff1ab9..f3dd24582dc 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -10,7 +10,10 @@ import { useQueryClient } from './QueryClientProvider' import { Accessor, createSignal, onCleanup } from 'solid-js' interface Options extends ContextOptions {} -export function useIsFetching(filters?: QueryFilters, options?: Options): Accessor +export function useIsFetching( + filters?: QueryFilters, + options?: Options, +): Accessor export function useIsFetching( queryKey?: QueryKey, filters?: QueryFilters, @@ -36,4 +39,4 @@ export function useIsFetching( }) return fetches -} \ No newline at end of file +} diff --git a/packages/solid-query/src/useIsMutating.ts b/packages/solid-query/src/useIsMutating.ts index 92d1a9e997f..3d11fe8c6bf 100644 --- a/packages/solid-query/src/useIsMutating.ts +++ b/packages/solid-query/src/useIsMutating.ts @@ -25,11 +25,13 @@ export function useIsMutating( arg3?: Options, ): Accessor { const [filters, options = {}] = parseMutationFilterArgs(arg1, arg2, arg3) - + const queryClient = useQueryClient({ context: options.context }) const mutationCache = queryClient.getMutationCache() - const [mutations, setMutations] = createSignal(queryClient.isMutating(filters)) + const [mutations, setMutations] = createSignal( + queryClient.isMutating(filters), + ) const unsubscribe = mutationCache.subscribe((result) => { setMutations(queryClient.isMutating(filters)) @@ -40,4 +42,4 @@ export function useIsMutating( }) return mutations -} \ No newline at end of file +} diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 83aa9db1d6d..75351e70396 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,5 +1,4 @@ - -import { CreateQueryOptions, SolidQueryKey } from './types' +import { CreateQueryOptions, SolidQueryKey } from './types' import { QueryFunction } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { @@ -18,17 +17,17 @@ export function parseQueryArgs< arg2?: | QueryFunction> | CreateQueryOptions, - arg3?: CreateQueryOptions + arg3?: CreateQueryOptions, ): CreateQueryOptions { - if(!isQueryKey(arg1)) { + if (!isQueryKey(arg1)) { const { queryKey: solidKey, ...opts } = arg1 as any if (solidKey) { return { ...opts, queryKey: solidKey(), - } - } - return arg1 + } + } + return arg1 } if (typeof arg2 === 'function') { @@ -36,4 +35,4 @@ export function parseQueryArgs< } return { ...arg2, queryKey: arg1() } as any -} \ No newline at end of file +} From e7c875936e491d91533455f19b53bdf142748b63 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 19:06:41 -0400 Subject: [PATCH 006/221] fix lint and typecheck errors - disable rule of hooks in solid-query --- packages/solid-query/.eslintrc | 5 +- .../__tests__/QueryClientProvider.test.tsx | 232 +++++++++--------- packages/solid-query/src/createBaseQuery.ts | 13 +- packages/solid-query/src/types.ts | 2 +- packages/solid-query/src/useIsFetching.ts | 9 +- packages/solid-query/src/useIsMutating.ts | 3 +- 6 files changed, 124 insertions(+), 140 deletions(-) diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc index df08b8b4dbd..cefbf99ca1b 100644 --- a/packages/solid-query/.eslintrc +++ b/packages/solid-query/.eslintrc @@ -4,6 +4,7 @@ "sourceType": "module" }, "rules": { - "react/react-in-jsx-scope": "off" + "react/react-in-jsx-scope": "off", + "react-hooks/rules-of-hooks": "off" } -} \ No newline at end of file +} diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx index dbdf2707e36..f5d9786dcae 100644 --- a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -1,15 +1,8 @@ -import { Context, createContext, useContext } from 'solid-js' import { render, screen, waitFor } from 'solid-testing-library' import { queryKey } from './utils' import { QueryCache } from '@tanstack/query-core' -import { renderToString } from 'solid-js/web' -import { - createQuery, - QueryClient, - QueryClientProvider, - useQueryClient, -} from '..' +import { createQuery, QueryClientProvider, useQueryClient } from '..' import { createQueryClient, sleep } from '../../../../tests/utils' describe('QueryClientProvider', () => { @@ -138,63 +131,64 @@ describe('QueryClientProvider', () => { expect(queryCache.find(key())?.options.cacheTime).toBe(Infinity) }) - describe('with custom context', () => { - it('uses the correct context', async () => { - const key = queryKey() - - const contextOuter = createContext(undefined) - const contextInner = createContext(undefined) - - const queryCacheOuter = new QueryCache() - const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) - - const queryCacheInner = new QueryCache() - const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) - - const queryCacheInnerInner = new QueryCache() - const queryClientInnerInner = new QueryClient({ - queryCache: queryCacheInnerInner, - }) - - function Page() { - const queryOuter = createQuery(key, async () => 'testOuter', { - context: contextOuter, - }) - const queryInner = createQuery(key, async () => 'testInner', { - context: contextInner, - }) - const queryInnerInner = createQuery(key, async () => 'testInnerInner') - - return ( -
-

- {queryOuter.data} {queryInner.data} {queryInnerInner.data} -

-
- ) - } - - // contextSharing should be ignored when passing a custom context. - const contextSharing = true - - render(() => ( - - - - - - - - )) - - await waitFor(() => - screen.getByText('testOuter testInner testInnerInner'), - ) - }) - }) + // TODO(lukemurray): add test when we implement context sharing. + // describe('with custom context', () => { + // it('uses the correct context', async () => { + // const key = queryKey() + + // const contextOuter = createContext(undefined) + // const contextInner = createContext(undefined) + + // const queryCacheOuter = new QueryCache() + // const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) + + // const queryCacheInner = new QueryCache() + // const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) + + // const queryCacheInnerInner = new QueryCache() + // const queryClientInnerInner = new QueryClient({ + // queryCache: queryCacheInnerInner, + // }) + + // function Page() { + // const queryOuter = createQuery(key, async () => 'testOuter', { + // context: contextOuter, + // }) + // const queryInner = createQuery(key, async () => 'testInner', { + // context: contextInner, + // }) + // const queryInnerInner = createQuery(key, async () => 'testInnerInner') + + // return ( + //
+ //

+ // {queryOuter.data} {queryInner.data} {queryInnerInner.data} + //

+ //
+ // ) + // } + + // // contextSharing should be ignored when passing a custom context. + // const contextSharing = true + + // render(() => ( + // + // + // + // + // + // + // + // )) + + // await waitFor(() => + // screen.getByText('testOuter testInner testInnerInner'), + // ) + // }) + // }) describe('useQueryClient', () => { test('should throw an error if no query client has been set', () => { @@ -214,58 +208,60 @@ describe('QueryClientProvider', () => { consoleMock.mockRestore() }) - test('should use window to get the context when contextSharing is true', () => { - const queryCache = new QueryCache() - const queryClient = createQueryClient({ queryCache }) - - let queryClientFromHook: QueryClient | undefined - let queryClientFromWindow: QueryClient | undefined - - function Page() { - queryClientFromHook = useQueryClient() - queryClientFromWindow = useContext( - window.SolidQueryClientContext as Context, - ) - return null - } - - render(() => ( - - - - )) - - expect(queryClientFromHook).toEqual(queryClient) - expect(queryClientFromWindow).toEqual(queryClient) - }) - - test('should not use window to get the context when contextSharing is true and window does not exist', () => { - const queryCache = new QueryCache() - const queryClient = createQueryClient({ queryCache }) - - // Mock a non web browser environment - const windowSpy = jest - .spyOn(window, 'window', 'get') - .mockImplementation(undefined) - - let queryClientFromHook: QueryClient | undefined - - function Page() { - queryClientFromHook = useQueryClient() - return null - } - - // TODO(lukemurray): this test doesn't pass because the page function is - // never called. I'm not sure why. - renderToString(() => ( - - - - )) - - expect(queryClientFromHook).toEqual(queryClient) - - windowSpy.mockRestore() - }) + // TODO(lukemurray): add test when we implement context sharing + // test('should use window to get the context when contextSharing is true', () => { + // const queryCache = new QueryCache() + // const queryClient = createQueryClient({ queryCache }) + + // let queryClientFromHook: QueryClient | undefined + // let queryClientFromWindow: QueryClient | undefined + + // function Page() { + // queryClientFromHook = useQueryClient() + // queryClientFromWindow = useContext( + // window.SolidQueryClientContext as Context, + // ) + // return null + // } + + // render(() => ( + // + // + // + // )) + + // expect(queryClientFromHook).toEqual(queryClient) + // expect(queryClientFromWindow).toEqual(queryClient) + // }) + + // TODO(lukemurray): add test when we implement context sharing + // test('should not use window to get the context when contextSharing is true and window does not exist', () => { + // const queryCache = new QueryCache() + // const queryClient = createQueryClient({ queryCache }) + + // // Mock a non web browser environment + // const windowSpy = jest + // .spyOn(window, 'window', 'get') + // .mockImplementation(undefined) + + // let queryClientFromHook: QueryClient | undefined + + // function Page() { + // queryClientFromHook = useQueryClient() + // return null + // } + + // // TODO(lukemurray): this test doesn't pass because the page function is + // // never called. I'm not sure why. + // renderToString(() => ( + // + // + // + // )) + + // expect(queryClientFromHook).toEqual(queryClient) + + // windowSpy.mockRestore() + // }) }) }) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index c3a2695bef3..6a028bd51c2 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -2,14 +2,7 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' import { CreateBaseQueryOptions } from './types' import { useQueryClient } from './QueryClientProvider' -import { - onMount, - onCleanup, - createComputed, - createResource, - createEffect, - batch, -} from 'solid-js' +import { onMount, onCleanup, createComputed, createResource } from 'solid-js' import { createStore } from 'solid-js/store' // Base Query Function that is used to create the query. @@ -33,7 +26,7 @@ export function createBaseQuery< const defaultedOptions = queryClient.defaultQueryOptions(options) defaultedOptions._optimisticResults = 'optimistic' - const observer = new QueryObserver(queryClient, defaultedOptions) + const observer = new Observer(queryClient, defaultedOptions) const [state, setState] = createStore>( // @ts-ignore @@ -41,7 +34,7 @@ export function createBaseQuery< ) const [dataResource, { refetch }] = createResource(() => { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { if (state.isSuccess) resolve(state.data) if (state.isError && !state.isFetching) { throw state.error diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 348af8ae5cf..298ac316010 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context, Accessor } from 'solid-js' +import type { Context } from 'solid-js' import type { QueryClient, QueryKey, diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index f3dd24582dc..6de342ca8e0 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -1,9 +1,4 @@ -import { - QueryKey, - notifyManager, - parseFilterArgs, - QueryFilters, -} from '@tanstack/query-core' +import { QueryKey, parseFilterArgs, QueryFilters } from '@tanstack/query-core' import { ContextOptions } from './types' import { useQueryClient } from './QueryClientProvider' @@ -30,7 +25,7 @@ export function useIsFetching( const [fetches, setFetches] = createSignal(queryClient.isFetching(filters)) - const unsubscribe = queryCache.subscribe((result) => { + const unsubscribe = queryCache.subscribe((_result) => { setFetches(queryClient.isFetching(filters)) }) diff --git a/packages/solid-query/src/useIsMutating.ts b/packages/solid-query/src/useIsMutating.ts index 3d11fe8c6bf..ada59ee94bc 100644 --- a/packages/solid-query/src/useIsMutating.ts +++ b/packages/solid-query/src/useIsMutating.ts @@ -1,5 +1,4 @@ import { - notifyManager, MutationKey, MutationFilters, parseMutationFilterArgs, @@ -33,7 +32,7 @@ export function useIsMutating( queryClient.isMutating(filters), ) - const unsubscribe = mutationCache.subscribe((result) => { + const unsubscribe = mutationCache.subscribe((_result) => { setMutations(queryClient.isMutating(filters)) }) From 77cbabf48eebf0ef553604c3afbbeec0ed8af226 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 20:01:32 -0400 Subject: [PATCH 007/221] fix npm run build --- packages/solid-query/package.json | 28 +++++++++++++++++----------- rollup.config.ts | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json index abedd50c244..10e19a4c869 100644 --- a/packages/solid-query/package.json +++ b/packages/solid-query/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-query", - "version": "4.2.3", + "version": "4.3.0-beta.4", "description": "Hooks for managing, caching and syncing asynchronous and remote data in Solid", "author": "tannerlinsley", "license": "MIT", @@ -10,20 +10,26 @@ "type": "github", "url": "https://github.com/sponsors/tannerlinsley" }, - "module": "build/esm/index.js", - "main": "build/cjs/solid-query/src/index.js", - "browser": "build/umd/index.production.js", - "types": "build/types/packages/solid-query/src/index.d.ts", - "sideEffects": [], + "types": "build/lib/index.d.ts", + "main": "build/lib/index.js", + "exports": { + ".": { + "types": "./build/lib/index.d.ts", + "import": "./build/lib/index.mjs", + "default": "./build/lib/index.js" + }, + "./package.json": "./package.json" + }, "scripts": { + "clean": "rm -rf ./build", "test:codemods": "../../node_modules/.bin/jest --config codemods/jest.config.js", "test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src", "test:jest": "yarn test:codemods && ../../node_modules/.bin/jest --config jest.config.js", - "test:jest:dev": "yarn test:jest --watch", - "compile": "../../node_modules/.bin/tsc -p tsconfig.json --noEmit --emitDeclarationOnly false" + "test:jest:dev": "yarn test:jest --watch" }, "files": [ - "build/*", + "build/lib/*", + "build/umd/*", "src", "codemods", "!codemods/jest.config.js", @@ -35,10 +41,10 @@ "jscodeshift": "^0.13.1" }, "dependencies": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" }, "peerDependencies": { "solid-js": "^1.5.4" }, "peerDependenciesMeta": {} -} \ No newline at end of file +} diff --git a/rollup.config.ts b/rollup.config.ts index 0ad96cf62e2..64bb2132e38 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -137,6 +137,20 @@ export default function rollup(options: RollupOptions): RollupOptions[] { '@tanstack/react-query': 'ReactQuery', }, }), + ...buildConfigs({ + name: 'solid-query', + packageDir: 'packages/solid-query', + jsName: 'SolidQuery', + outputFile: 'index', + entryFile: 'src/index.ts', + globals: { + 'solid-js': 'Solid', + '@tanstack/query-core': 'QueryCore', + }, + bundleUMDGlobals: [ + '@tanstack/query-core', + ], + }), ] } From e86a44a5ba7c42f0d018da94dab108fa8ef88efb Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 20:19:34 -0400 Subject: [PATCH 008/221] fix babel config conditionally apply babel react preset to packages other than solid-query. apply solid-babel-preset to solid query. --- babel.config.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/babel.config.js b/babel.config.js index 8503e70bcb0..1c7384078ae 100644 --- a/babel.config.js +++ b/babel.config.js @@ -17,7 +17,6 @@ module.exports = { }, ], '@babel/preset-typescript', - '@babel/react', ], plugins: [ cjs && ['@babel/transform-modules-commonjs', { loose }], @@ -32,4 +31,14 @@ module.exports = { }, ], ].filter(Boolean), + overrides: [ + { + exclude: './packages/solid-query/**', + presets: ['@babel/react'], + }, + { + include: './packages/solid-query/**', + presets: ['babel-preset-solid'], + }, + ], } From 0a18d58150b8bceb2abbf60ab026ed344fad09e6 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Thu, 8 Sep 2022 21:57:58 -0400 Subject: [PATCH 009/221] Completely reactive useIsFetching with correct queryKey types --- packages/solid-query/src/useIsFetching.ts | 50 ++++++++++++++++------- packages/solid-query/src/utils.ts | 24 ++++++++++- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index 6de342ca8e0..7e346c54efb 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -1,32 +1,54 @@ -import { QueryKey, parseFilterArgs, QueryFilters } from '@tanstack/query-core' +import { QueryFilters } from '@tanstack/query-core' -import { ContextOptions } from './types' +import { ContextOptions, SolidQueryKey } from './types' import { useQueryClient } from './QueryClientProvider' -import { Accessor, createSignal, onCleanup } from 'solid-js' +import { + Accessor, + createSignal, + onCleanup, + createComputed, + createMemo, +} from 'solid-js' +import { parseFilterArgs, SolidQueryFilters } from './utils' + interface Options extends ContextOptions {} export function useIsFetching( - filters?: QueryFilters, + filters?: SolidQueryFilters, options?: Options, ): Accessor export function useIsFetching( - queryKey?: QueryKey, - filters?: QueryFilters, + queryKey?: SolidQueryKey, + filters?: SolidQueryFilters, options?: Options, ): Accessor export function useIsFetching( - arg1?: QueryKey | QueryFilters, - arg2?: QueryFilters | Options, + arg1?: SolidQueryKey | SolidQueryFilters, + arg2?: SolidQueryFilters | Options, arg3?: Options, ): Accessor { - const [filters, options = {}] = parseFilterArgs(arg1, arg2, arg3) - const queryClient = useQueryClient({ context: options.context }) - const queryCache = queryClient.getQueryCache() + const [filtersObj, optionsObj = {}] = parseFilterArgs(arg1, arg2, arg3) + + const [filters, setFilters] = createSignal(filtersObj) + const [options, setOptions] = createSignal(optionsObj) + + const queryClient = createMemo(() => + useQueryClient({ context: options().context }), + ) + const queryCache = createMemo(() => queryClient().getQueryCache()) - const [fetches, setFetches] = createSignal(queryClient.isFetching(filters)) + const [fetches, setFetches] = createSignal( + queryClient().isFetching(filters as QueryFilters), + ) + + createComputed(() => { + const [filtersObj, optionsObj = {}] = parseFilterArgs(arg1, arg2, arg3) + setFilters(filtersObj) + setOptions(optionsObj) + }) - const unsubscribe = queryCache.subscribe((_result) => { - setFetches(queryClient.isFetching(filters)) + const unsubscribe = queryCache().subscribe(() => { + setFetches(queryClient().isFetching(filters() as QueryFilters)) }) onCleanup(() => { diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 75351e70396..2da23639415 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,5 +1,5 @@ import { CreateQueryOptions, SolidQueryKey } from './types' -import { QueryFunction } from '@tanstack/query-core' +import { QueryFunction, QueryFilters } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { return typeof value === 'function' @@ -36,3 +36,25 @@ export function parseQueryArgs< return { ...arg2, queryKey: arg1() } as any } + +export interface SolidQueryFilters extends Omit { + queryKey?: SolidQueryKey +} + +export type ParseFilterArgs = + T['queryKey'] extends () => infer R ? T & { queryKey: R } : T + +export function parseFilterArgs< + TFilters extends SolidQueryFilters, + TOptions = unknown, +>( + arg1?: SolidQueryKey | TFilters, + arg2?: TFilters | TOptions, + arg3?: TOptions, +): [ParseFilterArgs, TOptions | undefined] { + return ( + isQueryKey(arg1) + ? [{ ...arg2, queryKey: arg1() }, arg3] + : [{ ...arg1, queryKey: arg1?.queryKey?.() } || {}, arg2] + ) as [ParseFilterArgs, TOptions] +} From 712966c456d57010cba462bece0c49ca22d64ab4 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 22:09:35 -0400 Subject: [PATCH 010/221] fix build types. make tsconfig look like react query tsconifg - add incremental compilation - output types in ./build/lib - allow project references --- packages/solid-query/tsconfig.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json index f8c5b4861ac..6146a991595 100644 --- a/packages/solid-query/tsconfig.json +++ b/packages/solid-query/tsconfig.json @@ -1,11 +1,16 @@ { - "composite": true, "extends": "../../tsconfig.base.json", "compilerOptions": { - "outDir": "./build/types", + "composite": true, + "rootDir": "./src", + "outDir": "./build/lib", + "tsBuildInfoFile": "./build/.tsbuildinfo", "jsx": "preserve", "jsxImportSource": "solid-js", }, - "files": ["src/index.ts"], - "include": ["src"] + "include": ["src"], + "exclude": ["src/__tests__"], + "references": [ + { "path": "../query-core" } + ] } \ No newline at end of file From 62f287180dd5e8bdf26f8e0e52e292e8e422d930 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 23:14:00 -0400 Subject: [PATCH 011/221] add the first solid example --- examples/solid/basic-typescript/.eslintrc | 10 + examples/solid/basic-typescript/.gitignore | 4 + examples/solid/basic-typescript/README.md | 6 + examples/solid/basic-typescript/index.html | 16 + .../solid/basic-typescript/package-lock.json | 2479 +++++++++++++++++ examples/solid/basic-typescript/package.json | 22 + .../basic-typescript/src/assets/favicon.ico | Bin 0 -> 15086 bytes examples/solid/basic-typescript/src/index.tsx | 163 ++ examples/solid/basic-typescript/tsconfig.json | 15 + .../solid/basic-typescript/vite.config.ts | 15 + 10 files changed, 2730 insertions(+) create mode 100644 examples/solid/basic-typescript/.eslintrc create mode 100644 examples/solid/basic-typescript/.gitignore create mode 100644 examples/solid/basic-typescript/README.md create mode 100644 examples/solid/basic-typescript/index.html create mode 100644 examples/solid/basic-typescript/package-lock.json create mode 100644 examples/solid/basic-typescript/package.json create mode 100644 examples/solid/basic-typescript/src/assets/favicon.ico create mode 100644 examples/solid/basic-typescript/src/index.tsx create mode 100644 examples/solid/basic-typescript/tsconfig.json create mode 100644 examples/solid/basic-typescript/vite.config.ts diff --git a/examples/solid/basic-typescript/.eslintrc b/examples/solid/basic-typescript/.eslintrc new file mode 100644 index 00000000000..86b22fec59b --- /dev/null +++ b/examples/solid/basic-typescript/.eslintrc @@ -0,0 +1,10 @@ +{ + "parserOptions": { + "project": "./tsconfig.json", + "sourceType": "module" + }, + "rules": { + "react/react-in-jsx-scope": "off", + "jsx-a11y/anchor-is-valid": "off" + } +} diff --git a/examples/solid/basic-typescript/.gitignore b/examples/solid/basic-typescript/.gitignore new file mode 100644 index 00000000000..001e3f924bb --- /dev/null +++ b/examples/solid/basic-typescript/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.yalc +yalc.lock \ No newline at end of file diff --git a/examples/solid/basic-typescript/README.md b/examples/solid/basic-typescript/README.md new file mode 100644 index 00000000000..310f37f62fd --- /dev/null +++ b/examples/solid/basic-typescript/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` +- `npm run start` diff --git a/examples/solid/basic-typescript/index.html b/examples/solid/basic-typescript/index.html new file mode 100644 index 00000000000..48c59fc1242 --- /dev/null +++ b/examples/solid/basic-typescript/index.html @@ -0,0 +1,16 @@ + + + + + + + + Solid App + + + +
+ + + + diff --git a/examples/solid/basic-typescript/package-lock.json b/examples/solid/basic-typescript/package-lock.json new file mode 100644 index 00000000000..785e051eed2 --- /dev/null +++ b/examples/solid/basic-typescript/package-lock.json @@ -0,0 +1,2479 @@ +{ + "name": "@tanstack/query-example-solid-basic-typescript", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@tanstack/query-example-solid-basic-typescript", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } + }, + ".yalc/@tanstack/solid-query": { + "version": "4.2.3", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/solid-query": { + "version": "4.2.3", + "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "dependencies": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "dependencies": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "dependencies": { + "csstype": "^3.1.0" + } + }, + "node_modules/solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + }, + "peerDependencies": { + "solid-js": "^1.3" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "dependencies": { + "esbuild": "^0.15.6", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + }, + "peerDependencies": { + "solid-js": "^1.3.17", + "vite": "^3.0.0" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true + }, + "@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + } + }, + "@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "requires": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + } + }, + "@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + } + }, + "@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + } + }, + "@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "dev": true, + "optional": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + }, + "@tanstack/solid-query": { + "version": "4.2.3", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "requires": { + "@tanstack/query-core": "4.2.3" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + } + } + }, + "babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "requires": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + } + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "requires": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "requires": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "requires": { + "csstype": "^3.1.0" + } + }, + "solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "requires": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "requires": { + "esbuild": "^0.15.6", + "fsevents": "~2.3.2", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + } + }, + "vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "requires": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + } + } + } +} diff --git a/examples/solid/basic-typescript/package.json b/examples/solid/basic-typescript/package.json new file mode 100644 index 00000000000..158e03b8563 --- /dev/null +++ b/examples/solid/basic-typescript/package.json @@ -0,0 +1,22 @@ +{ + "name": "@tanstack/query-example-solid-basic-typescript", + "private": true, + "version": "0.0.0", + "description": "", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } +} diff --git a/examples/solid/basic-typescript/src/assets/favicon.ico b/examples/solid/basic-typescript/src/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b836b2bccac650e0e7d90514083add91d2c027ff GIT binary patch literal 15086 zcmeI32Y6Lgw#RQo0Y@EtmA&@a z>%VX~JRB7qO`13ut2?&Tb~rp84oCIs=KCidj&pqWB%^#k=3$2;oFCNVH(cTvg2?Ck zua+_V>;M1%EHI;OjS4~SYCbiyeXWK_$5|a}^+(18cdR{rcBk6ILps&z9{OsXW^?@N zKE>$q&tL)YJ|5J*W^?dPL^gr^&;nW zso#2j*ZLKIX+474)p`W1FCqa*I(V-kh2T{d-Vlwqj>6Uoyeh17Jq2bpw@W<*ZZ)rK zeKo&ZgYOr-)?mfL?hT*&C3FDe6G#^%3dz;>)tKujjTg*<7aMELcjK+EBDytDU`84$ zaI4534b`I8Ux-`UtI^M<12}(;^hFY9cdY$)ZDX;o5fe@u3tlH?u`eQcBQ)LyPP~yl zUJ%S`F|wp*BekSgBek+ml_F zEBZ86EBiJP?CMW{Y^t`5XpxlqPCIt7^8XRL&my5nuB^NJiU}RZcgKWfW3lgYC*H;y z@2Y-a?$=bU2KNVViZoN(N4LDS_bs2{hx4lZ7+D;|B-4-ACs`$5jmh746Q^6e_c8~Jzjt+UELmaWVXW}bbc8_nP zwxZ8E<`;Y3Z%kNtEgM^SHw^bu88bM;zBTwFl;P%MKN*`fwI zd{q=j##+FaI*!CPS_ga}I;5aO+Kg8U zgS;0VGG})&eyepTHIBYvJ-f9Z$eKZi@#t{dilaD}IP%r&OxByMy%f_AVn?xO2DtZ! zbWsQ9bkkS`vtU0m|8=d$!SL7gciIP9hhlN0*Mc*SF0!6$xU-H;{J)7F<(+n4aU?nr zKN3f2#B&BZNNfl`tpj*19qc}k@9v5t=UV8XV|3rtcAw+#-@1$6)S(MLIEN1k>^Zf} zIAVTTlM+J`9}*{m^AI{n3|T%XJ&t58*z(c4?LT0?a-B7!M|f3;9_d{Z9}J2a(`sYv zxYlQhqucT93sz2*d|g%?i4F(QL1NzWfu+OUam1Rj=cB-m*T{3e<*|M7Yw*Ft_@FBI z2ggtGJu7>pi0n0@gU(0A;z-uQ1H@4QF*zUnj}*sJ-uFo}{U1-9;Wrogdm?d?NWM!X z2km1YkbOsTx6ViAS|}-w#OBU8vgIT3ku4wnNG@1G991bV*5cPC2l-V@3i6wW+)fVi zSIO8mMTC5=M{wF^AUa#-yD*CBBE#Bkp(?JJ+h$JyrT=u! z``;b}J2)Q!?`FX)c+-LnyiUxrmx}+9{gM-r17V1~4(+D*FrACguP7g}CrCbuU{8>J z0Rc18OC4F*OMzQ~Tja*k$TyCj{BX$3?AZ67Dvus%v%6G9&brvy#H^nM?3l5w*ij4n zmgF3rk*BLuI3`KT*qb!^caT0ULUSADs5q&gox_0EMofdS>gPh7l&d|zZ^!_Hz~ zZRfHuo3=eHcDCU)Y>b@^8#5YsowyhGQJ=3Ktp0P`WOZTBbYvP5m~|m8@I`lZz{XAY z&*^&285iI^V6*YT;&v_*vokK#QPal97WGlb!278wCsqznXQIZd?6_&_;@%nRLj3!7 z9oA;Y23B%M2WY#;Wr%;7*u{1Zn&i z1%JHL2YK0Xfj!*8pE29t0~<%W#B!N7wy!^1Tv#?X@oL;l!M$pLI<;Y(#(gOG!DFp1Z)unyl-)G`4*#~##d&zO&WklyD?WT~3};gkS3*_)GTz__OeVTWk4B+T7n}$Ir|-v-vIc z*`Edzv;CZTPUCmR2Wt^~|8-eEbz((-b@IcZ#Pv8Zzo#w;=G3_=CvBd}VYK6S(+Bu1 zU>)Mt`8X#ftVd2t_>D_RVJbU5Sbe)QP<_4SZFMSY5-~hMo!U5&n3$}-**;aB+s(S$ z8v@38>Pq@TbtMByUjX*`PW;@yN( z*?R)Zb*2#=xQ7Qm2-iL!9>l&^#pZ(lP>~M|``dJ|`ykCNANgUFxD2e;S@j^Kl#;C~=qpg4YcPu?4vlREFFtjW@SAoefj16j*@9hd5Z zo2-LO_Jd*U2jx1umxQfA#7c@>*%<-V_j|0lP1 zas2Y0IUggJPsX0-@Ihh8>%jCurY#p4J}Asdi})M*r?Qp;utj6=yH#r|36r~@F{cOk z>s-lP6p(vhNd|fJDr@;B;~kw_4=gRjH@C^9dFXfvUmYcHt>K!{Iq4Bi!T*@MbN*bv z2j>&uZUFucjD5gAh`nF{pLYj;EAZF4k{MZr{p_Ki3&X$e`^#ED=|6|#?lHZBQhZ)0 z-yzo>j#)CMI~+bT0#n8U#%hdwt;a0JD!fm(jg`#z6&U4vYxFR$vqrgTKHtkI_qC6} z(C<|+{Y-o>c=VWM+)r@HJTmIf`JH1H?`8Bc$7<$CWl4W-jqHkYokPYfMwlx-vdhan zG*B6%d@lgyIvM4@0#xxI07WkuMSsNv+FmNluwyB9mOicOh%e&o(|VFO|A+qqU#adP zy*>2D)S%a-CE`!-MpybEeCR2tO;5q2Kec+(eQS6GwXgLwb9O@(G3S1IMlLdM9`pXl zytkP5A7TFWF2k?ygd%&D@3bUxb~D zc-^ghjxB2>AtZ<@@miJz$Sv&*8{vmtG&U z&&Q=-#@TyfarX3^z2Jul_c)Yb zQ^GI*un}2}w_bbZ=TZVZ4ZtGCb^bK&uAJP}GoPHYJza;%Y zyms2OFFIPi6VmG;Js!x%W}k<_H5**M@U(HlD+=HGmQOqw$~=?7&-aKO)9MCXjEaUI z-3s>g^e|Ywym0f<4`bKSKA-eDSe*7Iu8o6N6)xG}-F@@HFt98e>>lY|8Gd@R@L9r5 z3lFrHd+dQriG~;20`DvL7jE6+{|!#s;{3hTrco`_jtQ;RKIYZjukeL%ktXMSlzTo? zCWcYoE#RbbW5*R?kZUatClMYe9*%hzyt(klTTL!`2Y6$IyM-T-8oh9A!g*@mfop_A z!4G%fg~paO|IT4v55en22)7!?{iRPrxFq5I1%vRZX`07_7lj89E?9U0iwBlEp45J& zrmlGcxMSfji~P`bJ-U^7zJ=ed35L_sYZ6C)hV%$X?~3NKu&dlp_!G^A%G}In@o!SM zms+UQ&NYV)ALHVOciMeamj2dvaD#pE!(p)gp!*ceI2JofKZn7K8(gO5V&N1l3^E?% zy?n0yAiSUOKLH(XW5Y6I(3)RHVzCO`WJ`Fxu=vTo*CZA-KaU@De}U--&Eui3@Q|Xv z#k-W?hXgRVwI3wU>RdT7$S(|DE=bO#cjQ zKqt9-fACVHkROFhE8=*FZHaFi4<&ZCczstt7<>t}*~9P(CeiN%$mL2gdwxM(`R(biLiISugBeNG&q=%QYjmXU7KAycYs^ zm3m07^jTQ^l?$h$xe0^+xvTbU<9w|8t<><(Y=V1;4G_L$CG|bJ`Ah$U6RCsb=s9hi zh{ZP= zc>(*JMs3~F(OILW#(SLluAX-{^IA1?C+DI$qr`jFIFBvv+XepV2jQqRpH_lh?Q=?9 zS-7dwQ4>^F?E6ODTWa@Guhcbfi*wL6kUH!5vTVRL6~Ec`_S!H0Jd&FAo0>~<*0ZIK zz0_96-Y{OB-4%$gA!hB=wf0_$4Zg+(FO-ELCpEk&HN}e;5<=AZ*qQ3vUDK(T2Qt?* z{r*BiD0OD)rPQrNq;BV|pC`{T_zR1>uyIH5Mg`PrlbOF!S@X+x)IoyfzPhF?wamjS zjd~`vO{q;ujm@P7uItA|^>2$mvDx4Pwbp6Oe_u5;>Q;Y1rxT(db(o@>wytAa^HT?= zc0}E!EF1hc^~R5=mo~l_KfTO-u((aAOAo>ZH$_+KCng5;cd4aY^+WN2)X*&(gnow& z)=~3pjSb4xw}A~RbI&kraN|C0kdMtyf;*gRU!v|;u6gZtK%Yv?-<3Gnh7Gc)Y3ET# z%Etyb`RqEjIZqs<@|y^3)djpybB$Yew$E4EYv!rQyw#~?c{6sTj@6DhY|iIZslolK zwCny^KR4<#{6DLTQdAlWsB&CKvM4nK8!{`MiU;DuXCl=oT~y2GH6;m=St67xsvwn2 zslaC}eShOjdx~>c5dQ|^acd6y$hq{XP`^5pI4_>$ ztXLpt@A=*8s|ED>%fJ1Qa}(#KTbzp~*sqh<%X&6?h5M&*#w(C>y7Ym|*;W3%g`8RC zY_*y*&PM~9scoZMo=TkJ>(XCHA9?>xLp}4>(o--0F2FjA$(cxcs^vT+J;_@+tL)`G zkTBUdY{yVfXZ**FZuu+DSexaUb`Q_AF_Vm*R5{y-NPlV^&-(h@z_T9Dn-_WhcgfE@ zn|t$Yo-5Dg(zC03nxwyybB8?t$n&>656ZJ4eOm>b9eUgCuxq$i1)goY^IW@~XWD$} zv6JUx>CLpBVddFXdU$!(|C;aX+OL<_nR8$BpzkUud4}KZ6wU&vW{;}OE6-md+@la# z#WUD*XEu&;+CZ+S-{yJb8+o2HdOxh*8l$Ji>YZVK%|E?i>=*3QF8$hE^DKQLr>tia zqkqMC&XfIFIQ;)uGm<^>U9-nyS~UBdOV8P7s|HO!zG6V3)njpdxxq)Dj+)4`63-5@ zXG*^UeG2TA`8+SV#M7mu&}Z4}k7cv}id;-&zfUFa%l;$$HG8kzgZ<_XeHusD>$-~W z_CNCDo8+v2Xnqi`meW?dF!{OjbMF<{P`UD{3UW|Gq{d_=bk0*6(lD|z7KWYY7R#*)(qxJUL+mK WLaxim%Fn{v*G ['posts'], + async (): Promise> => { + const response = await fetch( + 'https://jsonplaceholder.typicode.com/posts', + { + method: 'GET', + }, + ) + return response.json() + }, + ) +} + +function Posts(props: { setPostId: Setter }) { + const queryClient = useQueryClient() + const state = createPosts() + + return ( + + ) +} + +const getPostById = async (id: number): Promise => { + const response = await fetch( + `https://jsonplaceholder.typicode.com/posts/${id}`, + { + method: 'GET', + }, + ) + return await response.json() +} + +function createPost(postId: number) { + return createQuery( + () => ['post', postId], + () => getPostById(postId), + { + enabled: !!postId, + }, + ) +} + +function Post(props: { postId: number; setPostId: Setter }) { + const state = createPost(props.postId) + + return ( +
+ + + + Loading... + + + Error: {(state.error as Error).message} + + + <> +

{state.data?.title}

+
+

{state.data?.body}

+
+
{state.isFetching ? 'Background Updating...' : ' '}
+ +
+
+
+ ) +} + +const App: Component = () => { + const [postId, setPostId] = createSignal(-1) + + return ( + +

+ As you visit the posts below, you will notice them in a loading state + the first time you load them. However, after you return to this list and + click on any posts you have already visited again, you will see them + load instantly and background refresh right before your eyes!{' '} + + (You may need to throttle your network speed to simulate longer + loading sequences) + +

+ {postId() > -1 ? ( + + ) : ( + + )} +
+ ) +} + +render(() => , document.getElementById('root') as HTMLElement) diff --git a/examples/solid/basic-typescript/tsconfig.json b/examples/solid/basic-typescript/tsconfig.json new file mode 100644 index 00000000000..249b2732a74 --- /dev/null +++ b/examples/solid/basic-typescript/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": ["vite/client"], + "noEmit": true, + "isolatedModules": true + } +} diff --git a/examples/solid/basic-typescript/vite.config.ts b/examples/solid/basic-typescript/vite.config.ts new file mode 100644 index 00000000000..598cdda9083 --- /dev/null +++ b/examples/solid/basic-typescript/vite.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite' +import solidPlugin from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solidPlugin()], + server: { + port: 3000, + }, + build: { + target: 'esnext', + }, + resolve: { + preserveSymlinks: true, + }, +}) From 2afd4474130d23b00179484bea68b80235126b73 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 09:39:20 -0400 Subject: [PATCH 012/221] fix query types --- .../src/__tests__/useQuery.types.test.tsx | 160 ++++++++++++++++++ packages/solid-query/src/createQuery.ts | 101 +++++++++-- packages/solid-query/src/types.ts | 44 ++++- 3 files changed, 286 insertions(+), 19 deletions(-) create mode 100644 packages/solid-query/src/__tests__/useQuery.types.test.tsx diff --git a/packages/solid-query/src/__tests__/useQuery.types.test.tsx b/packages/solid-query/src/__tests__/useQuery.types.test.tsx new file mode 100644 index 00000000000..1d82484d5b6 --- /dev/null +++ b/packages/solid-query/src/__tests__/useQuery.types.test.tsx @@ -0,0 +1,160 @@ +import { createQuery } from '../createQuery' + +export type Equal = (() => T extends X ? 1 : 2) extends < + T, +>() => T extends Y ? 1 : 2 + ? true + : false + +export type Expect = T + +const doNotExecute = (_func: () => void) => true + +describe('initialData', () => { + describe('Config object overload', () => { + it('TData should always be defined when initialData is provided as an object', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => ({ + wow: true, + }), + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + }) + + const result: Expect> = + true + return result + }) + }) + + it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + }) + + const result: Expect> = + true + return result + }) + }) + }) + + describe('Query key overload', () => { + it('TData should always be defined when initialData is provided', () => { + doNotExecute(() => { + const { data } = createQuery(() => ['key'], { + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery(() => ['key'], { + queryFn: () => { + return { + wow: true, + } + }, + }) + + const result: Expect> = + true + return result + }) + }) + }) + + describe('Query key and func', () => { + it('TData should always be defined when initialData is provided', () => { + doNotExecute(() => { + const { data } = createQuery( + () => ['key'], + () => { + return { + wow: true, + } + }, + { + initialData: { + wow: true, + }, + }, + ) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery( + () => ['key'], + () => { + return { + wow: true, + } + }, + ) + + const result: Expect> = + true + return result + }) + }) + }) +}) diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index b6594e9bcd0..4258a53310d 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,20 +1,44 @@ -import { QueryObserver, QueryFunction } from '@tanstack/query-core' -import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' +import { QueryFunction, QueryObserver } from '@tanstack/query-core' import { createComputed } from 'solid-js' import { createStore } from 'solid-js/store' -import { parseQueryArgs } from './utils' import { createBaseQuery } from './createBaseQuery' +import { + CreateQueryOptions, + CreateQueryResult, + DefinedCreateQueryResult, + SolidQueryKey, +} from './types' +import { parseQueryArgs } from './utils' -// There are several ways to create a query. -// 1. createQuery(options: CreateQueryOptions) -// 2. createQuery(querykey: () => Serializable[], options: CreateQueryOptions) -// 3. createQuery(querykey: () => Serializable[], queryFunc: Fetcher Function, options: CreateQueryOptions) -// 4. The fourth overload is a combination of all three function params +// HOOK + +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + options: Omit< + CreateQueryOptions, + 'initialData' + > & { initialData?: () => undefined }, +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + options: Omit< + CreateQueryOptions, + 'initialData' + > & { initialData: TQueryFnData | (() => TQueryFnData) }, +): DefinedCreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, >( options: CreateQueryOptions, ): CreateQueryResult @@ -22,9 +46,33 @@ export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey, + TQueryKey extends SolidQueryKey = SolidQueryKey, >( - queryKey: SolidQueryKey, + queryKey: TQueryKey, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'initialData' + > & { initialData?: () => undefined }, +): CreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'initialData' + > & { initialData: TQueryFnData | (() => TQueryFnData) }, +): DefinedCreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, options?: Omit< CreateQueryOptions, 'queryKey' @@ -34,7 +82,34 @@ export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + // TODO(lukemurray): not sure if we want to use return type here + queryFn: QueryFunction>, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData' + > & { initialData?: () => undefined }, +): CreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + queryFn: QueryFunction>, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData' + > & { initialData: TQueryFnData | (() => TQueryFnData) }, +): DefinedCreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, >( queryKey: TQueryKey, queryFn: QueryFunction>, @@ -47,7 +122,7 @@ export function createQuery< TQueryFnData, TError, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey, + TQueryKey extends SolidQueryKey = SolidQueryKey, >( arg1: TQueryKey | CreateQueryOptions, arg2?: diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 298ac316010..e984a87f594 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,13 +1,14 @@ -import type { Context } from 'solid-js' import type { + DefinedQueryObserverResult, + MutateFunction, + MutationObserverOptions, + MutationObserverResult, QueryClient, QueryKey, QueryObserverOptions, QueryObserverResult, - MutateFunction, - MutationObserverOptions, - MutationObserverResult, } from '@tanstack/query-core' +import type { Context } from 'solid-js' export interface ContextOptions { /** @@ -23,6 +24,7 @@ export interface CreateBaseQueryOptions< TError = unknown, TData = TQueryFnData, TQueryData = TQueryFnData, + // TODO(lukemurray): maybe this should be a solid query key? TQueryKey extends QueryKey = QueryKey, > extends ContextOptions, QueryObserverOptions {} @@ -40,6 +42,21 @@ export interface CreateQueryOptions< ReturnType > {} +// export interface UseInfiniteQueryOptions< +// TQueryFnData = unknown, +// TError = unknown, +// TData = TQueryFnData, +// TQueryData = TQueryFnData, +// TQueryKey extends QueryKey = QueryKey, +// > extends ContextOptions, +// InfiniteQueryObserverOptions< +// TQueryFnData, +// TError, +// TData, +// TQueryData, +// TQueryKey +// > {} + export type CreateBaseQueryResult< TData = unknown, TError = unknown, @@ -50,6 +67,21 @@ export type CreateQueryResult< TError = unknown, > = CreateBaseQueryResult +export type DefinedCreateBaseQueryResult< + TData = unknown, + TError = unknown, +> = DefinedQueryObserverResult + +export type DefinedCreateQueryResult< + TData = unknown, + TError = unknown, +> = DefinedCreateBaseQueryResult + +// export type UseInfiniteQueryResult< +// TData = unknown, +// TError = unknown, +// > = InfiniteQueryObserverResult + export interface CreateMutationOptions< TData = unknown, TError = unknown, @@ -77,8 +109,6 @@ export type CreateMutateAsyncFunction< TContext = unknown, > = MutateFunction -type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } - export type CreateBaseMutationResult< TData = unknown, TError = unknown, @@ -97,3 +127,5 @@ export type CreateMutationResult< TVariables = unknown, TContext = unknown, > = CreateBaseMutationResult + +type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } From 73be3fb39671b152cdd26a432c5be8dd78efb9af Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 09:44:08 -0400 Subject: [PATCH 013/221] rename useQuery test to createQuery --- .../{useQuery.types.test.tsx => createQuery.types.test.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/solid-query/src/__tests__/{useQuery.types.test.tsx => createQuery.types.test.tsx} (100%) diff --git a/packages/solid-query/src/__tests__/useQuery.types.test.tsx b/packages/solid-query/src/__tests__/createQuery.types.test.tsx similarity index 100% rename from packages/solid-query/src/__tests__/useQuery.types.test.tsx rename to packages/solid-query/src/__tests__/createQuery.types.test.tsx From f01de0f4eb5390c6f415dac049172e2f1c67b08d Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 10:07:00 -0400 Subject: [PATCH 014/221] get eslint to pass. now we should be able to successfully run npm test on every commit. --- packages/solid-query/.eslintrc | 2 +- packages/solid-query/src/QueryClientProvider.tsx | 3 ++- packages/solid-query/src/createBaseQuery.ts | 4 ++-- packages/solid-query/src/useIsFetching.ts | 10 +++++++--- packages/solid-query/src/utils.ts | 2 +- packages/solid-query/tsconfig.lint.json | 15 +++++++++++++++ 6 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 packages/solid-query/tsconfig.lint.json diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc index cefbf99ca1b..a1437a22aac 100644 --- a/packages/solid-query/.eslintrc +++ b/packages/solid-query/.eslintrc @@ -1,6 +1,6 @@ { "parserOptions": { - "project": "./tsconfig.json", + "project": "./tsconfig.lint.json", "sourceType": "module" }, "rules": { diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index 0d049fdad7e..12067d7dee9 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -26,8 +26,9 @@ interface Props { // Simple Query Client Context Provider export const QueryClientProvider: Component = (props) => { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime check. if (!props.client) { - throw new Error('No queryClient found.') + throw new Error('No QueryClient set, use QueryClientProvider to set one') } onMount(() => props.client.mount()) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 6a028bd51c2..d613f40b55b 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -56,8 +56,8 @@ export function createBaseQuery< }) createComputed(() => { - const defaultedOptions = queryClient.defaultQueryOptions(options) - observer.setOptions(defaultedOptions) + const newDefaultedOptions = queryClient.defaultQueryOptions(options) + observer.setOptions(newDefaultedOptions) }) const handler = { diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index 7e346c54efb..241832cc5cd 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -42,9 +42,13 @@ export function useIsFetching( ) createComputed(() => { - const [filtersObj, optionsObj = {}] = parseFilterArgs(arg1, arg2, arg3) - setFilters(filtersObj) - setOptions(optionsObj) + const [newFiltersObj, newOptionsObj = {}] = parseFilterArgs( + arg1, + arg2, + arg3, + ) + setFilters(newFiltersObj) + setOptions(newOptionsObj) }) const unsubscribe = queryCache().subscribe(() => { diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 2da23639415..3ea93b6cb1f 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -55,6 +55,6 @@ export function parseFilterArgs< return ( isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1() }, arg3] - : [{ ...arg1, queryKey: arg1?.queryKey?.() } || {}, arg2] + : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] ) as [ParseFilterArgs, TOptions] } diff --git a/packages/solid-query/tsconfig.lint.json b/packages/solid-query/tsconfig.lint.json new file mode 100644 index 00000000000..0fb829ee95a --- /dev/null +++ b/packages/solid-query/tsconfig.lint.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "rootDir": "./src", + "outDir": "./build/lib", + "tsBuildInfoFile": "./build/.tsbuildinfo", + "jsx": "preserve", + "jsxImportSource": "solid-js", + }, + "include": ["src"], + "references": [ + { "path": "../query-core" } + ] +} From f363c0887a07dd860d0ceedcb619d758d80797f1 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 10:15:05 -0400 Subject: [PATCH 015/221] remove unused codemods test --- packages/solid-query/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json index 10e19a4c869..625e3923c34 100644 --- a/packages/solid-query/package.json +++ b/packages/solid-query/package.json @@ -22,9 +22,8 @@ }, "scripts": { "clean": "rm -rf ./build", - "test:codemods": "../../node_modules/.bin/jest --config codemods/jest.config.js", "test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src", - "test:jest": "yarn test:codemods && ../../node_modules/.bin/jest --config jest.config.js", + "test:jest": "../../node_modules/.bin/jest --config jest.config.js", "test:jest:dev": "yarn test:jest --watch" }, "files": [ From 5d7fc344586ea2a9f1cd98402f26e4fa5c90e7b2 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 11:07:14 -0400 Subject: [PATCH 016/221] add createQuery test --- .../src/__tests__/createQuery.test.tsx | 5752 +++++++++++++++++ 1 file changed, 5752 insertions(+) create mode 100644 packages/solid-query/src/__tests__/createQuery.test.tsx diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx new file mode 100644 index 00000000000..6a873027471 --- /dev/null +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -0,0 +1,5752 @@ +import { screen, waitFor, fireEvent } from 'solid-testing-library' +import '@testing-library/jest-dom' +import { + expectType, + mockVisibilityState, + sleep, + setActTimeout, + mockNavigatorOnLine, + mockLogger, + createQueryClient, +} from '../../../../tests/utils' +import { renderWithClient, Blink, queryKey } from './utils' +import { + createQuery, + CreateQueryResult, + QueryCache, + QueryFunction, + QueryFunctionContext, + CreateQueryOptions, + DefinedCreateQueryResult, +} from '..' + +describe('useQuery', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should return the correct types', () => { + const key = queryKey() + + // @ts-ignore + // eslint-disable-next-line + function Page() { + // unspecified query function should default to unknown + const noQueryFn = createQuery(key) + expectType(noQueryFn.data) + expectType(noQueryFn.error) + + // it should infer the result type from the query function + const fromQueryFn = createQuery(key, () => 'test') + expectType(fromQueryFn.data) + expectType(fromQueryFn.error) + + // it should be possible to specify the result type + const withResult = createQuery(key, () => 'test') + expectType(withResult.data) + expectType(withResult.error) + + // it should be possible to specify the error type + const withError = createQuery(key, () => 'test') + expectType(withError.data) + expectType(withError.error) + + // it should provide the result type in the configuration + createQuery([key], async () => true, { + onSuccess: (data) => expectType(data), + onSettled: (data) => expectType(data), + }) + + // it should be possible to specify a union type as result type + const unionTypeSync = createQuery( + key, + () => (Math.random() > 0.5 ? 'a' : 'b'), + { + onSuccess: (data) => expectType<'a' | 'b'>(data), + }, + ) + expectType<'a' | 'b' | undefined>(unionTypeSync.data) + const unionTypeAsync = createQuery<'a' | 'b'>( + key, + () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'), + { + onSuccess: (data) => expectType<'a' | 'b'>(data), + }, + ) + expectType<'a' | 'b' | undefined>(unionTypeAsync.data) + + // should error when the query function result does not match with the specified type + // @ts-expect-error + createQuery(key, () => 'test') + + // it should infer the result type from a generic query function + function queryFn(): Promise { + return Promise.resolve({} as T) + } + + const fromGenericQueryFn = createQuery(key, () => queryFn()) + expectType(fromGenericQueryFn.data) + expectType(fromGenericQueryFn.error) + + const fromGenericOptionsQueryFn = createQuery({ + queryKey: key, + queryFn: () => queryFn(), + }) + expectType(fromGenericOptionsQueryFn.data) + expectType(fromGenericOptionsQueryFn.error) + + type MyData = number + type MyQueryKey = readonly ['my-data', number] + + const getMyDataArrayKey: QueryFunction = async ({ + queryKey: [, n], + }) => { + return n + 42 + } + + createQuery({ + queryKey: ['my-data', 100], + queryFn: getMyDataArrayKey, + }) + + const getMyDataStringKey: QueryFunction = async ( + context, + ) => { + expectType<['1']>(context.queryKey) + return Number(context.queryKey[0]) + 42 + } + + createQuery({ + queryKey: ['1'], + queryFn: getMyDataStringKey, + }) + + // it should handle query-functions that return Promise + createQuery(key, () => + fetch('return Promise').then((resp) => resp.json()), + ) + + // handles wrapped queries with custom fetcher passed as inline queryFn + const useWrappedQuery = < + TQueryKey extends [string, Record?], + TQueryFnData, + TError, + TData = TQueryFnData, + >( + qk: TQueryKey, + fetcher: ( + obj: TQueryKey[1], + token: string, + // return type must be wrapped with TQueryFnReturn + ) => Promise, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData' + >, + ) => createQuery(qk, () => fetcher(qk[1], 'token'), options) + const test = useWrappedQuery([''], async () => '1') + expectType(test.data) + + // handles wrapped queries with custom fetcher passed directly to useQuery + const useWrappedFuncStyleQuery = < + TQueryKey extends [string, Record?], + TQueryFnData, + TError, + TData = TQueryFnData, + >( + qk: TQueryKey, + fetcher: () => Promise, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData' + >, + ) => createQuery(qk, fetcher, options) + const testFuncStyle = useWrappedFuncStyleQuery([''], async () => true) + expectType(testFuncStyle.data) + } + }) + + // See https://github.com/tannerlinsley/react-query/issues/105 + it('should allow to set default data value', async () => { + const key = queryKey() + + function Page() { + const { data = 'default' } = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + return ( +
+

{data}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('default') + + await waitFor(() => rendered.getByText('test')) + }) + + it('should return the correct states for a successful query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + states.push(state) + + if (state.isLoading) { + expectType(state.data) + expectType(state.error) + return loading + } + + if (state.isLoadingError) { + expectType(state.data) + expectType(state.error) + return {state.error.message} + } + + expectType(state.data) + expectType(state.error) + return {state.data} + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('test')) + + expect(states.length).toEqual(2) + + expect(states[0]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'loading', + fetchStatus: 'fetching', + }) + + expect(states[1]).toEqual({ + data: 'test', + dataUpdatedAt: expect.any(Number), + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + isError: false, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isPaused: false, + isLoading: false, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: true, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'success', + fetchStatus: 'idle', + }) + }) + + it('should return the correct states for an unsuccessful query', async () => { + const key = queryKey() + + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery( + key, + () => Promise.reject('rejected'), + { + retry: 1, + retryDelay: 1, + }, + ) + + states.push(state) + + return ( +
+

Status: {state.status}

+
Failure Count: {state.failureCount}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('Status: error')) + + expect(states[0]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'loading', + fetchStatus: 'fetching', + }) + + expect(states[1]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 1, + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'loading', + fetchStatus: 'fetching', + }) + + expect(states[2]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: 'rejected', + errorUpdatedAt: expect.any(Number), + failureCount: 2, + errorUpdateCount: 1, + isError: true, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isPaused: false, + isLoading: false, + isLoadingError: true, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'error', + fetchStatus: 'idle', + }) + }) + + it('should set isFetchedAfterMount to true after a query has been fetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, () => 'prefetched') + + function Page() { + const state = createQuery(key, () => 'data') + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(states.length).toBe(2) + + expect(states[0]).toMatchObject({ + data: 'prefetched', + isFetched: true, + isFetchedAfterMount: false, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isFetched: true, + isFetchedAfterMount: true, + }) + }) + + it('should call onSuccess after a query has been fetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSuccess = jest.fn() + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'data' + }, + { onSuccess }, + ) + states.push(state) + return
data: {state.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: data') + expect(states.length).toBe(2) + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(onSuccess).toHaveBeenCalledWith('data') + }) + + it('should call onSuccess after a query has been refetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSuccess = jest.fn() + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + count++ + await sleep(10) + return 'data' + count + }, + { onSuccess }, + ) + + states.push(state) + + return ( +
+
data: {state.data}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: data1') + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await rendered.findByText('data: data2') + + expect(states.length).toBe(3) //loading, success, success after refetch + expect(count).toBe(2) + expect(onSuccess).toHaveBeenCalledTimes(2) + }) + + it('should call onSuccess after a disabled query has been fetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSuccess = jest.fn() + + function Page() { + const state = createQuery(key, () => 'data', { + enabled: false, + onSuccess, + }) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 10) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(onSuccess).toHaveBeenCalledWith('data') + }) + + it('should not call onSuccess if a component has unmounted', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSuccess = jest.fn() + + function Page() { + const [show, setShow] = React.useState(true) + + React.useEffect(() => { + setShow(false) + }, [setShow]) + + return show ? : null + } + + function Component() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'data' + }, + { onSuccess }, + ) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + expect(states.length).toBe(1) + expect(onSuccess).toHaveBeenCalledTimes(0) + }) + + it('should call onError after a query has been fetched with an error', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onError = jest.fn() + + function Page() { + const state = createQuery(key, () => Promise.reject('error'), { + retry: false, + onError, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(states.length).toBe(2) + expect(onError).toHaveBeenCalledTimes(1) + expect(onError).toHaveBeenCalledWith('error') + }) + + it('should not call onError when receiving a CancelledError', async () => { + const key = queryKey() + const onError = jest.fn() + + function Page() { + const { status, fetchStatus } = createQuery( + key, + async () => { + await sleep(10) + return 23 + }, + { + onError, + }, + ) + return ( + + status: {status}, fetchStatus: {fetchStatus} + + ) + } + + const rendered = renderWithClient(queryClient, ) + + await sleep(5) + await queryClient.cancelQueries(key) + // query cancellation will reset the query to it's initial state + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: idle'), + ) + expect(onError).not.toHaveBeenCalled() + }) + + it('should call onSettled after a query has been fetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSettled = jest.fn() + + function Page() { + const state = createQuery(key, () => 'data', { onSettled }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(states.length).toBe(2) + expect(onSettled).toHaveBeenCalledTimes(1) + expect(onSettled).toHaveBeenCalledWith('data', null) + }) + + it('should call onSettled after a query has been fetched with an error', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSettled = jest.fn() + + function Page() { + const state = createQuery(key, () => Promise.reject('error'), { + retry: false, + onSettled, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(states.length).toBe(2) + expect(onSettled).toHaveBeenCalledTimes(1) + expect(onSettled).toHaveBeenCalledWith(undefined, 'error') + }) + + it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => { + const key = queryKey() + let fetchCount = 0 + + function Page() { + const { refetch } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + return 'data' + }, + { enabled: false, initialData: 'initialData' }, + ) + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 5) + setActTimeout(() => { + refetch({ cancelRefetch: false }) + }, 5) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + // first refetch only, second refetch is ignored + expect(fetchCount).toBe(1) + }) + + it('should cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we have data already', async () => { + const key = queryKey() + let fetchCount = 0 + + function Page() { + const { refetch } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + return 'data' + }, + { enabled: false, initialData: 'initialData' }, + ) + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 5) + setActTimeout(() => { + refetch() + }, 5) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + // first refetch (gets cancelled) and second refetch + expect(fetchCount).toBe(2) + }) + + it('should not cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we do not have data yet', async () => { + const key = queryKey() + let fetchCount = 0 + + function Page() { + const { refetch } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + return 'data' + }, + { enabled: false }, + ) + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 5) + setActTimeout(() => { + refetch() + }, 5) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + // first refetch will not get cancelled, second one gets skipped + expect(fetchCount).toBe(1) + }) + + it('should be able to watch a query without providing a query function', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + queryClient.setQueryDefaults(key, { queryFn: () => 'data' }) + + function Page() { + const state = createQuery(key) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'data' }) + }) + + it('should pick up a query when re-mounting with cacheTime 0', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [toggle, setToggle] = React.useState(false) + + return ( +
+ + {toggle ? ( + + ) : ( + + )} +
+ ) + } + + function Component({ value }: { value: string }) { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'data: ' + value + }, + { + cacheTime: 0, + notifyOnChangeProps: 'all', + }, + ) + states.push(state) + return ( +
+
{state.data}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: 1') + + fireEvent.click(rendered.getByRole('button', { name: /toggle/i })) + + await rendered.findByText('data: 2') + + expect(states.length).toBe(4) + // First load + expect(states[0]).toMatchObject({ + isLoading: true, + isSuccess: false, + isFetching: true, + }) + // First success + expect(states[1]).toMatchObject({ + isLoading: false, + isSuccess: true, + isFetching: false, + }) + // Switch, goes to fetching + expect(states[2]).toMatchObject({ + isLoading: false, + isSuccess: true, + isFetching: true, + }) + // Second success + expect(states[3]).toMatchObject({ + isLoading: false, + isSuccess: true, + isFetching: false, + }) + }) + + it('should not get into an infinite loop when removing a query with cacheTime 0 and rerendering', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [, rerender] = React.useState({}) + + const state = createQuery( + key, + async () => { + await sleep(5) + return 'data' + }, + { + cacheTime: 0, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { remove } = state + + React.useEffect(() => { + setActTimeout(() => { + remove() + rerender({}) + }, 20) + }, [remove]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(5) + // First load + expect(states[0]).toMatchObject({ isLoading: true, isSuccess: false }) + // First success + expect(states[1]).toMatchObject({ isLoading: false, isSuccess: true }) + // Remove + expect(states[2]).toMatchObject({ isLoading: true, isSuccess: false }) + // Hook state update + expect(states[3]).toMatchObject({ isLoading: true, isSuccess: false }) + // Second success + expect(states[4]).toMatchObject({ isLoading: false, isSuccess: true }) + }) + + it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'test', { + refetchOnMount: false, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should not fetch when refetchOnMount is false and data has been fetched already', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + queryClient.setQueryData(key, 'prefetched') + + function Page() { + const state = createQuery(key, () => 'test', { + refetchOnMount: false, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(1) + expect(states[0]).toMatchObject({ data: 'prefetched' }) + }) + + it('should be able to select a part of the data with select', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => ({ name: 'test' }), { + select: (data) => data.name, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should be able to select a part of the data with select in object syntax', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: () => ({ name: 'test' }), + select: (data) => data.name, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should not re-render when it should only re-render only data change and the selected data did not change', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => ({ name: 'test' }), { + select: (data) => data.name, + notifyOnChangeProps: ['data'], + }) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 5) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should throw an error when a selector throws', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const error = new Error('Select Error') + + function Page() { + const state = createQuery(key, () => ({ name: 'test' }), { + select: () => { + throw error + }, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(mockLogger.error).toHaveBeenCalledWith(error) + expect(states.length).toBe(2) + + expect(states[0]).toMatchObject({ status: 'loading', data: undefined }) + expect(states[1]).toMatchObject({ status: 'error', error }) + }) + + it('should not re-run a stable select when it re-renders if selector throws an error', async () => { + const key = queryKey() + const error = new Error('Select Error') + let runs = 0 + + function Page() { + const [, rerender] = React.useReducer(() => ({}), {}) + const state = createQuery( + key, + () => (runs === 0 ? 'test' : 'test2'), + { + select: React.useCallback(() => { + runs++ + throw error + }, []), + }, + ) + return ( +
+
error: {state.error?.message}
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('error: Select Error')) + expect(runs).toEqual(1) + fireEvent.click(rendered.getByRole('button', { name: 'rerender' })) + await sleep(10) + expect(runs).toEqual(1) + fireEvent.click(rendered.getByRole('button', { name: 'refetch' })) + await sleep(10) + expect(runs).toEqual(2) + }) + + it('should track properties and only re-render when a tracked property changes', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + states.push(state) + + const { refetch, data } = state + + React.useEffect(() => { + setActTimeout(() => { + if (data) { + refetch() + } + }, 20) + }, [refetch, data]) + + return ( +
+

{data ?? null}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('test')) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should always re-render if we are tracking props but not using any', async () => { + const key = queryKey() + let renderCount = 0 + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'test') + + states.push(state) + + React.useEffect(() => { + renderCount++ + }, [state]) + + return ( +
+

hello

+
+ ) + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(renderCount).toBe(2) + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should be able to remove a query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const [, rerender] = React.useState({}) + const state = createQuery(key, () => ++count, { + notifyOnChangeProps: 'all', + }) + + states.push(state) + + const { remove } = state + + return ( +
+ + + data: {state.data ?? 'null'} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /remove/i })) + + await sleep(20) + fireEvent.click(rendered.getByRole('button', { name: /rerender/i })) + await waitFor(() => rendered.getByText('data: 2')) + + expect(states.length).toBe(4) + // Initial + expect(states[0]).toMatchObject({ status: 'loading', data: undefined }) + // Fetched + expect(states[1]).toMatchObject({ status: 'success', data: 1 }) + // Remove + Hook state update, batched + expect(states[2]).toMatchObject({ status: 'loading', data: undefined }) + // Fetched + expect(states[3]).toMatchObject({ status: 'success', data: 2 }) + }) + + it('should create a new query when refetching a removed query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + return ++count + }, + { notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { remove, refetch } = state + + return ( +
+ + + data: {state.data ?? 'null'} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /remove/i })) + + await sleep(50) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => rendered.getByText('data: 2')) + + expect(states.length).toBe(4) + // Initial + expect(states[0]).toMatchObject({ data: undefined, dataUpdatedAt: 0 }) + // Fetched + expect(states[1]).toMatchObject({ data: 1 }) + // Switch + expect(states[2]).toMatchObject({ data: undefined, dataUpdatedAt: 0 }) + // Fetched + expect(states[3]).toMatchObject({ data: 2 }) + }) + + it('should share equal data structures between query results', async () => { + const key = queryKey() + + const result1 = [ + { id: '1', done: false }, + { id: '2', done: false }, + ] + + const result2 = [ + { id: '1', done: false }, + { id: '2', done: true }, + ] + + const states: CreateQueryResult[] = [] + + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count === 1 ? result1 : result2 + }, + { notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { refetch } = state + + return ( +
+ + data: {String(state.data?.[1]?.done)} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: false')) + await sleep(20) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => rendered.getByText('data: true')) + + await waitFor(() => expect(states.length).toBe(4)) + + const todos = states[2]?.data + const todo1 = todos?.[0] + const todo2 = todos?.[1] + + const newTodos = states[3]?.data + const newTodo1 = newTodos?.[0] + const newTodo2 = newTodos?.[1] + + expect(todos).toEqual(result1) + expect(newTodos).toEqual(result2) + expect(newTodos).not.toBe(todos) + expect(newTodo1).toBe(todo1) + expect(newTodo2).not.toBe(todo2) + + return null + }) + + it('should use query function from hook when the existing query does not have a query function', async () => { + const key = queryKey() + const results: DefinedCreateQueryResult[] = [] + + queryClient.setQueryData(key, 'set') + + function Page() { + const result = createQuery( + key, + async () => { + await sleep(10) + return 'fetched' + }, + { + initialData: 'initial', + staleTime: Infinity, + }, + ) + + results.push(result) + + return ( +
+
isFetching: {result.isFetching}
+ + data: {result.data} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: set')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => rendered.getByText('data: fetched')) + + await waitFor(() => expect(results.length).toBe(3)) + + expect(results[0]).toMatchObject({ data: 'set', isFetching: false }) + expect(results[1]).toMatchObject({ data: 'set', isFetching: true }) + expect(results[2]).toMatchObject({ data: 'fetched', isFetching: false }) + }) + + it('should update query stale state and refetch when invalidated with invalidateQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { staleTime: Infinity, notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + return ( +
+ + data: {state.data} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + await waitFor(() => rendered.getByText('data: 2')) + + await waitFor(() => expect(states.length).toBe(4)) + + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isRefetching: false, + isSuccess: false, + isStale: true, + }) + expect(states[1]).toMatchObject({ + data: 1, + isFetching: false, + isRefetching: false, + isSuccess: true, + isStale: false, + }) + expect(states[2]).toMatchObject({ + data: 1, + isFetching: true, + isRefetching: true, + isSuccess: true, + isStale: true, + }) + expect(states[3]).toMatchObject({ + data: 2, + isFetching: false, + isRefetching: false, + isSuccess: true, + isStale: false, + }) + }) + + it('should not update disabled query when refetched with refetchQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { enabled: false }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + queryClient.refetchQueries({ queryKey: key }) + }, 20) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + + expect(states.length).toBe(1) + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: false, + isSuccess: false, + isStale: true, + }) + }) + + it('should not refetch disabled query when invalidated with invalidateQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { enabled: false }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + queryClient.invalidateQueries(key) + }, 20) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(1) + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: false, + isSuccess: false, + isStale: true, + }) + }) + + it('should not fetch when switching to a disabled query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery( + [key, count], + async () => { + await sleep(5) + return count + }, + { enabled: count === 0 }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + setCount(1) + }, 10) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + + expect(states.length).toBe(3) + + // Fetch query + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isSuccess: false, + }) + // Fetched query + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + }) + // Switch to disabled query + expect(states[2]).toMatchObject({ + data: undefined, + isFetching: false, + isSuccess: false, + }) + }) + + it('should keep the previous data when keepPreviousData is set', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery( + [key, count], + async () => { + await sleep(10) + return count + }, + { keepPreviousData: true }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + setCount(1) + }, 20) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(states.length).toBe(5)) + + // Initial + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isSuccess: false, + isPreviousData: false, + }) + // Fetched + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[2]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // Hook state update + expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ + data: 1, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should transition to error state when keepPreviousData is set', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page({ count }: { count: number }) { + const state = createQuery( + [key, count], + async () => { + await sleep(10) + if (count === 2) { + throw new Error('Error test') + } + return Promise.resolve(count) + }, + { + retry: false, + keepPreviousData: true, + }, + ) + + states.push(state) + + return ( +
+

data: {state.data}

+

error: {state.error?.message}

+

previous data: {state.isPreviousData}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('data: 0')) + act(() => rendered.rerender()) + await waitFor(() => rendered.getByText('data: 1')) + act(() => rendered.rerender()) + await waitFor(() => rendered.getByText('error: Error test')) + + await waitFor(() => expect(states.length).toBe(8)) + // Initial + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + status: 'loading', + error: null, + isPreviousData: false, + }) + // Fetched + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + status: 'success', + error: null, + isPreviousData: false, + }) + // rerender Page 1 + expect(states[2]).toMatchObject({ + data: 0, + isFetching: true, + status: 'success', + error: null, + isPreviousData: true, + }) + // Hook state update + expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + status: 'success', + error: null, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ + data: 1, + isFetching: false, + status: 'success', + error: null, + isPreviousData: false, + }) + // rerender Page 2 + expect(states[5]).toMatchObject({ + data: 1, + isFetching: true, + status: 'success', + error: null, + isPreviousData: true, + }) + // Hook state update again + expect(states[6]).toMatchObject({ + data: 1, + isFetching: true, + status: 'success', + error: null, + isPreviousData: true, + }) + // Error + expect(states[7]).toMatchObject({ + data: undefined, + isFetching: false, + status: 'error', + isPreviousData: false, + }) + expect(states[7]?.error).toHaveProperty('message', 'Error test') + }) + + it('should not show initial data from next query if keepPreviousData is set', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery( + [key, count], + async () => { + await sleep(10) + return count + }, + { initialData: 99, keepPreviousData: true }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + setCount(1) + }, 20) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(states.length).toBe(5)) + + // Initial + expect(states[0]).toMatchObject({ + data: 99, + isFetching: true, + isSuccess: true, + isPreviousData: false, + }) + // Fetched + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[2]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // Hook state update + expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ + data: 1, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should keep the previous data on disabled query when keepPreviousData is set', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery( + [key, count], + async () => { + await sleep(10) + return count + }, + { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + refetch() + + setActTimeout(() => { + setCount(1) + }, 20) + + setActTimeout(() => { + refetch() + }, 30) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(6) + + // Disabled query + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: false, + isSuccess: false, + isPreviousData: false, + }) + // Fetching query + expect(states[1]).toMatchObject({ + data: undefined, + isFetching: true, + isSuccess: false, + isPreviousData: false, + }) + // Fetched query + expect(states[2]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[3]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPreviousData: true, + }) + // Fetching new query + expect(states[4]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // Fetched new query + expect(states[5]).toMatchObject({ + data: 1, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should keep the previous data on disabled query when keepPreviousData is set and switching query key multiple times', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + queryClient.setQueryData([key, 10], 10) + + await sleep(10) + + function Page() { + const [count, setCount] = React.useState(10) + + const state = createQuery( + [key, count], + async () => { + await sleep(10) + return count + }, + { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + setCount(11) + }, 20) + setActTimeout(() => { + setCount(12) + }, 30) + setActTimeout(() => { + refetch() + }, 40) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(5) + + // Disabled query + expect(states[0]).toMatchObject({ + data: 10, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[1]).toMatchObject({ + data: 10, + isFetching: false, + isSuccess: true, + isPreviousData: true, + }) + // State update + expect(states[2]).toMatchObject({ + data: 10, + isFetching: false, + isSuccess: true, + isPreviousData: true, + }) + // Refetch + expect(states[3]).toMatchObject({ + data: 10, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // Refetch done + expect(states[4]).toMatchObject({ + data: 12, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should use the correct query function when components use different configurations', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function FirstComponent() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 1 + }, + { notifyOnChangeProps: 'all' }, + ) + const refetch = state.refetch + + states.push(state) + + return ( +
+ + data: {state.data} +
+ ) + } + + function SecondComponent() { + createQuery(key, () => 2, { notifyOnChangeProps: 'all' }) + return null + } + + function Page() { + return ( + <> + + + + ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + + await waitFor(() => expect(states.length).toBe(4)) + + expect(states[0]).toMatchObject({ + data: undefined, + }) + expect(states[1]).toMatchObject({ + data: 1, + }) + expect(states[2]).toMatchObject({ + data: 1, + }) + // This state should be 1 instead of 2 + expect(states[3]).toMatchObject({ + data: 1, + }) + }) + + it('should be able to set different stale times for a query', async () => { + const key = queryKey() + const states1: CreateQueryResult[] = [] + const states2: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, async () => { + await sleep(10) + return 'prefetch' + }) + + await sleep(20) + + function FirstComponent() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'one' + }, + { + staleTime: 100, + }, + ) + states1.push(state) + return null + } + + function SecondComponent() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'two' + }, + { + staleTime: 10, + }, + ) + states2.push(state) + return null + } + + function Page() { + return ( + <> + + + + ) + } + + renderWithClient(queryClient, ) + + await sleep(200) + + expect(states1.length).toBe(4) + expect(states2.length).toBe(3) + + expect(states1).toMatchObject([ + // First render + { + data: 'prefetch', + isStale: false, + }, + // Second useQuery started fetching + { + data: 'prefetch', + isStale: false, + }, + // Second useQuery data came in + { + data: 'two', + isStale: false, + }, + // Data became stale after 100ms + { + data: 'two', + isStale: true, + }, + ]) + + expect(states2).toMatchObject([ + // First render, data is stale and starts fetching + { + data: 'prefetch', + isStale: true, + }, + // Second useQuery data came in + { + data: 'two', + isStale: false, + }, + // Data became stale after 5ms + { + data: 'two', + isStale: true, + }, + ]) + }) + + it('should re-render when a query becomes stale', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'test', { + staleTime: 50, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(3) + expect(states[0]).toMatchObject({ isStale: true }) + expect(states[1]).toMatchObject({ isStale: false }) + expect(states[2]).toMatchObject({ isStale: true }) + }) + + it('should notify query cache when a query becomes stale', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const fn = jest.fn() + + const unsubscribe = queryCache.subscribe(fn) + + function Page() { + const state = createQuery(key, () => 'test', { + staleTime: 10, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + unsubscribe() + + // 1. Query added -> loading + // 2. Observer result updated -> loading + // 3. Observer added + // 4. Query updated -> success + // 5. Observer result updated -> success + // 6. Query updated -> stale + // 7. Observer options updated + // 8. Observer result updated -> stale + // 9. Observer options updated + expect(fn).toHaveBeenCalledTimes(9) + }) + + it('should not re-render when it should only re-render on data changes and the data did not change', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(5) + return 'test' + }, + { + notifyOnChangeProps: ['data'], + }, + ) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 10) + }, [refetch]) + return null + } + + renderWithClient(queryClient, ) + + await sleep(30) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: undefined, + status: 'loading', + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'test', + status: 'success', + isFetching: false, + }) + }) + + // See https://github.com/tannerlinsley/react-query/issues/137 + it('should not override initial data in dependent queries', async () => { + const key1 = queryKey() + const key2 = queryKey() + + function Page() { + const first = createQuery(key1, () => 'data', { + enabled: false, + initialData: 'init', + }) + + const second = createQuery(key2, () => 'data', { + enabled: false, + initialData: 'init', + }) + + return ( +
+

First Data: {first.data}

+

Second Data: {second.data}

+
First Status: {first.status}
+
Second Status: {second.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('First Data: init') + rendered.getByText('Second Data: init') + rendered.getByText('First Status: success') + rendered.getByText('Second Status: success') + }) + + it('should not override query configuration on render', async () => { + const key = queryKey() + + const queryFn1 = async () => { + await sleep(10) + return 'data1' + } + + const queryFn2 = async () => { + await sleep(10) + return 'data2' + } + + function Page() { + createQuery(key, queryFn1) + createQuery(key, queryFn2) + return null + } + + renderWithClient(queryClient, ) + + expect(queryCache.find(key)!.options.queryFn).toBe(queryFn1) + }) + + it('should render correct states even in case of useEffect triggering delays', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + const originalUseEffect = React.useEffect + + // Try to simulate useEffect timing delay + // @ts-ignore + React.useEffect = (...args: any[]) => { + originalUseEffect(() => { + setTimeout(() => { + args[0]() + }, 10) + }, args[1]) + } + + function Page() { + const state = createQuery(key, () => 'data', { staleTime: Infinity }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + queryClient.setQueryData(key, 'data') + await sleep(50) + + // @ts-ignore + React.useEffect = originalUseEffect + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ status: 'loading' }) + expect(states[1]).toMatchObject({ status: 'success' }) + }) + + it('should batch re-renders', async () => { + const key = queryKey() + + let renders = 0 + + const queryFn = async () => { + await sleep(15) + return 'data' + } + + function Page() { + createQuery(key, queryFn) + createQuery(key, queryFn) + renders++ + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + + // Should be 2 instead of 3 + expect(renders).toBe(2) + }) + + it('should batch re-renders including hook callbacks', async () => { + const key = queryKey() + + let renders = 0 + let callbackCount = 0 + + const queryFn = async () => { + await sleep(10) + return 'data' + } + + function Page() { + const [count, setCount] = React.useState(0) + createQuery(key, queryFn, { + onSuccess: () => { + setCount((x) => x + 1) + }, + }) + createQuery(key, queryFn, { + onSuccess: () => { + setCount((x) => x + 1) + }, + }) + + React.useEffect(() => { + renders++ + callbackCount = count + }) + + return
count: {count}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('count: 2')) + + // Should be 2 / 3 instead of 5, uSES batches differently + expect(renders).toBe(process.env.REACTJS_VERSION === '17' ? 2 : 3) + + // Both callbacks should have been executed + expect(callbackCount).toBe(2) + }) + + it('should render latest data even if react has discarded certain renders', async () => { + const key = queryKey() + + function Page() { + const [, setNewState] = React.useState('state') + const state = createQuery(key, () => 'data') + React.useEffect(() => { + setActTimeout(() => { + queryClient.setQueryData(key, 'new') + // Update with same state to make react discard the next render + setNewState('state') + }, 10) + }, []) + return
{state.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('new')) + }) + + // See https://github.com/tannerlinsley/react-query/issues/170 + it('should start with status loading, fetchStatus idle if enabled is false', async () => { + const key1 = queryKey() + const key2 = queryKey() + + function Page() { + const first = createQuery(key1, () => 'data', { + enabled: false, + }) + const second = createQuery(key2, () => 'data') + + return ( +
+
+ First Status: {first.status}, {first.fetchStatus} +
+
+ Second Status: {second.status}, {second.fetchStatus} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // use "act" to wait for state update and prevent console warning + + rendered.getByText('First Status: loading, idle') + await waitFor(() => rendered.getByText('Second Status: loading, fetching')) + await waitFor(() => rendered.getByText('Second Status: success, idle')) + }) + + // See https://github.com/tannerlinsley/react-query/issues/144 + it('should be in "loading" state by default', async () => { + const key = queryKey() + + function Page() { + const { status } = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + return
status: {status}
+ } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('status: loading') + }) + + // See https://github.com/tannerlinsley/react-query/issues/147 + it('should not pass stringified variables to query function', async () => { + const key = queryKey() + const variables = { number: 5, boolean: false, object: {}, array: [] } + type CustomQueryKey = [typeof key, typeof variables] + const states: CreateQueryResult[] = [] + + const queryFn = async (ctx: QueryFunctionContext) => { + await sleep(10) + return ctx.queryKey + } + + function Page() { + const state = createQuery([key, variables], queryFn) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + + expect(states[1]?.data).toEqual([key, variables]) + }) + + it('should not refetch query on focus when `enabled` is set to `false`', async () => { + const key = queryKey() + const queryFn = jest.fn().mockReturnValue('data') + + function Page() { + const { data = 'default' } = createQuery(key, queryFn, { + enabled: false, + }) + + return ( +
+

{data}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('default')) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + expect(queryFn).not.toHaveBeenCalled() + }) + + it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to `false`', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery(key, () => count++, { + staleTime: 0, + refetchOnWindowFocus: false, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + }) + + it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to a function that returns `false`', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery(key, () => count++, { + staleTime: 0, + refetchOnWindowFocus: () => false, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + }) + + it('should not refetch fresh query on focus when `refetchOnWindowFocus` is set to `true`', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery(key, () => count++, { + staleTime: Infinity, + refetchOnWindowFocus: true, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + }) + + it('should refetch fresh query on focus when `refetchOnWindowFocus` is set to `always`', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + return count++ + }, + { + staleTime: Infinity, + refetchOnWindowFocus: 'always', + }, + ) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(20) + + await waitFor(() => expect(states.length).toBe(4)) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + expect(states[2]).toMatchObject({ data: 0, isFetching: true }) + expect(states[3]).toMatchObject({ data: 1, isFetching: false }) + }) + + it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + return count++ + }, + { + staleTime: 0, + retry: 0, + refetchOnWindowFocus: (query) => (query.state.data || 0) < 1, + }, + ) + states.push(state) + return
data: {String(state.data)}
+ } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: 0') + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await rendered.findByText('data: 1') + + // refetch should happen + expect(states.length).toBe(4) + + expect(states[2]).toMatchObject({ data: 0, isFetching: true }) + expect(states[3]).toMatchObject({ data: 1, isFetching: false }) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(20) + + // no more refetch now + expect(states.length).toBe(4) + }) + + it('should refetch fresh query when refetchOnMount is set to always', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, () => 'prefetched') + + function Page() { + const state = createQuery(key, () => 'data', { + refetchOnMount: 'always', + staleTime: Infinity, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: 'prefetched', + isStale: false, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: false, + isFetching: false, + }) + }) + + it('should refetch stale query when refetchOnMount is set to true', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, () => 'prefetched') + + await sleep(10) + + function Page() { + const state = createQuery(key, () => 'data', { + refetchOnMount: true, + staleTime: 0, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: 'prefetched', + isStale: true, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: true, + isFetching: false, + }) + }) + + it('should set status to error if queryFn throws', async () => { + const key = queryKey() + + function Page() { + const { status, error } = createQuery( + key, + () => { + return Promise.reject('Error test jaylen') + }, + { retry: false }, + ) + + return ( +
+

{status}

+

{error}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('error')) + await waitFor(() => rendered.getByText('Error test jaylen')) + }) + + it('should throw error if queryFn throws and useErrorBoundary is in use', async () => { + const key = queryKey() + + function Page() { + const { status, error } = createQuery( + key, + () => Promise.reject('Error test jaylen'), + { retry: false, useErrorBoundary: true }, + ) + + return ( +
+

{status}

+

{error}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, +
error boundary
}> + +
, + ) + + await waitFor(() => rendered.getByText('error boundary')) + }) + + it('should update with data if we observe no properties and useErrorBoundary', async () => { + const key = queryKey() + + let result: CreateQueryResult | undefined + + function Page() { + const query = createQuery(key, () => Promise.resolve('data'), { + useErrorBoundary: true, + }) + + React.useEffect(() => { + result = query + }) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(result?.data).toBe('data') + }) + + it('should set status to error instead of throwing when error should not be thrown', async () => { + const key = queryKey() + + function Page() { + const { status, error } = createQuery( + key, + () => Promise.reject('Local Error'), + { + retry: false, + useErrorBoundary: (err) => err !== 'Local Error', + }, + ) + + return ( +
+

{status}

+

{error}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, +
error boundary
}> + +
, + ) + + await waitFor(() => rendered.getByText('error')) + await waitFor(() => rendered.getByText('Local Error')) + }) + + it('should throw error instead of setting status when error should be thrown', async () => { + const key = queryKey() + + function Page() { + const { status, error } = createQuery( + key, + () => Promise.reject(new Error('Remote Error')), + { + retry: false, + useErrorBoundary: (err) => err.message !== 'Local Error', + }, + ) + + return ( +
+

{status}

+

{error?.message ?? ''}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, + ( +
+
error boundary
+ {/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} +
{error?.message}
+
+ )} + > + +
, + ) + + await waitFor(() => rendered.getByText('error boundary')) + await waitFor(() => rendered.getByText('Remote Error')) + }) + + it('should continue retries when observers unmount and remount while waiting for a retry (#3031)', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const result = createQuery( + key, + async () => { + count++ + await sleep(10) + return Promise.reject('some error') + }, + { + retry: 2, + retryDelay: 100, + }, + ) + + return ( +
+
error: {result.error ?? 'null'}
+
failureCount: {result.failureCount}
+
+ ) + } + + function App() { + const [show, toggle] = React.useReducer((x) => !x, true) + + return ( +
+ + {show && } +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('failureCount: 1')) + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + await waitFor(() => rendered.getByRole('button', { name: /show/i })) + fireEvent.click(rendered.getByRole('button', { name: /show/i })) + await waitFor(() => rendered.getByText('error: some error')) + + expect(count).toBe(3) + }) + + it('should restart when observers unmount and remount while waiting for a retry when query was cancelled in between (#3031)', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const result = createQuery( + key, + async () => { + count++ + await sleep(10) + return Promise.reject('some error') + }, + { + retry: 2, + retryDelay: 100, + }, + ) + + return ( +
+
error: {result.error ?? 'null'}
+
failureCount: {result.failureCount}
+
+ ) + } + + function App() { + const [show, toggle] = React.useReducer((x) => !x, true) + + return ( +
+ + + {show && } +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('failureCount: 1')) + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + fireEvent.click(rendered.getByRole('button', { name: /cancel/i })) + await waitFor(() => rendered.getByRole('button', { name: /show/i })) + fireEvent.click(rendered.getByRole('button', { name: /show/i })) + await waitFor(() => rendered.getByText('error: some error')) + + // initial fetch (1), which will be cancelled, followed by new mount(2) + 2 retries = 4 + expect(count).toBe(4) + }) + + it('should always fetch if refetchOnMount is set to always', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, () => 'prefetched') + + function Page() { + const state = createQuery(key, () => 'data', { + refetchOnMount: 'always', + staleTime: 50, + }) + states.push(state) + return ( +
+
data: {state.data ?? 'null'}
+
isFetching: {state.isFetching}
+
isStale: {state.isStale}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data')) + await waitFor(() => expect(states.length).toBe(3)) + + expect(states[0]).toMatchObject({ + data: 'prefetched', + isStale: false, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: false, + isFetching: false, + }) + expect(states[2]).toMatchObject({ + data: 'data', + isStale: true, + isFetching: false, + }) + }) + + it('should fetch if initial data is set', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'data', { + initialData: 'initial', + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + + expect(states.length).toBe(2) + + expect(states[0]).toMatchObject({ + data: 'initial', + isStale: true, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: true, + isFetching: false, + }) + }) + + it('should not fetch if initial data is set with a stale time', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'data', { + staleTime: 50, + initialData: 'initial', + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: 'initial', + isStale: false, + isFetching: false, + }) + expect(states[1]).toMatchObject({ + data: 'initial', + isStale: true, + isFetching: false, + }) + }) + + it('should fetch if initial data updated at is older than stale time', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + const oneSecondAgo = Date.now() - 1000 + + function Page() { + const state = createQuery(key, () => 'data', { + staleTime: 50, + initialData: 'initial', + initialDataUpdatedAt: oneSecondAgo, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(3) + expect(states[0]).toMatchObject({ + data: 'initial', + isStale: true, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: false, + isFetching: false, + }) + expect(states[2]).toMatchObject({ + data: 'data', + isStale: true, + isFetching: false, + }) + }) + + it('should fetch if "initial data updated at" is exactly 0', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'data', { + staleTime: 10 * 1000, // 10 seconds + initialData: 'initial', + initialDataUpdatedAt: 0, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: 'initial', + isStale: true, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: false, + isFetching: false, + }) + }) + + it('should keep initial data when the query key changes', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult<{ count: number }>[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + const state = createQuery([key, count], () => ({ count: 10 }), { + staleTime: Infinity, + initialData: () => ({ count }), + }) + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + setCount(1) + }, 10) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + // Initial + expect(states[0]).toMatchObject({ data: { count: 0 } }) + // Set state + expect(states[1]).toMatchObject({ data: { count: 1 } }) + }) + + it('should retry specified number of times', async () => { + const key = queryKey() + + const queryFn = jest.fn() + queryFn.mockImplementation(() => { + return Promise.reject('Error test Barrett') + }) + + function Page() { + const { status, failureCount } = createQuery(key, queryFn, { + retry: 1, + retryDelay: 1, + }) + + return ( +
+

{status}

+

Failed {failureCount} times

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('loading')) + await waitFor(() => rendered.getByText('error')) + + // query should fail `retry + 1` times, since first time isn't a "retry" + await waitFor(() => rendered.getByText('Failed 2 times')) + + expect(queryFn).toHaveBeenCalledTimes(2) + }) + + it('should not retry if retry function `false`', async () => { + const key = queryKey() + + const queryFn = jest.fn() + + queryFn.mockImplementationOnce(() => { + return Promise.reject('Error test Tanner') + }) + + queryFn.mockImplementation(() => { + return Promise.reject('NoRetry') + }) + + function Page() { + const { status, failureCount, error } = createQuery< + unknown, + string, + [string] + >(key, queryFn, { + retryDelay: 1, + retry: (_failureCount, err) => err !== 'NoRetry', + }) + + return ( +
+

{status}

+

Failed {failureCount} times

+

{error}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('loading')) + await waitFor(() => rendered.getByText('error')) + + await waitFor(() => rendered.getByText('Failed 2 times')) + await waitFor(() => rendered.getByText('NoRetry')) + + expect(queryFn).toHaveBeenCalledTimes(2) + }) + + it('should extract retryDelay from error', async () => { + const key = queryKey() + + type DelayError = { delay: number } + + const queryFn = jest.fn() + queryFn.mockImplementation(() => { + return Promise.reject({ delay: 50 }) + }) + + function Page() { + const { status, failureCount } = createQuery(key, queryFn, { + retry: 1, + retryDelay: (_, error: DelayError) => error.delay, + }) + + return ( +
+

{status}

+

Failed {failureCount} times

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await sleep(10) + + expect(queryFn).toHaveBeenCalledTimes(1) + + await waitFor(() => rendered.getByText('Failed 2 times')) + + expect(queryFn).toHaveBeenCalledTimes(2) + }) + + // See https://github.com/tannerlinsley/react-query/issues/160 + it('should continue retry after focus regain', async () => { + const key = queryKey() + + // make page unfocused + const visibilityMock = mockVisibilityState('hidden') + + let count = 0 + + function Page() { + const query = createQuery( + key, + () => { + count++ + return Promise.reject(`fetching error ${count}`) + }, + { + retry: 3, + retryDelay: 1, + }, + ) + + return ( +
+
error {String(query.error)}
+
status {query.status}
+
failureCount {query.failureCount}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // The query should display the first error result + await waitFor(() => rendered.getByText('failureCount 1')) + await waitFor(() => rendered.getByText('status loading')) + await waitFor(() => rendered.getByText('error null')) + + // Check if the query really paused + await sleep(10) + await waitFor(() => rendered.getByText('failureCount 1')) + + act(() => { + // reset visibilityState to original value + visibilityMock.mockRestore() + window.dispatchEvent(new FocusEvent('focus')) + }) + + // Wait for the final result + await waitFor(() => rendered.getByText('failureCount 4')) + await waitFor(() => rendered.getByText('status error')) + await waitFor(() => rendered.getByText('error fetching error 4')) + + // Check if the query really stopped + await sleep(10) + await waitFor(() => rendered.getByText('failureCount 4')) + + // Check if the error has been logged in the console + expect(mockLogger.error).toHaveBeenCalledWith('fetching error 4') + }) + + it('should fetch on mount when a query was already created with setQueryData', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + queryClient.setQueryData(key, 'prefetched') + + function Page() { + const state = createQuery(key, () => 'data') + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states).toMatchObject([ + { + data: 'prefetched', + isFetching: true, + isStale: true, + }, + { + data: 'data', + isFetching: false, + isStale: true, + }, + ]) + }) + + it('should refetch after focus regain', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + // make page unfocused + const visibilityMock = mockVisibilityState('hidden') + + // set data in cache to check if the hook query fn is actually called + queryClient.setQueryData(key, 'prefetched') + + function Page() { + const state = createQuery(key, async () => { + await sleep(10) + return 'data' + }) + states.push(state) + return ( +
+ {state.data}, {state.isStale}, {state.isFetching} +
+ ) + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(states.length).toBe(2)) + + act(() => { + // reset visibilityState to original value + visibilityMock.mockRestore() + window.dispatchEvent(new FocusEvent('focus')) + }) + + await waitFor(() => expect(states.length).toBe(4)) + + expect(states).toMatchObject([ + { + data: 'prefetched', + isFetching: true, + isStale: true, + }, + { + data: 'data', + isFetching: false, + isStale: true, + }, + { + data: 'data', + isFetching: true, + isStale: true, + }, + { + data: 'data', + isFetching: false, + isStale: true, + }, + ]) + }) + + // See https://github.com/tannerlinsley/react-query/issues/195 + it('should refetch if stale after a prefetch', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + const queryFn = jest.fn() + queryFn.mockImplementation(() => 'data') + + const prefetchQueryFn = jest.fn() + prefetchQueryFn.mockImplementation(() => 'not yet...') + + await queryClient.prefetchQuery(key, prefetchQueryFn, { + staleTime: 10, + }) + + await sleep(11) + + function Page() { + const state = createQuery(key, queryFn) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(states.length).toBe(2)) + + expect(prefetchQueryFn).toHaveBeenCalledTimes(1) + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should not refetch if not stale after a prefetch', async () => { + const key = queryKey() + + const queryFn = jest.fn() + queryFn.mockImplementation(() => 'data') + + const prefetchQueryFn = jest.fn, unknown[]>() + prefetchQueryFn.mockImplementation(async () => { + await sleep(10) + return 'not yet...' + }) + + await queryClient.prefetchQuery(key, prefetchQueryFn, { + staleTime: 1000, + }) + + await sleep(0) + + function Page() { + createQuery(key, queryFn, { + staleTime: 1000, + }) + return null + } + + renderWithClient(queryClient, ) + + await sleep(0) + + expect(prefetchQueryFn).toHaveBeenCalledTimes(1) + expect(queryFn).toHaveBeenCalledTimes(0) + }) + + // See https://github.com/tannerlinsley/react-query/issues/190 + it('should reset failureCount on successful fetch', async () => { + const key = queryKey() + + function Page() { + let counter = 0 + + const query = createQuery( + key, + async () => { + if (counter < 2) { + counter++ + throw new Error('error') + } else { + return 'data' + } + }, + { retryDelay: 10 }, + ) + + return ( +
+
failureCount {query.failureCount}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('failureCount 2')) + await waitFor(() => rendered.getByText('failureCount 0')) + }) + + // See https://github.com/tannerlinsley/react-query/issues/199 + it('should use prefetched data for dependent query', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const [enabled, setEnabled] = React.useState(false) + const [isPrefetched, setPrefetched] = React.useState(false) + + const query = createQuery( + key, + async () => { + count++ + await sleep(10) + return count + }, + { + enabled, + }, + ) + + React.useEffect(() => { + async function prefetch() { + await queryClient.prefetchQuery(key, () => + Promise.resolve('prefetched data'), + ) + act(() => setPrefetched(true)) + } + prefetch() + }, []) + + return ( +
+ {isPrefetched &&
isPrefetched
} + +
data: {query.data}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('isPrefetched')) + + fireEvent.click(rendered.getByText('setKey')) + await waitFor(() => rendered.getByText('data: prefetched data')) + await waitFor(() => rendered.getByText('data: 1')) + expect(count).toBe(1) + }) + + it('should support dependent queries via the enable config option', async () => { + const key = queryKey() + + function Page() { + const [shouldFetch, setShouldFetch] = React.useState(false) + + const query = createQuery(key, () => 'data', { + enabled: shouldFetch, + }) + + return ( +
+
FetchStatus: {query.fetchStatus}
+

Data: {query.data || 'no data'}

+ {query.isStale ? ( + + ) : null} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('FetchStatus: idle') + rendered.getByText('Data: no data') + + fireEvent.click(rendered.getByText('fetch')) + + await waitFor(() => rendered.getByText('FetchStatus: fetching')) + await waitFor(() => [ + rendered.getByText('FetchStatus: idle'), + rendered.getByText('Data: data'), + ]) + }) + + it('should mark query as fetching, when using initialData', async () => { + const key = queryKey() + const results: DefinedCreateQueryResult[] = [] + + function Page() { + const result = createQuery(key, () => 'serverData', { + initialData: 'data', + }) + results.push(result) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(results.length).toBe(2) + expect(results[0]).toMatchObject({ data: 'data', isFetching: true }) + expect(results[1]).toMatchObject({ data: 'serverData', isFetching: false }) + }) + + it('should initialize state properly, when initialData is falsy', async () => { + const key = queryKey() + const results: DefinedCreateQueryResult[] = [] + + function Page() { + const result = createQuery(key, () => 1, { initialData: 0 }) + results.push(result) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(results.length).toBe(2) + expect(results[0]).toMatchObject({ data: 0, isFetching: true }) + expect(results[1]).toMatchObject({ data: 1, isFetching: false }) + }) + + // // See https://github.com/tannerlinsley/react-query/issues/214 + it('data should persist when enabled is changed to false', async () => { + const key = queryKey() + const results: DefinedCreateQueryResult[] = [] + + function Page() { + const [shouldFetch, setShouldFetch] = React.useState(true) + + const result = createQuery(key, () => 'fetched data', { + enabled: shouldFetch, + initialData: shouldFetch ? 'initial' : 'initial falsy', + }) + + results.push(result) + + React.useEffect(() => { + setActTimeout(() => { + setShouldFetch(false) + }, 5) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + expect(results.length).toBe(3) + expect(results[0]).toMatchObject({ data: 'initial', isStale: true }) + expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true }) + expect(results[2]).toMatchObject({ data: 'fetched data', isStale: true }) + }) + + it('it should support enabled:false in query object syntax', async () => { + const key = queryKey() + const queryFn = jest.fn() + queryFn.mockImplementation(() => 'data') + + function Page() { + const { fetchStatus } = createQuery({ + queryKey: key, + queryFn, + enabled: false, + }) + return
fetchStatus: {fetchStatus}
+ } + + const rendered = renderWithClient(queryClient, ) + + expect(queryFn).not.toHaveBeenCalled() + expect(queryCache.find(key)).not.toBeUndefined() + rendered.getByText('fetchStatus: idle') + }) + + // See https://github.com/tannerlinsley/react-query/issues/360 + test('should init to status:loading, fetchStatus:idle when enabled is false', async () => { + const key = queryKey() + + function Page() { + const query = createQuery(key, () => 'data', { + enabled: false, + }) + + return ( +
+
+ status: {query.status}, {query.fetchStatus} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('status: loading, idle')) + }) + + test('should not schedule garbage collection, if cacheTimeout is set to `Infinity`', async () => { + const key = queryKey() + + function Page() { + const query = createQuery(key, () => 'fetched data', { + cacheTime: Infinity, + }) + return
{query.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('fetched data')) + + rendered.unmount() + + const query = queryCache.find(key) + // @ts-expect-error + expect(query!.cacheTimeout).toBe(undefined) + }) + + it('should not cause memo churn when data does not change', async () => { + const key = queryKey() + const queryFn = jest.fn().mockReturnValue('data') + const memoFn = jest.fn() + + function Page() { + const result = createQuery(key, async () => { + await sleep(10) + return ( + queryFn() || { + data: { + nested: true, + }, + } + ) + }) + + React.useMemo(() => { + memoFn() + return result.data + }, [result.data]) + + return ( +
+
status {result.status}
+
isFetching {result.isFetching ? 'true' : 'false'}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('status loading')) + await waitFor(() => rendered.getByText('status success')) + fireEvent.click(rendered.getByText('refetch')) + await waitFor(() => rendered.getByText('isFetching true')) + await waitFor(() => rendered.getByText('isFetching false')) + expect(queryFn).toHaveBeenCalledTimes(2) + expect(memoFn).toHaveBeenCalledTimes(2) + }) + + it('should update data upon interval changes', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const [int, setInt] = React.useState(200) + const { data } = createQuery(key, () => count++, { + refetchInterval: int, + }) + + React.useEffect(() => { + if (data === 2) { + setInt(0) + } + }, [data]) + + return
count: {data}
+ } + + const rendered = renderWithClient(queryClient, ) + + // mount + await waitFor(() => rendered.getByText('count: 0')) + await waitFor(() => rendered.getByText('count: 1')) + await waitFor(() => rendered.getByText('count: 2')) + }) + + it('should refetch in an interval depending on function result', async () => { + const key = queryKey() + let count = 0 + const states: CreateQueryResult[] = [] + + function Page() { + const queryInfo = createQuery( + key, + async () => { + await sleep(10) + return count++ + }, + { + refetchInterval: (data = 0) => (data < 2 ? 10 : false), + }, + ) + + states.push(queryInfo) + + return ( +
+

count: {queryInfo.data}

+

status: {queryInfo.status}

+

data: {queryInfo.data}

+

refetch: {queryInfo.isRefetching}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('count: 2')) + + expect(states.length).toEqual(6) + + expect(states).toMatchObject([ + { + status: 'loading', + isFetching: true, + data: undefined, + }, + { + status: 'success', + isFetching: false, + data: 0, + }, + { + status: 'success', + isFetching: true, + data: 0, + }, + { + status: 'success', + isFetching: false, + data: 1, + }, + { + status: 'success', + isFetching: true, + data: 1, + }, + { + status: 'success', + isFetching: false, + data: 2, + }, + ]) + }) + + it('should not interval fetch with a refetchInterval of 0', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const queryInfo = createQuery(key, () => 1, { + refetchInterval: 0, + }) + + states.push(queryInfo) + + return
count: {queryInfo.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('count: 1')) + + await sleep(10) //extra sleep to make sure we're not re-fetching + + expect(states.length).toEqual(2) + + expect(states).toMatchObject([ + { + status: 'loading', + isFetching: true, + data: undefined, + }, + { + status: 'success', + isFetching: false, + data: 1, + }, + ]) + }) + + it('should accept an empty string as query key', async () => { + function Page() { + const result = createQuery([''], (ctx) => ctx.queryKey) + return <>{JSON.stringify(result.data)} + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('')) + }) + + it('should accept an object as query key', async () => { + function Page() { + const result = createQuery([{ a: 'a' }], (ctx) => ctx.queryKey) + return <>{JSON.stringify(result.data)} + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('[{"a":"a"}]')) + }) + + it('should refetch if any query instance becomes enabled', async () => { + const key = queryKey() + + const queryFn = jest.fn().mockReturnValue('data') + + function Disabled() { + createQuery(key, queryFn, { enabled: false }) + return null + } + + function Page() { + const [enabled, setEnabled] = React.useState(false) + const result = createQuery(key, queryFn, { enabled }) + return ( + <> + +
{result.data}
+ + + ) + } + + const rendered = renderWithClient(queryClient, ) + expect(queryFn).toHaveBeenCalledTimes(0) + fireEvent.click(rendered.getByText('enable')) + await waitFor(() => rendered.getByText('data')) + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should use placeholder data while the query loads', async () => { + const key1 = queryKey() + + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key1, () => 'data', { + placeholderData: 'placeholder', + }) + + states.push(state) + + return ( +
+

Data: {state.data}

+
Status: {state.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: data')) + + expect(states).toMatchObject([ + { + isSuccess: true, + isPlaceholderData: true, + data: 'placeholder', + }, + { + isSuccess: true, + isPlaceholderData: false, + data: 'data', + }, + ]) + }) + + it('should use placeholder data even for disabled queries', async () => { + const key1 = queryKey() + + const states: { state: CreateQueryResult; count: number }[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery(key1, () => 'data', { + placeholderData: 'placeholder', + enabled: count === 0, + }) + + states.push({ state, count }) + + React.useEffect(() => { + setCount(1) + }, []) + + return ( +
+

Data: {state.data}

+
Status: {state.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: data')) + + expect(states).toMatchObject([ + { + state: { + isSuccess: true, + isPlaceholderData: true, + data: 'placeholder', + }, + count: 0, + }, + { + state: { + isSuccess: true, + isPlaceholderData: true, + data: 'placeholder', + }, + count: 1, + }, + { + state: { + isSuccess: true, + isPlaceholderData: false, + data: 'data', + }, + count: 1, + }, + ]) + }) + + it('placeholder data should run through select', async () => { + const key1 = queryKey() + + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key1, () => 1, { + placeholderData: 23, + select: (data) => String(data * 2), + }) + + states.push(state) + + return ( +
+

Data: {state.data}

+
Status: {state.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: 2')) + + expect(states).toMatchObject([ + { + isSuccess: true, + isPlaceholderData: true, + data: '46', + }, + { + isSuccess: true, + isPlaceholderData: false, + data: '2', + }, + ]) + }) + + it('placeholder data function result should run through select', async () => { + const key1 = queryKey() + + const states: CreateQueryResult[] = [] + let placeholderFunctionRunCount = 0 + + function Page() { + const state = createQuery(key1, () => 1, { + placeholderData: () => { + placeholderFunctionRunCount++ + return 23 + }, + select: (data) => String(data * 2), + }) + + states.push(state) + + return ( +
+

Data: {state.data}

+
Status: {state.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: 2')) + + rendered.rerender() + + expect(states).toMatchObject([ + { + isSuccess: true, + isPlaceholderData: true, + data: '46', + }, + { + isSuccess: true, + isPlaceholderData: false, + data: '2', + }, + { + isSuccess: true, + isPlaceholderData: false, + data: '2', + }, + ]) + + expect(placeholderFunctionRunCount).toEqual(1) + }) + + it('select should only run when dependencies change if memoized', async () => { + const key1 = queryKey() + + let selectRun = 0 + + function Page() { + const [count, inc] = React.useReducer((prev) => prev + 1, 2) + + const state = createQuery( + key1, + async () => { + await sleep(10) + return 0 + }, + { + select: React.useCallback( + (data: number) => { + selectRun++ + return `selected ${data + count}` + }, + [count], + ), + placeholderData: 99, + }, + ) + + return ( +
+

Data: {state.data}

+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: selected 101')) // 99 + 2 + expect(selectRun).toBe(1) + + await waitFor(() => rendered.getByText('Data: selected 2')) // 0 + 2 + expect(selectRun).toBe(2) + + fireEvent.click(rendered.getByRole('button', { name: /inc/i })) + + await waitFor(() => rendered.getByText('Data: selected 3')) // 0 + 3 + expect(selectRun).toBe(3) + }) + + it('select should always return the correct state', async () => { + const key1 = queryKey() + + function Page() { + const [count, inc] = React.useReducer((prev) => prev + 1, 2) + const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1) + + const state = createQuery( + key1, + async () => { + await sleep(10) + return 0 + }, + { + select: React.useCallback( + (data: number) => { + return `selected ${data + count}` + }, + [count], + ), + placeholderData: 99, + }, + ) + + return ( +
+

Data: {state.data}

+

forceValue: {forceValue}

+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: selected 101')) // 99 + 2 + + await waitFor(() => rendered.getByText('Data: selected 2')) // 0 + 2 + + fireEvent.click(rendered.getByRole('button', { name: /inc/i })) + + await waitFor(() => rendered.getByText('Data: selected 3')) // 0 + 3 + + fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i })) + + await waitFor(() => rendered.getByText('forceValue: 2')) + // data should still be 3 after an independent re-render + await waitFor(() => rendered.getByText('Data: selected 3')) + }) + + it('select should structurally share data', async () => { + const key1 = queryKey() + const states: Array> = [] + + function Page() { + const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1) + + const state = createQuery( + key1, + async () => { + await sleep(10) + return [1, 2] + }, + { + select: (res) => res.map((x) => x + 1), + }, + ) + + React.useEffect(() => { + if (state.data) { + states.push(state.data) + } + }, [state.data]) + + return ( +
+

Data: {JSON.stringify(state.data)}

+

forceValue: {forceValue}

+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: [2,3]')) + expect(states).toHaveLength(1) + + fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i })) + + await waitFor(() => rendered.getByText('forceValue: 2')) + await waitFor(() => rendered.getByText('Data: [2,3]')) + + // effect should not be triggered again due to structural sharing + expect(states).toHaveLength(1) + }) + + it('should cancel the query function when there are no more subscriptions', async () => { + const key = queryKey() + let cancelFn: jest.Mock = jest.fn() + + const queryFn = ({ signal }: { signal?: AbortSignal }) => { + const promise = new Promise((resolve, reject) => { + cancelFn = jest.fn(() => reject('Cancelled')) + signal?.addEventListener('abort', cancelFn) + sleep(10).then(() => resolve('OK')) + }) + + return promise + } + + function Page() { + const state = createQuery(key, queryFn) + return ( +
+

Status: {state.status}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, + + + , + ) + + await waitFor(() => rendered.getByText('off')) + + if (typeof AbortSignal === 'function') { + expect(cancelFn).toHaveBeenCalled() + } + }) + + it('should cancel the query if the signal was consumed and there are no more subscriptions', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + const queryFn: QueryFunction = async ( + ctx, + ) => { + const [, limit] = ctx.queryKey + const value = limit % 2 && ctx.signal ? 'abort' : `data ${limit}` + await sleep(25) + return value + } + + function Page(props: { limit: number }) { + const state = createQuery([key, props.limit], queryFn) + states[props.limit] = state + return ( +
+

Status: {state.status}

+

data: {state.data}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, + + + + + + , + ) + + await waitFor(() => rendered.getByText('off')) + await sleep(20) + + await waitFor(() => expect(states).toHaveLength(4)) + + expect(queryCache.find([key, 0])?.state).toMatchObject({ + data: 'data 0', + status: 'success', + dataUpdateCount: 1, + }) + + if (typeof AbortSignal === 'function') { + expect(queryCache.find([key, 1])?.state).toMatchObject({ + data: undefined, + status: 'loading', + fetchStatus: 'idle', + }) + } else { + expect(queryCache.find([key, 1])?.state).toMatchObject({ + data: 'data 1', + status: 'success', + dataUpdateCount: 1, + }) + } + + expect(queryCache.find([key, 2])?.state).toMatchObject({ + data: 'data 2', + status: 'success', + dataUpdateCount: 1, + }) + + if (typeof AbortSignal === 'function') { + expect(queryCache.find([key, 3])?.state).toMatchObject({ + data: undefined, + status: 'loading', + fetchStatus: 'idle', + }) + } else { + expect(queryCache.find([key, 3])?.state).toMatchObject({ + data: 'data 3', + status: 'success', + dataUpdateCount: 1, + }) + } + }) + + it('should refetch when quickly switching to a failed query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + const queryFn = async () => { + await sleep(50) + return 'OK' + } + + function Page() { + const [id, setId] = React.useState(1) + const [hasChanged, setHasChanged] = React.useState(false) + + const state = createQuery([key, id], queryFn) + + states.push(state) + + React.useEffect(() => { + setId((prevId) => (prevId === 1 ? 2 : 1)) + setHasChanged(true) + }, [hasChanged]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + expect(states.length).toBe(4) + // Load query 1 + expect(states[0]).toMatchObject({ + status: 'loading', + error: null, + }) + // Load query 2 + expect(states[1]).toMatchObject({ + status: 'loading', + error: null, + }) + // Load query 1 + expect(states[2]).toMatchObject({ + status: 'loading', + error: null, + }) + // Loaded query 1 + expect(states[3]).toMatchObject({ + status: 'success', + error: null, + }) + }) + + it('should update query state and refetch when reset with resetQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { staleTime: Infinity }, + ) + + states.push(state) + + return ( +
+ +
data: {state.data ?? 'null'}
+
isFetching: {state.isFetching}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /reset/i })) + + await waitFor(() => expect(states.length).toBe(4)) + + await waitFor(() => rendered.getByText('data: 2')) + + expect(count).toBe(2) + + expect(states[0]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: true, + isSuccess: false, + isStale: true, + }) + expect(states[1]).toMatchObject({ + data: 1, + isLoading: false, + isFetching: false, + isSuccess: true, + isStale: false, + }) + expect(states[2]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: true, + isSuccess: false, + isStale: true, + }) + expect(states[3]).toMatchObject({ + data: 2, + isLoading: false, + isFetching: false, + isSuccess: true, + isStale: false, + }) + }) + + it('should update query state and not refetch when resetting a disabled query with resetQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { staleTime: Infinity, enabled: false, notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { refetch } = state + + return ( +
+ + +
data: {state.data ?? 'null'}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: null')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /reset/i })) + + await waitFor(() => rendered.getByText('data: null')) + await waitFor(() => expect(states.length).toBe(4)) + + expect(count).toBe(1) + + expect(states[0]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: false, + isSuccess: false, + isStale: true, + }) + expect(states[1]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: true, + isSuccess: false, + isStale: true, + }) + expect(states[2]).toMatchObject({ + data: 1, + isLoading: false, + isFetching: false, + isSuccess: true, + isStale: false, + }) + expect(states[3]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: false, + isSuccess: false, + isStale: true, + }) + }) + + it('should only call the query hash function once each render', async () => { + const key = queryKey() + + let hashes = 0 + let renders = 0 + + function queryKeyHashFn(x: any) { + hashes++ + return JSON.stringify(x) + } + + function Page() { + React.useEffect(() => { + renders++ + }) + + createQuery(key, () => 'test', { queryKeyHashFn }) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(renders).toBe(2) + expect(hashes).toBe(2) + }) + + it('should refetch when changed enabled to true in error state', async () => { + const queryFn = jest.fn() + queryFn.mockImplementation(async () => { + await sleep(10) + return Promise.reject(new Error('Suspense Error Bingo')) + }) + + function Page({ enabled }: { enabled: boolean }) { + const { error, isLoading } = createQuery(['key'], queryFn, { + enabled, + retry: false, + retryOnMount: false, + refetchOnMount: false, + refetchOnWindowFocus: false, + }) + + if (isLoading) { + return
status: loading
+ } + if (error instanceof Error) { + return
error
+ } + return
rendered
+ } + + function App() { + const [enabled, toggle] = React.useReducer((x) => !x, true) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // initial state check + rendered.getByText('status: loading') + + // // render error state component + await waitFor(() => rendered.getByText('error')) + expect(queryFn).toBeCalledTimes(1) + + // change to enabled to false + fireEvent.click(rendered.getByLabelText('retry')) + await waitFor(() => rendered.getByText('error')) + expect(queryFn).toBeCalledTimes(1) + + // // change to enabled to true + fireEvent.click(rendered.getByLabelText('retry')) + expect(queryFn).toBeCalledTimes(2) + }) + + it('should refetch when query key changed when previous status is error', async () => { + function Page({ id }: { id: number }) { + const { error, isLoading } = createQuery( + [id], + async () => { + await sleep(10) + if (id % 2 === 1) { + return Promise.reject(new Error('Error')) + } else { + return 'data' + } + }, + { + retry: false, + retryOnMount: false, + refetchOnMount: false, + refetchOnWindowFocus: false, + }, + ) + + if (isLoading) { + return
status: loading
+ } + if (error instanceof Error) { + return
error
+ } + return
rendered
+ } + + function App() { + const [id, changeId] = React.useReducer((x) => x + 1, 1) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // initial state check + rendered.getByText('status: loading') + + // render error state component + await waitFor(() => rendered.getByText('error')) + + // change to unmount query + fireEvent.click(rendered.getByLabelText('change')) + await waitFor(() => rendered.getByText('rendered')) + + // change to mount new query + fireEvent.click(rendered.getByLabelText('change')) + await waitFor(() => rendered.getByText('error')) + }) + + it('should refetch when query key changed when switching between erroneous queries', async () => { + function Page({ id }: { id: boolean }) { + const { error, isFetching } = createQuery( + [id], + async () => { + await sleep(10) + return Promise.reject(new Error('Error')) + }, + { + retry: false, + retryOnMount: false, + refetchOnMount: false, + refetchOnWindowFocus: false, + }, + ) + + if (isFetching) { + return
status: fetching
+ } + if (error instanceof Error) { + return
error
+ } + return
rendered
+ } + + function App() { + const [value, toggle] = React.useReducer((x) => !x, true) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // initial state check + rendered.getByText('status: fetching') + + // render error state component + await waitFor(() => rendered.getByText('error')) + + // change to mount second query + fireEvent.click(rendered.getByLabelText('change')) + await waitFor(() => rendered.getByText('status: fetching')) + await waitFor(() => rendered.getByText('error')) + + // change to mount first query again + fireEvent.click(rendered.getByLabelText('change')) + await waitFor(() => rendered.getByText('status: fetching')) + await waitFor(() => rendered.getByText('error')) + }) + + it('should have no error in loading state when refetching after error occurred', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const error = new Error('oops') + + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + if (count === 0) { + count++ + throw error + } + return 5 + }, + { + retry: false, + }, + ) + + states.push(state) + + if (state.isLoading) { + return
status: loading
+ } + if (state.error instanceof Error) { + return ( +
+
error
+ +
+ ) + } + return
data: {state.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('error')) + + fireEvent.click(rendered.getByRole('button', { name: 'refetch' })) + await waitFor(() => rendered.getByText('data: 5')) + + await waitFor(() => expect(states.length).toBe(4)) + + expect(states[0]).toMatchObject({ + status: 'loading', + data: undefined, + error: null, + }) + + expect(states[1]).toMatchObject({ + status: 'error', + data: undefined, + error, + }) + + expect(states[2]).toMatchObject({ + status: 'loading', + data: undefined, + error: null, + }) + + expect(states[3]).toMatchObject({ + status: 'success', + data: 5, + error: null, + }) + }) + + describe('networkMode online', () => { + it('online queries should not start fetching if you are offline', async () => { + const onlineMock = mockNavigatorOnLine(false) + + const key = queryKey() + const states: Array = [] + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + await sleep(10) + return 'data' + }, + }) + + React.useEffect(() => { + states.push(state.fetchStatus) + }) + + return ( +
+
+ status: {state.status}, isPaused: {String(state.isPaused)} +
+
data: {state.data}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('status: loading, isPaused: true')) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await waitFor(() => + rendered.getByText('status: success, isPaused: false'), + ) + await waitFor(() => { + expect(rendered.getByText('data: data')).toBeInTheDocument() + }) + + expect(states).toEqual(['paused', 'fetching', 'idle']) + + onlineMock.mockRestore() + }) + + it('online queries should not refetch if you are offline', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus}, + failureCount: {state.failureCount} +
+
data: {state.data}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data1')) + + const onlineMock = mockNavigatorOnLine(false) + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await waitFor(() => + rendered.getByText( + 'status: success, fetchStatus: paused, failureCount: 0', + ), + ) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await waitFor(() => + rendered.getByText( + 'status: success, fetchStatus: fetching, failureCount: 0', + ), + ) + await waitFor(() => + rendered.getByText( + 'status: success, fetchStatus: idle, failureCount: 0', + ), + ) + + await waitFor(() => { + expect(rendered.getByText('data: data2')).toBeInTheDocument() + }) + + onlineMock.mockRestore() + }) + + it('online queries should not refetch if you are offline and refocus', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data1')) + + const onlineMock = mockNavigatorOnLine(false) + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + + window.dispatchEvent(new FocusEvent('focus')) + await sleep(15) + + await waitFor(() => + expect(rendered.queryByText('data: data2')).not.toBeInTheDocument(), + ) + expect(count).toBe(1) + onlineMock.mockRestore() + }) + + it('online queries should not refetch while already paused', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+ +
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: paused'), + ) + + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await sleep(15) + + // invalidation should not trigger a refetch + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: paused'), + ) + + expect(count).toBe(0) + onlineMock.mockRestore() + }) + + it('online queries should not refetch while already paused if data is in the cache', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + initialData: 'initial', + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+ +
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + await waitFor(() => { + expect(rendered.getByText('data: initial')).toBeInTheDocument() + }) + + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await sleep(15) + + // invalidation should not trigger a refetch + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + + expect(count).toBe(0) + onlineMock.mockRestore() + }) + + it('online queries should not get stuck in fetching state when pausing multiple times', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + initialData: 'initial', + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+ +
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + await waitFor(() => { + expect(rendered.getByText('data: initial')).toBeInTheDocument() + }) + + // triggers one pause + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await sleep(15) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + + // triggers a second pause + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + onlineMock.mockReturnValue(true) + act(() => { + window.dispatchEvent(new Event('online')) + }) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: idle'), + ) + await waitFor(() => { + expect(rendered.getByText('data: data1')).toBeInTheDocument() + }) + + expect(count).toBe(1) + onlineMock.mockRestore() + }) + + it('online queries should pause retries if you are offline', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async (): Promise => { + count++ + await sleep(10) + throw new Error('failed' + count) + }, + retry: 2, + retryDelay: 10, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus}, + failureCount: {state.failureCount} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText( + 'status: loading, fetchStatus: fetching, failureCount: 1', + ), + ) + + const onlineMock = mockNavigatorOnLine(false) + + await sleep(20) + + await waitFor(() => + rendered.getByText( + 'status: loading, fetchStatus: paused, failureCount: 1', + ), + ) + + expect(count).toBe(1) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await waitFor(() => + rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), + ) + + expect(count).toBe(3) + + onlineMock.mockRestore() + }) + + it('online queries should fetch if paused and we go online even if already unmounted (because not cancelled)', async () => { + const key = queryKey() + let count = 0 + + function Component() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+
+ ) + } + + function Page() { + const [show, setShow] = React.useState(true) + + return ( +
+ {show && } + +
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: paused'), + ) + + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(15) + + expect(queryClient.getQueryState(key)).toMatchObject({ + fetchStatus: 'idle', + status: 'success', + }) + + expect(count).toBe(1) + + onlineMock.mockRestore() + }) + + it('online queries should not fetch if paused and we go online when cancelled and no refetchOnReconnect', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + refetchOnReconnect: false, + }) + + return ( +
+ +
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: paused'), + ) + + fireEvent.click(rendered.getByRole('button', { name: /cancel/i })) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: idle'), + ) + + expect(count).toBe(0) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(15) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: idle'), + ) + + expect(count).toBe(0) + + onlineMock.mockRestore() + }) + + it('online queries should not fetch if paused and we go online if already unmounted when signal consumed', async () => { + const key = queryKey() + let count = 0 + + function Component() { + const state = createQuery({ + queryKey: key, + queryFn: async ({ signal }) => { + count++ + await sleep(10) + return `${signal ? 'signal' : 'data'}${count}` + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+
+ ) + } + + function Page() { + const [show, setShow] = React.useState(true) + + return ( +
+ {show && } + + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: idle'), + ) + + const onlineMock = mockNavigatorOnLine(false) + + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + + await sleep(15) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(15) + + expect(queryClient.getQueryState(key)).toMatchObject({ + fetchStatus: 'idle', + status: 'success', + }) + + expect(count).toBe(typeof AbortSignal === 'function' ? 1 : 2) + + onlineMock.mockRestore() + }) + }) + + describe('networkMode always', () => { + it('always queries should start fetching even if you are offline', async () => { + const onlineMock = mockNavigatorOnLine(false) + + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data ' + count + }, + networkMode: 'always', + }) + + return ( +
+
+ status: {state.status}, isPaused: {String(state.isPaused)} +
+
data: {state.data}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: success, isPaused: false'), + ) + + await waitFor(() => { + expect(rendered.getByText('data: data 1')).toBeInTheDocument() + }) + + onlineMock.mockRestore() + }) + + it('always queries should not pause retries', async () => { + const onlineMock = mockNavigatorOnLine(false) + + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async (): Promise => { + count++ + await sleep(10) + throw new Error('error ' + count) + }, + networkMode: 'always', + retry: 1, + retryDelay: 5, + }) + + return ( +
+
+ status: {state.status}, isPaused: {String(state.isPaused)} +
+
+ error: {state.error instanceof Error && state.error.message} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('status: error, isPaused: false')) + + await waitFor(() => { + expect(rendered.getByText('error: error 2')).toBeInTheDocument() + }) + + expect(count).toBe(2) + + onlineMock.mockRestore() + }) + }) + + describe('networkMode offlineFirst', () => { + it('offlineFirst queries should start fetching if you are offline, but pause retries', async () => { + const onlineMock = mockNavigatorOnLine(false) + + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async (): Promise => { + count++ + await sleep(10) + throw new Error('failed' + count) + }, + retry: 2, + retryDelay: 1, + networkMode: 'offlineFirst', + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus}, + failureCount: {state.failureCount} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText( + 'status: loading, fetchStatus: paused, failureCount: 1', + ), + ) + + expect(count).toBe(1) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await waitFor(() => + rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), + ) + + expect(count).toBe(3) + + onlineMock.mockRestore() + }) + }) + + it('it should have status=error on mount when a query has failed', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const error = new Error('oops') + + const queryFn = async (): Promise => { + throw error + } + + function Page() { + const state = createQuery(key, queryFn, { + retry: false, + retryOnMount: false, + }) + + states.push(state) + + return <> + } + + await queryClient.prefetchQuery(key, queryFn) + renderWithClient(queryClient, ) + + await waitFor(() => expect(states).toHaveLength(1)) + + expect(states[0]).toMatchObject({ + status: 'error', + error, + }) + }) + + it('setQueryData - should not call onSuccess callback of active observers', async () => { + const key = queryKey() + const onSuccess = jest.fn() + + function Page() { + const state = createQuery(key, () => 'data', { onSuccess }) + return ( +
+
data: {state.data}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data')) + fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i })) + await waitFor(() => rendered.getByText('data: newData')) + + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(onSuccess).toHaveBeenCalledWith('data') + }) + + it('setQueryData - should respect updatedAt', async () => { + const key = queryKey() + + function Page() { + const state = createQuery(key, () => 'data') + return ( +
+
data: {state.data}
+
dataUpdatedAt: {state.dataUpdatedAt}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data')) + fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i })) + await waitFor(() => rendered.getByText('data: newData')) + await waitFor(() => { + expect(rendered.getByText('dataUpdatedAt: 100')).toBeInTheDocument() + }) + }) + + it('errorUpdateCount should increased on each fetch failure', async () => { + const key = queryKey() + const error = new Error('oops') + + function Page() { + const { refetch, errorUpdateCount } = createQuery( + key, + async (): Promise => { + throw error + }, + { + retry: false, + }, + ) + return ( +
+ + data: {errorUpdateCount} +
+ ) + } + const rendered = renderWithClient(queryClient, ) + const fetchBtn = rendered.getByRole('button', { name: 'refetch' }) + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(fetchBtn) + await waitFor(() => rendered.getByText('data: 2')) + fireEvent.click(fetchBtn) + await waitFor(() => rendered.getByText('data: 3')) + }) +}) From c8f7dda77b8ae3d027c4036f59ead2a7eb0df163 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 11:07:48 -0400 Subject: [PATCH 017/221] fix type tests and add comments to errors --- .../src/__tests__/createQuery.test.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 6a873027471..865db302788 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -22,6 +22,7 @@ import { describe('useQuery', () => { const queryCache = new QueryCache() + // TODO(lukemurray): not sure why this is failing const queryClient = createQueryClient({ queryCache }) it('should return the correct types', () => { @@ -51,10 +52,14 @@ describe('useQuery', () => { expectType(withError.error) // it should provide the result type in the configuration - createQuery([key], async () => true, { - onSuccess: (data) => expectType(data), - onSettled: (data) => expectType(data), - }) + createQuery( + () => [key()], + async () => true, + { + onSuccess: (data) => expectType(data), + onSettled: (data) => expectType(data), + }, + ) // it should be possible to specify a union type as result type const unionTypeSync = createQuery( @@ -88,15 +93,18 @@ describe('useQuery', () => { expectType(fromGenericQueryFn.error) const fromGenericOptionsQueryFn = createQuery({ - queryKey: key, + // TODO(lukemurray): when passing the queryKey as options how do we make it reactive? + queryKey: key(), queryFn: () => queryFn(), }) expectType(fromGenericOptionsQueryFn.data) expectType(fromGenericOptionsQueryFn.error) type MyData = number + // TODO(lukemurray): this should be a function to match SolidQueryKey. type MyQueryKey = readonly ['my-data', number] + // TODO(lukemurray): errors if MyQueryKey is a function. const getMyDataArrayKey: QueryFunction = async ({ queryKey: [, n], }) => { @@ -104,6 +112,7 @@ describe('useQuery', () => { } createQuery({ + // TODO(lukemurray): fails because MyQueryKey is not a function and QueryFunction type doesn't support SolidQueryKey queryKey: ['my-data', 100], queryFn: getMyDataArrayKey, }) From 9dc86351a6e0562b21da5d3e2c647a9af5f09a00 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 11:24:52 -0400 Subject: [PATCH 018/221] fix comment in types --- packages/solid-query/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index e984a87f594..960f274e1c5 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -12,7 +12,7 @@ import type { Context } from 'solid-js' export interface ContextOptions { /** - * Use this to pass your React Query context. Otherwise, `defaultContext` will be used. + * Use this to pass your Solid Query context. Otherwise, `defaultContext` will be used. */ context?: Context } From 566bb6112719965d09ba6b7880781672761d3d7e Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 9 Sep 2022 11:33:33 -0400 Subject: [PATCH 019/221] Keep comments and better organization of types by functions --- packages/solid-query/src/createQuery.ts | 15 +++++---- packages/solid-query/src/types.ts | 42 ++++++++++--------------- packages/solid-query/src/utils.ts | 18 +++++------ 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index 4258a53310d..374dbe2fac0 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,17 +1,20 @@ -import { QueryFunction, QueryObserver } from '@tanstack/query-core' -import { createComputed } from 'solid-js' -import { createStore } from 'solid-js/store' -import { createBaseQuery } from './createBaseQuery' +import { QueryObserver, QueryFunction } from '@tanstack/query-core' import { CreateQueryOptions, CreateQueryResult, DefinedCreateQueryResult, SolidQueryKey, } from './types' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' import { parseQueryArgs } from './utils' +import { createBaseQuery } from './createBaseQuery' -// HOOK - +// There are several ways to create a query. +// 1. createQuery(options: CreateQueryOptions) +// 2. createQuery(querykey: () => Serializable[], options: CreateQueryOptions) +// 3. createQuery(querykey: () => Serializable[], queryFunc: Fetcher Function, options: CreateQueryOptions) +// 4. The fourth overload is a combination of all three function params export function createQuery< TQueryFnData = unknown, TError = unknown, diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index e984a87f594..b5dd4878db6 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,14 +1,15 @@ +import type { Context, Accessor } from 'solid-js' import type { - DefinedQueryObserverResult, - MutateFunction, - MutationObserverOptions, - MutationObserverResult, QueryClient, QueryKey, QueryObserverOptions, QueryObserverResult, + MutateFunction, + MutationObserverOptions, + MutationObserverResult, + DefinedQueryObserverResult, + QueryFilters, } from '@tanstack/query-core' -import type { Context } from 'solid-js' export interface ContextOptions { /** @@ -17,6 +18,7 @@ export interface ContextOptions { context?: Context } +/* --- Create Query and Create Base Query Types --- */ export type SolidQueryKey = () => readonly unknown[] export interface CreateBaseQueryOptions< @@ -24,7 +26,6 @@ export interface CreateBaseQueryOptions< TError = unknown, TData = TQueryFnData, TQueryData = TQueryFnData, - // TODO(lukemurray): maybe this should be a solid query key? TQueryKey extends QueryKey = QueryKey, > extends ContextOptions, QueryObserverOptions {} @@ -42,21 +43,6 @@ export interface CreateQueryOptions< ReturnType > {} -// export interface UseInfiniteQueryOptions< -// TQueryFnData = unknown, -// TError = unknown, -// TData = TQueryFnData, -// TQueryData = TQueryFnData, -// TQueryKey extends QueryKey = QueryKey, -// > extends ContextOptions, -// InfiniteQueryObserverOptions< -// TQueryFnData, -// TError, -// TData, -// TQueryData, -// TQueryKey -// > {} - export type CreateBaseQueryResult< TData = unknown, TError = unknown, @@ -77,11 +63,7 @@ export type DefinedCreateQueryResult< TError = unknown, > = DefinedCreateBaseQueryResult -// export type UseInfiniteQueryResult< -// TData = unknown, -// TError = unknown, -// > = InfiniteQueryObserverResult - +/* --- Create Mutation Types --- */ export interface CreateMutationOptions< TData = unknown, TError = unknown, @@ -129,3 +111,11 @@ export type CreateMutationResult< > = CreateBaseMutationResult type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } + +/* --- Use Is Fetching Types --- */ +export interface SolidQueryFilters extends Omit { + queryKey?: SolidQueryKey +} + +export type ParseFilterArgs = + T['queryKey'] extends () => infer R ? T & { queryKey: R } : T diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 3ea93b6cb1f..f164bec4454 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,5 +1,10 @@ -import { CreateQueryOptions, SolidQueryKey } from './types' -import { QueryFunction, QueryFilters } from '@tanstack/query-core' +import { + CreateQueryOptions, + SolidQueryKey, + SolidQueryFilters, + ParseFilterArgs, +} from './types' +import { QueryFunction } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { return typeof value === 'function' @@ -37,13 +42,6 @@ export function parseQueryArgs< return { ...arg2, queryKey: arg1() } as any } -export interface SolidQueryFilters extends Omit { - queryKey?: SolidQueryKey -} - -export type ParseFilterArgs = - T['queryKey'] extends () => infer R ? T & { queryKey: R } : T - export function parseFilterArgs< TFilters extends SolidQueryFilters, TOptions = unknown, @@ -55,6 +53,6 @@ export function parseFilterArgs< return ( isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1() }, arg3] - : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] + : [{ ...arg1, queryKey: arg1?.queryKey?.() } || {}, arg2] ) as [ParseFilterArgs, TOptions] } From c048a75e0a3c780119243296e87f777b1faef823 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 9 Sep 2022 12:00:39 -0400 Subject: [PATCH 020/221] Fix: Typo in useIsFetching --- packages/solid-query/src/useIsFetching.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index 241832cc5cd..dfa78d79c79 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -1,6 +1,6 @@ import { QueryFilters } from '@tanstack/query-core' -import { ContextOptions, SolidQueryKey } from './types' +import { ContextOptions, SolidQueryKey, SolidQueryFilters } from './types' import { useQueryClient } from './QueryClientProvider' import { Accessor, @@ -9,7 +9,7 @@ import { createComputed, createMemo, } from 'solid-js' -import { parseFilterArgs, SolidQueryFilters } from './utils' +import { parseFilterArgs } from './utils' interface Options extends ContextOptions {} From 4ac03a5b3aee3d040ac7454c5877aadebdb900ee Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 11:53:44 -0400 Subject: [PATCH 021/221] update test utils --- packages/solid-query/src/__tests__/utils.ts | 5 -- packages/solid-query/src/__tests__/utils.tsx | 65 ++++++++++++++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) delete mode 100644 packages/solid-query/src/__tests__/utils.ts create mode 100644 packages/solid-query/src/__tests__/utils.tsx diff --git a/packages/solid-query/src/__tests__/utils.ts b/packages/solid-query/src/__tests__/utils.ts deleted file mode 100644 index c6bbb39643a..00000000000 --- a/packages/solid-query/src/__tests__/utils.ts +++ /dev/null @@ -1,5 +0,0 @@ -let queryKeyCount = 0 -export function queryKey(): () => Array { - const localQueryKeyCount = queryKeyCount++ - return () => [`query_${localQueryKeyCount}`] -} diff --git a/packages/solid-query/src/__tests__/utils.tsx b/packages/solid-query/src/__tests__/utils.tsx new file mode 100644 index 00000000000..d17650115fa --- /dev/null +++ b/packages/solid-query/src/__tests__/utils.tsx @@ -0,0 +1,65 @@ +import { QueryClient, QueryClientProvider } from '..' +import { render } from 'solid-testing-library' +import { + JSX, + createEffect, + createSignal, + onCleanup, + ParentProps, + Show, +} from 'solid-js' + +let queryKeyCount = 0 +export function queryKey(): () => Array { + const localQueryKeyCount = queryKeyCount++ + return () => [`query_${localQueryKeyCount}`] +} + +export function setActTimeout(fn: () => void, ms?: number) { + return setTimeout(() => { + fn() + }, ms) +} + +export function renderWithClient( + client: QueryClient, + ui: JSX.Element, + // options: ContextOptions = {}, +): ReturnType { + // TODO(lukemurray): add support for context options + // + return render(() => ( + {ui} + )) + // TODO(lukemurray): the react version returns rerender but the solid-testing-library + // doesn't support rerender + // return { + // ...result, + // rerender: (rerenderUi: React.ReactElement) => + // rerender( + // + // {rerenderUi} + // , + // ), + // } as any +} + +export const Blink = ( + props: { + duration: number + } & ParentProps, +) => { + const [shouldShow, setShouldShow] = createSignal(true) + + createEffect(() => { + setShouldShow(true) + const timeout = setActTimeout(() => setShouldShow(false), props.duration) + onCleanup(() => clearTimeout(timeout)) + }) + + return ( + off}> + <>{props.children} + + ) +} From 990bfa41682700afd4f8c17635ac032873d7cde6 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 12:05:40 -0400 Subject: [PATCH 022/221] shoudl allow to set default data value passing --- .../src/__tests__/createQuery.test.tsx | 158 +++++++++--------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 865db302788..8b14898aad8 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -4,12 +4,11 @@ import { expectType, mockVisibilityState, sleep, - setActTimeout, mockNavigatorOnLine, mockLogger, createQueryClient, } from '../../../../tests/utils' -import { renderWithClient, Blink, queryKey } from './utils' +import { renderWithClient, Blink, queryKey, setActTimeout } from './utils' import { createQuery, CreateQueryResult, @@ -22,7 +21,6 @@ import { describe('useQuery', () => { const queryCache = new QueryCache() - // TODO(lukemurray): not sure why this is failing const queryClient = createQueryClient({ queryCache }) it('should return the correct types', () => { @@ -179,23 +177,23 @@ describe('useQuery', () => { const key = queryKey() function Page() { - const { data = 'default' } = createQuery(key, async () => { + const state = createQuery(key, async () => { await sleep(10) return 'test' }) return (
-

{data}

+

{state.data ?? 'default'}

) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, () => ) - rendered.getByText('default') + screen.getByText('default') - await waitFor(() => rendered.getByText('test')) + await waitFor(() => screen.getByText('test')) }) it('should return the correct states for a successful query', async () => { @@ -502,7 +500,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 10) @@ -524,9 +522,9 @@ describe('useQuery', () => { const onSuccess = jest.fn() function Page() { - const [show, setShow] = React.useState(true) + const [show, setShow] = NotReact.useState(true) - React.useEffect(() => { + NotReact.useEffect(() => { setShow(false) }, [setShow]) @@ -664,7 +662,7 @@ describe('useQuery', () => { { enabled: false, initialData: 'initialData' }, ) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 5) @@ -698,7 +696,7 @@ describe('useQuery', () => { { enabled: false, initialData: 'initialData' }, ) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 5) @@ -732,7 +730,7 @@ describe('useQuery', () => { { enabled: false }, ) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 5) @@ -777,7 +775,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [toggle, setToggle] = React.useState(false) + const [toggle, setToggle] = NotReact.useState(false) return (
@@ -851,7 +849,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [, rerender] = React.useState({}) + const [, rerender] = NotReact.useState({}) const state = createQuery( key, @@ -869,7 +867,7 @@ describe('useQuery', () => { const { remove } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { remove() rerender({}) @@ -997,7 +995,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 5) @@ -1047,12 +1045,12 @@ describe('useQuery', () => { let runs = 0 function Page() { - const [, rerender] = React.useReducer(() => ({}), {}) + const [, rerender] = NotReact.useReducer(() => ({}), {}) const state = createQuery( key, () => (runs === 0 ? 'test' : 'test2'), { - select: React.useCallback(() => { + select: NotReact.useCallback(() => { runs++ throw error }, []), @@ -1093,7 +1091,7 @@ describe('useQuery', () => { const { refetch, data } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { if (data) { refetch() @@ -1127,7 +1125,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { renderCount++ }, [state]) @@ -1153,7 +1151,7 @@ describe('useQuery', () => { let count = 0 function Page() { - const [, rerender] = React.useState({}) + const [, rerender] = NotReact.useState({}) const state = createQuery(key, () => ++count, { notifyOnChangeProps: 'all', }) @@ -1434,7 +1432,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { queryClient.refetchQueries({ queryKey: key }) }, 20) @@ -1474,7 +1472,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { queryClient.invalidateQueries(key) }, 20) @@ -1501,7 +1499,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery( [key, count], @@ -1514,7 +1512,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(1) }, 10) @@ -1554,7 +1552,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery( [key, count], @@ -1567,7 +1565,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(1) }, 20) @@ -1727,7 +1725,7 @@ describe('useQuery', () => { const states: DefinedCreateQueryResult[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery( [key, count], @@ -1740,7 +1738,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(1) }, 20) @@ -1795,7 +1793,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery( [key, count], @@ -1810,7 +1808,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { refetch() setActTimeout(() => { @@ -1884,7 +1882,7 @@ describe('useQuery', () => { await sleep(10) function Page() { - const [count, setCount] = React.useState(10) + const [count, setCount] = NotReact.useState(10) const state = createQuery( [key, count], @@ -1899,7 +1897,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(11) }, 20) @@ -2192,7 +2190,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 10) @@ -2279,11 +2277,11 @@ describe('useQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - const originalUseEffect = React.useEffect + const originalUseEffect = NotReact.useEffect // Try to simulate useEffect timing delay // @ts-ignore - React.useEffect = (...args: any[]) => { + NotReact.useEffect = (...args: any[]) => { originalUseEffect(() => { setTimeout(() => { args[0]() @@ -2302,7 +2300,7 @@ describe('useQuery', () => { await sleep(50) // @ts-ignore - React.useEffect = originalUseEffect + NotReact.useEffect = originalUseEffect expect(states.length).toBe(2) expect(states[0]).toMatchObject({ status: 'loading' }) @@ -2346,7 +2344,7 @@ describe('useQuery', () => { } function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) createQuery(key, queryFn, { onSuccess: () => { setCount((x) => x + 1) @@ -2358,7 +2356,7 @@ describe('useQuery', () => { }, }) - React.useEffect(() => { + NotReact.useEffect(() => { renders++ callbackCount = count }) @@ -2381,9 +2379,9 @@ describe('useQuery', () => { const key = queryKey() function Page() { - const [, setNewState] = React.useState('state') + const [, setNewState] = NotReact.useState('state') const state = createQuery(key, () => 'data') - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { queryClient.setQueryData(key, 'new') // Update with same state to make react discard the next render @@ -2807,7 +2805,7 @@ describe('useQuery', () => { useErrorBoundary: true, }) - React.useEffect(() => { + NotReact.useEffect(() => { result = query }) @@ -2920,7 +2918,7 @@ describe('useQuery', () => { } function App() { - const [show, toggle] = React.useReducer((x) => !x, true) + const [show, toggle] = NotReact.useReducer((x) => !x, true) return (
@@ -2968,7 +2966,7 @@ describe('useQuery', () => { } function App() { - const [show, toggle] = React.useReducer((x) => !x, true) + const [show, toggle] = NotReact.useReducer((x) => !x, true) return (
@@ -3171,14 +3169,14 @@ describe('useQuery', () => { const states: DefinedCreateQueryResult<{ count: number }>[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery([key, count], () => ({ count: 10 }), { staleTime: Infinity, initialData: () => ({ count }), }) states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(1) }, 10) @@ -3563,8 +3561,8 @@ describe('useQuery', () => { let count = 0 function Page() { - const [enabled, setEnabled] = React.useState(false) - const [isPrefetched, setPrefetched] = React.useState(false) + const [enabled, setEnabled] = NotReact.useState(false) + const [isPrefetched, setPrefetched] = NotReact.useState(false) const query = createQuery( key, @@ -3578,7 +3576,7 @@ describe('useQuery', () => { }, ) - React.useEffect(() => { + NotReact.useEffect(() => { async function prefetch() { await queryClient.prefetchQuery(key, () => Promise.resolve('prefetched data'), @@ -3610,7 +3608,7 @@ describe('useQuery', () => { const key = queryKey() function Page() { - const [shouldFetch, setShouldFetch] = React.useState(false) + const [shouldFetch, setShouldFetch] = NotReact.useState(false) const query = createQuery(key, () => 'data', { enabled: shouldFetch, @@ -3687,7 +3685,7 @@ describe('useQuery', () => { const results: DefinedCreateQueryResult[] = [] function Page() { - const [shouldFetch, setShouldFetch] = React.useState(true) + const [shouldFetch, setShouldFetch] = NotReact.useState(true) const result = createQuery(key, () => 'fetched data', { enabled: shouldFetch, @@ -3696,7 +3694,7 @@ describe('useQuery', () => { results.push(result) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setShouldFetch(false) }, 5) @@ -3796,7 +3794,7 @@ describe('useQuery', () => { ) }) - React.useMemo(() => { + NotReact.useMemo(() => { memoFn() return result.data }, [result.data]) @@ -3826,12 +3824,12 @@ describe('useQuery', () => { let count = 0 function Page() { - const [int, setInt] = React.useState(200) + const [int, setInt] = NotReact.useState(200) const { data } = createQuery(key, () => count++, { refetchInterval: int, }) - React.useEffect(() => { + NotReact.useEffect(() => { if (data === 2) { setInt(0) } @@ -3986,7 +3984,7 @@ describe('useQuery', () => { } function Page() { - const [enabled, setEnabled] = React.useState(false) + const [enabled, setEnabled] = NotReact.useState(false) const result = createQuery(key, queryFn, { enabled }) return ( <> @@ -4047,7 +4045,7 @@ describe('useQuery', () => { const states: { state: CreateQueryResult; count: number }[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery(key1, () => 'data', { placeholderData: 'placeholder', @@ -4056,7 +4054,7 @@ describe('useQuery', () => { states.push({ state, count }) - React.useEffect(() => { + NotReact.useEffect(() => { setCount(1) }, []) @@ -4194,7 +4192,7 @@ describe('useQuery', () => { let selectRun = 0 function Page() { - const [count, inc] = React.useReducer((prev) => prev + 1, 2) + const [count, inc] = NotReact.useReducer((prev) => prev + 1, 2) const state = createQuery( key1, @@ -4203,7 +4201,7 @@ describe('useQuery', () => { return 0 }, { - select: React.useCallback( + select: NotReact.useCallback( (data: number) => { selectRun++ return `selected ${data + count}` @@ -4239,8 +4237,11 @@ describe('useQuery', () => { const key1 = queryKey() function Page() { - const [count, inc] = React.useReducer((prev) => prev + 1, 2) - const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1) + const [count, inc] = NotReact.useReducer((prev) => prev + 1, 2) + const [forceValue, forceUpdate] = NotReact.useReducer( + (prev) => prev + 1, + 1, + ) const state = createQuery( key1, @@ -4249,7 +4250,7 @@ describe('useQuery', () => { return 0 }, { - select: React.useCallback( + select: NotReact.useCallback( (data: number) => { return `selected ${data + count}` }, @@ -4290,7 +4291,10 @@ describe('useQuery', () => { const states: Array> = [] function Page() { - const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1) + const [forceValue, forceUpdate] = NotReact.useReducer( + (prev) => prev + 1, + 1, + ) const state = createQuery( key1, @@ -4303,7 +4307,7 @@ describe('useQuery', () => { }, ) - React.useEffect(() => { + NotReact.useEffect(() => { if (state.data) { states.push(state.data) } @@ -4458,14 +4462,14 @@ describe('useQuery', () => { } function Page() { - const [id, setId] = React.useState(1) - const [hasChanged, setHasChanged] = React.useState(false) + const [id, setId] = NotReact.useState(1) + const [hasChanged, setHasChanged] = NotReact.useState(false) const state = createQuery([key, id], queryFn) states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setId((prevId) => (prevId === 1 ? 2 : 1)) setHasChanged(true) }, [hasChanged]) @@ -4651,7 +4655,7 @@ describe('useQuery', () => { } function Page() { - React.useEffect(() => { + NotReact.useEffect(() => { renders++ }) @@ -4693,7 +4697,7 @@ describe('useQuery', () => { } function App() { - const [enabled, toggle] = React.useReducer((x) => !x, true) + const [enabled, toggle] = NotReact.useReducer((x) => !x, true) return (
@@ -4754,7 +4758,7 @@ describe('useQuery', () => { } function App() { - const [id, changeId] = React.useReducer((x) => x + 1, 1) + const [id, changeId] = NotReact.useReducer((x) => x + 1, 1) return (
@@ -4809,7 +4813,7 @@ describe('useQuery', () => { } function App() { - const [value, toggle] = React.useReducer((x) => !x, true) + const [value, toggle] = NotReact.useReducer((x) => !x, true) return (
@@ -4929,7 +4933,7 @@ describe('useQuery', () => { }, }) - React.useEffect(() => { + NotReact.useEffect(() => { states.push(state.fetchStatus) }) @@ -5334,7 +5338,7 @@ describe('useQuery', () => { } function Page() { - const [show, setShow] = React.useState(true) + const [show, setShow] = NotReact.useState(true) return (
@@ -5454,7 +5458,7 @@ describe('useQuery', () => { } function Page() { - const [show, setShow] = React.useState(true) + const [show, setShow] = NotReact.useState(true) return (
From 23d72a15254f1397fdc8e6463d7fa6ca73202fdf Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 13:29:02 -0400 Subject: [PATCH 023/221] change createBaseQuery to use mutate instead of refetch - this resolve an issue where `state` would update an extra time in effects. The first update is from "setState" on the store. The second update is from "refetch" returning after the Promise waits for a single tick. With mutate we can batch "setState" and "refetch" to avoid the tick from the promise. - TBD I'm not sure what the implication of this change is for suspense or error boundaries. --- packages/solid-query/src/createBaseQuery.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index d613f40b55b..3f3f289157b 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -2,7 +2,13 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' import { CreateBaseQueryOptions } from './types' import { useQueryClient } from './QueryClientProvider' -import { onMount, onCleanup, createComputed, createResource } from 'solid-js' +import { + onMount, + onCleanup, + createComputed, + createResource, + batch, +} from 'solid-js' import { createStore } from 'solid-js/store' // Base Query Function that is used to create the query. @@ -33,7 +39,7 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions), ) - const [dataResource, { refetch }] = createResource(() => { + const [dataResource, { mutate }] = createResource(() => { return new Promise((resolve) => { if (state.isSuccess) resolve(state.data) if (state.isError && !state.isFetching) { @@ -44,9 +50,10 @@ export function createBaseQuery< const unsubscribe = observer.subscribe((result) => { const reconciledResult = result - // @ts-ignore - setState(reconciledResult) - refetch() + batch(() => { + setState(reconciledResult) + mutate(() => reconciledResult.data) + }) }) onCleanup(() => unsubscribe()) From 4a2e236bef39684321f2b3fc000aebd4c4254469 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 13:49:31 -0400 Subject: [PATCH 024/221] correct state for successful query working --- .../src/__tests__/createQuery.test.tsx | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 8b14898aad8..7f47f7d9b26 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1,4 +1,4 @@ -import { screen, waitFor, fireEvent } from 'solid-testing-library' +import { screen, waitFor, fireEvent, render } from 'solid-testing-library' import '@testing-library/jest-dom' import { expectType, @@ -17,7 +17,9 @@ import { QueryFunctionContext, CreateQueryOptions, DefinedCreateQueryResult, + QueryClientProvider, } from '..' +import { JSX, Match, Switch, createRenderEffect } from 'solid-js' describe('useQuery', () => { const queryCache = new QueryCache() @@ -200,34 +202,50 @@ describe('useQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - function Page() { + function Page(): JSX.Element { const state = createQuery(key, async () => { await sleep(10) return 'test' }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) if (state.isLoading) { expectType(state.data) expectType(state.error) - return loading - } - - if (state.isLoadingError) { + } else if (state.isLoadingError) { expectType(state.data) expectType(state.error) - return {state.error.message} + } else { + expectType(state.data) + expectType(state.error) } - expectType(state.data) - expectType(state.error) - return {state.data} - } - - const rendered = renderWithClient(queryClient, ) + return ( + + + loading + + + {state.error!.message} + + + {state.data} + + + ) + } + + // renderWithClient(queryClient, () => ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('test')) + await waitFor(() => screen.getByText('test')) expect(states.length).toEqual(2) From aadb48f4172f3e71210dc4adfc0a93e0af13c4d1 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 13:51:53 -0400 Subject: [PATCH 025/221] correct states for incorrect query passing --- .../solid-query/src/__tests__/createQuery.test.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 7f47f7d9b26..3d02961f7d8 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -317,7 +317,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -327,9 +329,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + // renderWithClient(queryClient, () => ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('Status: error')) + await waitFor(() => screen.getByText('Status: error')) expect(states[0]).toEqual({ data: undefined, From 3f160df813ee5b95563ac7d156b99a3fe8276366 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 13:59:11 -0400 Subject: [PATCH 026/221] translate set isFetchedAfterMount --- .../solid-query/src/__tests__/createQuery.test.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 3d02961f7d8..290aafe137b 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -421,15 +421,23 @@ describe('useQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, () => 'prefetched') + // TODO(lukemurray): do we want reactivity on this key? + await queryClient.prefetchQuery(key(), () => 'prefetched') function Page() { const state = createQuery(key, () => 'data') - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + // renderWithClient(queryClient, () => ) + render(() => ( + + + + )) await sleep(10) expect(states.length).toBe(2) From 5ac2c113ca973d807ca088dba163544418bb3881 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 14:19:19 -0400 Subject: [PATCH 027/221] partial conversion of createQuery tests to solid --- .../src/__tests__/createQuery.test.tsx | 1468 ++++++++++++----- 1 file changed, 1032 insertions(+), 436 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 290aafe137b..e7298aed047 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -19,7 +19,15 @@ import { DefinedCreateQueryResult, QueryClientProvider, } from '..' -import { JSX, Match, Switch, createRenderEffect } from 'solid-js' +import { + JSX, + Match, + Switch, + createRenderEffect, + createEffect, + createSignal, + Show, +} from 'solid-js' describe('useQuery', () => { const queryCache = new QueryCache() @@ -191,7 +199,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, () => ) + render(() => ( + + + + )) screen.getByText('default') @@ -238,7 +250,6 @@ describe('useQuery', () => { ) } - // renderWithClient(queryClient, () => ) render(() => ( @@ -329,7 +340,6 @@ describe('useQuery', () => { ) } - // renderWithClient(queryClient, () => ) render(() => ( @@ -432,7 +442,6 @@ describe('useQuery', () => { return null } - // renderWithClient(queryClient, () => ) render(() => ( @@ -468,13 +477,19 @@ describe('useQuery', () => { }, { onSuccess }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return
data: {state.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: data') + await screen.findByText('data: data') expect(states.length).toBe(2) expect(onSuccess).toHaveBeenCalledTimes(1) expect(onSuccess).toHaveBeenCalledWith('data') @@ -497,7 +512,9 @@ describe('useQuery', () => { { onSuccess }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -507,11 +524,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: data1') - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) - await rendered.findByText('data: data2') + await screen.findByText('data: data1') + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await screen.findByText('data: data2') expect(states.length).toBe(3) //loading, success, success after refetch expect(count).toBe(2) @@ -529,20 +550,25 @@ describe('useQuery', () => { onSuccess, }) - states.push(state) - - const { refetch } = state + createRenderEffect(() => { + states.push({ ...state }) + }) - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch setActTimeout(() => { refetch() }, 10) - }, [refetch]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) expect(onSuccess).toHaveBeenCalledTimes(1) @@ -555,13 +581,16 @@ describe('useQuery', () => { const onSuccess = jest.fn() function Page() { - const [show, setShow] = NotReact.useState(true) + const [show, setShow] = createSignal(true) - NotReact.useEffect(() => { + createEffect(() => { setShow(false) - }, [setShow]) - - return show ? : null + }) + return ( + + + + ) } function Component() { @@ -573,11 +602,17 @@ describe('useQuery', () => { }, { onSuccess }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) expect(states.length).toBe(1) @@ -594,11 +629,18 @@ describe('useQuery', () => { retry: false, onError, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) + return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(states.length).toBe(2) @@ -611,7 +653,7 @@ describe('useQuery', () => { const onError = jest.fn() function Page() { - const { status, fetchStatus } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -623,19 +665,21 @@ describe('useQuery', () => { ) return ( - status: {status}, fetchStatus: {fetchStatus} + status: {state.status}, fetchStatus: {state.fetchStatus} ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(5) - await queryClient.cancelQueries(key) + await queryClient.cancelQueries(key()) // query cancellation will reset the query to it's initial state - await waitFor(() => - rendered.getByText('status: loading, fetchStatus: idle'), - ) + await waitFor(() => screen.getByText('status: loading, fetchStatus: idle')) expect(onError).not.toHaveBeenCalled() }) @@ -646,11 +690,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, () => 'data', { onSettled }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(states.length).toBe(2) @@ -668,11 +718,17 @@ describe('useQuery', () => { retry: false, onSettled, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(states.length).toBe(2) @@ -707,7 +763,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) // first refetch only, second refetch is ignored @@ -741,7 +801,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) // first refetch (gets cancelled) and second refetch @@ -775,7 +839,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) // first refetch will not get cancelled, second one gets skipped @@ -790,11 +858,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -834,7 +908,9 @@ describe('useQuery', () => { notifyOnChangeProps: 'all', }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
{state.data}
@@ -842,13 +918,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: 1') + await screen.findByText('data: 1') - fireEvent.click(rendered.getByRole('button', { name: /toggle/i })) + fireEvent.click(screen.getByRole('button', { name: /toggle/i })) - await rendered.findByText('data: 2') + await screen.findByText('data: 2') expect(states.length).toBe(4) // First load @@ -896,7 +976,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { remove } = state @@ -910,7 +992,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -935,11 +1021,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'test', { refetchOnMount: false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -958,11 +1050,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'test', { refetchOnMount: false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -978,11 +1076,17 @@ describe('useQuery', () => { const state = createQuery(key, () => ({ name: 'test' }), { select: (data) => data.name, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -1001,11 +1105,17 @@ describe('useQuery', () => { queryFn: () => ({ name: 'test' }), select: (data) => data.name, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -1024,7 +1134,9 @@ describe('useQuery', () => { notifyOnChangeProps: ['data'], }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -1037,7 +1149,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -1057,11 +1173,17 @@ describe('useQuery', () => { throw error }, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -1098,14 +1220,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('error: Select Error')) + await waitFor(() => screen.getByText('error: Select Error')) expect(runs).toEqual(1) - fireEvent.click(rendered.getByRole('button', { name: 'rerender' })) + fireEvent.click(screen.getByRole('button', { name: 'rerender' })) await sleep(10) expect(runs).toEqual(1) - fireEvent.click(rendered.getByRole('button', { name: 'refetch' })) + fireEvent.click(screen.getByRole('button', { name: 'refetch' })) await sleep(10) expect(runs).toEqual(2) }) @@ -1120,7 +1246,9 @@ describe('useQuery', () => { return 'test' }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch, data } = state @@ -1139,9 +1267,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('test')) + await waitFor(() => screen.getByText('test')) expect(states.length).toBe(2) expect(states[0]).toMatchObject({ data: undefined }) @@ -1156,7 +1288,9 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, () => 'test') - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { renderCount++ @@ -1169,7 +1303,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(renderCount).toBe(2) @@ -1189,7 +1327,9 @@ describe('useQuery', () => { notifyOnChangeProps: 'all', }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { remove } = state @@ -1202,14 +1342,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /remove/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /remove/i })) await sleep(20) - fireEvent.click(rendered.getByRole('button', { name: /rerender/i })) - await waitFor(() => rendered.getByText('data: 2')) + fireEvent.click(screen.getByRole('button', { name: /rerender/i })) + await waitFor(() => screen.getByText('data: 2')) expect(states.length).toBe(4) // Initial @@ -1237,7 +1381,9 @@ describe('useQuery', () => { { notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { remove, refetch } = state @@ -1250,14 +1396,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /remove/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /remove/i })) await sleep(50) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('data: 2')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: 2')) expect(states.length).toBe(4) // Initial @@ -1298,7 +1448,9 @@ describe('useQuery', () => { { notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -1310,12 +1462,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: false')) + await waitFor(() => screen.getByText('data: false')) await sleep(20) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('data: true')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: true')) await waitFor(() => expect(states.length).toBe(4)) @@ -1368,11 +1524,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: set')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('data: fetched')) + await waitFor(() => screen.getByText('data: set')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: fetched')) await waitFor(() => expect(results.length).toBe(3)) @@ -1397,7 +1557,9 @@ describe('useQuery', () => { { staleTime: Infinity, notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -1409,11 +1571,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) - await waitFor(() => rendered.getByText('data: 2')) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) + await waitFor(() => screen.getByText('data: 2')) await waitFor(() => expect(states.length).toBe(4)) @@ -1463,7 +1629,9 @@ describe('useQuery', () => { { enabled: false }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1474,7 +1642,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) @@ -1503,7 +1675,9 @@ describe('useQuery', () => { { enabled: false }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1514,7 +1688,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -1543,7 +1721,9 @@ describe('useQuery', () => { { enabled: count === 0 }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1554,7 +1734,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) @@ -1596,7 +1780,9 @@ describe('useQuery', () => { { keepPreviousData: true }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1607,7 +1793,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states.length).toBe(5)) @@ -1668,7 +1858,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -1679,12 +1871,12 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('data: 0')) - act(() => rendered.rerender()) - await waitFor(() => rendered.getByText('data: 1')) - act(() => rendered.rerender()) - await waitFor(() => rendered.getByText('error: Error test')) + renderWithClient(queryClient, ) + await waitFor(() => screen.getByText('data: 0')) + act(() => screen.rerender()) + await waitFor(() => screen.getByText('data: 1')) + act(() => screen.rerender()) + await waitFor(() => screen.getByText('error: Error test')) await waitFor(() => expect(states.length).toBe(8)) // Initial @@ -1769,7 +1961,9 @@ describe('useQuery', () => { { initialData: 99, keepPreviousData: true }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1780,7 +1974,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states.length).toBe(5)) @@ -1837,7 +2035,9 @@ describe('useQuery', () => { { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -1856,7 +2056,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -1926,7 +2130,9 @@ describe('useQuery', () => { { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -1945,7 +2151,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -2003,7 +2213,9 @@ describe('useQuery', () => { ) const refetch = state.refetch - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -2027,10 +2239,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) await waitFor(() => expect(states.length).toBe(4)) @@ -2100,7 +2316,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(200) @@ -2157,11 +2377,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'test', { staleTime: 50, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -2182,11 +2408,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'test', { staleTime: 10, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) unsubscribe() @@ -2219,7 +2451,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -2231,7 +2465,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(30) @@ -2274,12 +2512,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('First Data: init') - rendered.getByText('Second Data: init') - rendered.getByText('First Status: success') - rendered.getByText('Second Status: success') + screen.getByText('First Data: init') + screen.getByText('Second Data: init') + screen.getByText('First Status: success') + screen.getByText('Second Status: success') }) it('should not override query configuration on render', async () => { @@ -2301,7 +2543,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) expect(queryCache.find(key)!.options.queryFn).toBe(queryFn1) }) @@ -2324,11 +2570,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, () => 'data', { staleTime: Infinity }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) queryClient.setQueryData(key, 'data') await sleep(50) @@ -2357,7 +2609,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) @@ -2397,9 +2653,13 @@ describe('useQuery', () => { return
count: {count}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('count: 2')) + await waitFor(() => screen.getByText('count: 2')) // Should be 2 / 3 instead of 5, uSES batches differently expect(renders).toBe(process.env.REACTJS_VERSION === '17' ? 2 : 3) @@ -2424,9 +2684,13 @@ describe('useQuery', () => { return
{state.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('new')) + await waitFor(() => screen.getByText('new')) }) // See https://github.com/tannerlinsley/react-query/issues/170 @@ -2452,13 +2716,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) // use "act" to wait for state update and prevent console warning - rendered.getByText('First Status: loading, idle') - await waitFor(() => rendered.getByText('Second Status: loading, fetching')) - await waitFor(() => rendered.getByText('Second Status: success, idle')) + screen.getByText('First Status: loading, idle') + await waitFor(() => screen.getByText('Second Status: loading, fetching')) + await waitFor(() => screen.getByText('Second Status: success, idle')) }) // See https://github.com/tannerlinsley/react-query/issues/144 @@ -2474,9 +2742,13 @@ describe('useQuery', () => { return
status: {status}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('status: loading') + screen.getByText('status: loading') }) // See https://github.com/tannerlinsley/react-query/issues/147 @@ -2493,11 +2765,17 @@ describe('useQuery', () => { function Page() { const state = createQuery([key, variables], queryFn) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) @@ -2520,9 +2798,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('default')) + await waitFor(() => screen.getByText('default')) act(() => { window.dispatchEvent(new FocusEvent('focus')) @@ -2541,11 +2823,17 @@ describe('useQuery', () => { staleTime: 0, refetchOnWindowFocus: false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2570,11 +2858,17 @@ describe('useQuery', () => { staleTime: 0, refetchOnWindowFocus: () => false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2599,11 +2893,17 @@ describe('useQuery', () => { staleTime: Infinity, refetchOnWindowFocus: true, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2635,11 +2935,17 @@ describe('useQuery', () => { refetchOnWindowFocus: 'always', }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) @@ -2674,13 +2980,19 @@ describe('useQuery', () => { refetchOnWindowFocus: (query) => (query.state.data || 0) < 1, }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return
data: {String(state.data)}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: 0') + await screen.findByText('data: 0') expect(states.length).toBe(2) expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) @@ -2690,7 +3002,7 @@ describe('useQuery', () => { window.dispatchEvent(new FocusEvent('focus')) }) - await rendered.findByText('data: 1') + await screen.findByText('data: 1') // refetch should happen expect(states.length).toBe(4) @@ -2719,11 +3031,17 @@ describe('useQuery', () => { refetchOnMount: 'always', staleTime: Infinity, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2753,11 +3071,17 @@ describe('useQuery', () => { refetchOnMount: true, staleTime: 0, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2794,10 +3118,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('error')) - await waitFor(() => rendered.getByText('Error test jaylen')) + await waitFor(() => screen.getByText('error')) + await waitFor(() => screen.getByText('Error test jaylen')) }) it('should throw error if queryFn throws and useErrorBoundary is in use', async () => { @@ -2818,14 +3146,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient,
error boundary
}>
, ) - await waitFor(() => rendered.getByText('error boundary')) + await waitFor(() => screen.getByText('error boundary')) }) it('should update with data if we observe no properties and useErrorBoundary', async () => { @@ -2845,7 +3173,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2873,15 +3205,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient,
error boundary
}>
, ) - await waitFor(() => rendered.getByText('error')) - await waitFor(() => rendered.getByText('Local Error')) + await waitFor(() => screen.getByText('error')) + await waitFor(() => screen.getByText('Local Error')) }) it('should throw error instead of setting status when error should be thrown', async () => { @@ -2905,7 +3237,7 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient, ( @@ -2920,8 +3252,8 @@ describe('useQuery', () => { , ) - await waitFor(() => rendered.getByText('error boundary')) - await waitFor(() => rendered.getByText('Remote Error')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('Remote Error')) }) it('should continue retries when observers unmount and remount while waiting for a retry (#3031)', async () => { @@ -2961,13 +3293,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('failureCount: 1')) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) - await waitFor(() => rendered.getByRole('button', { name: /show/i })) - fireEvent.click(rendered.getByRole('button', { name: /show/i })) - await waitFor(() => rendered.getByText('error: some error')) + await waitFor(() => screen.getByText('failureCount: 1')) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) + await waitFor(() => screen.getByRole('button', { name: /show/i })) + fireEvent.click(screen.getByRole('button', { name: /show/i })) + await waitFor(() => screen.getByText('error: some error')) expect(count).toBe(3) }) @@ -3012,14 +3344,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('failureCount: 1')) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) - fireEvent.click(rendered.getByRole('button', { name: /cancel/i })) - await waitFor(() => rendered.getByRole('button', { name: /show/i })) - fireEvent.click(rendered.getByRole('button', { name: /show/i })) - await waitFor(() => rendered.getByText('error: some error')) + await waitFor(() => screen.getByText('failureCount: 1')) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) + fireEvent.click(screen.getByRole('button', { name: /cancel/i })) + await waitFor(() => screen.getByRole('button', { name: /show/i })) + fireEvent.click(screen.getByRole('button', { name: /show/i })) + await waitFor(() => screen.getByText('error: some error')) // initial fetch (1), which will be cancelled, followed by new mount(2) + 2 retries = 4 expect(count).toBe(4) @@ -3036,7 +3368,9 @@ describe('useQuery', () => { refetchOnMount: 'always', staleTime: 50, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
data: {state.data ?? 'null'}
@@ -3046,9 +3380,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data')) + await waitFor(() => screen.getByText('data: data')) await waitFor(() => expect(states.length).toBe(3)) expect(states[0]).toMatchObject({ @@ -3076,11 +3414,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'data', { initialData: 'initial', }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) @@ -3107,11 +3451,17 @@ describe('useQuery', () => { staleTime: 50, initialData: 'initial', }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -3140,11 +3490,17 @@ describe('useQuery', () => { initialData: 'initial', initialDataUpdatedAt: oneSecondAgo, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -3176,11 +3532,17 @@ describe('useQuery', () => { initialData: 'initial', initialDataUpdatedAt: 0, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -3207,7 +3569,9 @@ describe('useQuery', () => { staleTime: Infinity, initialData: () => ({ count }), }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -3218,7 +3582,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -3251,13 +3619,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('loading')) - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('loading')) + await waitFor(() => screen.getByText('error')) // query should fail `retry + 1` times, since first time isn't a "retry" - await waitFor(() => rendered.getByText('Failed 2 times')) + await waitFor(() => screen.getByText('Failed 2 times')) expect(queryFn).toHaveBeenCalledTimes(2) }) @@ -3294,13 +3666,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('loading')) - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('loading')) + await waitFor(() => screen.getByText('error')) - await waitFor(() => rendered.getByText('Failed 2 times')) - await waitFor(() => rendered.getByText('NoRetry')) + await waitFor(() => screen.getByText('Failed 2 times')) + await waitFor(() => screen.getByText('NoRetry')) expect(queryFn).toHaveBeenCalledTimes(2) }) @@ -3329,13 +3705,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(queryFn).toHaveBeenCalledTimes(1) - await waitFor(() => rendered.getByText('Failed 2 times')) + await waitFor(() => screen.getByText('Failed 2 times')) expect(queryFn).toHaveBeenCalledTimes(2) }) @@ -3371,16 +3751,20 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) // The query should display the first error result - await waitFor(() => rendered.getByText('failureCount 1')) - await waitFor(() => rendered.getByText('status loading')) - await waitFor(() => rendered.getByText('error null')) + await waitFor(() => screen.getByText('failureCount 1')) + await waitFor(() => screen.getByText('status loading')) + await waitFor(() => screen.getByText('error null')) // Check if the query really paused await sleep(10) - await waitFor(() => rendered.getByText('failureCount 1')) + await waitFor(() => screen.getByText('failureCount 1')) act(() => { // reset visibilityState to original value @@ -3389,13 +3773,13 @@ describe('useQuery', () => { }) // Wait for the final result - await waitFor(() => rendered.getByText('failureCount 4')) - await waitFor(() => rendered.getByText('status error')) - await waitFor(() => rendered.getByText('error fetching error 4')) + await waitFor(() => screen.getByText('failureCount 4')) + await waitFor(() => screen.getByText('status error')) + await waitFor(() => screen.getByText('error fetching error 4')) // Check if the query really stopped await sleep(10) - await waitFor(() => rendered.getByText('failureCount 4')) + await waitFor(() => screen.getByText('failureCount 4')) // Check if the error has been logged in the console expect(mockLogger.error).toHaveBeenCalledWith('fetching error 4') @@ -3409,11 +3793,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, () => 'data') - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -3447,7 +3837,9 @@ describe('useQuery', () => { await sleep(10) return 'data' }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
{state.data}, {state.isStale}, {state.isFetching} @@ -3455,7 +3847,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states.length).toBe(2)) @@ -3510,11 +3906,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, queryFn) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states.length).toBe(2)) @@ -3547,7 +3949,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(0) @@ -3582,10 +3988,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('failureCount 2')) - await waitFor(() => rendered.getByText('failureCount 0')) + await waitFor(() => screen.getByText('failureCount 2')) + await waitFor(() => screen.getByText('failureCount 0')) }) // See https://github.com/tannerlinsley/react-query/issues/199 @@ -3628,12 +4038,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('isPrefetched')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('isPrefetched')) - fireEvent.click(rendered.getByText('setKey')) - await waitFor(() => rendered.getByText('data: prefetched data')) - await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(screen.getByText('setKey')) + await waitFor(() => screen.getByText('data: prefetched data')) + await waitFor(() => screen.getByText('data: 1')) expect(count).toBe(1) }) @@ -3658,17 +4072,21 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('FetchStatus: idle') - rendered.getByText('Data: no data') + screen.getByText('FetchStatus: idle') + screen.getByText('Data: no data') - fireEvent.click(rendered.getByText('fetch')) + fireEvent.click(screen.getByText('fetch')) - await waitFor(() => rendered.getByText('FetchStatus: fetching')) + await waitFor(() => screen.getByText('FetchStatus: fetching')) await waitFor(() => [ - rendered.getByText('FetchStatus: idle'), - rendered.getByText('Data: data'), + screen.getByText('FetchStatus: idle'), + screen.getByText('Data: data'), ]) }) @@ -3684,7 +4102,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -3703,7 +4125,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -3736,7 +4162,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) expect(results.length).toBe(3) @@ -3759,11 +4189,15 @@ describe('useQuery', () => { return
fetchStatus: {fetchStatus}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) expect(queryFn).not.toHaveBeenCalled() expect(queryCache.find(key)).not.toBeUndefined() - rendered.getByText('fetchStatus: idle') + screen.getByText('fetchStatus: idle') }) // See https://github.com/tannerlinsley/react-query/issues/360 @@ -3784,9 +4218,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('status: loading, idle')) + await waitFor(() => screen.getByText('status: loading, idle')) }) test('should not schedule garbage collection, if cacheTimeout is set to `Infinity`', async () => { @@ -3799,11 +4237,15 @@ describe('useQuery', () => { return
{query.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('fetched data')) + await waitFor(() => screen.getByText('fetched data')) - rendered.unmount() + screen.unmount() const query = queryCache.find(key) // @ts-expect-error @@ -3841,13 +4283,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('status loading')) - await waitFor(() => rendered.getByText('status success')) - fireEvent.click(rendered.getByText('refetch')) - await waitFor(() => rendered.getByText('isFetching true')) - await waitFor(() => rendered.getByText('isFetching false')) + await waitFor(() => screen.getByText('status loading')) + await waitFor(() => screen.getByText('status success')) + fireEvent.click(screen.getByText('refetch')) + await waitFor(() => screen.getByText('isFetching true')) + await waitFor(() => screen.getByText('isFetching false')) expect(queryFn).toHaveBeenCalledTimes(2) expect(memoFn).toHaveBeenCalledTimes(2) }) @@ -3871,12 +4317,16 @@ describe('useQuery', () => { return
count: {data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) // mount - await waitFor(() => rendered.getByText('count: 0')) - await waitFor(() => rendered.getByText('count: 1')) - await waitFor(() => rendered.getByText('count: 2')) + await waitFor(() => screen.getByText('count: 0')) + await waitFor(() => screen.getByText('count: 1')) + await waitFor(() => screen.getByText('count: 2')) }) it('should refetch in an interval depending on function result', async () => { @@ -3908,9 +4358,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('count: 2')) + await waitFor(() => screen.getByText('count: 2')) expect(states.length).toEqual(6) @@ -3962,9 +4416,13 @@ describe('useQuery', () => { return
count: {queryInfo.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('count: 1')) + await waitFor(() => screen.getByText('count: 1')) await sleep(10) //extra sleep to make sure we're not re-fetching @@ -3990,9 +4448,13 @@ describe('useQuery', () => { return <>{JSON.stringify(result.data)} } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('')) + await waitFor(() => screen.getByText('')) }) it('should accept an object as query key', async () => { @@ -4001,9 +4463,13 @@ describe('useQuery', () => { return <>{JSON.stringify(result.data)} } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('[{"a":"a"}]')) + await waitFor(() => screen.getByText('[{"a":"a"}]')) }) it('should refetch if any query instance becomes enabled', async () => { @@ -4028,10 +4494,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) expect(queryFn).toHaveBeenCalledTimes(0) - fireEvent.click(rendered.getByText('enable')) - await waitFor(() => rendered.getByText('data')) + fireEvent.click(screen.getByText('enable')) + await waitFor(() => screen.getByText('data')) expect(queryFn).toHaveBeenCalledTimes(1) }) @@ -4045,7 +4515,9 @@ describe('useQuery', () => { placeholderData: 'placeholder', }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -4055,8 +4527,12 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: data')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: data')) expect(states).toMatchObject([ { @@ -4099,8 +4575,12 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: data')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: data')) expect(states).toMatchObject([ { @@ -4141,7 +4621,9 @@ describe('useQuery', () => { select: (data) => String(data * 2), }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -4151,8 +4633,12 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: 2')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: 2')) expect(states).toMatchObject([ { @@ -4183,7 +4669,9 @@ describe('useQuery', () => { select: (data) => String(data * 2), }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -4193,10 +4681,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: 2')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: 2')) - rendered.rerender() + screen.rerender() expect(states).toMatchObject([ { @@ -4253,16 +4745,20 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: selected 101')) // 99 + 2 + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: selected 101')) // 99 + 2 expect(selectRun).toBe(1) - await waitFor(() => rendered.getByText('Data: selected 2')) // 0 + 2 + await waitFor(() => screen.getByText('Data: selected 2')) // 0 + 2 expect(selectRun).toBe(2) - fireEvent.click(rendered.getByRole('button', { name: /inc/i })) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) - await waitFor(() => rendered.getByText('Data: selected 3')) // 0 + 3 + await waitFor(() => screen.getByText('Data: selected 3')) // 0 + 3 expect(selectRun).toBe(3) }) @@ -4303,20 +4799,24 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: selected 101')) // 99 + 2 + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: selected 101')) // 99 + 2 - await waitFor(() => rendered.getByText('Data: selected 2')) // 0 + 2 + await waitFor(() => screen.getByText('Data: selected 2')) // 0 + 2 - fireEvent.click(rendered.getByRole('button', { name: /inc/i })) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) - await waitFor(() => rendered.getByText('Data: selected 3')) // 0 + 3 + await waitFor(() => screen.getByText('Data: selected 3')) // 0 + 3 - fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i })) + fireEvent.click(screen.getByRole('button', { name: /forceUpdate/i })) - await waitFor(() => rendered.getByText('forceValue: 2')) + await waitFor(() => screen.getByText('forceValue: 2')) // data should still be 3 after an independent re-render - await waitFor(() => rendered.getByText('Data: selected 3')) + await waitFor(() => screen.getByText('Data: selected 3')) }) it('select should structurally share data', async () => { @@ -4355,14 +4855,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: [2,3]')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: [2,3]')) expect(states).toHaveLength(1) - fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i })) + fireEvent.click(screen.getByRole('button', { name: /forceUpdate/i })) - await waitFor(() => rendered.getByText('forceValue: 2')) - await waitFor(() => rendered.getByText('Data: [2,3]')) + await waitFor(() => screen.getByText('forceValue: 2')) + await waitFor(() => screen.getByText('Data: [2,3]')) // effect should not be triggered again due to structural sharing expect(states).toHaveLength(1) @@ -4391,14 +4895,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient, , ) - await waitFor(() => rendered.getByText('off')) + await waitFor(() => screen.getByText('off')) if (typeof AbortSignal === 'function') { expect(cancelFn).toHaveBeenCalled() @@ -4429,7 +4933,7 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient, @@ -4439,7 +4943,7 @@ describe('useQuery', () => { , ) - await waitFor(() => rendered.getByText('off')) + await waitFor(() => screen.getByText('off')) await sleep(20) await waitFor(() => expect(states).toHaveLength(4)) @@ -4500,7 +5004,9 @@ describe('useQuery', () => { const state = createQuery([key, id], queryFn) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setId((prevId) => (prevId === 1 ? 2 : 1)) @@ -4510,7 +5016,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) expect(states.length).toBe(4) @@ -4552,7 +5062,9 @@ describe('useQuery', () => { { staleTime: Infinity }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -4563,14 +5075,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /reset/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) await waitFor(() => expect(states.length).toBe(4)) - await waitFor(() => rendered.getByText('data: 2')) + await waitFor(() => screen.getByText('data: 2')) expect(count).toBe(2) @@ -4620,7 +5136,9 @@ describe('useQuery', () => { { staleTime: Infinity, enabled: false, notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -4633,15 +5151,19 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: null')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: null')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /reset/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) - await waitFor(() => rendered.getByText('data: null')) + await waitFor(() => screen.getByText('data: null')) await waitFor(() => expect(states.length).toBe(4)) expect(count).toBe(1) @@ -4696,7 +5218,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -4742,22 +5268,22 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) // initial state check - rendered.getByText('status: loading') + screen.getByText('status: loading') // // render error state component - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('error')) expect(queryFn).toBeCalledTimes(1) // change to enabled to false - fireEvent.click(rendered.getByLabelText('retry')) - await waitFor(() => rendered.getByText('error')) + fireEvent.click(screen.getByLabelText('retry')) + await waitFor(() => screen.getByText('error')) expect(queryFn).toBeCalledTimes(1) // // change to enabled to true - fireEvent.click(rendered.getByLabelText('retry')) + fireEvent.click(screen.getByLabelText('retry')) expect(queryFn).toBeCalledTimes(2) }) @@ -4803,21 +5329,21 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) // initial state check - rendered.getByText('status: loading') + screen.getByText('status: loading') // render error state component - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('error')) // change to unmount query - fireEvent.click(rendered.getByLabelText('change')) - await waitFor(() => rendered.getByText('rendered')) + fireEvent.click(screen.getByLabelText('change')) + await waitFor(() => screen.getByText('rendered')) // change to mount new query - fireEvent.click(rendered.getByLabelText('change')) - await waitFor(() => rendered.getByText('error')) + fireEvent.click(screen.getByLabelText('change')) + await waitFor(() => screen.getByText('error')) }) it('should refetch when query key changed when switching between erroneous queries', async () => { @@ -4858,23 +5384,23 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) // initial state check - rendered.getByText('status: fetching') + screen.getByText('status: fetching') // render error state component - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('error')) // change to mount second query - fireEvent.click(rendered.getByLabelText('change')) - await waitFor(() => rendered.getByText('status: fetching')) - await waitFor(() => rendered.getByText('error')) + fireEvent.click(screen.getByLabelText('change')) + await waitFor(() => screen.getByText('status: fetching')) + await waitFor(() => screen.getByText('error')) // change to mount first query again - fireEvent.click(rendered.getByLabelText('change')) - await waitFor(() => rendered.getByText('status: fetching')) - await waitFor(() => rendered.getByText('error')) + fireEvent.click(screen.getByLabelText('change')) + await waitFor(() => screen.getByText('status: fetching')) + await waitFor(() => screen.getByText('error')) }) it('should have no error in loading state when refetching after error occurred', async () => { @@ -4900,7 +5426,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) if (state.isLoading) { return
status: loading
@@ -4916,12 +5444,16 @@ describe('useQuery', () => { return
data: {state.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('error')) - fireEvent.click(rendered.getByRole('button', { name: 'refetch' })) - await waitFor(() => rendered.getByText('data: 5')) + fireEvent.click(screen.getByRole('button', { name: 'refetch' })) + await waitFor(() => screen.getByText('data: 5')) await waitFor(() => expect(states.length).toBe(4)) @@ -4980,18 +5512,20 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('status: loading, isPaused: true')) + await waitFor(() => screen.getByText('status: loading, isPaused: true')) onlineMock.mockReturnValue(true) window.dispatchEvent(new Event('online')) - await waitFor(() => - rendered.getByText('status: success, isPaused: false'), - ) + await waitFor(() => screen.getByText('status: success, isPaused: false')) await waitFor(() => { - expect(rendered.getByText('data: data')).toBeInTheDocument() + expect(screen.getByText('data: data')).toBeInTheDocument() }) expect(states).toEqual(['paused', 'fetching', 'idle']) @@ -5029,15 +5563,19 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data1')) + await waitFor(() => screen.getByText('data: data1')) const onlineMock = mockNavigatorOnLine(false) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: success, fetchStatus: paused, failureCount: 0', ), ) @@ -5046,18 +5584,16 @@ describe('useQuery', () => { window.dispatchEvent(new Event('online')) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: success, fetchStatus: fetching, failureCount: 0', ), ) await waitFor(() => - rendered.getByText( - 'status: success, fetchStatus: idle, failureCount: 0', - ), + screen.getByText('status: success, fetchStatus: idle, failureCount: 0'), ) await waitFor(() => { - expect(rendered.getByText('data: data2')).toBeInTheDocument() + expect(screen.getByText('data: data2')).toBeInTheDocument() }) onlineMock.mockRestore() @@ -5092,22 +5628,26 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data1')) + await waitFor(() => screen.getByText('data: data1')) const onlineMock = mockNavigatorOnLine(false) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) window.dispatchEvent(new FocusEvent('focus')) await sleep(15) await waitFor(() => - expect(rendered.queryByText('data: data2')).not.toBeInTheDocument(), + expect(screen.queryByText('data: data2')).not.toBeInTheDocument(), ) expect(count).toBe(1) onlineMock.mockRestore() @@ -5144,19 +5684,23 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: paused'), + screen.getByText('status: loading, fetchStatus: paused'), ) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await sleep(15) // invalidation should not trigger a refetch await waitFor(() => - rendered.getByText('status: loading, fetchStatus: paused'), + screen.getByText('status: loading, fetchStatus: paused'), ) expect(count).toBe(0) @@ -5195,22 +5739,26 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) await waitFor(() => { - expect(rendered.getByText('data: initial')).toBeInTheDocument() + expect(screen.getByText('data: initial')).toBeInTheDocument() }) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await sleep(15) // invalidation should not trigger a refetch await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) expect(count).toBe(0) @@ -5249,22 +5797,26 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) await waitFor(() => { - expect(rendered.getByText('data: initial')).toBeInTheDocument() + expect(screen.getByText('data: initial')).toBeInTheDocument() }) // triggers one pause - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await sleep(15) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) // triggers a second pause @@ -5278,10 +5830,10 @@ describe('useQuery', () => { }) await waitFor(() => - rendered.getByText('status: success, fetchStatus: idle'), + screen.getByText('status: success, fetchStatus: idle'), ) await waitFor(() => { - expect(rendered.getByText('data: data1')).toBeInTheDocument() + expect(screen.getByText('data: data1')).toBeInTheDocument() }) expect(count).toBe(1) @@ -5314,10 +5866,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: loading, fetchStatus: fetching, failureCount: 1', ), ) @@ -5327,7 +5883,7 @@ describe('useQuery', () => { await sleep(20) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: loading, fetchStatus: paused, failureCount: 1', ), ) @@ -5338,7 +5894,7 @@ describe('useQuery', () => { window.dispatchEvent(new Event('online')) await waitFor(() => - rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), + screen.getByText('status: error, fetchStatus: idle, failureCount: 3'), ) expect(count).toBe(3) @@ -5383,13 +5939,17 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: paused'), + screen.getByText('status: loading, fetchStatus: paused'), ) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) onlineMock.mockReturnValue(true) window.dispatchEvent(new Event('online')) @@ -5438,16 +5998,20 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: paused'), + screen.getByText('status: loading, fetchStatus: paused'), ) - fireEvent.click(rendered.getByRole('button', { name: /cancel/i })) + fireEvent.click(screen.getByRole('button', { name: /cancel/i })) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: idle'), + screen.getByText('status: loading, fetchStatus: idle'), ) expect(count).toBe(0) @@ -5458,7 +6022,7 @@ describe('useQuery', () => { await sleep(15) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: idle'), + screen.getByText('status: loading, fetchStatus: idle'), ) expect(count).toBe(0) @@ -5506,21 +6070,25 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: success, fetchStatus: idle'), + screen.getByText('status: success, fetchStatus: idle'), ) const onlineMock = mockNavigatorOnLine(false) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) await sleep(15) @@ -5568,14 +6136,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => - rendered.getByText('status: success, isPaused: false'), - ) + await waitFor(() => screen.getByText('status: success, isPaused: false')) await waitFor(() => { - expect(rendered.getByText('data: data 1')).toBeInTheDocument() + expect(screen.getByText('data: data 1')).toBeInTheDocument() }) onlineMock.mockRestore() @@ -5612,12 +6182,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('status: error, isPaused: false')) + await waitFor(() => screen.getByText('status: error, isPaused: false')) await waitFor(() => { - expect(rendered.getByText('error: error 2')).toBeInTheDocument() + expect(screen.getByText('error: error 2')).toBeInTheDocument() }) expect(count).toBe(2) @@ -5656,10 +6230,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: loading, fetchStatus: paused, failureCount: 1', ), ) @@ -5670,7 +6248,7 @@ describe('useQuery', () => { window.dispatchEvent(new Event('online')) await waitFor(() => - rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), + screen.getByText('status: error, fetchStatus: idle, failureCount: 3'), ) expect(count).toBe(3) @@ -5694,13 +6272,19 @@ describe('useQuery', () => { retryOnMount: false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return <> } await queryClient.prefetchQuery(key, queryFn) - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states).toHaveLength(1)) @@ -5726,11 +6310,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data')) - fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i })) - await waitFor(() => rendered.getByText('data: newData')) + await waitFor(() => screen.getByText('data: data')) + fireEvent.click(screen.getByRole('button', { name: /setQueryData/i })) + await waitFor(() => screen.getByText('data: newData')) expect(onSuccess).toHaveBeenCalledTimes(1) expect(onSuccess).toHaveBeenCalledWith('data') @@ -5756,13 +6344,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data')) - fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i })) - await waitFor(() => rendered.getByText('data: newData')) + await waitFor(() => screen.getByText('data: data')) + fireEvent.click(screen.getByRole('button', { name: /setQueryData/i })) + await waitFor(() => screen.getByText('data: newData')) await waitFor(() => { - expect(rendered.getByText('dataUpdatedAt: 100')).toBeInTheDocument() + expect(screen.getByText('dataUpdatedAt: 100')).toBeInTheDocument() }) }) @@ -5787,12 +6379,16 @@ describe('useQuery', () => {
) } - const rendered = renderWithClient(queryClient, ) - const fetchBtn = rendered.getByRole('button', { name: 'refetch' }) - await waitFor(() => rendered.getByText('data: 1')) + render(() => ( + + + + )) + const fetchBtn = screen.getByRole('button', { name: 'refetch' }) + await waitFor(() => screen.getByText('data: 1')) fireEvent.click(fetchBtn) - await waitFor(() => rendered.getByText('data: 2')) + await waitFor(() => screen.getByText('data: 2')) fireEvent.click(fetchBtn) - await waitFor(() => rendered.getByText('data: 3')) + await waitFor(() => screen.getByText('data: 3')) }) }) From 4e2a6ca8a4e30b8fa4dcf10ebe99212711950ccc Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 15:10:11 -0400 Subject: [PATCH 028/221] replace remaining instances of renderWithClient --- .../src/__tests__/createQuery.test.tsx | 125 +++++++++++------- 1 file changed, 77 insertions(+), 48 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index e7298aed047..8fe2ab488b9 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -8,7 +8,7 @@ import { mockLogger, createQueryClient, } from '../../../../tests/utils' -import { renderWithClient, Blink, queryKey, setActTimeout } from './utils' +import { Blink, queryKey, setActTimeout } from './utils' import { createQuery, CreateQueryResult, @@ -1871,7 +1871,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => screen.getByText('data: 0')) act(() => screen.rerender()) await waitFor(() => screen.getByText('data: 1')) @@ -3146,12 +3150,13 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, -
error boundary
}> - -
, - ) + render(() => ( + +
error boundary
}> + +
+
+ )) await waitFor(() => screen.getByText('error boundary')) }) @@ -3205,12 +3210,13 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, -
error boundary
}> - -
, - ) + render(() => ( + +
error boundary
}> + +
+
+ )) await waitFor(() => screen.getByText('error')) await waitFor(() => screen.getByText('Local Error')) @@ -3237,20 +3243,21 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, - ( -
-
error boundary
- {/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} -
{error?.message}
-
- )} - > - -
, - ) + render(() => ( + + ( +
+
error boundary
+ {/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} +
{error?.message}
+
+ )} + > + +
+
+ )) await waitFor(() => screen.getByText('error boundary')) await waitFor(() => screen.getByText('Remote Error')) @@ -3293,7 +3300,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => screen.getByText('failureCount: 1')) fireEvent.click(screen.getByRole('button', { name: /hide/i })) @@ -3344,7 +3355,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => screen.getByText('failureCount: 1')) fireEvent.click(screen.getByRole('button', { name: /hide/i })) @@ -4895,12 +4910,13 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, - - - , - ) + render(() => ( + + + + + + )) await waitFor(() => screen.getByText('off')) @@ -4933,15 +4949,16 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, - - - - - - , - ) + render(() => ( + + + + + + + + + )) await waitFor(() => screen.getByText('off')) await sleep(20) @@ -5268,7 +5285,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) // initial state check screen.getByText('status: loading') @@ -5329,7 +5350,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) // initial state check screen.getByText('status: loading') @@ -5384,7 +5409,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) // initial state check screen.getByText('status: fetching') From fe69166ff59611f78d9297792b602b8acd54274a Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 15:13:35 -0400 Subject: [PATCH 029/221] replace useQuery with createQuery --- .../solid-query/src/__tests__/createQuery.test.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 8fe2ab488b9..339f9bc619a 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -29,7 +29,7 @@ import { Show, } from 'solid-js' -describe('useQuery', () => { +describe('createQuery', () => { const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) @@ -163,7 +163,7 @@ describe('useQuery', () => { const test = useWrappedQuery([''], async () => '1') expectType(test.data) - // handles wrapped queries with custom fetcher passed directly to useQuery + // handles wrapped queries with custom fetcher passed directly to createQuery const useWrappedFuncStyleQuery = < TQueryKey extends [string, Record?], TQueryFnData, @@ -2337,12 +2337,12 @@ describe('useQuery', () => { data: 'prefetch', isStale: false, }, - // Second useQuery started fetching + // Second createQuery started fetching { data: 'prefetch', isStale: false, }, - // Second useQuery data came in + // Second createQuery data came in { data: 'two', isStale: false, @@ -2360,7 +2360,7 @@ describe('useQuery', () => { data: 'prefetch', isStale: true, }, - // Second useQuery data came in + // Second createQuery data came in { data: 'two', isStale: false, From b5528a2521ba8645b3aefc6a966ec5f69cf5e6c7 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 15:26:50 -0400 Subject: [PATCH 030/221] add comment about excluding tests in tsconfig.json --- packages/solid-query/tsconfig.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json index 6146a991595..ec95ade5cea 100644 --- a/packages/solid-query/tsconfig.json +++ b/packages/solid-query/tsconfig.json @@ -9,7 +9,13 @@ "jsxImportSource": "solid-js", }, "include": ["src"], - "exclude": ["src/__tests__"], + // TODO(lukemurray): if we exclude tests, we get errors about missing react import + // the errors occur because the vscode typescript server only looks at tsconfig.json + // files for type check settings. + // eventually we should remove `jsx: react` from tsconfig.base.json + // but that will require adding `jsx: react` to all package level tsconfig.json + // so lets wait. + // "exclude": ["src/__tests__"], "references": [ { "path": "../query-core" } ] From 9891e87cb31ef937c107dfb00a0739494285b9be Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 15:27:06 -0400 Subject: [PATCH 031/221] translate some more tests in createQuery --- .../src/__tests__/createQuery.test.tsx | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 339f9bc619a..8fab47edecf 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -741,7 +741,7 @@ describe('createQuery', () => { let fetchCount = 0 function Page() { - const { refetch } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -751,14 +751,14 @@ describe('createQuery', () => { { enabled: false, initialData: 'initialData' }, ) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - refetch() + state.refetch() }, 5) setActTimeout(() => { - refetch({ cancelRefetch: false }) + state.refetch({ cancelRefetch: false }) }, 5) - }, [refetch]) + }) return null } @@ -779,7 +779,7 @@ describe('createQuery', () => { let fetchCount = 0 function Page() { - const { refetch } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -789,14 +789,14 @@ describe('createQuery', () => { { enabled: false, initialData: 'initialData' }, ) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - refetch() + state.refetch() }, 5) setActTimeout(() => { - refetch() + state.refetch() }, 5) - }, [refetch]) + }) return null } @@ -817,7 +817,7 @@ describe('createQuery', () => { let fetchCount = 0 function Page() { - const { refetch } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -827,14 +827,14 @@ describe('createQuery', () => { { enabled: false }, ) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - refetch() + state.refetch() }, 5) setActTimeout(() => { - refetch() + state.refetch() }, 5) - }, [refetch]) + }) return null } @@ -854,7 +854,8 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryDefaults(key, { queryFn: () => 'data' }) + // TODO(lukemurray): do we want this to be reactive. + queryClient.setQueryDefaults(key(), { queryFn: () => 'data' }) function Page() { const state = createQuery(key) @@ -882,16 +883,19 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [toggle, setToggle] = NotReact.useState(false) + const [toggle, setToggle] = createSignal(false) return (
- {toggle ? ( - - ) : ( - - )} + + + + + + + +
) } From d32beb8310c2c86c59d6e65f7f0c81893220b62e Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 17:24:31 -0400 Subject: [PATCH 032/221] revert mutate change --- packages/solid-query/src/createBaseQuery.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 3f3f289157b..0104fad717f 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -39,7 +39,7 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions), ) - const [dataResource, { mutate }] = createResource(() => { + const [dataResource, { refetch }] = createResource(() => { return new Promise((resolve) => { if (state.isSuccess) resolve(state.data) if (state.isError && !state.isFetching) { @@ -50,10 +50,8 @@ export function createBaseQuery< const unsubscribe = observer.subscribe((result) => { const reconciledResult = result - batch(() => { - setState(reconciledResult) - mutate(() => reconciledResult.data) - }) + setState(reconciledResult) + refetch() }) onCleanup(() => unsubscribe()) From 0fbe6ea5ad5b334722b76ea77b5cded7f6b311e8 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 18:08:39 -0400 Subject: [PATCH 033/221] add simple example but in typescript --- examples/solid/simple/.eslintrc | 10 + examples/solid/simple/.gitignore | 4 + examples/solid/simple/README.md | 6 + examples/solid/simple/index.html | 16 + examples/solid/simple/package-lock.json | 2479 ++++++++++++++++++ examples/solid/simple/package.json | 22 + examples/solid/simple/src/assets/favicon.ico | Bin 0 -> 15086 bytes examples/solid/simple/src/index.tsx | 53 + examples/solid/simple/tsconfig.json | 15 + examples/solid/simple/vite.config.ts | 15 + packages/solid-query/src/types.ts | 2 +- 11 files changed, 2621 insertions(+), 1 deletion(-) create mode 100644 examples/solid/simple/.eslintrc create mode 100644 examples/solid/simple/.gitignore create mode 100644 examples/solid/simple/README.md create mode 100644 examples/solid/simple/index.html create mode 100644 examples/solid/simple/package-lock.json create mode 100644 examples/solid/simple/package.json create mode 100644 examples/solid/simple/src/assets/favicon.ico create mode 100644 examples/solid/simple/src/index.tsx create mode 100644 examples/solid/simple/tsconfig.json create mode 100644 examples/solid/simple/vite.config.ts diff --git a/examples/solid/simple/.eslintrc b/examples/solid/simple/.eslintrc new file mode 100644 index 00000000000..f40d2bc7f1b --- /dev/null +++ b/examples/solid/simple/.eslintrc @@ -0,0 +1,10 @@ +{ + "parserOptions": { + "project": "./tsconfig.json", + "sourceType": "module" + }, + "rules": { + "react/react-in-jsx-scope": "off", + "jsx-a11y/accessible-emoji": "off" + } +} diff --git a/examples/solid/simple/.gitignore b/examples/solid/simple/.gitignore new file mode 100644 index 00000000000..001e3f924bb --- /dev/null +++ b/examples/solid/simple/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.yalc +yalc.lock \ No newline at end of file diff --git a/examples/solid/simple/README.md b/examples/solid/simple/README.md new file mode 100644 index 00000000000..310f37f62fd --- /dev/null +++ b/examples/solid/simple/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` +- `npm run start` diff --git a/examples/solid/simple/index.html b/examples/solid/simple/index.html new file mode 100644 index 00000000000..48c59fc1242 --- /dev/null +++ b/examples/solid/simple/index.html @@ -0,0 +1,16 @@ + + + + + + + + Solid App + + + +
+ + + + diff --git a/examples/solid/simple/package-lock.json b/examples/solid/simple/package-lock.json new file mode 100644 index 00000000000..beeb2f12554 --- /dev/null +++ b/examples/solid/simple/package-lock.json @@ -0,0 +1,2479 @@ +{ + "name": "@tanstack/query-example-solid-simple", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@tanstack/query-example-solid-simple", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } + }, + ".yalc/@tanstack/solid-query": { + "version": "4.2.3", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/solid-query": { + "version": "4.2.3", + "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "dependencies": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "dependencies": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "dependencies": { + "csstype": "^3.1.0" + } + }, + "node_modules/solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + }, + "peerDependencies": { + "solid-js": "^1.3" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "dependencies": { + "esbuild": "^0.15.6", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + }, + "peerDependencies": { + "solid-js": "^1.3.17", + "vite": "^3.0.0" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true + }, + "@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + } + }, + "@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "requires": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + } + }, + "@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + } + }, + "@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + } + }, + "@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "dev": true, + "optional": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + }, + "@tanstack/solid-query": { + "version": "4.2.3", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "requires": { + "@tanstack/query-core": "4.2.3" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + } + } + }, + "babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "requires": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + } + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "requires": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "requires": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "requires": { + "csstype": "^3.1.0" + } + }, + "solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "requires": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "requires": { + "esbuild": "^0.15.6", + "fsevents": "~2.3.2", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + } + }, + "vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "requires": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + } + } + } +} diff --git a/examples/solid/simple/package.json b/examples/solid/simple/package.json new file mode 100644 index 00000000000..0568cc4e257 --- /dev/null +++ b/examples/solid/simple/package.json @@ -0,0 +1,22 @@ +{ + "name": "@tanstack/query-example-solid-simple", + "private": true, + "version": "0.0.0", + "description": "", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } +} diff --git a/examples/solid/simple/src/assets/favicon.ico b/examples/solid/simple/src/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b836b2bccac650e0e7d90514083add91d2c027ff GIT binary patch literal 15086 zcmeI32Y6Lgw#RQo0Y@EtmA&@a z>%VX~JRB7qO`13ut2?&Tb~rp84oCIs=KCidj&pqWB%^#k=3$2;oFCNVH(cTvg2?Ck zua+_V>;M1%EHI;OjS4~SYCbiyeXWK_$5|a}^+(18cdR{rcBk6ILps&z9{OsXW^?@N zKE>$q&tL)YJ|5J*W^?dPL^gr^&;nW zso#2j*ZLKIX+474)p`W1FCqa*I(V-kh2T{d-Vlwqj>6Uoyeh17Jq2bpw@W<*ZZ)rK zeKo&ZgYOr-)?mfL?hT*&C3FDe6G#^%3dz;>)tKujjTg*<7aMELcjK+EBDytDU`84$ zaI4534b`I8Ux-`UtI^M<12}(;^hFY9cdY$)ZDX;o5fe@u3tlH?u`eQcBQ)LyPP~yl zUJ%S`F|wp*BekSgBek+ml_F zEBZ86EBiJP?CMW{Y^t`5XpxlqPCIt7^8XRL&my5nuB^NJiU}RZcgKWfW3lgYC*H;y z@2Y-a?$=bU2KNVViZoN(N4LDS_bs2{hx4lZ7+D;|B-4-ACs`$5jmh746Q^6e_c8~Jzjt+UELmaWVXW}bbc8_nP zwxZ8E<`;Y3Z%kNtEgM^SHw^bu88bM;zBTwFl;P%MKN*`fwI zd{q=j##+FaI*!CPS_ga}I;5aO+Kg8U zgS;0VGG})&eyepTHIBYvJ-f9Z$eKZi@#t{dilaD}IP%r&OxByMy%f_AVn?xO2DtZ! zbWsQ9bkkS`vtU0m|8=d$!SL7gciIP9hhlN0*Mc*SF0!6$xU-H;{J)7F<(+n4aU?nr zKN3f2#B&BZNNfl`tpj*19qc}k@9v5t=UV8XV|3rtcAw+#-@1$6)S(MLIEN1k>^Zf} zIAVTTlM+J`9}*{m^AI{n3|T%XJ&t58*z(c4?LT0?a-B7!M|f3;9_d{Z9}J2a(`sYv zxYlQhqucT93sz2*d|g%?i4F(QL1NzWfu+OUam1Rj=cB-m*T{3e<*|M7Yw*Ft_@FBI z2ggtGJu7>pi0n0@gU(0A;z-uQ1H@4QF*zUnj}*sJ-uFo}{U1-9;Wrogdm?d?NWM!X z2km1YkbOsTx6ViAS|}-w#OBU8vgIT3ku4wnNG@1G991bV*5cPC2l-V@3i6wW+)fVi zSIO8mMTC5=M{wF^AUa#-yD*CBBE#Bkp(?JJ+h$JyrT=u! z``;b}J2)Q!?`FX)c+-LnyiUxrmx}+9{gM-r17V1~4(+D*FrACguP7g}CrCbuU{8>J z0Rc18OC4F*OMzQ~Tja*k$TyCj{BX$3?AZ67Dvus%v%6G9&brvy#H^nM?3l5w*ij4n zmgF3rk*BLuI3`KT*qb!^caT0ULUSADs5q&gox_0EMofdS>gPh7l&d|zZ^!_Hz~ zZRfHuo3=eHcDCU)Y>b@^8#5YsowyhGQJ=3Ktp0P`WOZTBbYvP5m~|m8@I`lZz{XAY z&*^&285iI^V6*YT;&v_*vokK#QPal97WGlb!278wCsqznXQIZd?6_&_;@%nRLj3!7 z9oA;Y23B%M2WY#;Wr%;7*u{1Zn&i z1%JHL2YK0Xfj!*8pE29t0~<%W#B!N7wy!^1Tv#?X@oL;l!M$pLI<;Y(#(gOG!DFp1Z)unyl-)G`4*#~##d&zO&WklyD?WT~3};gkS3*_)GTz__OeVTWk4B+T7n}$Ir|-v-vIc z*`Edzv;CZTPUCmR2Wt^~|8-eEbz((-b@IcZ#Pv8Zzo#w;=G3_=CvBd}VYK6S(+Bu1 zU>)Mt`8X#ftVd2t_>D_RVJbU5Sbe)QP<_4SZFMSY5-~hMo!U5&n3$}-**;aB+s(S$ z8v@38>Pq@TbtMByUjX*`PW;@yN( z*?R)Zb*2#=xQ7Qm2-iL!9>l&^#pZ(lP>~M|``dJ|`ykCNANgUFxD2e;S@j^Kl#;C~=qpg4YcPu?4vlREFFtjW@SAoefj16j*@9hd5Z zo2-LO_Jd*U2jx1umxQfA#7c@>*%<-V_j|0lP1 zas2Y0IUggJPsX0-@Ihh8>%jCurY#p4J}Asdi})M*r?Qp;utj6=yH#r|36r~@F{cOk z>s-lP6p(vhNd|fJDr@;B;~kw_4=gRjH@C^9dFXfvUmYcHt>K!{Iq4Bi!T*@MbN*bv z2j>&uZUFucjD5gAh`nF{pLYj;EAZF4k{MZr{p_Ki3&X$e`^#ED=|6|#?lHZBQhZ)0 z-yzo>j#)CMI~+bT0#n8U#%hdwt;a0JD!fm(jg`#z6&U4vYxFR$vqrgTKHtkI_qC6} z(C<|+{Y-o>c=VWM+)r@HJTmIf`JH1H?`8Bc$7<$CWl4W-jqHkYokPYfMwlx-vdhan zG*B6%d@lgyIvM4@0#xxI07WkuMSsNv+FmNluwyB9mOicOh%e&o(|VFO|A+qqU#adP zy*>2D)S%a-CE`!-MpybEeCR2tO;5q2Kec+(eQS6GwXgLwb9O@(G3S1IMlLdM9`pXl zytkP5A7TFWF2k?ygd%&D@3bUxb~D zc-^ghjxB2>AtZ<@@miJz$Sv&*8{vmtG&U z&&Q=-#@TyfarX3^z2Jul_c)Yb zQ^GI*un}2}w_bbZ=TZVZ4ZtGCb^bK&uAJP}GoPHYJza;%Y zyms2OFFIPi6VmG;Js!x%W}k<_H5**M@U(HlD+=HGmQOqw$~=?7&-aKO)9MCXjEaUI z-3s>g^e|Ywym0f<4`bKSKA-eDSe*7Iu8o6N6)xG}-F@@HFt98e>>lY|8Gd@R@L9r5 z3lFrHd+dQriG~;20`DvL7jE6+{|!#s;{3hTrco`_jtQ;RKIYZjukeL%ktXMSlzTo? zCWcYoE#RbbW5*R?kZUatClMYe9*%hzyt(klTTL!`2Y6$IyM-T-8oh9A!g*@mfop_A z!4G%fg~paO|IT4v55en22)7!?{iRPrxFq5I1%vRZX`07_7lj89E?9U0iwBlEp45J& zrmlGcxMSfji~P`bJ-U^7zJ=ed35L_sYZ6C)hV%$X?~3NKu&dlp_!G^A%G}In@o!SM zms+UQ&NYV)ALHVOciMeamj2dvaD#pE!(p)gp!*ceI2JofKZn7K8(gO5V&N1l3^E?% zy?n0yAiSUOKLH(XW5Y6I(3)RHVzCO`WJ`Fxu=vTo*CZA-KaU@De}U--&Eui3@Q|Xv z#k-W?hXgRVwI3wU>RdT7$S(|DE=bO#cjQ zKqt9-fACVHkROFhE8=*FZHaFi4<&ZCczstt7<>t}*~9P(CeiN%$mL2gdwxM(`R(biLiISugBeNG&q=%QYjmXU7KAycYs^ zm3m07^jTQ^l?$h$xe0^+xvTbU<9w|8t<><(Y=V1;4G_L$CG|bJ`Ah$U6RCsb=s9hi zh{ZP= zc>(*JMs3~F(OILW#(SLluAX-{^IA1?C+DI$qr`jFIFBvv+XepV2jQqRpH_lh?Q=?9 zS-7dwQ4>^F?E6ODTWa@Guhcbfi*wL6kUH!5vTVRL6~Ec`_S!H0Jd&FAo0>~<*0ZIK zz0_96-Y{OB-4%$gA!hB=wf0_$4Zg+(FO-ELCpEk&HN}e;5<=AZ*qQ3vUDK(T2Qt?* z{r*BiD0OD)rPQrNq;BV|pC`{T_zR1>uyIH5Mg`PrlbOF!S@X+x)IoyfzPhF?wamjS zjd~`vO{q;ujm@P7uItA|^>2$mvDx4Pwbp6Oe_u5;>Q;Y1rxT(db(o@>wytAa^HT?= zc0}E!EF1hc^~R5=mo~l_KfTO-u((aAOAo>ZH$_+KCng5;cd4aY^+WN2)X*&(gnow& z)=~3pjSb4xw}A~RbI&kraN|C0kdMtyf;*gRU!v|;u6gZtK%Yv?-<3Gnh7Gc)Y3ET# z%Etyb`RqEjIZqs<@|y^3)djpybB$Yew$E4EYv!rQyw#~?c{6sTj@6DhY|iIZslolK zwCny^KR4<#{6DLTQdAlWsB&CKvM4nK8!{`MiU;DuXCl=oT~y2GH6;m=St67xsvwn2 zslaC}eShOjdx~>c5dQ|^acd6y$hq{XP`^5pI4_>$ ztXLpt@A=*8s|ED>%fJ1Qa}(#KTbzp~*sqh<%X&6?h5M&*#w(C>y7Ym|*;W3%g`8RC zY_*y*&PM~9scoZMo=TkJ>(XCHA9?>xLp}4>(o--0F2FjA$(cxcs^vT+J;_@+tL)`G zkTBUdY{yVfXZ**FZuu+DSexaUb`Q_AF_Vm*R5{y-NPlV^&-(h@z_T9Dn-_WhcgfE@ zn|t$Yo-5Dg(zC03nxwyybB8?t$n&>656ZJ4eOm>b9eUgCuxq$i1)goY^IW@~XWD$} zv6JUx>CLpBVddFXdU$!(|C;aX+OL<_nR8$BpzkUud4}KZ6wU&vW{;}OE6-md+@la# z#WUD*XEu&;+CZ+S-{yJb8+o2HdOxh*8l$Ji>YZVK%|E?i>=*3QF8$hE^DKQLr>tia zqkqMC&XfIFIQ;)uGm<^>U9-nyS~UBdOV8P7s|HO!zG6V3)njpdxxq)Dj+)4`63-5@ zXG*^UeG2TA`8+SV#M7mu&}Z4}k7cv}id;-&zfUFa%l;$$HG8kzgZ<_XeHusD>$-~W z_CNCDo8+v2Xnqi`meW?dF!{OjbMF<{P`UD{3UW|Gq{d_=bk0*6(lD|z7KWYY7R#*)(qxJUL+mK WLaxim%Fn{v*G + + + ) +} + +function Example() { + const state = createQuery( + () => ['repoData'], + async () => { + const response = await fetch( + 'https://api.github.com/repos/tannerlinsley/react-query', + { + method: 'GET', + }, + ) + return response.json() + }, + ) + + return ( + + Loading... + + {'An error has occurred: ' + (state.error as Error).message} + + +
+

{state.data.name}

+

{state.data.description}

+ 👀 {state.data.subscribers_count}{' '} + ✨ {state.data.stargazers_count}{' '} + 🍴 {state.data.forks_count} +
{state.isFetching ? 'Updating...' : ''}
+
+
+
+ ) +} +render(() => , document.getElementById('root') as HTMLElement) diff --git a/examples/solid/simple/tsconfig.json b/examples/solid/simple/tsconfig.json new file mode 100644 index 00000000000..249b2732a74 --- /dev/null +++ b/examples/solid/simple/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": ["vite/client"], + "noEmit": true, + "isolatedModules": true + } +} diff --git a/examples/solid/simple/vite.config.ts b/examples/solid/simple/vite.config.ts new file mode 100644 index 00000000000..598cdda9083 --- /dev/null +++ b/examples/solid/simple/vite.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite' +import solidPlugin from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solidPlugin()], + server: { + port: 3000, + }, + build: { + target: 'esnext', + }, + resolve: { + preserveSymlinks: true, + }, +}) diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index b5dd4878db6..6fd77e172fd 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context, Accessor } from 'solid-js' +import type { Context } from 'solid-js' import type { QueryClient, QueryKey, From 478201770db7833154a8b44944e4e95b06a4db85 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 18:11:10 -0400 Subject: [PATCH 034/221] add examples to package.json --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d4cd42b82bd..35b8e2ce43d 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,9 @@ "./examples/react/rick-morty", "./examples/react/simple", "./examples/react/star-wars", - "./examples/react/suspense" + "./examples/react/suspense", + "./examples/solid/basic-typescript", + "./examples/solid/simple" ], "devDependencies": { "@babel/core": "^7.17.9", From c5745a2ee5ed9a28387809dc20b4e75f2706b26c Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 18:24:42 -0400 Subject: [PATCH 035/221] add temporary readme documenting examples progress --- examples/solid/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 examples/solid/README.md diff --git a/examples/solid/README.md b/examples/solid/README.md new file mode 100644 index 00000000000..26f35891cde --- /dev/null +++ b/examples/solid/README.md @@ -0,0 +1,22 @@ +# Examples to Add + +- auto-refetching 🚫 nextjs (react only) +- basic 🚫 javascript (only converting typescript) +- basic-graphql-request 🔴 +- basic-typescript 🟢 +- custom-hooks 🚫 not implemented in react +- default-query-function 🔴 +- focus-refetching 🚫 not implemented in react +- load-more-infinite-scroll 🚫 nextjs (react only) +- nextjs 🚫 nextjs (react only) +- offline 🔴 +- optimistic-updates 🚫 not implemented in react +- optimistic-updates-typescript 🚫 nextjs (react only) +- pagination 🚫 nextjs (react only) +- playground 🔴 +- prefetching 🚫 nextjs (react only) +- react-native 🚫 react native (react only) +- rick-morty 🔴 +- simple 🟢 +- star-wars 🔴 +- suspense 🔴 From da98b262990478453fa21dde94c1bc73cc94d3ad Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 18:34:10 -0400 Subject: [PATCH 036/221] add the graphql example --- examples/solid/README.md | 2 +- .../solid/basic-graphql-request/.eslintrc | 10 + .../solid/basic-graphql-request/.gitignore | 4 + .../solid/basic-graphql-request/README.md | 6 + .../solid/basic-graphql-request/index.html | 16 + .../basic-graphql-request/package-lock.json | 2727 +++++++++++++++++ .../solid/basic-graphql-request/package.json | 24 + .../src/assets/favicon.ico | Bin 0 -> 15086 bytes .../solid/basic-graphql-request/src/index.tsx | 168 + .../solid/basic-graphql-request/tsconfig.json | 15 + .../basic-graphql-request/vite.config.ts | 15 + package.json | 3 +- 12 files changed, 2988 insertions(+), 2 deletions(-) create mode 100644 examples/solid/basic-graphql-request/.eslintrc create mode 100644 examples/solid/basic-graphql-request/.gitignore create mode 100644 examples/solid/basic-graphql-request/README.md create mode 100644 examples/solid/basic-graphql-request/index.html create mode 100644 examples/solid/basic-graphql-request/package-lock.json create mode 100644 examples/solid/basic-graphql-request/package.json create mode 100644 examples/solid/basic-graphql-request/src/assets/favicon.ico create mode 100644 examples/solid/basic-graphql-request/src/index.tsx create mode 100644 examples/solid/basic-graphql-request/tsconfig.json create mode 100644 examples/solid/basic-graphql-request/vite.config.ts diff --git a/examples/solid/README.md b/examples/solid/README.md index 26f35891cde..c3433cae739 100644 --- a/examples/solid/README.md +++ b/examples/solid/README.md @@ -2,7 +2,7 @@ - auto-refetching 🚫 nextjs (react only) - basic 🚫 javascript (only converting typescript) -- basic-graphql-request 🔴 +- basic-graphql-request 🟢 - basic-typescript 🟢 - custom-hooks 🚫 not implemented in react - default-query-function 🔴 diff --git a/examples/solid/basic-graphql-request/.eslintrc b/examples/solid/basic-graphql-request/.eslintrc new file mode 100644 index 00000000000..86b22fec59b --- /dev/null +++ b/examples/solid/basic-graphql-request/.eslintrc @@ -0,0 +1,10 @@ +{ + "parserOptions": { + "project": "./tsconfig.json", + "sourceType": "module" + }, + "rules": { + "react/react-in-jsx-scope": "off", + "jsx-a11y/anchor-is-valid": "off" + } +} diff --git a/examples/solid/basic-graphql-request/.gitignore b/examples/solid/basic-graphql-request/.gitignore new file mode 100644 index 00000000000..001e3f924bb --- /dev/null +++ b/examples/solid/basic-graphql-request/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.yalc +yalc.lock \ No newline at end of file diff --git a/examples/solid/basic-graphql-request/README.md b/examples/solid/basic-graphql-request/README.md new file mode 100644 index 00000000000..310f37f62fd --- /dev/null +++ b/examples/solid/basic-graphql-request/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` +- `npm run start` diff --git a/examples/solid/basic-graphql-request/index.html b/examples/solid/basic-graphql-request/index.html new file mode 100644 index 00000000000..48c59fc1242 --- /dev/null +++ b/examples/solid/basic-graphql-request/index.html @@ -0,0 +1,16 @@ + + + + + + + + Solid App + + + +
+ + + + diff --git a/examples/solid/basic-graphql-request/package-lock.json b/examples/solid/basic-graphql-request/package-lock.json new file mode 100644 index 00000000000..58fcf3c6d22 --- /dev/null +++ b/examples/solid/basic-graphql-request/package-lock.json @@ -0,0 +1,2727 @@ +{ + "name": "@tanstack/query-example-solid-basic-graphql-request", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@tanstack/query-example-solid-basic-graphql-request", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "graphql": "^16.6.0", + "graphql-request": "^5.0.0", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } + }, + ".yalc/@tanstack/solid-query": { + "version": "4.2.3", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", + "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/solid-query": { + "version": "4.2.3", + "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "dependencies": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/extract-files": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", + "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==", + "engines": { + "node": "^10.17.0 || ^12.0.0 || >= 13.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/jaydenseric" + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graphql": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", + "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-request": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-5.0.0.tgz", + "integrity": "sha512-SpVEnIo2J5k2+Zf76cUkdvIRaq5FMZvGQYnA4lUWYbc99m+fHh4CZYRRO/Ff4tCLQ613fzCm3SiDT64ubW5Gyw==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "cross-fetch": "^3.1.5", + "extract-files": "^9.0.0", + "form-data": "^3.0.0" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "dependencies": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "dependencies": { + "csstype": "^3.1.0" + } + }, + "node_modules/solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + }, + "peerDependencies": { + "solid-js": "^1.3" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "dependencies": { + "esbuild": "^0.15.6", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + }, + "peerDependencies": { + "solid-js": "^1.3.17", + "vite": "^3.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true + }, + "@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + } + }, + "@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "requires": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + } + }, + "@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + } + }, + "@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + } + }, + "@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "dev": true, + "optional": true + }, + "@graphql-typed-document-node/core": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", + "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==", + "requires": {} + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + }, + "@tanstack/solid-query": { + "version": "4.2.3", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "requires": { + "@tanstack/query-core": "4.2.3" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + } + } + }, + "babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "requires": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + } + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "requires": { + "node-fetch": "2.6.7" + } + }, + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "requires": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "extract-files": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", + "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==" + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graphql": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", + "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==" + }, + "graphql-request": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-5.0.0.tgz", + "integrity": "sha512-SpVEnIo2J5k2+Zf76cUkdvIRaq5FMZvGQYnA4lUWYbc99m+fHh4CZYRRO/Ff4tCLQ613fzCm3SiDT64ubW5Gyw==", + "requires": { + "@graphql-typed-document-node/core": "^3.1.1", + "cross-fetch": "^3.1.5", + "extract-files": "^9.0.0", + "form-data": "^3.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "requires": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "requires": { + "csstype": "^3.1.0" + } + }, + "solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "requires": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "requires": { + "esbuild": "^0.15.6", + "fsevents": "~2.3.2", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + } + }, + "vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "requires": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } +} diff --git a/examples/solid/basic-graphql-request/package.json b/examples/solid/basic-graphql-request/package.json new file mode 100644 index 00000000000..45ab277c6e3 --- /dev/null +++ b/examples/solid/basic-graphql-request/package.json @@ -0,0 +1,24 @@ +{ + "name": "@tanstack/query-example-solid-basic-graphql-request", + "private": true, + "version": "0.0.0", + "description": "", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "graphql": "^16.6.0", + "graphql-request": "^5.0.0", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } +} diff --git a/examples/solid/basic-graphql-request/src/assets/favicon.ico b/examples/solid/basic-graphql-request/src/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b836b2bccac650e0e7d90514083add91d2c027ff GIT binary patch literal 15086 zcmeI32Y6Lgw#RQo0Y@EtmA&@a z>%VX~JRB7qO`13ut2?&Tb~rp84oCIs=KCidj&pqWB%^#k=3$2;oFCNVH(cTvg2?Ck zua+_V>;M1%EHI;OjS4~SYCbiyeXWK_$5|a}^+(18cdR{rcBk6ILps&z9{OsXW^?@N zKE>$q&tL)YJ|5J*W^?dPL^gr^&;nW zso#2j*ZLKIX+474)p`W1FCqa*I(V-kh2T{d-Vlwqj>6Uoyeh17Jq2bpw@W<*ZZ)rK zeKo&ZgYOr-)?mfL?hT*&C3FDe6G#^%3dz;>)tKujjTg*<7aMELcjK+EBDytDU`84$ zaI4534b`I8Ux-`UtI^M<12}(;^hFY9cdY$)ZDX;o5fe@u3tlH?u`eQcBQ)LyPP~yl zUJ%S`F|wp*BekSgBek+ml_F zEBZ86EBiJP?CMW{Y^t`5XpxlqPCIt7^8XRL&my5nuB^NJiU}RZcgKWfW3lgYC*H;y z@2Y-a?$=bU2KNVViZoN(N4LDS_bs2{hx4lZ7+D;|B-4-ACs`$5jmh746Q^6e_c8~Jzjt+UELmaWVXW}bbc8_nP zwxZ8E<`;Y3Z%kNtEgM^SHw^bu88bM;zBTwFl;P%MKN*`fwI zd{q=j##+FaI*!CPS_ga}I;5aO+Kg8U zgS;0VGG})&eyepTHIBYvJ-f9Z$eKZi@#t{dilaD}IP%r&OxByMy%f_AVn?xO2DtZ! zbWsQ9bkkS`vtU0m|8=d$!SL7gciIP9hhlN0*Mc*SF0!6$xU-H;{J)7F<(+n4aU?nr zKN3f2#B&BZNNfl`tpj*19qc}k@9v5t=UV8XV|3rtcAw+#-@1$6)S(MLIEN1k>^Zf} zIAVTTlM+J`9}*{m^AI{n3|T%XJ&t58*z(c4?LT0?a-B7!M|f3;9_d{Z9}J2a(`sYv zxYlQhqucT93sz2*d|g%?i4F(QL1NzWfu+OUam1Rj=cB-m*T{3e<*|M7Yw*Ft_@FBI z2ggtGJu7>pi0n0@gU(0A;z-uQ1H@4QF*zUnj}*sJ-uFo}{U1-9;Wrogdm?d?NWM!X z2km1YkbOsTx6ViAS|}-w#OBU8vgIT3ku4wnNG@1G991bV*5cPC2l-V@3i6wW+)fVi zSIO8mMTC5=M{wF^AUa#-yD*CBBE#Bkp(?JJ+h$JyrT=u! z``;b}J2)Q!?`FX)c+-LnyiUxrmx}+9{gM-r17V1~4(+D*FrACguP7g}CrCbuU{8>J z0Rc18OC4F*OMzQ~Tja*k$TyCj{BX$3?AZ67Dvus%v%6G9&brvy#H^nM?3l5w*ij4n zmgF3rk*BLuI3`KT*qb!^caT0ULUSADs5q&gox_0EMofdS>gPh7l&d|zZ^!_Hz~ zZRfHuo3=eHcDCU)Y>b@^8#5YsowyhGQJ=3Ktp0P`WOZTBbYvP5m~|m8@I`lZz{XAY z&*^&285iI^V6*YT;&v_*vokK#QPal97WGlb!278wCsqznXQIZd?6_&_;@%nRLj3!7 z9oA;Y23B%M2WY#;Wr%;7*u{1Zn&i z1%JHL2YK0Xfj!*8pE29t0~<%W#B!N7wy!^1Tv#?X@oL;l!M$pLI<;Y(#(gOG!DFp1Z)unyl-)G`4*#~##d&zO&WklyD?WT~3};gkS3*_)GTz__OeVTWk4B+T7n}$Ir|-v-vIc z*`Edzv;CZTPUCmR2Wt^~|8-eEbz((-b@IcZ#Pv8Zzo#w;=G3_=CvBd}VYK6S(+Bu1 zU>)Mt`8X#ftVd2t_>D_RVJbU5Sbe)QP<_4SZFMSY5-~hMo!U5&n3$}-**;aB+s(S$ z8v@38>Pq@TbtMByUjX*`PW;@yN( z*?R)Zb*2#=xQ7Qm2-iL!9>l&^#pZ(lP>~M|``dJ|`ykCNANgUFxD2e;S@j^Kl#;C~=qpg4YcPu?4vlREFFtjW@SAoefj16j*@9hd5Z zo2-LO_Jd*U2jx1umxQfA#7c@>*%<-V_j|0lP1 zas2Y0IUggJPsX0-@Ihh8>%jCurY#p4J}Asdi})M*r?Qp;utj6=yH#r|36r~@F{cOk z>s-lP6p(vhNd|fJDr@;B;~kw_4=gRjH@C^9dFXfvUmYcHt>K!{Iq4Bi!T*@MbN*bv z2j>&uZUFucjD5gAh`nF{pLYj;EAZF4k{MZr{p_Ki3&X$e`^#ED=|6|#?lHZBQhZ)0 z-yzo>j#)CMI~+bT0#n8U#%hdwt;a0JD!fm(jg`#z6&U4vYxFR$vqrgTKHtkI_qC6} z(C<|+{Y-o>c=VWM+)r@HJTmIf`JH1H?`8Bc$7<$CWl4W-jqHkYokPYfMwlx-vdhan zG*B6%d@lgyIvM4@0#xxI07WkuMSsNv+FmNluwyB9mOicOh%e&o(|VFO|A+qqU#adP zy*>2D)S%a-CE`!-MpybEeCR2tO;5q2Kec+(eQS6GwXgLwb9O@(G3S1IMlLdM9`pXl zytkP5A7TFWF2k?ygd%&D@3bUxb~D zc-^ghjxB2>AtZ<@@miJz$Sv&*8{vmtG&U z&&Q=-#@TyfarX3^z2Jul_c)Yb zQ^GI*un}2}w_bbZ=TZVZ4ZtGCb^bK&uAJP}GoPHYJza;%Y zyms2OFFIPi6VmG;Js!x%W}k<_H5**M@U(HlD+=HGmQOqw$~=?7&-aKO)9MCXjEaUI z-3s>g^e|Ywym0f<4`bKSKA-eDSe*7Iu8o6N6)xG}-F@@HFt98e>>lY|8Gd@R@L9r5 z3lFrHd+dQriG~;20`DvL7jE6+{|!#s;{3hTrco`_jtQ;RKIYZjukeL%ktXMSlzTo? zCWcYoE#RbbW5*R?kZUatClMYe9*%hzyt(klTTL!`2Y6$IyM-T-8oh9A!g*@mfop_A z!4G%fg~paO|IT4v55en22)7!?{iRPrxFq5I1%vRZX`07_7lj89E?9U0iwBlEp45J& zrmlGcxMSfji~P`bJ-U^7zJ=ed35L_sYZ6C)hV%$X?~3NKu&dlp_!G^A%G}In@o!SM zms+UQ&NYV)ALHVOciMeamj2dvaD#pE!(p)gp!*ceI2JofKZn7K8(gO5V&N1l3^E?% zy?n0yAiSUOKLH(XW5Y6I(3)RHVzCO`WJ`Fxu=vTo*CZA-KaU@De}U--&Eui3@Q|Xv z#k-W?hXgRVwI3wU>RdT7$S(|DE=bO#cjQ zKqt9-fACVHkROFhE8=*FZHaFi4<&ZCczstt7<>t}*~9P(CeiN%$mL2gdwxM(`R(biLiISugBeNG&q=%QYjmXU7KAycYs^ zm3m07^jTQ^l?$h$xe0^+xvTbU<9w|8t<><(Y=V1;4G_L$CG|bJ`Ah$U6RCsb=s9hi zh{ZP= zc>(*JMs3~F(OILW#(SLluAX-{^IA1?C+DI$qr`jFIFBvv+XepV2jQqRpH_lh?Q=?9 zS-7dwQ4>^F?E6ODTWa@Guhcbfi*wL6kUH!5vTVRL6~Ec`_S!H0Jd&FAo0>~<*0ZIK zz0_96-Y{OB-4%$gA!hB=wf0_$4Zg+(FO-ELCpEk&HN}e;5<=AZ*qQ3vUDK(T2Qt?* z{r*BiD0OD)rPQrNq;BV|pC`{T_zR1>uyIH5Mg`PrlbOF!S@X+x)IoyfzPhF?wamjS zjd~`vO{q;ujm@P7uItA|^>2$mvDx4Pwbp6Oe_u5;>Q;Y1rxT(db(o@>wytAa^HT?= zc0}E!EF1hc^~R5=mo~l_KfTO-u((aAOAo>ZH$_+KCng5;cd4aY^+WN2)X*&(gnow& z)=~3pjSb4xw}A~RbI&kraN|C0kdMtyf;*gRU!v|;u6gZtK%Yv?-<3Gnh7Gc)Y3ET# z%Etyb`RqEjIZqs<@|y^3)djpybB$Yew$E4EYv!rQyw#~?c{6sTj@6DhY|iIZslolK zwCny^KR4<#{6DLTQdAlWsB&CKvM4nK8!{`MiU;DuXCl=oT~y2GH6;m=St67xsvwn2 zslaC}eShOjdx~>c5dQ|^acd6y$hq{XP`^5pI4_>$ ztXLpt@A=*8s|ED>%fJ1Qa}(#KTbzp~*sqh<%X&6?h5M&*#w(C>y7Ym|*;W3%g`8RC zY_*y*&PM~9scoZMo=TkJ>(XCHA9?>xLp}4>(o--0F2FjA$(cxcs^vT+J;_@+tL)`G zkTBUdY{yVfXZ**FZuu+DSexaUb`Q_AF_Vm*R5{y-NPlV^&-(h@z_T9Dn-_WhcgfE@ zn|t$Yo-5Dg(zC03nxwyybB8?t$n&>656ZJ4eOm>b9eUgCuxq$i1)goY^IW@~XWD$} zv6JUx>CLpBVddFXdU$!(|C;aX+OL<_nR8$BpzkUud4}KZ6wU&vW{;}OE6-md+@la# z#WUD*XEu&;+CZ+S-{yJb8+o2HdOxh*8l$Ji>YZVK%|E?i>=*3QF8$hE^DKQLr>tia zqkqMC&XfIFIQ;)uGm<^>U9-nyS~UBdOV8P7s|HO!zG6V3)njpdxxq)Dj+)4`63-5@ zXG*^UeG2TA`8+SV#M7mu&}Z4}k7cv}id;-&zfUFa%l;$$HG8kzgZ<_XeHusD>$-~W z_CNCDo8+v2Xnqi`meW?dF!{OjbMF<{P`UD{3UW|Gq{d_=bk0*6(lD|z7KWYY7R#*)(qxJUL+mK WLaxim%Fn{v*G +

+ As you visit the posts below, you will notice them in a loading state + the first time you load them. However, after you return to this list and + click on any posts you have already visited again, you will see them + load instantly and background refresh right before your eyes!{' '} + + (You may need to throttle your network speed to simulate longer + loading sequences) + +

+ {postId() > -1 ? ( + + ) : ( + + )} + + ) +} + +function createPosts() { + return createQuery( + () => ['posts'], + async () => { + const { + posts: { data }, + } = await request( + endpoint, + gql` + query { + posts { + data { + id + title + } + } + } + `, + ) + return data + }, + ) +} + +function Posts(props: { setPostId: Setter }) { + const queryClient = useQueryClient() + const state = createPosts() + + return ( + + ) +} + +function createPost(postId: Accessor) { + return createQuery( + () => ['post', postId()], + async (context) => { + const { post } = await request( + endpoint, + gql` + query { + post(id: ${context.queryKey[1]}) { + id + title + body + } + } + `, + ) + + return post + }, + { + enabled: !!postId, + }, + ) +} + +function Post(props: { postId: number; setPostId: Setter }) { + const state = createPost(() => props.postId) + + return ( +
+ + + + Loading... + + + Error: {(state.error as Error).message} + + + <> +

{state.data.title}

+
+

{state.data.body}

+
+
{state.isFetching ? 'Background Updating...' : ' '}
+ +
+
+
+ ) +} + +render(() => , document.getElementById('root') as HTMLElement) diff --git a/examples/solid/basic-graphql-request/tsconfig.json b/examples/solid/basic-graphql-request/tsconfig.json new file mode 100644 index 00000000000..249b2732a74 --- /dev/null +++ b/examples/solid/basic-graphql-request/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": ["vite/client"], + "noEmit": true, + "isolatedModules": true + } +} diff --git a/examples/solid/basic-graphql-request/vite.config.ts b/examples/solid/basic-graphql-request/vite.config.ts new file mode 100644 index 00000000000..598cdda9083 --- /dev/null +++ b/examples/solid/basic-graphql-request/vite.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite' +import solidPlugin from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solidPlugin()], + server: { + port: 3000, + }, + build: { + target: 'esnext', + }, + resolve: { + preserveSymlinks: true, + }, +}) diff --git a/package.json b/package.json index 35b8e2ce43d..13e6a4c76a4 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,8 @@ "./examples/react/star-wars", "./examples/react/suspense", "./examples/solid/basic-typescript", - "./examples/solid/simple" + "./examples/solid/simple", + "./examples/solid/basic-graphql-request" ], "devDependencies": { "@babel/core": "^7.17.9", From f0f32d571497e638c85280b9583dd76eaa4049ac Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sat, 10 Sep 2022 12:23:16 -0400 Subject: [PATCH 037/221] add default query function example --- examples/solid/README.md | 2 +- .../solid/default-query-function/.eslintrc | 10 + .../solid/default-query-function/.gitignore | 4 + .../solid/default-query-function/README.md | 6 + .../solid/default-query-function/index.html | 16 + .../default-query-function/package-lock.json | 2479 +++++++++++++++++ .../solid/default-query-function/package.json | 22 + .../src/assets/favicon.ico | Bin 0 -> 15086 bytes .../default-query-function/src/index.tsx | 138 + .../default-query-function/tsconfig.json | 15 + .../default-query-function/vite.config.ts | 15 + package.json | 3 +- 12 files changed, 2708 insertions(+), 2 deletions(-) create mode 100644 examples/solid/default-query-function/.eslintrc create mode 100644 examples/solid/default-query-function/.gitignore create mode 100644 examples/solid/default-query-function/README.md create mode 100644 examples/solid/default-query-function/index.html create mode 100644 examples/solid/default-query-function/package-lock.json create mode 100644 examples/solid/default-query-function/package.json create mode 100644 examples/solid/default-query-function/src/assets/favicon.ico create mode 100644 examples/solid/default-query-function/src/index.tsx create mode 100644 examples/solid/default-query-function/tsconfig.json create mode 100644 examples/solid/default-query-function/vite.config.ts diff --git a/examples/solid/README.md b/examples/solid/README.md index c3433cae739..30d1ce8a295 100644 --- a/examples/solid/README.md +++ b/examples/solid/README.md @@ -5,7 +5,7 @@ - basic-graphql-request 🟢 - basic-typescript 🟢 - custom-hooks 🚫 not implemented in react -- default-query-function 🔴 +- default-query-function 🟡 (green styling for cached post not working) - focus-refetching 🚫 not implemented in react - load-more-infinite-scroll 🚫 nextjs (react only) - nextjs 🚫 nextjs (react only) diff --git a/examples/solid/default-query-function/.eslintrc b/examples/solid/default-query-function/.eslintrc new file mode 100644 index 00000000000..86b22fec59b --- /dev/null +++ b/examples/solid/default-query-function/.eslintrc @@ -0,0 +1,10 @@ +{ + "parserOptions": { + "project": "./tsconfig.json", + "sourceType": "module" + }, + "rules": { + "react/react-in-jsx-scope": "off", + "jsx-a11y/anchor-is-valid": "off" + } +} diff --git a/examples/solid/default-query-function/.gitignore b/examples/solid/default-query-function/.gitignore new file mode 100644 index 00000000000..001e3f924bb --- /dev/null +++ b/examples/solid/default-query-function/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.yalc +yalc.lock \ No newline at end of file diff --git a/examples/solid/default-query-function/README.md b/examples/solid/default-query-function/README.md new file mode 100644 index 00000000000..310f37f62fd --- /dev/null +++ b/examples/solid/default-query-function/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` +- `npm run start` diff --git a/examples/solid/default-query-function/index.html b/examples/solid/default-query-function/index.html new file mode 100644 index 00000000000..48c59fc1242 --- /dev/null +++ b/examples/solid/default-query-function/index.html @@ -0,0 +1,16 @@ + + + + + + + + Solid App + + + +
+ + + + diff --git a/examples/solid/default-query-function/package-lock.json b/examples/solid/default-query-function/package-lock.json new file mode 100644 index 00000000000..09f8fa1320d --- /dev/null +++ b/examples/solid/default-query-function/package-lock.json @@ -0,0 +1,2479 @@ +{ + "name": "@tanstack/query-example-solid-default-query-function", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@tanstack/query-example-solid-default-query-function", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } + }, + ".yalc/@tanstack/solid-query": { + "version": "4.2.3", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/solid-query": { + "version": "4.2.3", + "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "dependencies": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "dependencies": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "dependencies": { + "csstype": "^3.1.0" + } + }, + "node_modules/solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + }, + "peerDependencies": { + "solid-js": "^1.3" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "dependencies": { + "esbuild": "^0.15.6", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + }, + "peerDependencies": { + "solid-js": "^1.3.17", + "vite": "^3.0.0" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true + }, + "@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + } + }, + "@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "requires": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + } + }, + "@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + } + }, + "@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + } + }, + "@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "dev": true, + "optional": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + }, + "@tanstack/solid-query": { + "version": "4.2.3", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "requires": { + "@tanstack/query-core": "4.2.3" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + } + } + }, + "babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "requires": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + } + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "requires": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "requires": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "requires": { + "csstype": "^3.1.0" + } + }, + "solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "requires": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "requires": { + "esbuild": "^0.15.6", + "fsevents": "~2.3.2", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + } + }, + "vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "requires": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + } + } + } +} diff --git a/examples/solid/default-query-function/package.json b/examples/solid/default-query-function/package.json new file mode 100644 index 00000000000..a3cbd144f0c --- /dev/null +++ b/examples/solid/default-query-function/package.json @@ -0,0 +1,22 @@ +{ + "name": "@tanstack/query-example-solid-default-query-function", + "private": true, + "version": "0.0.0", + "description": "", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } +} diff --git a/examples/solid/default-query-function/src/assets/favicon.ico b/examples/solid/default-query-function/src/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b836b2bccac650e0e7d90514083add91d2c027ff GIT binary patch literal 15086 zcmeI32Y6Lgw#RQo0Y@EtmA&@a z>%VX~JRB7qO`13ut2?&Tb~rp84oCIs=KCidj&pqWB%^#k=3$2;oFCNVH(cTvg2?Ck zua+_V>;M1%EHI;OjS4~SYCbiyeXWK_$5|a}^+(18cdR{rcBk6ILps&z9{OsXW^?@N zKE>$q&tL)YJ|5J*W^?dPL^gr^&;nW zso#2j*ZLKIX+474)p`W1FCqa*I(V-kh2T{d-Vlwqj>6Uoyeh17Jq2bpw@W<*ZZ)rK zeKo&ZgYOr-)?mfL?hT*&C3FDe6G#^%3dz;>)tKujjTg*<7aMELcjK+EBDytDU`84$ zaI4534b`I8Ux-`UtI^M<12}(;^hFY9cdY$)ZDX;o5fe@u3tlH?u`eQcBQ)LyPP~yl zUJ%S`F|wp*BekSgBek+ml_F zEBZ86EBiJP?CMW{Y^t`5XpxlqPCIt7^8XRL&my5nuB^NJiU}RZcgKWfW3lgYC*H;y z@2Y-a?$=bU2KNVViZoN(N4LDS_bs2{hx4lZ7+D;|B-4-ACs`$5jmh746Q^6e_c8~Jzjt+UELmaWVXW}bbc8_nP zwxZ8E<`;Y3Z%kNtEgM^SHw^bu88bM;zBTwFl;P%MKN*`fwI zd{q=j##+FaI*!CPS_ga}I;5aO+Kg8U zgS;0VGG})&eyepTHIBYvJ-f9Z$eKZi@#t{dilaD}IP%r&OxByMy%f_AVn?xO2DtZ! zbWsQ9bkkS`vtU0m|8=d$!SL7gciIP9hhlN0*Mc*SF0!6$xU-H;{J)7F<(+n4aU?nr zKN3f2#B&BZNNfl`tpj*19qc}k@9v5t=UV8XV|3rtcAw+#-@1$6)S(MLIEN1k>^Zf} zIAVTTlM+J`9}*{m^AI{n3|T%XJ&t58*z(c4?LT0?a-B7!M|f3;9_d{Z9}J2a(`sYv zxYlQhqucT93sz2*d|g%?i4F(QL1NzWfu+OUam1Rj=cB-m*T{3e<*|M7Yw*Ft_@FBI z2ggtGJu7>pi0n0@gU(0A;z-uQ1H@4QF*zUnj}*sJ-uFo}{U1-9;Wrogdm?d?NWM!X z2km1YkbOsTx6ViAS|}-w#OBU8vgIT3ku4wnNG@1G991bV*5cPC2l-V@3i6wW+)fVi zSIO8mMTC5=M{wF^AUa#-yD*CBBE#Bkp(?JJ+h$JyrT=u! z``;b}J2)Q!?`FX)c+-LnyiUxrmx}+9{gM-r17V1~4(+D*FrACguP7g}CrCbuU{8>J z0Rc18OC4F*OMzQ~Tja*k$TyCj{BX$3?AZ67Dvus%v%6G9&brvy#H^nM?3l5w*ij4n zmgF3rk*BLuI3`KT*qb!^caT0ULUSADs5q&gox_0EMofdS>gPh7l&d|zZ^!_Hz~ zZRfHuo3=eHcDCU)Y>b@^8#5YsowyhGQJ=3Ktp0P`WOZTBbYvP5m~|m8@I`lZz{XAY z&*^&285iI^V6*YT;&v_*vokK#QPal97WGlb!278wCsqznXQIZd?6_&_;@%nRLj3!7 z9oA;Y23B%M2WY#;Wr%;7*u{1Zn&i z1%JHL2YK0Xfj!*8pE29t0~<%W#B!N7wy!^1Tv#?X@oL;l!M$pLI<;Y(#(gOG!DFp1Z)unyl-)G`4*#~##d&zO&WklyD?WT~3};gkS3*_)GTz__OeVTWk4B+T7n}$Ir|-v-vIc z*`Edzv;CZTPUCmR2Wt^~|8-eEbz((-b@IcZ#Pv8Zzo#w;=G3_=CvBd}VYK6S(+Bu1 zU>)Mt`8X#ftVd2t_>D_RVJbU5Sbe)QP<_4SZFMSY5-~hMo!U5&n3$}-**;aB+s(S$ z8v@38>Pq@TbtMByUjX*`PW;@yN( z*?R)Zb*2#=xQ7Qm2-iL!9>l&^#pZ(lP>~M|``dJ|`ykCNANgUFxD2e;S@j^Kl#;C~=qpg4YcPu?4vlREFFtjW@SAoefj16j*@9hd5Z zo2-LO_Jd*U2jx1umxQfA#7c@>*%<-V_j|0lP1 zas2Y0IUggJPsX0-@Ihh8>%jCurY#p4J}Asdi})M*r?Qp;utj6=yH#r|36r~@F{cOk z>s-lP6p(vhNd|fJDr@;B;~kw_4=gRjH@C^9dFXfvUmYcHt>K!{Iq4Bi!T*@MbN*bv z2j>&uZUFucjD5gAh`nF{pLYj;EAZF4k{MZr{p_Ki3&X$e`^#ED=|6|#?lHZBQhZ)0 z-yzo>j#)CMI~+bT0#n8U#%hdwt;a0JD!fm(jg`#z6&U4vYxFR$vqrgTKHtkI_qC6} z(C<|+{Y-o>c=VWM+)r@HJTmIf`JH1H?`8Bc$7<$CWl4W-jqHkYokPYfMwlx-vdhan zG*B6%d@lgyIvM4@0#xxI07WkuMSsNv+FmNluwyB9mOicOh%e&o(|VFO|A+qqU#adP zy*>2D)S%a-CE`!-MpybEeCR2tO;5q2Kec+(eQS6GwXgLwb9O@(G3S1IMlLdM9`pXl zytkP5A7TFWF2k?ygd%&D@3bUxb~D zc-^ghjxB2>AtZ<@@miJz$Sv&*8{vmtG&U z&&Q=-#@TyfarX3^z2Jul_c)Yb zQ^GI*un}2}w_bbZ=TZVZ4ZtGCb^bK&uAJP}GoPHYJza;%Y zyms2OFFIPi6VmG;Js!x%W}k<_H5**M@U(HlD+=HGmQOqw$~=?7&-aKO)9MCXjEaUI z-3s>g^e|Ywym0f<4`bKSKA-eDSe*7Iu8o6N6)xG}-F@@HFt98e>>lY|8Gd@R@L9r5 z3lFrHd+dQriG~;20`DvL7jE6+{|!#s;{3hTrco`_jtQ;RKIYZjukeL%ktXMSlzTo? zCWcYoE#RbbW5*R?kZUatClMYe9*%hzyt(klTTL!`2Y6$IyM-T-8oh9A!g*@mfop_A z!4G%fg~paO|IT4v55en22)7!?{iRPrxFq5I1%vRZX`07_7lj89E?9U0iwBlEp45J& zrmlGcxMSfji~P`bJ-U^7zJ=ed35L_sYZ6C)hV%$X?~3NKu&dlp_!G^A%G}In@o!SM zms+UQ&NYV)ALHVOciMeamj2dvaD#pE!(p)gp!*ceI2JofKZn7K8(gO5V&N1l3^E?% zy?n0yAiSUOKLH(XW5Y6I(3)RHVzCO`WJ`Fxu=vTo*CZA-KaU@De}U--&Eui3@Q|Xv z#k-W?hXgRVwI3wU>RdT7$S(|DE=bO#cjQ zKqt9-fACVHkROFhE8=*FZHaFi4<&ZCczstt7<>t}*~9P(CeiN%$mL2gdwxM(`R(biLiISugBeNG&q=%QYjmXU7KAycYs^ zm3m07^jTQ^l?$h$xe0^+xvTbU<9w|8t<><(Y=V1;4G_L$CG|bJ`Ah$U6RCsb=s9hi zh{ZP= zc>(*JMs3~F(OILW#(SLluAX-{^IA1?C+DI$qr`jFIFBvv+XepV2jQqRpH_lh?Q=?9 zS-7dwQ4>^F?E6ODTWa@Guhcbfi*wL6kUH!5vTVRL6~Ec`_S!H0Jd&FAo0>~<*0ZIK zz0_96-Y{OB-4%$gA!hB=wf0_$4Zg+(FO-ELCpEk&HN}e;5<=AZ*qQ3vUDK(T2Qt?* z{r*BiD0OD)rPQrNq;BV|pC`{T_zR1>uyIH5Mg`PrlbOF!S@X+x)IoyfzPhF?wamjS zjd~`vO{q;ujm@P7uItA|^>2$mvDx4Pwbp6Oe_u5;>Q;Y1rxT(db(o@>wytAa^HT?= zc0}E!EF1hc^~R5=mo~l_KfTO-u((aAOAo>ZH$_+KCng5;cd4aY^+WN2)X*&(gnow& z)=~3pjSb4xw}A~RbI&kraN|C0kdMtyf;*gRU!v|;u6gZtK%Yv?-<3Gnh7Gc)Y3ET# z%Etyb`RqEjIZqs<@|y^3)djpybB$Yew$E4EYv!rQyw#~?c{6sTj@6DhY|iIZslolK zwCny^KR4<#{6DLTQdAlWsB&CKvM4nK8!{`MiU;DuXCl=oT~y2GH6;m=St67xsvwn2 zslaC}eShOjdx~>c5dQ|^acd6y$hq{XP`^5pI4_>$ ztXLpt@A=*8s|ED>%fJ1Qa}(#KTbzp~*sqh<%X&6?h5M&*#w(C>y7Ym|*;W3%g`8RC zY_*y*&PM~9scoZMo=TkJ>(XCHA9?>xLp}4>(o--0F2FjA$(cxcs^vT+J;_@+tL)`G zkTBUdY{yVfXZ**FZuu+DSexaUb`Q_AF_Vm*R5{y-NPlV^&-(h@z_T9Dn-_WhcgfE@ zn|t$Yo-5Dg(zC03nxwyybB8?t$n&>656ZJ4eOm>b9eUgCuxq$i1)goY^IW@~XWD$} zv6JUx>CLpBVddFXdU$!(|C;aX+OL<_nR8$BpzkUud4}KZ6wU&vW{;}OE6-md+@la# z#WUD*XEu&;+CZ+S-{yJb8+o2HdOxh*8l$Ji>YZVK%|E?i>=*3QF8$hE^DKQLr>tia zqkqMC&XfIFIQ;)uGm<^>U9-nyS~UBdOV8P7s|HO!zG6V3)njpdxxq)Dj+)4`63-5@ zXG*^UeG2TA`8+SV#M7mu&}Z4}k7cv}id;-&zfUFa%l;$$HG8kzgZ<_XeHusD>$-~W z_CNCDo8+v2Xnqi`meW?dF!{OjbMF<{P`UD{3UW|Gq{d_=bk0*6(lD|z7KWYY7R#*)(qxJUL+mK WLaxim%Fn{v*G = async ({ queryKey }) => { + const response = await fetch( + `https://jsonplaceholder.typicode.com${queryKey[0]}`, + { + method: 'GET', + }, + ) + return response.json() +} + +// provide the default query function to your app via the query client +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + queryFn: defaultQueryFn, + }, + }, +}) + +function App() { + const [postId, setPostId] = createSignal(-1) + + return ( + +

+ As you visit the posts below, you will notice them in a loading state + the first time you load them. However, after you return to this list and + click on any posts you have already visited again, you will see them + load instantly and background refresh right before your eyes!{' '} + + (You may need to throttle your network speed to simulate longer + loading sequences) + +

+ -1} fallback={}> + + +
+ ) +} + +function Posts(props: { setPostId: Setter }) { + const queryClient = useQueryClient() + + // All you have to do now is pass a key! + const state = createQuery(() => ['/posts']) + + return ( +
+

Posts

+ +
+ ) +} + +function Post(props: { postId: number; setPostId: Setter }) { + // You can even leave out the queryFn and just go straight into options + const state = createQuery(() => [`/posts/${props.postId}`], { + enabled: !!props.postId, + }) + + return ( +
+ + + + Loading... + + + Error: {(state.error as Error).message} + + + <> +

{state.data.title}

+
+

{state.data.body}

+
+
{state.isFetching ? 'Background Updating...' : ' '}
+ +
+
+
+ ) +} + +render(() => , document.getElementById('root') as HTMLElement) diff --git a/examples/solid/default-query-function/tsconfig.json b/examples/solid/default-query-function/tsconfig.json new file mode 100644 index 00000000000..249b2732a74 --- /dev/null +++ b/examples/solid/default-query-function/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": ["vite/client"], + "noEmit": true, + "isolatedModules": true + } +} diff --git a/examples/solid/default-query-function/vite.config.ts b/examples/solid/default-query-function/vite.config.ts new file mode 100644 index 00000000000..598cdda9083 --- /dev/null +++ b/examples/solid/default-query-function/vite.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite' +import solidPlugin from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solidPlugin()], + server: { + port: 3000, + }, + build: { + target: 'esnext', + }, + resolve: { + preserveSymlinks: true, + }, +}) diff --git a/package.json b/package.json index 13e6a4c76a4..bee4a979a96 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,8 @@ "./examples/react/suspense", "./examples/solid/basic-typescript", "./examples/solid/simple", - "./examples/solid/basic-graphql-request" + "./examples/solid/basic-graphql-request", + "./examples/solid/default-query-function" ], "devDependencies": { "@babel/core": "^7.17.9", From e1b4e85ab17078a003b8458220cb07d7772ef2b5 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Sat, 10 Sep 2022 12:33:24 -0400 Subject: [PATCH 038/221] chore: update package-lock.json --- package-lock.json | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2e91ecd746f..464b5a19a75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42972,10 +42972,11 @@ } }, "packages/solid-query": { - "version": "4.2.3", + "name": "@tanstack/solid-query", + "version": "4.3.0-beta.4", "license": "MIT", "dependencies": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" }, "devDependencies": { "@types/jscodeshift": "^0.11.3", @@ -42988,15 +42989,6 @@ "peerDependencies": { "solid-js": "^1.5.4" } - }, - "packages/solid-query/node_modules/@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } } }, "dependencies": { @@ -49804,16 +49796,9 @@ "@tanstack/solid-query": { "version": "file:packages/solid-query", "requires": { - "@tanstack/query-core": "4.2.3", + "@tanstack/query-core": "4.3.0-beta.4", "@types/jscodeshift": "^0.11.3", "jscodeshift": "^0.13.1" - }, - "dependencies": { - "@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" - } } }, "@testing-library/dom": { From cf804a1340c9aad25a811bbfa1691cc994a88196 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sat, 10 Sep 2022 18:17:40 -0400 Subject: [PATCH 039/221] Fix eslint config to make it stop complaining --- packages/solid-query/.eslintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc index a1437a22aac..514261e3fc9 100644 --- a/packages/solid-query/.eslintrc +++ b/packages/solid-query/.eslintrc @@ -1,6 +1,6 @@ { "parserOptions": { - "project": "./tsconfig.lint.json", + "project": "./packages/solid-query/tsconfig.lint.json", "sourceType": "module" }, "rules": { From 50f652d9ff3fd9c62d1bd531cd20b338ea9860a0 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sat, 10 Sep 2022 18:23:19 -0400 Subject: [PATCH 040/221] Add createInfiniteQuery --- .../solid-query/src/createInfiniteQuery.ts | 115 ++++++++++++++++++ packages/solid-query/src/index.ts | 33 ++--- packages/solid-query/src/types.ts | 33 ++++- packages/solid-query/src/utils.ts | 22 ++-- 4 files changed, 163 insertions(+), 40 deletions(-) create mode 100644 packages/solid-query/src/createInfiniteQuery.ts diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts new file mode 100644 index 00000000000..608772f4f00 --- /dev/null +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -0,0 +1,115 @@ +import { + QueryObserver, + InfiniteQueryObserver, + QueryFunction, +} from '@tanstack/query-core' +import { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + SolidQueryKey, +} from './types' +import { createBaseQuery } from './createBaseQuery' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' + +export function createInfiniteQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + options: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult +export function createInfiniteQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + options?: Omit< + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' + >, +): CreateInfiniteQueryResult +export function createInfiniteQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + queryFn: QueryFunction>, + options?: Omit< + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' | 'queryFn' + >, +): CreateInfiniteQueryResult +export function createInfiniteQuery< + TQueryFnData, + TError, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + arg1: + | TQueryKey + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg2?: + | QueryFunction> + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg3?: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult { + // The parseQuery Args functions helps normalize the arguments into the correct form. + // Whatever the parameters are, they are normalized into the correct form. + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) + + // Watch for changes in the options and update the parsed options. + createComputed(() => { + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) + + return createBaseQuery( + parsedOptions, + InfiniteQueryObserver as typeof QueryObserver, + ) as CreateInfiniteQueryResult +} diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index d11b5f5de9a..ed83fa58d90 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -1,26 +1,7 @@ -// Re-export core -export * from '@tanstack/query-core' - -// Solid Query -export * from './types' -// export { useQueries } from './useQueries' -// export type { QueriesResults, QueriesOptions } from './useQueries' -export { createQuery } from './createQuery' -export { - QueryClientContext as defaultContext, - QueryClientProvider, - useQueryClient, -} from './QueryClientProvider' -// export type { QueryClientProviderProps } from './QueryClientProvider' -// export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' -// export { useHydrate, Hydrate } from './Hydrate' -// export type { HydrateProps } from './Hydrate' -// export { -// QueryErrorResetBoundary, -// useQueryErrorResetBoundary, -// } from './QueryErrorResetBoundary' -export { useIsFetching } from './useIsFetching' -export { useIsMutating } from './useIsMutating' -export { createMutation } from './createMutation' -// export { useInfiniteQuery } from './useInfiniteQuery' -// export { useIsRestoring, IsRestoringProvider } from './isRestoring' +export * from './createQuery' +export * from './createInfiniteQuery' +export * from './QueryClientProvider' +export * from './createMutation' +export * from './useIsMutating' +export * from './useIsFetching' +export { QueryClient } from '@tanstack/query-core' diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 20ea33fb4a3..bb98e5996ae 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context, Accessor } from 'solid-js' +import type { Context } from 'solid-js' import type { QueryClient, QueryKey, @@ -8,7 +8,10 @@ import type { MutationObserverOptions, MutationObserverResult, DefinedQueryObserverResult, + InfiniteQueryObserverOptions, + InfiniteQueryObserverResult, QueryFilters, + QueryOptions, } from '@tanstack/query-core' export interface ContextOptions { @@ -63,6 +66,34 @@ export type DefinedCreateQueryResult< TError = unknown, > = DefinedCreateBaseQueryResult +export type ParseQueryArgs< + TOptions extends QueryOptions>, + TQueryKey extends () => readonly unknown[] = SolidQueryKey, +> = TOptions['queryKey'] extends () => infer R + ? TOptions & { queryKey: R } + : TOptions + +/* --- Create Infinite Queries Types --- */ +export interface CreateInfiniteQueryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey, +> extends ContextOptions, + InfiniteQueryObserverOptions< + TQueryFnData, + TError, + TData, + TQueryData, + ReturnType + > {} + +export type CreateInfiniteQueryResult< + TData = unknown, + TError = unknown, +> = InfiniteQueryObserverResult + /* --- Create Mutation Types --- */ export interface CreateMutationOptions< TData = unknown, diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index f164bec4454..6dc1f31787d 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,10 +1,10 @@ import { - CreateQueryOptions, SolidQueryKey, SolidQueryFilters, ParseFilterArgs, + ParseQueryArgs, } from './types' -import { QueryFunction } from '@tanstack/query-core' +import { QueryFunction, QueryOptions } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { return typeof value === 'function' @@ -13,17 +13,13 @@ export function isQueryKey(value: unknown): value is SolidQueryKey { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. export function parseQueryArgs< - TQueryFnData, - TError, - TData = TQueryFnData, + TOptions extends QueryOptions>, TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( - arg1: TQueryKey | CreateQueryOptions, - arg2?: - | QueryFunction> - | CreateQueryOptions, - arg3?: CreateQueryOptions, -): CreateQueryOptions { + arg1: TQueryKey | TOptions, + arg2?: QueryFunction> | TOptions, + arg3?: TOptions, +): ParseQueryArgs { if (!isQueryKey(arg1)) { const { queryKey: solidKey, ...opts } = arg1 as any if (solidKey) { @@ -32,7 +28,7 @@ export function parseQueryArgs< queryKey: solidKey(), } } - return arg1 + return arg1 as any } if (typeof arg2 === 'function') { @@ -53,6 +49,6 @@ export function parseFilterArgs< return ( isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1() }, arg3] - : [{ ...arg1, queryKey: arg1?.queryKey?.() } || {}, arg2] + : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] ) as [ParseFilterArgs, TOptions] } From 2238d821fd46ffc481a8e117a4580ac728d71de0 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Sun, 11 Sep 2022 15:38:07 -0400 Subject: [PATCH 041/221] fix: jest tests, copy over React query index file --- packages/solid-query/src/index.ts | 33 ++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index ed83fa58d90..5e5d3c88154 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -1,7 +1,26 @@ -export * from './createQuery' -export * from './createInfiniteQuery' -export * from './QueryClientProvider' -export * from './createMutation' -export * from './useIsMutating' -export * from './useIsFetching' -export { QueryClient } from '@tanstack/query-core' +// Re-export core +export * from '@tanstack/query-core' + +// Solid Query +export * from './types' +// export { useQueries } from './useQueries' +// export type { QueriesResults, QueriesOptions } from './useQueries' +export { createQuery } from './createQuery' +export { + QueryClientContext as defaultContext, + QueryClientProvider, + useQueryClient, +} from './QueryClientProvider' +// export type { QueryClientProviderProps } from './QueryClientProvider' +// export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' +// export { useHydrate, Hydrate } from './Hydrate' +// export type { HydrateProps } from './Hydrate' +// export { +// QueryErrorResetBoundary, +// useQueryErrorResetBoundary, +// } from './QueryErrorResetBoundary' +export { useIsFetching } from './useIsFetching' +export { useIsMutating } from './useIsMutating' +export { createMutation } from './createMutation' +export { createInfiniteQuery } from './createInfiniteQuery' +// export { useIsRestoring, IsRestoringProvider } from './isRestoring' From 1652073f7b4b1417d29405f2122918f8061ac438 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Sun, 11 Sep 2022 16:49:18 -0400 Subject: [PATCH 042/221] fix: resolve data field to value of state when not loading, otherwise return the dataResource to trigger suspense --- packages/solid-query/src/createBaseQuery.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 0104fad717f..3cf13af077f 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -7,7 +7,6 @@ import { onCleanup, createComputed, createResource, - batch, } from 'solid-js' import { createStore } from 'solid-js/store' @@ -49,8 +48,7 @@ export function createBaseQuery< }) const unsubscribe = observer.subscribe((result) => { - const reconciledResult = result - setState(reconciledResult) + setState(result) refetch() }) @@ -71,7 +69,10 @@ export function createBaseQuery< prop: keyof QueryObserverResult, ): any { if (prop === 'data') { - return dataResource() + if (state.isLoading) { + return dataResource() + } + return state.data } return Reflect.get(target, prop) }, From b479cba23fb35d60722abcaf39e9dabe1e38d842 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sat, 10 Sep 2022 14:52:30 -0400 Subject: [PATCH 043/221] add is fetching and is mutating tests --- .../src/__tests__/useIsFetching.test.tsx | 295 ++++++++++++++++++ .../src/__tests__/useIsMutating.test.tsx | 279 +++++++++++++++++ 2 files changed, 574 insertions(+) create mode 100644 packages/solid-query/src/__tests__/useIsFetching.test.tsx create mode 100644 packages/solid-query/src/__tests__/useIsMutating.test.tsx diff --git a/packages/solid-query/src/__tests__/useIsFetching.test.tsx b/packages/solid-query/src/__tests__/useIsFetching.test.tsx new file mode 100644 index 00000000000..fe856ff9ea6 --- /dev/null +++ b/packages/solid-query/src/__tests__/useIsFetching.test.tsx @@ -0,0 +1,295 @@ +import { fireEvent, render, waitFor, screen } from 'solid-testing-library' + +import { + createQueryClient, + setActTimeout, + sleep, +} from '../../../../tests/utils' +import { queryKey } from './utils' +import { createQuery, useIsFetching, QueryCache, QueryClientProvider } from '..' +import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js' + +describe('useIsFetching', () => { + // See https://github.com/tannerlinsley/react-query/issues/105 + it('should update as queries start and stop fetching', async () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + const key = queryKey() + + function IsFetching() { + const isFetching = useIsFetching() + return
isFetching: {isFetching()}
+ } + + function Query() { + const [ready, setReady] = createSignal(false) + + createQuery( + key, + async () => { + await sleep(50) + return 'test' + }, + { + enabled: ready(), + }, + ) + + return + } + + function Page() { + return ( +
+ + +
+ ) + } + + render(() => ( + + + + )) + + await screen.findByText('isFetching: 0') + fireEvent.click(screen.getByRole('button', { name: /setReady/i })) + await screen.findByText('isFetching: 1') + await screen.findByText('isFetching: 0') + }) + + it('should not update state while rendering', async () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + const key1 = queryKey() + const key2 = queryKey() + + const isFetchings: number[] = [] + + function IsFetching() { + const isFetching = useIsFetching() + createRenderEffect(() => { + isFetchings.push(isFetching()) + }) + return null + } + + function FirstQuery() { + createQuery(key1, async () => { + await sleep(100) + return 'data' + }) + return null + } + + function SecondQuery() { + createQuery(key2, async () => { + await sleep(100) + return 'data' + }) + return null + } + + function Page() { + const [renderSecond, setRenderSecond] = createSignal(false) + + createEffect(() => { + setActTimeout(() => { + setRenderSecond(true) + }, 50) + }) + + return ( + <> + + + + + + + ) + } + + render(() => ( + + + + )) + await waitFor(() => expect(isFetchings).toEqual([0, 1, 1, 2, 1, 0])) + }) + + it('should be able to filter', async () => { + const queryClient = createQueryClient() + const key1 = queryKey() + const key2 = queryKey() + + const isFetchings: number[] = [] + + function One() { + createQuery(key1, async () => { + await sleep(10) + return 'test' + }) + return null + } + + function Two() { + createQuery(key2, async () => { + await sleep(20) + return 'test' + }) + return null + } + + function Page() { + const [started, setStarted] = createSignal(false) + const isFetching = useIsFetching(key1) + + createRenderEffect(() => { + isFetchings.push(isFetching()) + }) + + return ( +
+ +
isFetching: {isFetching()}
+ + <> + + + + +
+ ) + } + + render(() => ( + + + + )) + + await screen.findByText('isFetching: 0') + fireEvent.click(screen.getByRole('button', { name: /setStarted/i })) + await screen.findByText('isFetching: 1') + await screen.findByText('isFetching: 0') + // at no point should we have isFetching: 2 + expect(isFetchings).toEqual(expect.not.arrayContaining([2])) + }) + + // TODO(lukemurray): add when we support custom contexts + // describe('with custom context', () => { + // it('should update as queries start and stop fetching', async () => { + // const context = createContext(undefined) + + // const queryCache = new QueryCache() + // const queryClient = createQueryClient({ queryCache }) + // const key = queryKey() + + // function Page() { + // const [ready, setReady] = createSignal(false) + + // const isFetching = useIsFetching(undefined, { context: context }) + + // createQuery( + // key, + // async () => { + // await sleep(50) + // return 'test' + // }, + // { + // enabled: ready(), + // context, + // }, + // ) + + // return ( + //
+ //
isFetching: {isFetching}
+ // + //
+ // ) + // } + + // const { findByText, getByRole } = renderWithClient( + // queryClient, + // , + // { + // context, + // }, + // ) + + // await findByText('isFetching: 0') + // fireEvent.click(getByRole('button', { name: /setReady/i })) + // await findByText('isFetching: 1') + // await findByText('isFetching: 0') + // }) + + // it('should throw if the context is not passed to useIsFetching', async () => { + // const context = React.createContext(undefined) + + // const queryCache = new QueryCache() + // const queryClient = createQueryClient({ queryCache }) + // const key = queryKey() + + // function Page() { + // const isFetching = useIsFetching() + + // createQuery(key, async () => 'test', { + // enabled: true, + // context, + // useErrorBoundary: true, + // }) + + // return ( + //
+ //
isFetching: {isFetching}
+ //
+ // ) + // } + + // const rendered = renderWithClient( + // queryClient, + //
error boundary
}> + // + //
, + // { + // context, + // }, + // ) + + // await waitFor(() => rendered.getByText('error boundary')) + // }) + // }) + + it('should show the correct fetching state when mounted after a query', async () => { + const queryClient = createQueryClient() + const key = queryKey() + + function Page() { + createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + const isFetching = useIsFetching() + + return ( +
+
isFetching: {isFetching()}
+
+ ) + } + + render(() => ( + + + + )) + + await screen.findByText('isFetching: 1') + await screen.findByText('isFetching: 0') + }) +}) diff --git a/packages/solid-query/src/__tests__/useIsMutating.test.tsx b/packages/solid-query/src/__tests__/useIsMutating.test.tsx new file mode 100644 index 00000000000..3a83903c141 --- /dev/null +++ b/packages/solid-query/src/__tests__/useIsMutating.test.tsx @@ -0,0 +1,279 @@ +import { waitFor, fireEvent, screen } from 'solid-testing-library' +import { useIsMutating, createMutation, QueryClientProvider } from '..' +import { createQueryClient, sleep } from '../../../../tests/utils' + +import { setActTimeout } from './utils' +import * as MutationCacheModule from '../../../query-core/src/mutationCache' +import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js' +import { render } from 'solid-testing-library' + +describe('useIsMutating', () => { + it('should return the number of fetching mutations', async () => { + const isMutatings: number[] = [] + const queryClient = createQueryClient() + + function IsMutating() { + const isMutating = useIsMutating() + createRenderEffect(() => { + isMutatings.push(isMutating()) + }) + return null + } + + function Mutations() { + const { mutate: mutate1 } = createMutation(['mutation1'], async () => { + await sleep(150) + return 'data' + }) + const { mutate: mutate2 } = createMutation(['mutation2'], async () => { + await sleep(50) + return 'data' + }) + + createEffect(() => { + mutate1() + setActTimeout(() => { + mutate2() + }, 50) + }) + + return null + } + + function Page() { + return ( +
+ + +
+ ) + } + + render(() => ( + + + + )) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 2, 1, 0])) + }) + + it('should filter correctly by mutationKey', async () => { + const isMutatings: number[] = [] + const queryClient = createQueryClient() + + function IsMutating() { + const isMutating = useIsMutating(['mutation1']) + createRenderEffect(() => { + isMutatings.push(isMutating()) + }) + return null + } + + function Page() { + const { mutate: mutate1 } = createMutation(['mutation1'], async () => { + await sleep(100) + return 'data' + }) + const { mutate: mutate2 } = createMutation(['mutation2'], async () => { + await sleep(100) + return 'data' + }) + + createEffect(() => { + mutate1() + mutate2() + }) + + return + } + + render(() => ( + + + + )) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0])) + }) + + it('should filter correctly by predicate', async () => { + const isMutatings: number[] = [] + const queryClient = createQueryClient() + + function IsMutating() { + const isMutating = useIsMutating({ + predicate: (mutation) => + mutation.options.mutationKey?.[0] === 'mutation1', + }) + createRenderEffect(() => { + isMutatings.push(isMutating()) + }) + return null + } + + function Page() { + const { mutate: mutate1 } = createMutation(['mutation1'], async () => { + await sleep(100) + return 'data' + }) + const { mutate: mutate2 } = createMutation(['mutation2'], async () => { + await sleep(100) + return 'data' + }) + + createEffect(() => { + mutate1() + mutate2() + }) + + return + } + + render(() => ( + + + + )) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0])) + }) + + it('should not change state if unmounted', async () => { + // We have to mock the MutationCache to not unsubscribe + // the listener when the component is unmounted + class MutationCacheMock extends MutationCacheModule.MutationCache { + subscribe(listener: any) { + super.subscribe(listener) + return () => void 0 + } + } + + const MutationCacheSpy = jest + .spyOn(MutationCacheModule, 'MutationCache') + .mockImplementation((fn) => { + return new MutationCacheMock(fn) + }) + + const queryClient = createQueryClient() + + function IsMutating() { + useIsMutating() + return null + } + + function Page() { + const [mounted, setMounted] = createSignal(true) + const { mutate: mutate1 } = createMutation(['mutation1'], async () => { + await sleep(10) + return 'data' + }) + + createEffect(() => { + mutate1() + }) + + return ( +
+ + + + +
+ ) + } + + render(() => ( + + + + )) + fireEvent.click(screen.getByText('unmount')) + + // Should not display the console error + // "Warning: Can't perform a React state update on an unmounted component" + + await sleep(20) + MutationCacheSpy.mockRestore() + }) + + // TODO(lukemurray): re-add when we support custom context. + // describe('with custom context', () => { + // it('should return the number of fetching mutations', async () => { + // const context = React.createContext(undefined) + + // const isMutatings: number[] = [] + // const queryClient = new QueryClient() + + // function IsMutating() { + // const isMutating = useIsMutating(undefined, { context }) + // isMutatings.push(isMutating) + // return null + // } + + // function Page() { + // const { mutate: mutate1 } = useMutation( + // ['mutation1'], + // async () => { + // await sleep(150) + // return 'data' + // }, + // { context }, + // ) + // const { mutate: mutate2 } = useMutation( + // ['mutation2'], + // async () => { + // await sleep(50) + // return 'data' + // }, + // { context }, + // ) + + // React.useEffect(() => { + // mutate1() + // setActTimeout(() => { + // mutate2() + // }, 50) + // }, [mutate1, mutate2]) + + // return + // } + + // renderWithClient(queryClient, , { context }) + // await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0])) + // }) + + // it('should throw if the context is not passed to useIsMutating', async () => { + // const context = React.createContext(undefined) + + // const isMutatings: number[] = [] + // const queryClient = new QueryClient() + + // function IsMutating() { + // const isMutating = useIsMutating(undefined) + // isMutatings.push(isMutating) + // return null + // } + + // function Page() { + // const { mutate } = useMutation(['mutation'], async () => 'data', { + // useErrorBoundary: true, + // context, + // }) + + // React.useEffect(() => { + // mutate() + // }, [mutate]) + + // return + // } + + // const rendered = renderWithClient( + // queryClient, + //
error boundary
}> + // + //
, + // { context }, + // ) + + // await waitFor(() => rendered.getByText('error boundary')) + // }) + // }) +}) From 3fb1bebb2a325449caf179342bb7fa4b12f00b5b Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 12:56:56 -0400 Subject: [PATCH 044/221] update provider to use context sharing --- .../solid-query/src/QueryClientProvider.tsx | 84 ++++--- .../__tests__/QueryClientProvider.test.tsx | 227 +++++++++--------- 2 files changed, 169 insertions(+), 142 deletions(-) diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index 12067d7dee9..9dfd87aaaf4 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -1,12 +1,12 @@ import type { QueryClient } from '@tanstack/query-core' import { - Component, Context, createContext, useContext, JSX, onMount, onCleanup, + mergeProps, } from 'solid-js' import { ContextOptions } from './types' @@ -16,31 +16,16 @@ declare global { } } -export const QueryClientContext = createContext() -export const QueryClientSharingContext = createContext(false) - -interface Props { - client: QueryClient - children: JSX.Element -} - -// Simple Query Client Context Provider -export const QueryClientProvider: Component = (props) => { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime check. - if (!props.client) { - throw new Error('No QueryClient set, use QueryClientProvider to set one') - } - - onMount(() => props.client.mount()) - onCleanup(() => props.client.unmount()) - - return ( - - {props.children} - - ) -} +export const defaultContext = createContext(undefined) +const QueryClientSharingContext = createContext(false) +// If we are given a context, we will use it. +// Otherwise, if contextSharing is on, we share the first and at least one +// instance of the context across the window +// to ensure that if React Query is used across +// different bundles or microfrontends they will +// all use the same **instance** of context, regardless +// of module scoping. function getQueryClientContext( context: Context | undefined, contextSharing: boolean, @@ -48,16 +33,15 @@ function getQueryClientContext( if (context) { return context } - if (contextSharing && typeof window !== 'undefined') { if (!window.SolidQueryClientContext) { - window.SolidQueryClientContext = QueryClientContext + window.SolidQueryClientContext = defaultContext } return window.SolidQueryClientContext } - return QueryClientContext + return defaultContext } export const useQueryClient = ({ context }: ContextOptions = {}) => { @@ -71,3 +55,47 @@ export const useQueryClient = ({ context }: ContextOptions = {}) => { return queryClient } + +type QueryClientProviderPropsBase = { + client: QueryClient + children?: JSX.Element +} +type QueryClientProviderPropsWithContext = ContextOptions & { + contextSharing?: never +} & QueryClientProviderPropsBase +type QueryClientProviderPropsWithContextSharing = { + context?: never + contextSharing?: boolean +} & QueryClientProviderPropsBase + +export type QueryClientProviderProps = + | QueryClientProviderPropsWithContext + | QueryClientProviderPropsWithContextSharing + +export const QueryClientProvider = ( + props: QueryClientProviderProps, +): JSX.Element => { + const mergedProps = mergeProps( + { + contextSharing: false, + }, + props, + ) + onMount(() => mergedProps.client.mount()) + onCleanup(() => mergedProps.client.unmount()) + + const QueryClientContext = getQueryClientContext( + mergedProps.context, + mergedProps.contextSharing, + ) + + return ( + + + {mergedProps.children} + + + ) +} diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx index f5d9786dcae..509fa0400af 100644 --- a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -1,9 +1,11 @@ import { render, screen, waitFor } from 'solid-testing-library' import { queryKey } from './utils' -import { QueryCache } from '@tanstack/query-core' +import { QueryCache, QueryClient } from '@tanstack/query-core' import { createQuery, QueryClientProvider, useQueryClient } from '..' import { createQueryClient, sleep } from '../../../../tests/utils' +import { Context, createContext, useContext } from 'solid-js' +import { renderToString } from 'solid-js/web' describe('QueryClientProvider', () => { test('sets a specific cache for all queries to use', async () => { @@ -131,64 +133,63 @@ describe('QueryClientProvider', () => { expect(queryCache.find(key())?.options.cacheTime).toBe(Infinity) }) - // TODO(lukemurray): add test when we implement context sharing. - // describe('with custom context', () => { - // it('uses the correct context', async () => { - // const key = queryKey() - - // const contextOuter = createContext(undefined) - // const contextInner = createContext(undefined) - - // const queryCacheOuter = new QueryCache() - // const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) - - // const queryCacheInner = new QueryCache() - // const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) - - // const queryCacheInnerInner = new QueryCache() - // const queryClientInnerInner = new QueryClient({ - // queryCache: queryCacheInnerInner, - // }) - - // function Page() { - // const queryOuter = createQuery(key, async () => 'testOuter', { - // context: contextOuter, - // }) - // const queryInner = createQuery(key, async () => 'testInner', { - // context: contextInner, - // }) - // const queryInnerInner = createQuery(key, async () => 'testInnerInner') - - // return ( - //
- //

- // {queryOuter.data} {queryInner.data} {queryInnerInner.data} - //

- //
- // ) - // } - - // // contextSharing should be ignored when passing a custom context. - // const contextSharing = true - - // render(() => ( - // - // - // - // - // - // - // - // )) - - // await waitFor(() => - // screen.getByText('testOuter testInner testInnerInner'), - // ) - // }) - // }) + describe('with custom context', () => { + it('uses the correct context', async () => { + const key = queryKey() + + const contextOuter = createContext(undefined) + const contextInner = createContext(undefined) + + const queryCacheOuter = new QueryCache() + const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) + + const queryCacheInner = new QueryCache() + const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) + + const queryCacheInnerInner = new QueryCache() + const queryClientInnerInner = new QueryClient({ + queryCache: queryCacheInnerInner, + }) + + function Page() { + const queryOuter = createQuery(key, async () => 'testOuter', { + context: contextOuter, + }) + const queryInner = createQuery(key, async () => 'testInner', { + context: contextInner, + }) + const queryInnerInner = createQuery(key, async () => 'testInnerInner') + + return ( +
+

+ {queryOuter.data} {queryInner.data} {queryInnerInner.data} +

+
+ ) + } + + // contextSharing should be ignored when passing a custom context. + const contextSharing = true + + render(() => ( + + + + + + + + )) + + await waitFor(() => + screen.getByText('testOuter testInner testInnerInner'), + ) + }) + }) describe('useQueryClient', () => { test('should throw an error if no query client has been set', () => { @@ -208,60 +209,58 @@ describe('QueryClientProvider', () => { consoleMock.mockRestore() }) - // TODO(lukemurray): add test when we implement context sharing - // test('should use window to get the context when contextSharing is true', () => { - // const queryCache = new QueryCache() - // const queryClient = createQueryClient({ queryCache }) - - // let queryClientFromHook: QueryClient | undefined - // let queryClientFromWindow: QueryClient | undefined - - // function Page() { - // queryClientFromHook = useQueryClient() - // queryClientFromWindow = useContext( - // window.SolidQueryClientContext as Context, - // ) - // return null - // } - - // render(() => ( - // - // - // - // )) - - // expect(queryClientFromHook).toEqual(queryClient) - // expect(queryClientFromWindow).toEqual(queryClient) - // }) - - // TODO(lukemurray): add test when we implement context sharing - // test('should not use window to get the context when contextSharing is true and window does not exist', () => { - // const queryCache = new QueryCache() - // const queryClient = createQueryClient({ queryCache }) - - // // Mock a non web browser environment - // const windowSpy = jest - // .spyOn(window, 'window', 'get') - // .mockImplementation(undefined) - - // let queryClientFromHook: QueryClient | undefined - - // function Page() { - // queryClientFromHook = useQueryClient() - // return null - // } - - // // TODO(lukemurray): this test doesn't pass because the page function is - // // never called. I'm not sure why. - // renderToString(() => ( - // - // - // - // )) - - // expect(queryClientFromHook).toEqual(queryClient) - - // windowSpy.mockRestore() - // }) + test('should use window to get the context when contextSharing is true', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + let queryClientFromHook: QueryClient | undefined + let queryClientFromWindow: QueryClient | undefined + + function Page() { + queryClientFromHook = useQueryClient() + queryClientFromWindow = useContext( + window.SolidQueryClientContext as Context, + ) + return null + } + + render(() => ( + + + + )) + + expect(queryClientFromHook).toEqual(queryClient) + expect(queryClientFromWindow).toEqual(queryClient) + }) + + test('should not use window to get the context when contextSharing is true and window does not exist', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + // Mock a non web browser environment + const windowSpy = jest + .spyOn(window, 'window', 'get') + .mockImplementation(undefined) + + let queryClientFromHook: QueryClient | undefined + + function Page() { + queryClientFromHook = useQueryClient() + return null + } + + // TODO(lukemurray): this test doesn't pass because the page function is + // never called. I'm not sure why. + renderToString(() => ( + + + + )) + + expect(queryClientFromHook).toEqual(queryClient) + + windowSpy.mockRestore() + }) }) }) From 06459d5099387db7efb33f2a461c6181f9fb2a37 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 13:18:31 -0400 Subject: [PATCH 045/221] add error reset boundary --- .../src/QueryErrorResetBoundary.tsx | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 packages/solid-query/src/QueryErrorResetBoundary.tsx diff --git a/packages/solid-query/src/QueryErrorResetBoundary.tsx b/packages/solid-query/src/QueryErrorResetBoundary.tsx new file mode 100644 index 00000000000..a501e7d7ffb --- /dev/null +++ b/packages/solid-query/src/QueryErrorResetBoundary.tsx @@ -0,0 +1,50 @@ +// CONTEXT + +import { createContext, createSignal, useContext, JSX } from 'solid-js' + +interface QueryErrorResetBoundaryValue { + clearReset: () => void + isReset: () => boolean + reset: () => void +} + +function createValue(): QueryErrorResetBoundaryValue { + const [isReset, setIsReset] = createSignal(false) + return { + clearReset: () => { + setIsReset(false) + }, + reset: () => { + setIsReset(true) + }, + isReset: () => { + return isReset() + }, + } +} + +const QueryErrorResetBoundaryContext = createContext(createValue()) + +// HOOK + +export const useQueryErrorResetBoundary = () => + useContext(QueryErrorResetBoundaryContext) + +// COMPONENT + +export interface QueryErrorResetBoundaryProps { + children: ((value: QueryErrorResetBoundaryValue) => JSX.Element) | JSX.Element +} + +export const QueryErrorResetBoundary = ( + props: QueryErrorResetBoundaryProps, +) => { + const [value] = createSignal(createValue()) + return ( + + {typeof props.children === 'function' + ? (props.children as Function)(value) + : props.children} + + ) +} From 05bd8b3624cc1c4699bc0ad6f69205c6f5564b09 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 13:20:01 -0400 Subject: [PATCH 046/221] update package exports --- .../src/__tests__/suspense.test.tsx | 1064 +++++++++++++++++ packages/solid-query/src/index.ts | 14 +- 2 files changed, 1071 insertions(+), 7 deletions(-) create mode 100644 packages/solid-query/src/__tests__/suspense.test.tsx diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx new file mode 100644 index 00000000000..d9d27d618c8 --- /dev/null +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -0,0 +1,1064 @@ +import { waitFor, fireEvent, render, screen } from 'solid-testing-library' + +import { sleep, createQueryClient } from '../../../../tests/utils' +import { queryKey } from './utils' +import { + createQuery, + QueryCache, + QueryErrorResetBoundary, + useQueryErrorResetBoundary, + CreateQueryResult, + CreateInfiniteQueryResult, + createInfiniteQuery, + QueryClientProvider, +} from '..' +import { createSignal, ErrorBoundary, Suspense } from 'solid-js' + +describe("useQuery's in Suspense mode", () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should render the correct amount of times in Suspense mode', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + let count = 0 + let renders = 0 + + function Page() { + renders++ + + const [stateKey, setStateKey] = createSignal(key()) + + const state = createQuery( + stateKey, + async () => { + count++ + await sleep(10) + return count + }, + { suspense: true }, + ) + + states.push(state) + + return ( +
+
+ ) + } + + render(() => ( + + + + + + )) + + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByLabelText('toggle')) + + await waitFor(() => screen.getByText('data: 2')) + + expect(renders).toBe(4) + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: 1, status: 'success' }) + expect(states[1]).toMatchObject({ data: 2, status: 'success' }) + }) + + it('should return the correct states for a successful infinite query', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const [multiplier, setMultiplier] = createSignal(1) + const state = createInfiniteQuery( + () => [`${key}_${multiplier}`], + async ({ pageParam = 1 }) => { + await sleep(10) + return Number(pageParam * multiplier()) + }, + { + suspense: true, + getNextPageParam: (lastPage) => lastPage + 1, + }, + ) + states.push(state) + return ( +
+ + data: {state.data?.pages.join(',')} +
+ ) + } + + render(() => ( + + + + + , + + )) + + await waitFor(() => screen.getByText('data: 1')) + + expect(states.length).toBe(1) + expect(states[0]).toMatchObject({ + data: { pages: [1], pageParams: [undefined] }, + status: 'success', + }) + + fireEvent.click(screen.getByText('next')) + await waitFor(() => screen.getByText('data: 2')) + + expect(states.length).toBe(2) + expect(states[1]).toMatchObject({ + data: { pages: [2], pageParams: [undefined] }, + status: 'success', + }) + }) + + it('should not call the queryFn twice when used in Suspense mode', async () => { + const key = queryKey() + + const queryFn = jest.fn() + queryFn.mockImplementation(() => { + sleep(10) + return 'data' + }) + + function Page() { + createQuery(() => [key()], queryFn, { suspense: true }) + + return <>rendered + } + + render(() => ( + + + + + , + + )) + + await waitFor(() => screen.getByText('rendered')) + + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should remove query instance when component unmounted', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + () => { + sleep(10) + return 'data' + }, + { suspense: true }, + ) + + return <>rendered + } + + function App() { + const [show, setShow] = createSignal(false) + + return ( + <> + {show() && } + +
+ )} + > + + + + + )} + + + )) + + await waitFor(() => screen.getByText('Loading...')) + + await waitFor(() => screen.getByText('error boundary')) + + await waitFor(() => screen.getByText('retry')) + + fireEvent.click(screen.getByText('retry')) + + await waitFor(() => screen.getByText('rendered')) + }) + + it('should retry fetch if the reset error boundary has been reset', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Suspense Error Bingo') + } else { + return 'data' + } + }, + { + retry: false, + suspense: true, + }, + ) + return
rendered
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + + + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('rendered')) + }) + + it('should refetch when re-mounting', async () => { + const key = queryKey() + let count = 0 + + function Component() { + const result = createQuery( + key, + async () => { + await sleep(100) + count++ + return count + }, + { + retry: false, + suspense: true, + staleTime: 0, + }, + ) + return ( +
+ data: {result.data} + fetching: {result.isFetching ? 'true' : 'false'} +
+ ) + } + + function Page() { + const [show, setShow] = createSignal(true) + return ( +
+ + {show() && } +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('data: 1')) + await waitFor(() => screen.getByText('fetching: false')) + await waitFor(() => screen.getByText('hide')) + fireEvent.click(screen.getByText('hide')) + await waitFor(() => screen.getByText('show')) + fireEvent.click(screen.getByText('show')) + await waitFor(() => screen.getByText('fetching: true')) + await waitFor(() => screen.getByText('data: 2')) + await waitFor(() => screen.getByText('fetching: false')) + }) + + it('should suspend when switching to a new query', async () => { + const key1 = queryKey() + const key2 = queryKey() + + function Component(props: { queryKey: Array }) { + const result = createQuery( + () => props.queryKey, + async () => { + await sleep(100) + return props.queryKey + }, + { + retry: false, + suspense: true, + }, + ) + return
data: {result.data}
+ } + + function Page() { + const [key, setKey] = createSignal(key1()) + return ( +
+ + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText(`data: ${key1}`)) + fireEvent.click(screen.getByText('switch')) + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText(`data: ${key2}`)) + expect( + // @ts-expect-error + queryClient.getQueryCache().find(key2)!.observers[0].listeners.length, + ).toBe(1) + }) + + it('should retry fetch if the reset error boundary has been reset with global hook', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Suspense Error Bingo') + } else { + return 'data' + } + }, + { + retry: false, + suspense: true, + }, + ) + return
rendered
+ } + + function App() { + const { reset: resetQuery } = useQueryErrorResetBoundary() + return ( + ( +
+
error boundary
+ +
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('rendered')) + }) + + it('should throw errors to the error boundary by default', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + async (): Promise => { + await sleep(10) + throw new Error('Suspense Error a1x') + }, + { + retry: false, + suspense: true, + }, + ) + return
rendered
+ } + + function App() { + return ( + ( +
+
error boundary
+
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should not throw errors to the error boundary when useErrorBoundary: false', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + async (): Promise => { + await sleep(10) + throw new Error('Suspense Error a2x') + }, + { + retry: false, + suspense: true, + useErrorBoundary: false, + }, + ) + return
rendered
+ } + + function App() { + return ( + ( +
+
error boundary
+
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('rendered')) + }) + + it('should not throw errors to the error boundary when a useErrorBoundary function returns true', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + async (): Promise => { + await sleep(10) + return Promise.reject('Remote Error') + }, + { + retry: false, + suspense: true, + useErrorBoundary: (err) => err !== 'Local Error', + }, + ) + return
rendered
+ } + + function App() { + return ( + ( +
+
error boundary
+
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should not throw errors to the error boundary when a useErrorBoundary function returns false', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + async (): Promise => { + await sleep(10) + return Promise.reject('Local Error') + }, + { + retry: false, + suspense: true, + useErrorBoundary: (err) => err !== 'Local Error', + }, + ) + return
rendered
+ } + + function App() { + return ( + ( +
+
error boundary
+
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('rendered')) + }) + + it('should not call the queryFn when not enabled', async () => { + const key = queryKey() + + const queryFn = jest.fn, unknown[]>() + queryFn.mockImplementation(async () => { + await sleep(10) + return '23' + }) + + function Page() { + const [enabled, setEnabled] = createSignal(false) + const result = createQuery(() => [key()], queryFn, { + suspense: true, + enabled: enabled(), + }) + + return ( +
+ +

{result.data}

+
+ ) + } + + render(() => ( + + + + + + )) + + expect(queryFn).toHaveBeenCalledTimes(0) + + fireEvent.click(screen.getByRole('button', { name: /fire/i })) + + await waitFor(() => { + expect(screen.getByRole('heading').textContent).toBe('23') + }) + + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should error catched in error boundary without infinite loop', async () => { + const key = queryKey() + + let succeed = true + + function Page() { + const [nonce] = createSignal(0) + const queryKeys = () => [`${key()}-${succeed}`] + const result = createQuery( + queryKeys, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Suspense Error Bingo') + } else { + return nonce + } + }, + { + retry: false, + suspense: true, + }, + ) + return ( +
+ rendered {result.data} + +
+ ) + } + + function App() { + const { reset } = useQueryErrorResetBoundary() + return ( +
error boundary
}> + + + +
+ ) + } + + render(() => ( + + + + )) + + // render suspense fallback (Loading...) + await waitFor(() => screen.getByText('Loading...')) + // resolve promise -> render Page (rendered) + await waitFor(() => screen.getByText('rendered')) + + // change query key + succeed = false + // reset query -> and throw error + fireEvent.click(screen.getByLabelText('fail')) + // render error boundary fallback (error boundary) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should error catched in error boundary without infinite loop when query keys changed', async () => { + let succeed = true + + function Page() { + const [key, rerender] = React.useReducer((x) => x + 1, 0) + const queryKeys = [key, succeed] + + const result = createQuery( + queryKeys, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Suspense Error Bingo') + } else { + return 'data' + } + }, + { + retry: false, + suspense: true, + }, + ) + return ( +
+ rendered {result.data} + +
+ ) + } + + function App() { + const { reset } = useQueryErrorResetBoundary() + return ( +
error boundary
}> + + + +
+ ) + } + + render(() => ( + + + + )) + + // render suspense fallback (Loading...) + await waitFor(() => screen.getByText('Loading...')) + // resolve promise -> render Page (rendered) + await waitFor(() => screen.getByText('rendered')) + + // change promise result to error + succeed = false + // change query key + fireEvent.click(screen.getByLabelText('fail')) + // render error boundary fallback (error boundary) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should error catched in error boundary without infinite loop when enabled changed', async () => { + function Page() { + const queryKeys = '1' + const [enabled, setEnabled] = createSignal(false) + + const result = createQuery( + () => [queryKeys], + async () => { + await sleep(10) + throw new Error('Suspense Error Bingo') + }, + { + retry: false, + suspense: true, + enabled: enabled(), + }, + ) + return ( +
+ rendered {result.data} + +
+ ) + } + + function App() { + const { reset } = useQueryErrorResetBoundary() + return ( +
error boundary
}> + + + +
+ ) + } + + render(() => ( + + + + )) + + // render empty data with 'rendered' when enabled is false + await waitFor(() => screen.getByText('rendered')) + + // change enabled to true + fireEvent.click(screen.getByLabelText('fail')) + + // render pending fallback + await waitFor(() => screen.getByText('Loading...')) + + // render error boundary fallback (error boundary) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should render the correct amount of times in Suspense mode when cacheTime is set to 0', async () => { + const key = queryKey() + let state: CreateQueryResult | null = null + + let count = 0 + let renders = 0 + + function Page() { + renders++ + + state = createQuery( + key, + async () => { + count++ + await sleep(10) + return count + }, + { suspense: true, cacheTime: 0 }, + ) + + return ( +
+ rendered +
+ ) + } + + render(() => ( + + + + + + )) + + await waitFor(() => + expect(state).toMatchObject({ + data: 1, + status: 'success', + }), + ) + + expect(renders).toBe(2) + expect(screen.queryByText('rendered')).not.toBeNull() + }) +}) diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 5e5d3c88154..5da9ff50167 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -7,18 +7,18 @@ export * from './types' // export type { QueriesResults, QueriesOptions } from './useQueries' export { createQuery } from './createQuery' export { - QueryClientContext as defaultContext, + defaultContext, QueryClientProvider, useQueryClient, } from './QueryClientProvider' -// export type { QueryClientProviderProps } from './QueryClientProvider' -// export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' +export type { QueryClientProviderProps } from './QueryClientProvider' +export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' // export { useHydrate, Hydrate } from './Hydrate' // export type { HydrateProps } from './Hydrate' -// export { -// QueryErrorResetBoundary, -// useQueryErrorResetBoundary, -// } from './QueryErrorResetBoundary' +export { + QueryErrorResetBoundary, + useQueryErrorResetBoundary, +} from './QueryErrorResetBoundary' export { useIsFetching } from './useIsFetching' export { useIsMutating } from './useIsMutating' export { createMutation } from './createMutation' From 14d7aa1248c523afd8cc87a7853794947e890529 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 14:29:46 -0400 Subject: [PATCH 047/221] add reset error boundary tests --- .../QueryResetErrorBoundary.test.tsx | 635 ++++++++++++++++++ 1 file changed, 635 insertions(+) create mode 100644 packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx diff --git a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx new file mode 100644 index 00000000000..224cb253d07 --- /dev/null +++ b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx @@ -0,0 +1,635 @@ +import { waitFor, fireEvent, render, screen } from 'solid-testing-library' + +import { sleep, createQueryClient } from '../../../../tests/utils' +import { queryKey } from './utils' +import { + createQuery, + QueryCache, + QueryClientProvider, + QueryErrorResetBoundary, +} from '..' +import { createEffect, createSignal, ErrorBoundary, Suspense } from 'solid-js' + +describe('QueryErrorResetBoundary', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should retry fetch if the reset error boundary has been reset', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+ , +
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + }) + + it('should not throw error if query is disabled', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data, status } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + enabled: !succeed, + useErrorBoundary: true, + }, + ) + return ( +
+
status: {status}
+
{data}
+
+ ) + } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('status: error')) + }) + + it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const [enabled, setEnabled] = createSignal(false) + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + enabled: enabled(), + useErrorBoundary: true, + }, + ) + + createEffect(() => { + setEnabled(true) + }) + + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + }) + + it('should throw error if query is disabled and manually refetched', async () => { + const key = queryKey() + + function Page() { + const { data, refetch, status, fetchStatus } = createQuery( + key, + async () => { + throw new Error('Error') + }, + { + retry: false, + enabled: false, + useErrorBoundary: true, + }, + ) + + return ( +
+ +
+ status: {status}, fetchStatus: {fetchStatus} +
+
{data}
+
+ ) + } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('status: loading, fetchStatus: idle')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should not retry fetch if the reset error boundary has not been reset', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {() => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + initialData: 'initial', + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + }) + + it('should not retry fetch if the reset error boundary has not been reset after a previous reset', async () => { + const key = queryKey() + + let succeed = false + let shouldReset = true + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + shouldReset = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + succeed = true + shouldReset = false + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should throw again on error after the reset error boundary has been reset', async () => { + const key = queryKey() + let fetchCount = 0 + + function Page() { + const { data } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + throw new Error('Error') + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + expect(fetchCount).toBe(3) + }) + + it('should never render the component while the query is in error state', async () => { + const key = queryKey() + let fetchCount = 0 + let renders = 0 + + function Page() { + const { data } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + if (fetchCount > 2) { + return 'data' + } else { + throw new Error('Error') + } + }, + { + retry: false, + suspense: true, + }, + ) + renders++ + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + loading
}> + + + + )} + + + )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + expect(fetchCount).toBe(3) + expect(renders).toBe(1) + }) + + it('should render children', async () => { + function Page() { + return ( +
+ page +
+ ) + } + + render(() => ( + + + + + + )) + + expect(screen.queryByText('page')).not.toBeNull() + }) + + it('should show error boundary when using tracked queries even though we do not track the error field', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + }) +}) From 400ed07edd3dac5809c2c99ad3efb80a951608e2 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 17:09:47 -0400 Subject: [PATCH 048/221] add property tracking to query --- packages/solid-query/src/createBaseQuery.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 3cf13af077f..7acb18709b0 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -2,12 +2,7 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' import { CreateBaseQueryOptions } from './types' import { useQueryClient } from './QueryClientProvider' -import { - onMount, - onCleanup, - createComputed, - createResource, -} from 'solid-js' +import { onMount, onCleanup, createComputed, createResource } from 'solid-js' import { createStore } from 'solid-js/store' // Base Query Function that is used to create the query. @@ -78,5 +73,12 @@ export function createBaseQuery< }, } - return new Proxy(state, handler) as QueryObserverResult + const proxyResult = new Proxy(state, handler) as QueryObserverResult< + TData, + TError + > + + return !defaultedOptions.notifyOnChangeProps + ? observer.trackResult(proxyResult) + : proxyResult } From 88e6d98bd0743b2c82497a3ef89c61f4a6ba1608 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 17:09:59 -0400 Subject: [PATCH 049/221] get another query test passing --- packages/solid-query/src/__tests__/createQuery.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 8fab47edecf..c4d0ad8fd50 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1048,7 +1048,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryData(key, 'prefetched') + queryClient.setQueryData(key(), 'prefetched') function Page() { const state = createQuery(key, () => 'test', { From 4b6a26414d762c230923e75012edebe509dc0ab2 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 17:11:23 -0400 Subject: [PATCH 050/221] another test passes --- packages/solid-query/src/__tests__/createQuery.test.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index c4d0ad8fd50..a8d63467382 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1142,13 +1142,12 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch } = state - - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch setActTimeout(() => { refetch() }, 5) - }, [refetch]) + }) return null } From cd4c935388ac08f879cc815c75ae3da7c4474ae2 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 18:04:18 -0400 Subject: [PATCH 051/221] more tests transpiled --- .../src/__tests__/createQuery.test.tsx | 182 +++++++++--------- 1 file changed, 86 insertions(+), 96 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index a8d63467382..bfd42e06a48 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -27,7 +27,9 @@ import { createEffect, createSignal, Show, + ErrorBoundary, } from 'solid-js' +import { untrack } from 'solid-js/web' describe('createQuery', () => { const queryCache = new QueryCache() @@ -1253,19 +1255,19 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch, data } = state - - NotReact.useEffect(() => { + createEffect(() => { + const data = state.data + const refetch = state.refetch setActTimeout(() => { if (data) { refetch() } }, 20) - }, [refetch, data]) + }) return (
-

{data ?? null}

+

{state.data ?? null}

) } @@ -1295,9 +1297,10 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { + const _trackState = { ...state } renderCount++ - }, [state]) + }) return (
@@ -1388,12 +1391,10 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { remove, refetch } = state - return (
- - + + data: {state.data ?? 'null'}
) @@ -1499,7 +1500,7 @@ describe('createQuery', () => { const key = queryKey() const results: DefinedCreateQueryResult[] = [] - queryClient.setQueryData(key, 'set') + queryClient.setQueryData(key(), 'set') function Page() { const result = createQuery( @@ -1519,7 +1520,7 @@ describe('createQuery', () => { return (
isFetching: {result.isFetching}
- data: {result.data} @@ -1566,7 +1567,7 @@ describe('createQuery', () => { return (
- data: {state.data} @@ -1636,11 +1637,11 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - queryClient.refetchQueries({ queryKey: key }) + queryClient.refetchQueries({ queryKey: key() }) }, 20) - }, []) + }) return null } @@ -1682,11 +1683,11 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - queryClient.invalidateQueries(key) + queryClient.invalidateQueries(key()) }, 20) - }, []) + }) return null } @@ -1713,26 +1714,26 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(5) - return count + return count() }, - { enabled: count === 0 }, + { enabled: count() === 0 }, ) createRenderEffect(() => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setCount(1) }, 10) - }, []) + }) return null } @@ -1772,13 +1773,13 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(10) - return count + return count() }, { keepPreviousData: true }, ) @@ -1787,11 +1788,11 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setCount(1) }, 20) - }, []) + }) return null } @@ -1845,15 +1846,15 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - function Page({ count }: { count: number }) { + function Page(props: { count: number }) { const state = createQuery( - [key, count], + () => [key(), props.count], async () => { await sleep(10) - if (count === 2) { + if (props.count === 2) { throw new Error('Error test') } - return Promise.resolve(count) + return Promise.resolve(props.count) }, { retry: false, @@ -1957,13 +1958,13 @@ describe('createQuery', () => { const states: DefinedCreateQueryResult[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(10) - return count + return count() }, { initialData: 99, keepPreviousData: true }, ) @@ -1972,11 +1973,11 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setCount(1) }, 20) - }, []) + }) return null } @@ -2031,13 +2032,13 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(10) - return count + return count() }, { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) @@ -2046,9 +2047,8 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch } = state - - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch refetch() setActTimeout(() => { @@ -2058,7 +2058,7 @@ describe('createQuery', () => { setActTimeout(() => { refetch() }, 30) - }, [refetch]) + }) return null } @@ -2126,13 +2126,13 @@ describe('createQuery', () => { await sleep(10) function Page() { - const [count, setCount] = NotReact.useState(10) + const [count, setCount] = createSignal(10) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(10) - return count + return count() }, { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) @@ -2141,9 +2141,8 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch } = state - - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch setActTimeout(() => { setCount(11) }, 20) @@ -2153,7 +2152,7 @@ describe('createQuery', () => { setActTimeout(() => { refetch() }, 40) - }, [refetch]) + }) return null } @@ -2218,7 +2217,6 @@ describe('createQuery', () => { }, { notifyOnChangeProps: 'all' }, ) - const refetch = state.refetch createRenderEffect(() => { states.push({ ...state }) @@ -2226,7 +2224,7 @@ describe('createQuery', () => { return (
- + data: {state.data}
) @@ -2277,7 +2275,7 @@ describe('createQuery', () => { const states1: CreateQueryResult[] = [] const states2: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, async () => { + await queryClient.prefetchQuery(key(), async () => { await sleep(10) return 'prefetch' }) @@ -2295,7 +2293,9 @@ describe('createQuery', () => { staleTime: 100, }, ) - states1.push(state) + createRenderEffect(() => { + states1.push({ ...state }) + }) return null } @@ -2310,7 +2310,9 @@ describe('createQuery', () => { staleTime: 10, }, ) - states2.push(state) + createRenderEffect(() => { + states2.push({ ...state }) + }) return null } @@ -2462,13 +2464,12 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch } = state - - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch setActTimeout(() => { refetch() }, 10) - }, [refetch]) + }) return null } @@ -2556,10 +2557,11 @@ describe('createQuery', () => { )) - expect(queryCache.find(key)!.options.queryFn).toBe(queryFn1) + expect(queryCache.find(key())!.options.queryFn).toBe(queryFn1) }) - it('should render correct states even in case of useEffect triggering delays', async () => { + // TODO(lukemurray): this seems like a react implementation detail + it.skip('should render correct states even in case of useEffect triggering delays', async () => { const key = queryKey() const states: CreateQueryResult[] = [] @@ -2640,7 +2642,7 @@ describe('createQuery', () => { } function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) createQuery(key, queryFn, { onSuccess: () => { setCount((x) => x + 1) @@ -2652,12 +2654,12 @@ describe('createQuery', () => { }, }) - NotReact.useEffect(() => { + createEffect(() => { renders++ - callbackCount = count + callbackCount = count() }) - return
count: {count}
+ return
count: {count()}
} render(() => ( @@ -2679,15 +2681,15 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const [, setNewState] = NotReact.useState('state') + const [, setNewState] = createSignal('state') const state = createQuery(key, () => 'data') - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - queryClient.setQueryData(key, 'new') + queryClient.setQueryData(key(), 'new') // Update with same state to make react discard the next render setNewState('state') }, 10) - }, []) + }) return
{state.data}
} @@ -2771,7 +2773,7 @@ describe('createQuery', () => { } function Page() { - const state = createQuery([key, variables], queryFn) + const state = createQuery(() => [key(), variables], queryFn) createRenderEffect(() => { states.push({ ...state }) }) @@ -2813,9 +2815,7 @@ describe('createQuery', () => { await waitFor(() => screen.getByText('default')) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) expect(queryFn).not.toHaveBeenCalled() }) @@ -2844,9 +2844,7 @@ describe('createQuery', () => { await sleep(10) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await sleep(10) @@ -2879,9 +2877,7 @@ describe('createQuery', () => { await sleep(10) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await sleep(10) @@ -2914,9 +2910,7 @@ describe('createQuery', () => { await sleep(10) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await sleep(10) @@ -2956,9 +2950,7 @@ describe('createQuery', () => { await sleep(20) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await sleep(20) @@ -3005,9 +2997,7 @@ describe('createQuery', () => { expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) expect(states[1]).toMatchObject({ data: 0, isFetching: false }) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await screen.findByText('data: 1') @@ -3155,7 +3145,7 @@ describe('createQuery', () => { render(() => ( -
error boundary
}> +
error boundary
}>
@@ -3174,7 +3164,7 @@ describe('createQuery', () => { useErrorBoundary: true, }) - NotReact.useEffect(() => { + createEffect(() => { result = query }) @@ -3215,7 +3205,7 @@ describe('createQuery', () => { render(() => ( -
error boundary
}> +
error boundary
}>
@@ -3249,7 +3239,7 @@ describe('createQuery', () => { render(() => ( ( + fallback={(error) => (
error boundary
{/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} From f57f7cf71a8846276d9736253ec9e969ba5e8c0d Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 18:17:19 -0400 Subject: [PATCH 052/221] fix custom context in create base query --- packages/solid-query/src/createBaseQuery.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 7acb18709b0..4ae344430fe 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -22,7 +22,7 @@ export function createBaseQuery< >, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient() + const queryClient = useQueryClient({ context: options.context }) const defaultedOptions = queryClient.defaultQueryOptions(options) defaultedOptions._optimisticResults = 'optimistic' From 587ef2e48bfb93a229a88595e94fd7dc0e2be081 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 18:36:36 -0400 Subject: [PATCH 053/221] update query error reset boundary tests --- .../QueryResetErrorBoundary.test.tsx | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx index 224cb253d07..be3c6974589 100644 --- a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx +++ b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx @@ -20,7 +20,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -35,7 +35,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -78,7 +78,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data, status } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -96,8 +96,8 @@ describe('QueryErrorResetBoundary', () => { ) return (
-
status: {status}
-
{data}
+
status: {state.status}
+
{state.data}
) } @@ -142,7 +142,7 @@ describe('QueryErrorResetBoundary', () => { function Page() { const [enabled, setEnabled] = createSignal(false) - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -163,7 +163,7 @@ describe('QueryErrorResetBoundary', () => { setEnabled(true) }) - return
{data}
+ return
{state.data}
} render(() => ( @@ -203,7 +203,7 @@ describe('QueryErrorResetBoundary', () => { const key = queryKey() function Page() { - const { data, refetch, status, fetchStatus } = createQuery( + const state = createQuery( key, async () => { throw new Error('Error') @@ -217,11 +217,11 @@ describe('QueryErrorResetBoundary', () => { return (
- +
- status: {status}, fetchStatus: {fetchStatus} + status: {state.status}, fetchStatus: {state.fetchStatus}
-
{data}
+
{state.data}
) } @@ -263,7 +263,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -278,7 +278,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -319,7 +319,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -335,7 +335,7 @@ describe('QueryErrorResetBoundary', () => { initialData: 'initial', }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -378,7 +378,7 @@ describe('QueryErrorResetBoundary', () => { let shouldReset = true function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -393,7 +393,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -440,7 +440,7 @@ describe('QueryErrorResetBoundary', () => { let fetchCount = 0 function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -452,7 +452,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -497,7 +497,7 @@ describe('QueryErrorResetBoundary', () => { let renders = 0 function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -514,7 +514,7 @@ describe('QueryErrorResetBoundary', () => { }, ) renders++ - return
{data}
+ return
{state.data}
} render(() => ( @@ -582,7 +582,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -597,7 +597,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( From 806942a5543fb15a3dea679946a26e78d7636bdc Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 19:17:04 -0400 Subject: [PATCH 054/221] most error reset boundary test cases passing --- .../src/QueryErrorResetBoundary.tsx | 2 +- packages/solid-query/src/createBaseQuery.ts | 66 ++++++++++++++++--- packages/solid-query/src/utils.ts | 12 ++++ 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/packages/solid-query/src/QueryErrorResetBoundary.tsx b/packages/solid-query/src/QueryErrorResetBoundary.tsx index a501e7d7ffb..2066f3a6299 100644 --- a/packages/solid-query/src/QueryErrorResetBoundary.tsx +++ b/packages/solid-query/src/QueryErrorResetBoundary.tsx @@ -43,7 +43,7 @@ export const QueryErrorResetBoundary = ( return ( {typeof props.children === 'function' - ? (props.children as Function)(value) + ? (props.children as Function)(value()) : props.children} ) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 4ae344430fe..bd8d4b62ff8 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -2,8 +2,17 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' import { CreateBaseQueryOptions } from './types' import { useQueryClient } from './QueryClientProvider' -import { onMount, onCleanup, createComputed, createResource } from 'solid-js' +import { + onMount, + onCleanup, + createComputed, + createResource, + createMemo, + createEffect, +} from 'solid-js' import { createStore } from 'solid-js/store' +import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary' +import { shouldThrowError } from './utils' // Base Query Function that is used to create the query. export function createBaseQuery< @@ -23,14 +32,32 @@ export function createBaseQuery< Observer: typeof QueryObserver, ): QueryObserverResult { const queryClient = useQueryClient({ context: options.context }) + const errorResetBoundary = useQueryErrorResetBoundary() + const defaultedOptions = createMemo(() => { + const computedOptions = queryClient.defaultQueryOptions(options) + computedOptions._optimisticResults = 'optimistic' + if (computedOptions.suspense) { + // Always set stale time when using suspense to prevent + // fetching again when directly mounting after suspending + if (typeof computedOptions.staleTime !== 'number') { + computedOptions.staleTime = 1000 + } + } + + if (computedOptions.suspense || computedOptions.useErrorBoundary) { + // Prevent retrying failed query if the error boundary has not been reset yet + if (!errorResetBoundary.isReset()) { + computedOptions.retryOnMount = false + } + } + return computedOptions + }) - const defaultedOptions = queryClient.defaultQueryOptions(options) - defaultedOptions._optimisticResults = 'optimistic' - const observer = new Observer(queryClient, defaultedOptions) + const observer = new Observer(queryClient, defaultedOptions()) const [state, setState] = createStore>( // @ts-ignore - observer.getOptimisticResult(defaultedOptions), + observer.getOptimisticResult(defaultedOptions()), ) const [dataResource, { refetch }] = createResource(() => { @@ -50,12 +77,17 @@ export function createBaseQuery< onCleanup(() => unsubscribe()) onMount(() => { - observer.setOptions(defaultedOptions, { listeners: false }) + observer.setOptions(defaultedOptions(), { listeners: false }) }) createComputed(() => { - const newDefaultedOptions = queryClient.defaultQueryOptions(options) - observer.setOptions(newDefaultedOptions) + observer.setOptions(defaultedOptions()) + }) + + createEffect(() => { + if (errorResetBoundary.isReset()) { + errorResetBoundary.clearReset() + } }) const handler = { @@ -64,7 +96,21 @@ export function createBaseQuery< prop: keyof QueryObserverResult, ): any { if (prop === 'data') { - if (state.isLoading) { + // handle suspense + const isSuspense = + defaultedOptions().suspense && state.isLoading && state.isFetching + + // handle error boundary + const isErrorBoundary = + state.isError && + !errorResetBoundary.isReset() && + !state.isFetching && + shouldThrowError(defaultedOptions().useErrorBoundary, [ + state.error, + observer.getCurrentQuery(), + ]) + + if (isSuspense || isErrorBoundary) { return dataResource() } return state.data @@ -78,7 +124,7 @@ export function createBaseQuery< TError > - return !defaultedOptions.notifyOnChangeProps + return !defaultedOptions().notifyOnChangeProps ? observer.trackResult(proxyResult) : proxyResult } diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 6dc1f31787d..4f239b90a0e 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -52,3 +52,15 @@ export function parseFilterArgs< : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] ) as [ParseFilterArgs, TOptions] } + +export function shouldThrowError boolean>( + _useErrorBoundary: boolean | T | undefined, + params: Parameters, +): boolean { + // Allow useErrorBoundary function to override throwing behavior on a per-error basis + if (typeof _useErrorBoundary === 'function') { + return _useErrorBoundary(...params) + } + + return !!_useErrorBoundary +} From 5604855409a56e32b24c64771c9a178ac19dbe90 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 19:45:45 -0400 Subject: [PATCH 055/221] get a suspense test passing --- .../src/__tests__/suspense.test.tsx | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index d9d27d618c8..5c87a61ca2e 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -12,7 +12,13 @@ import { createInfiniteQuery, QueryClientProvider, } from '..' -import { createSignal, ErrorBoundary, Suspense } from 'solid-js' +import { + createRenderEffect, + createSignal, + ErrorBoundary, + on, + Suspense, +} from 'solid-js' describe("useQuery's in Suspense mode", () => { const queryCache = new QueryCache() @@ -26,8 +32,6 @@ describe("useQuery's in Suspense mode", () => { let renders = 0 function Page() { - renders++ - const [stateKey, setStateKey] = createSignal(key()) const state = createQuery( @@ -40,7 +44,15 @@ describe("useQuery's in Suspense mode", () => { { suspense: true }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) + + createRenderEffect( + on([() => ({ ...state }), key], () => { + renders++ + }), + ) return (
@@ -64,9 +76,12 @@ describe("useQuery's in Suspense mode", () => { await waitFor(() => screen.getByText('data: 2')) expect(renders).toBe(4) - expect(states.length).toBe(2) - expect(states[0]).toMatchObject({ data: 1, status: 'success' }) - expect(states[1]).toMatchObject({ data: 2, status: 'success' }) + // TODO(lukemurray): verify that this expectation is valid. this is 2 in + // react, but 4 in solid, because in solid suspense is triggered on read and + // the component needs to render in order to trigger suspense. + expect(states.length).toBe(4) + expect(states[1]).toMatchObject({ data: 1, status: 'success' }) + expect(states[3]).toMatchObject({ data: 2, status: 'success' }) }) it('should return the correct states for a successful infinite query', async () => { @@ -86,7 +101,11 @@ describe("useQuery's in Suspense mode", () => { getNextPageParam: (lastPage) => lastPage + 1, }, ) - states.push(state) + + createRenderEffect(() => { + states.push({ ...state }) + }) + return (
From 8555f144fea7dea659ed882fa125ba8c9d3dc5c1 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 20:56:13 -0400 Subject: [PATCH 056/221] bunch of suspense cases passing --- .../src/__tests__/suspense.test.tsx | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index 5c87a61ca2e..fcc8f35757f 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -91,7 +91,7 @@ describe("useQuery's in Suspense mode", () => { function Page() { const [multiplier, setMultiplier] = createSignal(1) const state = createInfiniteQuery( - () => [`${key}_${multiplier}`], + () => [`${key()}_${multiplier()}`], async ({ pageParam = 1 }) => { await sleep(10) return Number(pageParam * multiplier()) @@ -119,14 +119,15 @@ describe("useQuery's in Suspense mode", () => { - , )) await waitFor(() => screen.getByText('data: 1')) - expect(states.length).toBe(1) - expect(states[0]).toMatchObject({ + // TODO(lukemurray): in react this is 1 in solid this is 2 because suspense + // occurs on read. + expect(states.length).toBe(2) + expect(states[1]).toMatchObject({ data: { pages: [1], pageParams: [undefined] }, status: 'success', }) @@ -134,8 +135,9 @@ describe("useQuery's in Suspense mode", () => { fireEvent.click(screen.getByText('next')) await waitFor(() => screen.getByText('data: 2')) - expect(states.length).toBe(2) - expect(states[1]).toMatchObject({ + // TODO(lukemurray): in react this is 2 and in solid it is 4 + expect(states.length).toBe(4) + expect(states[3]).toMatchObject({ data: { pages: [2], pageParams: [undefined] }, status: 'success', }) @@ -161,7 +163,6 @@ describe("useQuery's in Suspense mode", () => { - , )) @@ -230,7 +231,7 @@ describe("useQuery's in Suspense mode", () => { () => [key()], async () => { await sleep(10) - return key + return key() }, { suspense: true, @@ -247,7 +248,6 @@ describe("useQuery's in Suspense mode", () => { - , )) @@ -318,7 +318,7 @@ describe("useQuery's in Suspense mode", () => { let succeed = false function Page() { - createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -335,6 +335,12 @@ describe("useQuery's in Suspense mode", () => { }, ) + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -384,7 +390,7 @@ describe("useQuery's in Suspense mode", () => { let succeed = false function Page() { - createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -399,6 +405,13 @@ describe("useQuery's in Suspense mode", () => { suspense: true, }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} From e32a6f1a78626d229c822ecc792ca9837fc9581d Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 21:01:59 -0400 Subject: [PATCH 057/221] even more suspense tests working --- .../src/__tests__/suspense.test.tsx | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index fcc8f35757f..e5157d35534 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -558,13 +558,13 @@ describe("useQuery's in Suspense mode", () => { )) await waitFor(() => screen.getByText('Loading...')) - await waitFor(() => screen.getByText(`data: ${key1}`)) + await waitFor(() => screen.getByText(`data: ${key1()}`)) fireEvent.click(screen.getByText('switch')) await waitFor(() => screen.getByText('Loading...')) - await waitFor(() => screen.getByText(`data: ${key2}`)) + await waitFor(() => screen.getByText(`data: ${key2()}`)) expect( // @ts-expect-error - queryClient.getQueryCache().find(key2)!.observers[0].listeners.length, + queryClient.getQueryCache().find(key2())!.observers[0].listeners.length, ).toBe(1) }) @@ -574,7 +574,7 @@ describe("useQuery's in Suspense mode", () => { let succeed = false function Page() { - createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -589,6 +589,13 @@ describe("useQuery's in Suspense mode", () => { suspense: true, }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -638,7 +645,7 @@ describe("useQuery's in Suspense mode", () => { const key = queryKey() function Page() { - createQuery( + const state = createQuery( key, async (): Promise => { await sleep(10) @@ -649,6 +656,13 @@ describe("useQuery's in Suspense mode", () => { suspense: true, }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -682,7 +696,7 @@ describe("useQuery's in Suspense mode", () => { const key = queryKey() function Page() { - createQuery( + const state = createQuery( key, async (): Promise => { await sleep(10) @@ -694,6 +708,13 @@ describe("useQuery's in Suspense mode", () => { useErrorBoundary: false, }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -727,7 +748,7 @@ describe("useQuery's in Suspense mode", () => { const key = queryKey() function Page() { - createQuery( + const state = createQuery( key, async (): Promise => { await sleep(10) @@ -739,6 +760,13 @@ describe("useQuery's in Suspense mode", () => { useErrorBoundary: (err) => err !== 'Local Error', }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -772,7 +800,7 @@ describe("useQuery's in Suspense mode", () => { const key = queryKey() function Page() { - createQuery( + const state = createQuery( key, async (): Promise => { await sleep(10) @@ -784,6 +812,13 @@ describe("useQuery's in Suspense mode", () => { useErrorBoundary: (err) => err !== 'Local Error', }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} From d0c8b1ee43b9a9aac3a6e80e30eb11b83bbd593d Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 21:33:38 -0400 Subject: [PATCH 058/221] finish migrating suspense tests --- packages/solid-query/src/__tests__/suspense.test.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index e5157d35534..709a5fd22b0 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -1091,8 +1091,6 @@ describe("useQuery's in Suspense mode", () => { let renders = 0 function Page() { - renders++ - state = createQuery( key, async () => { @@ -1103,6 +1101,12 @@ describe("useQuery's in Suspense mode", () => { { suspense: true, cacheTime: 0 }, ) + createRenderEffect( + on([() => ({ ...state })], () => { + renders++ + }), + ) + return (
rendered From 7e8d8b2f3b53ba4e38ea9f52f506d1ae03585aa3 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 22:05:40 -0400 Subject: [PATCH 059/221] add fetching/mutating cases with custom context --- .../src/__tests__/useIsFetching.test.tsx | 180 +++++++++-------- .../src/__tests__/useIsMutating.test.tsx | 183 ++++++++++-------- 2 files changed, 193 insertions(+), 170 deletions(-) diff --git a/packages/solid-query/src/__tests__/useIsFetching.test.tsx b/packages/solid-query/src/__tests__/useIsFetching.test.tsx index fe856ff9ea6..96ee1a81e4b 100644 --- a/packages/solid-query/src/__tests__/useIsFetching.test.tsx +++ b/packages/solid-query/src/__tests__/useIsFetching.test.tsx @@ -6,8 +6,21 @@ import { sleep, } from '../../../../tests/utils' import { queryKey } from './utils' -import { createQuery, useIsFetching, QueryCache, QueryClientProvider } from '..' -import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js' +import { + createQuery, + useIsFetching, + QueryCache, + QueryClientProvider, + QueryClient, +} from '..' +import { + createContext, + createEffect, + createRenderEffect, + createSignal, + ErrorBoundary, + Show, +} from 'solid-js' describe('useIsFetching', () => { // See https://github.com/tannerlinsley/react-query/issues/105 @@ -179,90 +192,85 @@ describe('useIsFetching', () => { expect(isFetchings).toEqual(expect.not.arrayContaining([2])) }) - // TODO(lukemurray): add when we support custom contexts - // describe('with custom context', () => { - // it('should update as queries start and stop fetching', async () => { - // const context = createContext(undefined) - - // const queryCache = new QueryCache() - // const queryClient = createQueryClient({ queryCache }) - // const key = queryKey() - - // function Page() { - // const [ready, setReady] = createSignal(false) - - // const isFetching = useIsFetching(undefined, { context: context }) - - // createQuery( - // key, - // async () => { - // await sleep(50) - // return 'test' - // }, - // { - // enabled: ready(), - // context, - // }, - // ) - - // return ( - //
- //
isFetching: {isFetching}
- // - //
- // ) - // } - - // const { findByText, getByRole } = renderWithClient( - // queryClient, - // , - // { - // context, - // }, - // ) - - // await findByText('isFetching: 0') - // fireEvent.click(getByRole('button', { name: /setReady/i })) - // await findByText('isFetching: 1') - // await findByText('isFetching: 0') - // }) - - // it('should throw if the context is not passed to useIsFetching', async () => { - // const context = React.createContext(undefined) - - // const queryCache = new QueryCache() - // const queryClient = createQueryClient({ queryCache }) - // const key = queryKey() - - // function Page() { - // const isFetching = useIsFetching() - - // createQuery(key, async () => 'test', { - // enabled: true, - // context, - // useErrorBoundary: true, - // }) - - // return ( - //
- //
isFetching: {isFetching}
- //
- // ) - // } - - // const rendered = renderWithClient( - // queryClient, - //
error boundary
}> - // - //
, - // { - // context, - // }, - // ) - - // await waitFor(() => rendered.getByText('error boundary')) - // }) - // }) + describe('with custom context', () => { + it('should update as queries start and stop fetching', async () => { + const context = createContext(undefined) + + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + const key = queryKey() + + function Page() { + const [ready, setReady] = createSignal(false) + + const isFetching = useIsFetching(undefined, { context: context }) + + createQuery( + key, + async () => { + await sleep(50) + return 'test' + }, + { + enabled: ready(), + context, + }, + ) + + return ( +
+
isFetching: {isFetching}
+ +
+ ) + } + + render(() => ( + + + + )) + + await screen.findByText('isFetching: 0') + fireEvent.click(screen.getByRole('button', { name: /setReady/i })) + await screen.findByText('isFetching: 1') + await screen.findByText('isFetching: 0') + }) + + it('should throw if the context is not passed to useIsFetching', async () => { + const context = createContext(undefined) + + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + const key = queryKey() + + function Page() { + const isFetching = useIsFetching() + + createQuery(key, async () => 'test', { + enabled: true, + context, + useErrorBoundary: true, + }) + + return ( +
+
isFetching: {isFetching}
+
+ ) + } + + render(() => ( + +
error boundary
}> + +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + }) + }) it('should show the correct fetching state when mounted after a query', async () => { const queryClient = createQueryClient() diff --git a/packages/solid-query/src/__tests__/useIsMutating.test.tsx b/packages/solid-query/src/__tests__/useIsMutating.test.tsx index 3a83903c141..82d59162963 100644 --- a/packages/solid-query/src/__tests__/useIsMutating.test.tsx +++ b/packages/solid-query/src/__tests__/useIsMutating.test.tsx @@ -1,10 +1,22 @@ import { waitFor, fireEvent, screen } from 'solid-testing-library' -import { useIsMutating, createMutation, QueryClientProvider } from '..' +import { + useIsMutating, + createMutation, + QueryClientProvider, + QueryClient, +} from '..' import { createQueryClient, sleep } from '../../../../tests/utils' import { setActTimeout } from './utils' import * as MutationCacheModule from '../../../query-core/src/mutationCache' -import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js' +import { + createContext, + createEffect, + createRenderEffect, + createSignal, + ErrorBoundary, + Show, +} from 'solid-js' import { render } from 'solid-testing-library' describe('useIsMutating', () => { @@ -194,86 +206,89 @@ describe('useIsMutating', () => { MutationCacheSpy.mockRestore() }) - // TODO(lukemurray): re-add when we support custom context. - // describe('with custom context', () => { - // it('should return the number of fetching mutations', async () => { - // const context = React.createContext(undefined) - - // const isMutatings: number[] = [] - // const queryClient = new QueryClient() - - // function IsMutating() { - // const isMutating = useIsMutating(undefined, { context }) - // isMutatings.push(isMutating) - // return null - // } - - // function Page() { - // const { mutate: mutate1 } = useMutation( - // ['mutation1'], - // async () => { - // await sleep(150) - // return 'data' - // }, - // { context }, - // ) - // const { mutate: mutate2 } = useMutation( - // ['mutation2'], - // async () => { - // await sleep(50) - // return 'data' - // }, - // { context }, - // ) - - // React.useEffect(() => { - // mutate1() - // setActTimeout(() => { - // mutate2() - // }, 50) - // }, [mutate1, mutate2]) - - // return - // } - - // renderWithClient(queryClient, , { context }) - // await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0])) - // }) - - // it('should throw if the context is not passed to useIsMutating', async () => { - // const context = React.createContext(undefined) - - // const isMutatings: number[] = [] - // const queryClient = new QueryClient() - - // function IsMutating() { - // const isMutating = useIsMutating(undefined) - // isMutatings.push(isMutating) - // return null - // } - - // function Page() { - // const { mutate } = useMutation(['mutation'], async () => 'data', { - // useErrorBoundary: true, - // context, - // }) - - // React.useEffect(() => { - // mutate() - // }, [mutate]) - - // return - // } - - // const rendered = renderWithClient( - // queryClient, - //
error boundary
}> - // - //
, - // { context }, - // ) - - // await waitFor(() => rendered.getByText('error boundary')) - // }) - // }) + describe('with custom context', () => { + it('should return the number of fetching mutations', async () => { + const context = createContext(undefined) + + const isMutatings: number[] = [] + const queryClient = new QueryClient() + + function IsMutating() { + const isMutating = useIsMutating(undefined, { context }) + isMutatings.push(isMutating()) + return null + } + + function Page() { + const { mutate: mutate1 } = createMutation( + ['mutation1'], + async () => { + await sleep(150) + return 'data' + }, + { context }, + ) + const { mutate: mutate2 } = createMutation( + ['mutation2'], + async () => { + await sleep(50) + return 'data' + }, + { context }, + ) + + createEffect(() => { + mutate1() + setActTimeout(() => { + mutate2() + }, 50) + }) + + return + } + + render(() => ( + + + + )) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0])) + }) + + it('should throw if the context is not passed to useIsMutating', async () => { + const context = createContext(undefined) + + const isMutatings: number[] = [] + const queryClient = new QueryClient() + + function IsMutating() { + const isMutating = useIsMutating(undefined) + isMutatings.push(isMutating()) + return null + } + + function Page() { + const { mutate } = createMutation(['mutation'], async () => 'data', { + useErrorBoundary: true, + context, + }) + + createEffect(() => { + mutate() + }) + + return + } + + render(() => ( + +
error boundary
}> + +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + }) + }) }) From 823a51f74f84b7de36339b70bbf0f3abf273b10e Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 22:23:23 -0400 Subject: [PATCH 060/221] add infinite query and mutation tests --- .../__tests__/createInfiniteQuery.test.tsx | 1768 +++++++++++++++++ .../src/__tests__/createMutation.test.tsx | 1094 ++++++++++ 2 files changed, 2862 insertions(+) create mode 100644 packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx create mode 100644 packages/solid-query/src/__tests__/createMutation.test.tsx diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx new file mode 100644 index 00000000000..672ab72f4b5 --- /dev/null +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -0,0 +1,1768 @@ +import { waitFor, fireEvent } from 'solid-testing-library' + +import { sleep, createQueryClient } from '../../../../tests/utils' + +import { renderWithClient, Blink, queryKey, setActTimeout } from './utils' +import { + createInfiniteQuery, + CreateInfiniteQueryResult, + QueryCache, + QueryFunctionContext, + InfiniteData, +} from '..' + +interface Result { + items: number[] + nextId?: number + prevId?: number + ts: number +} + +const pageSize = 10 + +const fetchItems = async ( + page: number, + ts: number, + noNext?: boolean, + noPrev?: boolean, +): Promise => { + await sleep(10) + return { + items: [...new Array(10)].fill(null).map((_, d) => page * pageSize + d), + nextId: noNext ? undefined : page + 1, + prevId: noPrev ? undefined : page - 1, + ts, + } +} + +describe('useInfiniteQuery', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should return the correct states for a successful query', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 0 }) => Number(pageParam), + { + getNextPageParam: (lastPage) => lastPage + 1, + }, + ) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + fetchNextPage: expect.any(Function), + fetchPreviousPage: expect.any(Function), + hasNextPage: undefined, + hasPreviousPage: undefined, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'loading', + fetchStatus: 'fetching', + }) + + expect(states[1]).toEqual({ + data: { pages: [0], pageParams: [undefined] }, + dataUpdatedAt: expect.any(Number), + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + fetchNextPage: expect.any(Function), + fetchPreviousPage: expect.any(Function), + hasNextPage: true, + hasPreviousPage: undefined, + isError: false, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isPaused: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isLoading: false, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: true, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'success', + fetchStatus: 'idle', + }) + }) + + it('should not throw when fetchNextPage returns an error', async () => { + const key = queryKey() + let noThrow: boolean + + function Page() { + const start = 1 + const state = createInfiniteQuery( + key, + async ({ pageParam = start }) => { + if (pageParam === 2) { + throw new Error('error') + } + return Number(pageParam) + }, + { + retry: 1, + retryDelay: 10, + getNextPageParam: (lastPage) => lastPage + 1, + }, + ) + + const { fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + .then(() => { + noThrow = true + }) + .catch(() => undefined) + }, 20) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(noThrow).toBe(true)) + }) + + it('should keep the previous data when keepPreviousData is set', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const [order, setOrder] = React.useState('desc') + + const state = createInfiniteQuery( + [key, order], + async ({ pageParam = 0 }) => { + await sleep(10) + return `${pageParam}-${order}` + }, + { + getNextPageParam: () => 1, + keepPreviousData: true, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + return ( +
+ + +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {String(state.isFetching)}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 0-desc')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 0-desc,1-desc')) + fireEvent.click(rendered.getByRole('button', { name: /order/i })) + + await waitFor(() => rendered.getByText('data: 0-asc')) + await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => expect(states.length).toBe(7)) + + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + isPreviousData: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: ['0-desc'] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: false, + }) + expect(states[2]).toMatchObject({ + data: { pages: ['0-desc'] }, + isFetching: true, + isFetchingNextPage: true, + isSuccess: true, + isPreviousData: false, + }) + expect(states[3]).toMatchObject({ + data: { pages: ['0-desc', '1-desc'] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[4]).toMatchObject({ + data: { pages: ['0-desc', '1-desc'] }, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: true, + }) + // Hook state update + expect(states[5]).toMatchObject({ + data: { pages: ['0-desc', '1-desc'] }, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: true, + }) + expect(states[6]).toMatchObject({ + data: { pages: ['0-asc'] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should be able to select a part of the data', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery(key, () => ({ count: 1 }), { + select: (data) => ({ + pages: data.pages.map((x) => `count: ${x.count}`), + pageParams: data.pageParams, + }), + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: undefined, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: ['count: 1'] }, + isSuccess: true, + }) + }) + + it('should be able to select a new result and not cause infinite renders', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult<{ count: number; id: number }>[] = + [] + let selectCalled = 0 + + function Page() { + const state = createInfiniteQuery(key, () => ({ count: 1 }), { + select: React.useCallback((data: InfiniteData<{ count: number }>) => { + selectCalled++ + return { + pages: data.pages.map((x) => ({ ...x, id: Math.random() })), + pageParams: data.pageParams, + } + }, []), + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + + expect(states.length).toBe(2) + expect(selectCalled).toBe(1) + expect(states[0]).toMatchObject({ + data: undefined, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: [{ count: 1 }] }, + isSuccess: true, + }) + }) + + it('should be able to reverse the data', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + async ({ pageParam = 0 }) => { + await sleep(10) + return Number(pageParam) + }, + { + select: (data) => ({ + pages: [...data.pages].reverse(), + pageParams: [...data.pageParams].reverse(), + }), + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + return ( +
+ +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {state.isFetching}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 0')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 1,0')) + + await waitFor(() => expect(states.length).toBe(4)) + expect(states[0]).toMatchObject({ + data: undefined, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: [0] }, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + data: { pages: [0] }, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + data: { pages: [1, 0] }, + isSuccess: true, + }) + }) + + it('should be able to fetch a previous page', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const start = 10 + const state = createInfiniteQuery( + key, + async ({ pageParam = start }) => { + await sleep(10) + return Number(pageParam) + }, + { + getPreviousPageParam: (firstPage) => firstPage - 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { fetchPreviousPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchPreviousPage() + }, 20) + }, [fetchPreviousPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(4) + expect(states[0]).toMatchObject({ + data: undefined, + hasNextPage: undefined, + hasPreviousPage: undefined, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: undefined, + hasPreviousPage: true, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: undefined, + hasPreviousPage: true, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: true, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + data: { pages: [9, 10] }, + hasNextPage: undefined, + hasPreviousPage: true, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isSuccess: true, + }) + }) + + it('should be able to refetch when providing page params manually', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery(key, async ({ pageParam = 10 }) => { + await sleep(10) + return Number(pageParam) + }) + + states.push(state) + + return ( +
+ + + +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {String(state.isFetching)}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 10')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 10,11')) + fireEvent.click( + rendered.getByRole('button', { name: /fetchPreviousPage/i }), + ) + await waitFor(() => rendered.getByText('data: 9,10,11')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + + await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => expect(states.length).toBe(8)) + + // Initial fetch + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isFetchingNextPage: false, + }) + // Initial fetch done + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch next page + expect(states[2]).toMatchObject({ + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: true, + }) + // Fetch next page done + expect(states[3]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch previous page + expect(states[4]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: true, + }) + // Fetch previous page done + expect(states[5]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + // Refetch + expect(states[6]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + // Refetch done + expect(states[7]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + }) + + it('should be able to refetch when providing page params automatically', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + async ({ pageParam = 10 }) => { + await sleep(10) + return Number(pageParam) + }, + { + getPreviousPageParam: (firstPage) => firstPage - 1, + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + return ( +
+ + + +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {String(state.isFetching)}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 10')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 10,11')) + fireEvent.click( + rendered.getByRole('button', { name: /fetchPreviousPage/i }), + ) + await waitFor(() => rendered.getByText('data: 9,10,11')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + + await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => expect(states.length).toBe(8)) + + // Initial fetch + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isFetchingNextPage: false, + }) + // Initial fetch done + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch next page + expect(states[2]).toMatchObject({ + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: true, + }) + // Fetch next page done + expect(states[3]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch previous page + expect(states[4]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: true, + }) + // Fetch previous page done + expect(states[5]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + // Refetch + expect(states[6]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + // Refetch done + expect(states[7]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + }) + + it('should be able to refetch only specific pages when refetchPages is provided', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const multiplier = React.useRef(1) + const state = createInfiniteQuery( + key, + async ({ pageParam = 10 }) => { + await sleep(10) + return Number(pageParam) * multiplier.current + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + return ( +
+ + +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {String(state.isFetching)}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 10')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 10,11')) + fireEvent.click(rendered.getByRole('button', { name: /refetchPage/i })) + + await waitFor(() => rendered.getByText('data: 20,11')) + await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => expect(states.length).toBe(6)) + + // Initial fetch + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isFetchingNextPage: false, + }) + // Initial fetch done + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch next page + expect(states[2]).toMatchObject({ + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: true, + }) + // Fetch next page done + expect(states[3]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Refetch + expect(states[4]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: true, + isFetchingNextPage: false, + }) + // Refetch done, only page one has been refetched and multiplied + expect(states[5]).toMatchObject({ + data: { pages: [20, 11] }, + isFetching: false, + isFetchingNextPage: false, + }) + }) + + it('should silently cancel any ongoing fetch when fetching more', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const start = 10 + const state = createInfiniteQuery( + key, + async ({ pageParam = start }) => { + await sleep(50) + return Number(pageParam) + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { refetch, fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 100) + setActTimeout(() => { + fetchNextPage() + }, 110) + }, [fetchNextPage, refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(300) + + expect(states.length).toBe(5) + expect(states[0]).toMatchObject({ + hasNextPage: undefined, + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + hasNextPage: true, + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + hasNextPage: true, + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + hasNextPage: true, + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: true, + isSuccess: true, + }) + expect(states[4]).toMatchObject({ + hasNextPage: true, + data: { pages: [10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should silently cancel an ongoing fetchNextPage request when another fetchNextPage is invoked', async () => { + const key = queryKey() + const start = 10 + const onAborts: jest.Mock[] = [] + const abortListeners: jest.Mock[] = [] + const fetchPage = jest.fn< + Promise, + [QueryFunctionContext] + >(async ({ pageParam = start, signal }) => { + if (signal) { + const onAbort = jest.fn() + const abortListener = jest.fn() + onAborts.push(onAbort) + abortListeners.push(abortListener) + signal.onabort = onAbort + signal.addEventListener('abort', abortListener) + } + await sleep(50) + return Number(pageParam) + }) + + function Page() { + const { fetchNextPage } = createInfiniteQuery(key, fetchPage, { + getNextPageParam: (lastPage) => lastPage + 1, + }) + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + }, 100) + setActTimeout(() => { + fetchNextPage() + }, 110) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(300) + + const expectedCallCount = 3 + expect(fetchPage).toBeCalledTimes(expectedCallCount) + expect(onAborts).toHaveLength(expectedCallCount) + expect(abortListeners).toHaveLength(expectedCallCount) + + let callIndex = 0 + const firstCtx = fetchPage.mock.calls[callIndex]![0] + expect(firstCtx.pageParam).toBeUndefined() + expect(firstCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(firstCtx.signal).toBeInstanceOf(AbortSignal) + expect(firstCtx.signal?.aborted).toBe(false) + expect(onAborts[callIndex]).not.toHaveBeenCalled() + expect(abortListeners[callIndex]).not.toHaveBeenCalled() + } + + callIndex = 1 + const secondCtx = fetchPage.mock.calls[callIndex]![0] + expect(secondCtx.pageParam).toBe(11) + expect(secondCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(secondCtx.signal).toBeInstanceOf(AbortSignal) + expect(secondCtx.signal?.aborted).toBe(true) + expect(onAborts[callIndex]).toHaveBeenCalledTimes(1) + expect(abortListeners[callIndex]).toHaveBeenCalledTimes(1) + } + + callIndex = 2 + const thirdCtx = fetchPage.mock.calls[callIndex]![0] + expect(thirdCtx.pageParam).toBe(11) + expect(thirdCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(thirdCtx.signal).toBeInstanceOf(AbortSignal) + expect(thirdCtx.signal?.aborted).toBe(false) + expect(onAborts[callIndex]).not.toHaveBeenCalled() + expect(abortListeners[callIndex]).not.toHaveBeenCalled() + } + }) + + it('should not cancel an ongoing fetchNextPage request when another fetchNextPage is invoked if `cancelRefetch: false` is used ', async () => { + const key = queryKey() + const start = 10 + const onAborts: jest.Mock[] = [] + const abortListeners: jest.Mock[] = [] + const fetchPage = jest.fn< + Promise, + [QueryFunctionContext] + >(async ({ pageParam = start, signal }) => { + if (signal) { + const onAbort = jest.fn() + const abortListener = jest.fn() + onAborts.push(onAbort) + abortListeners.push(abortListener) + signal.onabort = onAbort + signal.addEventListener('abort', abortListener) + } + await sleep(50) + return Number(pageParam) + }) + + function Page() { + const { fetchNextPage } = createInfiniteQuery(key, fetchPage, { + getNextPageParam: (lastPage) => lastPage + 1, + }) + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + }, 100) + setActTimeout(() => { + fetchNextPage({ cancelRefetch: false }) + }, 110) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(300) + + const expectedCallCount = 2 + expect(fetchPage).toBeCalledTimes(expectedCallCount) + expect(onAborts).toHaveLength(expectedCallCount) + expect(abortListeners).toHaveLength(expectedCallCount) + + let callIndex = 0 + const firstCtx = fetchPage.mock.calls[callIndex]![0] + expect(firstCtx.pageParam).toBeUndefined() + expect(firstCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(firstCtx.signal).toBeInstanceOf(AbortSignal) + expect(firstCtx.signal?.aborted).toBe(false) + expect(onAborts[callIndex]).not.toHaveBeenCalled() + expect(abortListeners[callIndex]).not.toHaveBeenCalled() + } + + callIndex = 1 + const secondCtx = fetchPage.mock.calls[callIndex]![0] + expect(secondCtx.pageParam).toBe(11) + expect(secondCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(secondCtx.signal).toBeInstanceOf(AbortSignal) + expect(secondCtx.signal?.aborted).toBe(false) + expect(onAborts[callIndex]).not.toHaveBeenCalled() + expect(abortListeners[callIndex]).not.toHaveBeenCalled() + } + }) + + it('should keep fetching first page when not loaded yet and triggering fetch more', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const start = 10 + const state = createInfiniteQuery( + key, + async ({ pageParam = start }) => { + await sleep(50) + return Number(pageParam) + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + }, 10) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + hasNextPage: undefined, + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + hasNextPage: true, + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should stop fetching additional pages when the component is unmounted and AbortSignal is consumed', async () => { + const key = queryKey() + let fetches = 0 + + const initialData = { pages: [1, 2, 3, 4], pageParams: [0, 1, 2, 3] } + + function List() { + createInfiniteQuery( + key, + async ({ pageParam = 0, signal: _ }) => { + fetches++ + await sleep(50) + return Number(pageParam) * 10 + }, + { + initialData, + getNextPageParam: (_, allPages) => { + return allPages.length === 4 ? undefined : allPages.length + }, + }, + ) + + return null + } + + function Page() { + const [show, setShow] = React.useState(true) + + React.useEffect(() => { + setActTimeout(() => { + setShow(false) + }, 75) + }, []) + + return show ? : null + } + + renderWithClient(queryClient, ) + + await sleep(300) + + if (typeof AbortSignal === 'function') { + expect(fetches).toBe(2) + expect(queryClient.getQueryState(key)).toMatchObject({ + data: initialData, + status: 'success', + error: null, + }) + } else { + // if AbortSignal is not consumed, fetches should not abort + expect(fetches).toBe(4) + expect(queryClient.getQueryState(key)).toMatchObject({ + data: { pages: [0, 10, 20, 30], pageParams: [0, 1, 2, 3] }, + status: 'success', + error: null, + }) + } + }) + + it('should be able to override the cursor in the fetchNextPage callback', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + async ({ pageParam = 0 }) => { + await sleep(10) + return Number(pageParam) + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage({ pageParam: 5 }) + }, 20) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(4) + expect(states[0]).toMatchObject({ + hasNextPage: undefined, + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + hasNextPage: true, + data: { pages: [0] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + hasNextPage: true, + data: { pages: [0] }, + isFetching: true, + isFetchingNextPage: true, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + hasNextPage: true, + data: { pages: [0, 5] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should be able to set new pages with the query client', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const [firstPage, setFirstPage] = React.useState(0) + + const state = createInfiniteQuery( + key, + async ({ pageParam = firstPage }) => { + await sleep(10) + return Number(pageParam) + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + queryClient.setQueryData(key, { pages: [7, 8], pageParams: [7, 8] }) + setFirstPage(7) + }, 20) + + setActTimeout(() => { + refetch() + }, 50) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(5) + expect(states[0]).toMatchObject({ + hasNextPage: undefined, + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + // After first fetch + expect(states[1]).toMatchObject({ + hasNextPage: true, + data: { pages: [0] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + // Set state + expect(states[2]).toMatchObject({ + hasNextPage: true, + data: { pages: [7, 8] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + // Refetch + expect(states[3]).toMatchObject({ + hasNextPage: true, + data: { pages: [7, 8] }, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + // Refetch done + expect(states[4]).toMatchObject({ + hasNextPage: true, + data: { pages: [7, 8] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should only refetch the first page when initialData is provided', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + async ({ pageParam }): Promise => { + await sleep(10) + return pageParam + }, + { + initialData: { pages: [1], pageParams: [1] }, + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + }, 20) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(4) + expect(states[0]).toMatchObject({ + data: { pages: [1] }, + hasNextPage: true, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[1]).toMatchObject({ + data: { pages: [1] }, + hasNextPage: true, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + data: { pages: [1] }, + hasNextPage: true, + isFetching: true, + isFetchingNextPage: true, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + data: { pages: [1, 2] }, + hasNextPage: true, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should set hasNextPage to false if getNextPageParam returns undefined', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 1 }) => Number(pageParam), + { + getNextPageParam: () => undefined, + }, + ) + + states.push(state) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: undefined, + hasNextPage: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: [1] }, + hasNextPage: false, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should compute hasNextPage correctly using initialData', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 10 }): number => pageParam, + { + initialData: { pages: [10], pageParams: [undefined] }, + getNextPageParam: (lastPage) => (lastPage === 10 ? 11 : undefined), + }, + ) + + states.push(state) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: true, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: true, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should compute hasNextPage correctly for falsy getFetchMore return value using initialData', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 10 }): number => pageParam, + { + initialData: { pages: [10], pageParams: [undefined] }, + getNextPageParam: () => undefined, + }, + ) + + states.push(state) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: false, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: false, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should not use selected data when computing hasNextPage', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 1 }) => Number(pageParam), + { + getNextPageParam: (lastPage) => (lastPage === 1 ? 2 : false), + select: (data) => ({ + pages: data.pages.map((x) => x.toString()), + pageParams: data.pageParams, + }), + }, + ) + + states.push(state) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: undefined, + hasNextPage: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: ['1'] }, + hasNextPage: true, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should build fresh cursors on refetch', async () => { + const key = queryKey() + + const genItems = (size: number) => + [...new Array(size)].fill(null).map((_, d) => d) + const items = genItems(15) + const limit = 3 + + const fetchItemsWithLimit = async (cursor = 0, ts: number) => { + await sleep(10) + return { + nextId: cursor + limit, + items: items.slice(cursor, cursor + limit), + ts, + } + } + + function Page() { + const fetchCountRef = React.useRef(0) + const { + status, + data, + error, + isFetchingNextPage, + fetchNextPage, + hasNextPage, + refetch, + } = createInfiniteQuery( + key, + ({ pageParam = 0 }) => + fetchItemsWithLimit(pageParam, fetchCountRef.current++), + { + getNextPageParam: (lastPage) => lastPage.nextId, + }, + ) + + return ( +
+

Pagination

+ {status === 'loading' ? ( + 'Loading...' + ) : status === 'error' ? ( + Error: {error.message} + ) : ( + <> +
Data:
+ {data.pages.map((page, i) => ( +
+
+ Page {i}: {page.ts} +
+
+ {page.items.map((item) => ( +

Item: {item}

+ ))} +
+
+ ))} +
+ + + +
+
{!isFetchingNextPage ? 'Background Updating...' : null}
+ + )} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('Loading...') + + await waitFor(() => rendered.getByText('Item: 2')) + await waitFor(() => rendered.getByText('Page 0: 0')) + + fireEvent.click(rendered.getByText('Load More')) + + await waitFor(() => rendered.getByText('Loading more...')) + await waitFor(() => rendered.getByText('Item: 5')) + await waitFor(() => rendered.getByText('Page 0: 0')) + await waitFor(() => rendered.getByText('Page 1: 1')) + + fireEvent.click(rendered.getByText('Load More')) + + await waitFor(() => rendered.getByText('Loading more...')) + await waitFor(() => rendered.getByText('Item: 8')) + await waitFor(() => rendered.getByText('Page 0: 0')) + await waitFor(() => rendered.getByText('Page 1: 1')) + await waitFor(() => rendered.getByText('Page 2: 2')) + + fireEvent.click(rendered.getByText('Refetch')) + + await waitFor(() => rendered.getByText('Background Updating...')) + await waitFor(() => rendered.getByText('Item: 8')) + await waitFor(() => rendered.getByText('Page 0: 3')) + await waitFor(() => rendered.getByText('Page 1: 4')) + await waitFor(() => rendered.getByText('Page 2: 5')) + + // ensure that Item: 4 is rendered before removing it + expect(rendered.queryAllByText('Item: 4')).toHaveLength(1) + + // remove Item: 4 + fireEvent.click(rendered.getByText('Remove item')) + + await waitFor(() => rendered.getByText('Background Updating...')) + // ensure that an additional item is rendered (it means that cursors were properly rebuilt) + await waitFor(() => rendered.getByText('Item: 9')) + await waitFor(() => rendered.getByText('Page 0: 6')) + await waitFor(() => rendered.getByText('Page 1: 7')) + await waitFor(() => rendered.getByText('Page 2: 8')) + + // ensure that Item: 4 is no longer rendered + expect(rendered.queryAllByText('Item: 4')).toHaveLength(0) + }) + + it('should compute hasNextPage correctly for falsy getFetchMore return value on refetching', async () => { + const key = queryKey() + const MAX = 2 + + function Page() { + const fetchCountRef = React.useRef(0) + const [isRemovedLastPage, setIsRemovedLastPage] = + React.useState(false) + const { + status, + data, + error, + isFetching, + isFetchingNextPage, + fetchNextPage, + hasNextPage, + refetch, + } = createInfiniteQuery( + key, + ({ pageParam = 0 }) => + fetchItems( + pageParam, + fetchCountRef.current++, + pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage), + ), + { + getNextPageParam: (lastPage) => lastPage.nextId, + }, + ) + + return ( +
+

Pagination

+ {status === 'loading' ? ( + 'Loading...' + ) : status === 'error' ? ( + Error: {error.message} + ) : ( + <> +
Data:
+ {data.pages.map((page, i) => ( +
+
+ Page {i}: {page.ts} +
+
+ {page.items.map((item) => ( +

Item: {item}

+ ))} +
+
+ ))} +
+ + + +
+
+ {isFetching && !isFetchingNextPage + ? 'Background Updating...' + : null} +
+ + )} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('Loading...') + + await waitFor(() => { + rendered.getByText('Item: 9') + rendered.getByText('Page 0: 0') + }) + + fireEvent.click(rendered.getByText('Load More')) + + await waitFor(() => rendered.getByText('Loading more...')) + + await waitFor(() => { + rendered.getByText('Item: 19') + rendered.getByText('Page 0: 0') + rendered.getByText('Page 1: 1') + }) + + fireEvent.click(rendered.getByText('Load More')) + + await waitFor(() => rendered.getByText('Loading more...')) + + await waitFor(() => { + rendered.getByText('Item: 29') + rendered.getByText('Page 0: 0') + rendered.getByText('Page 1: 1') + rendered.getByText('Page 2: 2') + }) + + rendered.getByText('Nothing more to load') + + fireEvent.click(rendered.getByText('Remove Last Page')) + + await sleep(10) + + fireEvent.click(rendered.getByText('Refetch')) + + await waitFor(() => rendered.getByText('Background Updating...')) + + await waitFor(() => { + rendered.getByText('Page 0: 3') + rendered.getByText('Page 1: 4') + }) + + expect(rendered.queryByText('Item: 29')).toBeNull() + expect(rendered.queryByText('Page 2: 5')).toBeNull() + + rendered.getByText('Nothing more to load') + }) + + it('should cancel the query function when there are no more subscriptions', async () => { + const key = queryKey() + let cancelFn: jest.Mock = jest.fn() + + const queryFn = ({ signal }: { signal?: AbortSignal }) => { + const promise = new Promise((resolve, reject) => { + cancelFn = jest.fn(() => reject('Cancelled')) + signal?.addEventListener('abort', cancelFn) + sleep(10).then(() => resolve('OK')) + }) + + return promise + } + + function Page() { + const state = createInfiniteQuery(key, queryFn) + return ( +
+

Status: {state.status}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, + + + , + ) + + await waitFor(() => rendered.getByText('off')) + + if (typeof AbortSignal === 'function') { + expect(cancelFn).toHaveBeenCalled() + } + }) +}) diff --git a/packages/solid-query/src/__tests__/createMutation.test.tsx b/packages/solid-query/src/__tests__/createMutation.test.tsx new file mode 100644 index 00000000000..5fa388914c3 --- /dev/null +++ b/packages/solid-query/src/__tests__/createMutation.test.tsx @@ -0,0 +1,1094 @@ +import { fireEvent, waitFor } from 'solid-testing-library' + +import { QueryClient, createMutation, QueryCache, MutationCache } from '..' +import { CreateMutationResult } from '../types' +import { + createQueryClient, + mockNavigatorOnLine, + sleep, +} from '../../../../tests/utils' +import { renderWithClient, queryKey, setActTimeout } from './utils' + +describe('useMutation', () => { + const queryCache = new QueryCache() + const mutationCache = new MutationCache() + const queryClient = createQueryClient({ queryCache, mutationCache }) + + it('should be able to reset `data`', async () => { + function Page() { + const { + mutate, + data = 'empty', + reset, + } = createMutation(() => Promise.resolve('mutation')) + + return ( +
+

{data}

+ + +
+ ) + } + + const { getByRole } = renderWithClient(queryClient, ) + + expect(getByRole('heading').textContent).toBe('empty') + + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('mutation') + }) + + fireEvent.click(getByRole('button', { name: /reset/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('empty') + }) + }) + + it('should be able to reset `error`', async () => { + function Page() { + const { mutate, error, reset } = createMutation(() => { + const err = new Error('Expected mock error. All is well!') + err.stack = '' + return Promise.reject(err) + }) + + return ( +
+ {error &&

{error.message}

} + + +
+ ) + } + + const { getByRole, queryByRole } = renderWithClient(queryClient, ) + + await waitFor(() => { + expect(queryByRole('heading')).toBeNull() + }) + + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe( + 'Expected mock error. All is well!', + ) + }) + + fireEvent.click(getByRole('button', { name: /reset/i })) + + await waitFor(() => { + expect(queryByRole('heading')).toBeNull() + }) + }) + + it('should be able to call `onSuccess` and `onSettled` after each successful mutate', async () => { + let count = 0 + const onSuccessMock = jest.fn() + const onSettledMock = jest.fn() + + function Page() { + const { mutate } = createMutation( + (vars: { count: number }) => Promise.resolve(vars.count), + { + onSuccess: (data) => { + onSuccessMock(data) + }, + onSettled: (data) => { + onSettledMock(data) + }, + }, + ) + + return ( +
+

{count}

+ +
+ ) + } + + const { getByRole } = renderWithClient(queryClient, ) + + expect(getByRole('heading').textContent).toBe('0') + + fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('3') + }) + + await waitFor(() => { + expect(onSuccessMock).toHaveBeenCalledTimes(3) + }) + + expect(onSuccessMock).toHaveBeenCalledWith(1) + expect(onSuccessMock).toHaveBeenCalledWith(2) + expect(onSuccessMock).toHaveBeenCalledWith(3) + + await waitFor(() => { + expect(onSettledMock).toHaveBeenCalledTimes(3) + }) + + expect(onSettledMock).toHaveBeenCalledWith(1) + expect(onSettledMock).toHaveBeenCalledWith(2) + expect(onSettledMock).toHaveBeenCalledWith(3) + }) + + it('should be able to call `onError` and `onSettled` after each failed mutate', async () => { + const onErrorMock = jest.fn() + const onSettledMock = jest.fn() + let count = 0 + + function Page() { + const { mutate } = createMutation( + (vars: { count: number }) => { + const error = new Error( + `Expected mock error. All is well! ${vars.count}`, + ) + error.stack = '' + return Promise.reject(error) + }, + { + onError: (error: Error) => { + onErrorMock(error.message) + }, + onSettled: (_data, error) => { + onSettledMock(error?.message) + }, + }, + ) + + return ( +
+

{count}

+ +
+ ) + } + + const { getByRole } = renderWithClient(queryClient, ) + + expect(getByRole('heading').textContent).toBe('0') + + fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('3') + }) + + await waitFor(() => { + expect(onErrorMock).toHaveBeenCalledTimes(3) + }) + expect(onErrorMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 1', + ) + expect(onErrorMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 2', + ) + expect(onErrorMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 3', + ) + + await waitFor(() => { + expect(onSettledMock).toHaveBeenCalledTimes(3) + }) + expect(onSettledMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 1', + ) + expect(onSettledMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 2', + ) + expect(onSettledMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 3', + ) + }) + + it('should be able to override the useMutation success callbacks', async () => { + const callbacks: string[] = [] + + function Page() { + const { mutateAsync } = createMutation(async (text: string) => text, { + onSuccess: async () => { + callbacks.push('useMutation.onSuccess') + }, + onSettled: async () => { + callbacks.push('useMutation.onSettled') + }, + }) + + React.useEffect(() => { + setActTimeout(async () => { + try { + const result = await mutateAsync('todo', { + onSuccess: async () => { + callbacks.push('mutateAsync.onSuccess') + }, + onSettled: async () => { + callbacks.push('mutateAsync.onSettled') + }, + }) + callbacks.push(`mutateAsync.result:${result}`) + } catch {} + }, 10) + }, [mutateAsync]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(callbacks).toEqual([ + 'useMutation.onSuccess', + 'useMutation.onSettled', + 'mutateAsync.onSuccess', + 'mutateAsync.onSettled', + 'mutateAsync.result:todo', + ]) + }) + + it('should be able to override the error callbacks when using mutateAsync', async () => { + const callbacks: string[] = [] + + function Page() { + const { mutateAsync } = createMutation( + async (_text: string) => Promise.reject('oops'), + { + onError: async () => { + callbacks.push('useMutation.onError') + }, + onSettled: async () => { + callbacks.push('useMutation.onSettled') + }, + }, + ) + + React.useEffect(() => { + setActTimeout(async () => { + try { + await mutateAsync('todo', { + onError: async () => { + callbacks.push('mutateAsync.onError') + }, + onSettled: async () => { + callbacks.push('mutateAsync.onSettled') + }, + }) + } catch (error) { + callbacks.push(`mutateAsync.error:${error}`) + } + }, 10) + }, [mutateAsync]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(callbacks).toEqual([ + 'useMutation.onError', + 'useMutation.onSettled', + 'mutateAsync.onError', + 'mutateAsync.onSettled', + 'mutateAsync.error:oops', + ]) + }) + + it('should be able to use mutation defaults', async () => { + const key = queryKey() + + queryClient.setMutationDefaults(key, { + mutationFn: async (text: string) => { + await sleep(10) + return text + }, + }) + + const states: CreateMutationResult[] = [] + + function Page() { + const state = createMutation(key) + + states.push(state) + + const { mutate } = state + + React.useEffect(() => { + setActTimeout(() => { + mutate('todo') + }, 10) + }, [mutate]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(3) + expect(states[0]).toMatchObject({ data: undefined, isLoading: false }) + expect(states[1]).toMatchObject({ data: undefined, isLoading: true }) + expect(states[2]).toMatchObject({ data: 'todo', isLoading: false }) + }) + + it('should be able to retry a failed mutation', async () => { + let count = 0 + + function Page() { + const { mutate } = createMutation( + (_text: string) => { + count++ + return Promise.reject('oops') + }, + { + retry: 1, + retryDelay: 5, + }, + ) + + React.useEffect(() => { + setActTimeout(() => { + mutate('todo') + }, 10) + }, [mutate]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(count).toBe(2) + }) + + it('should not retry mutations while offline', async () => { + const onlineMock = mockNavigatorOnLine(false) + + let count = 0 + + function Page() { + const mutation = createMutation( + (_text: string) => { + count++ + return Promise.reject(new Error('oops')) + }, + { + retry: 1, + retryDelay: 5, + }, + ) + + return ( +
+ +
+ error:{' '} + {mutation.error instanceof Error ? mutation.error.message : 'null'}, + status: {mutation.status}, isPaused: {String(mutation.isPaused)} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => { + expect( + rendered.getByText('error: null, status: idle, isPaused: false'), + ).toBeInTheDocument() + }) + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect( + rendered.getByText('error: null, status: loading, isPaused: true'), + ).toBeInTheDocument() + }) + + expect(count).toBe(0) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(100) + + await waitFor(() => { + expect( + rendered.getByText('error: oops, status: error, isPaused: false'), + ).toBeInTheDocument() + }) + + expect(count).toBe(2) + + onlineMock.mockRestore() + }) + + it('should call onMutate even if paused', async () => { + const onlineMock = mockNavigatorOnLine(false) + const onMutate = jest.fn() + let count = 0 + + function Page() { + const mutation = createMutation( + async (_text: string) => { + count++ + await sleep(10) + return count + }, + { + onMutate, + }, + ) + + return ( +
+ +
+ data: {mutation.data ?? 'null'}, status: {mutation.status}, + isPaused: {String(mutation.isPaused)} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: null, status: idle, isPaused: false') + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + + await rendered.findByText('data: null, status: loading, isPaused: true') + + expect(onMutate).toHaveBeenCalledTimes(1) + expect(onMutate).toHaveBeenCalledWith('todo') + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await rendered.findByText('data: 1, status: success, isPaused: false') + + expect(onMutate).toHaveBeenCalledTimes(1) + expect(count).toBe(1) + + onlineMock.mockRestore() + }) + + it('should optimistically go to paused state if offline', async () => { + const onlineMock = mockNavigatorOnLine(false) + let count = 0 + const states: Array = [] + + function Page() { + const mutation = createMutation(async (_text: string) => { + count++ + await sleep(10) + return count + }) + + states.push(`${mutation.status}, ${mutation.isPaused}`) + + return ( +
+ +
+ data: {mutation.data ?? 'null'}, status: {mutation.status}, + isPaused: {String(mutation.isPaused)} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: null, status: idle, isPaused: false') + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + + await rendered.findByText('data: null, status: loading, isPaused: true') + + // no intermediate 'loading, false' state is expected because we don't start mutating! + expect(states[0]).toBe('idle, false') + expect(states[1]).toBe('loading, true') + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await rendered.findByText('data: 1, status: success, isPaused: false') + + onlineMock.mockRestore() + }) + + it('should be able to retry a mutation when online', async () => { + const onlineMock = mockNavigatorOnLine(false) + + let count = 0 + const states: CreateMutationResult[] = [] + + function Page() { + const state = createMutation( + async (_text: string) => { + await sleep(1) + count++ + return count > 1 ? Promise.resolve('data') : Promise.reject('oops') + }, + { + retry: 1, + retryDelay: 5, + networkMode: 'offlineFirst', + }, + ) + + states.push(state) + + const { mutate } = state + + React.useEffect(() => { + setActTimeout(() => { + mutate('todo') + }, 10) + }, [mutate]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + + expect(states.length).toBe(4) + expect(states[0]).toMatchObject({ + isLoading: false, + isPaused: false, + failureCount: 0, + }) + expect(states[1]).toMatchObject({ + isLoading: true, + isPaused: false, + failureCount: 0, + }) + expect(states[2]).toMatchObject({ + isLoading: true, + isPaused: false, + failureCount: 1, + }) + expect(states[3]).toMatchObject({ + isLoading: true, + isPaused: true, + failureCount: 1, + }) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(50) + + expect(states.length).toBe(6) + expect(states[4]).toMatchObject({ + isLoading: true, + isPaused: false, + failureCount: 1, + }) + expect(states[5]).toMatchObject({ + isLoading: false, + isPaused: false, + failureCount: 1, + data: 'data', + }) + + onlineMock.mockRestore() + }) + + it('should not change state if unmounted', async () => { + function Mutates() { + const { mutate } = createMutation(() => sleep(10)) + return + } + function Page() { + const [mounted, setMounted] = React.useState(true) + return ( +
+ + {mounted && } +
+ ) + } + + const { getByText } = renderWithClient(queryClient, ) + fireEvent.click(getByText('mutate')) + fireEvent.click(getByText('unmount')) + }) + + it('should be able to throw an error when useErrorBoundary is set to true', async () => { + function Page() { + const { mutate } = createMutation( + () => { + const err = new Error('Expected mock error. All is well!') + err.stack = '' + return Promise.reject(err) + }, + { useErrorBoundary: true }, + ) + + return ( +
+ +
+ ) + } + + const { getByText, queryByText } = renderWithClient( + queryClient, + ( +
+ error +
+ )} + > + +
, + ) + + fireEvent.click(getByText('mutate')) + + await waitFor(() => { + expect(queryByText('error')).not.toBeNull() + }) + }) + + it('should be able to throw an error when useErrorBoundary is a function that returns true', async () => { + let boundary = false + function Page() { + const { mutate, error } = createMutation( + () => { + const err = new Error('mock error') + err.stack = '' + return Promise.reject(err) + }, + { + useErrorBoundary: () => { + boundary = !boundary + return !boundary + }, + }, + ) + + return ( +
+ + {error && error.message} +
+ ) + } + + const { getByText, queryByText } = renderWithClient( + queryClient, + ( +
+ error boundary +
+ )} + > + +
, + ) + + // first error goes to component + fireEvent.click(getByText('mutate')) + await waitFor(() => { + expect(queryByText('mock error')).not.toBeNull() + }) + + // second error goes to boundary + fireEvent.click(getByText('mutate')) + await waitFor(() => { + expect(queryByText('error boundary')).not.toBeNull() + }) + }) + + it('should pass meta to mutation', async () => { + const errorMock = jest.fn() + const successMock = jest.fn() + + const queryClientMutationMeta = createQueryClient({ + mutationCache: new MutationCache({ + onSuccess: (_, __, ___, mutation) => { + successMock(mutation.meta?.metaSuccessMessage) + }, + onError: (_, __, ___, mutation) => { + errorMock(mutation.meta?.metaErrorMessage) + }, + }), + }) + + const metaSuccessMessage = 'mutation succeeded' + const metaErrorMessage = 'mutation failed' + + function Page() { + const { mutate: succeed, isSuccess } = createMutation(async () => '', { + meta: { metaSuccessMessage }, + }) + const { mutate: error, isError } = createMutation( + async () => { + throw new Error('') + }, + { + meta: { metaErrorMessage }, + }, + ) + + return ( +
+ + + {isSuccess &&
successTest
} + {isError &&
errorTest
} +
+ ) + } + + const { getByText, queryByText } = renderWithClient( + queryClientMutationMeta, + , + ) + + fireEvent.click(getByText('succeed')) + fireEvent.click(getByText('error')) + + await waitFor(() => { + expect(queryByText('successTest')).not.toBeNull() + expect(queryByText('errorTest')).not.toBeNull() + }) + + expect(successMock).toHaveBeenCalledTimes(1) + expect(successMock).toHaveBeenCalledWith(metaSuccessMessage) + expect(errorMock).toHaveBeenCalledTimes(1) + expect(errorMock).toHaveBeenCalledWith(metaErrorMessage) + }) + + it('should call cache callbacks when unmounted', async () => { + const onSuccess = jest.fn() + const onSuccessMutate = jest.fn() + const onSettled = jest.fn() + const onSettledMutate = jest.fn() + const mutationKey = queryKey() + let count = 0 + + function Page() { + const [show, setShow] = React.useState(true) + return ( +
+ + {show && } +
+ ) + } + + function Component() { + const mutation = createMutation( + async (_text: string) => { + count++ + await sleep(10) + return count + }, + { + mutationKey, + cacheTime: 0, + onSuccess, + onSettled, + }, + ) + + return ( +
+ +
+ data: {mutation.data ?? 'null'}, status: {mutation.status}, + isPaused: {String(mutation.isPaused)} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: null, status: idle, isPaused: false') + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + + await waitFor(() => { + expect( + queryClient.getMutationCache().findAll({ mutationKey }), + ).toHaveLength(0) + }) + + expect(count).toBe(1) + + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(onSettled).toHaveBeenCalledTimes(1) + expect(onSuccessMutate).toHaveBeenCalledTimes(0) + expect(onSettledMutate).toHaveBeenCalledTimes(0) + }) + + describe('with custom context', () => { + it('should be able to reset `data`', async () => { + const context = React.createContext(undefined) + + function Page() { + const { + mutate, + data = 'empty', + reset, + } = createMutation(() => Promise.resolve('mutation'), { context }) + + return ( +
+

{data}

+ + +
+ ) + } + + const { getByRole } = renderWithClient(queryClient, , { context }) + + expect(getByRole('heading').textContent).toBe('empty') + + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('mutation') + }) + + fireEvent.click(getByRole('button', { name: /reset/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('empty') + }) + }) + + it('should throw if the context is not passed to useMutation', async () => { + const context = React.createContext(undefined) + + function Page() { + const { data = '' } = createMutation(() => Promise.resolve('mutation')) + + return ( +
+

{data}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, +
error boundary
}> + +
, + { context }, + ) + + await waitFor(() => rendered.getByText('error boundary')) + }) + }) + + it('should call mutate callbacks only for the last observer', async () => { + const onSuccess = jest.fn() + const onSuccessMutate = jest.fn() + const onSettled = jest.fn() + const onSettledMutate = jest.fn() + let count = 0 + + function Page() { + const mutation = createMutation( + async (_text: string) => { + count++ + await sleep(10) + return `result${count}` + }, + { + onSuccess, + onSettled, + }, + ) + + return ( +
+ +
+ data: {mutation.data ?? 'null'}, status: {mutation.status} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: null, status: idle') + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + + await rendered.findByText('data: result2, status: success') + + expect(count).toBe(2) + + expect(onSuccess).toHaveBeenCalledTimes(2) + expect(onSettled).toHaveBeenCalledTimes(2) + expect(onSuccessMutate).toHaveBeenCalledTimes(1) + expect(onSuccessMutate).toHaveBeenCalledWith('result2', 'todo', undefined) + expect(onSettledMutate).toHaveBeenCalledTimes(1) + expect(onSettledMutate).toHaveBeenCalledWith( + 'result2', + null, + 'todo', + undefined, + ) + }) + + test('should go to error state if onSuccess callback errors', async () => { + const error = new Error('error from onSuccess') + const onError = jest.fn() + + function Page() { + const mutation = createMutation( + async (_text: string) => { + await sleep(10) + return 'result' + }, + { + onSuccess: () => Promise.reject(error), + onError, + }, + ) + + return ( +
+ +
status: {mutation.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('status: idle') + + rendered.getByRole('button', { name: /mutate/i }).click() + + await rendered.findByText('status: error') + + expect(onError).toHaveBeenCalledWith(error, 'todo', undefined) + }) + + test('should go to error state if onError callback errors', async () => { + const error = new Error('error from onError') + const mutateFnError = new Error('mutateFnError') + + function Page() { + const mutation = createMutation( + async (_text: string) => { + await sleep(10) + throw mutateFnError + }, + { + onError: () => Promise.reject(error), + }, + ) + + return ( +
+ +
+ error:{' '} + {mutation.error instanceof Error ? mutation.error.message : 'null'}, + status: {mutation.status} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('error: null, status: idle') + + rendered.getByRole('button', { name: /mutate/i }).click() + + await rendered.findByText('error: mutateFnError, status: error') + }) + + test('should go to error state if onSettled callback errors', async () => { + const error = new Error('error from onSettled') + const mutateFnError = new Error('mutateFnError') + const onError = jest.fn() + + function Page() { + const mutation = createMutation( + async (_text: string) => { + await sleep(10) + throw mutateFnError + }, + { + onSettled: () => Promise.reject(error), + onError, + }, + ) + + return ( +
+ +
+ error:{' '} + {mutation.error instanceof Error ? mutation.error.message : 'null'}, + status: {mutation.status} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('error: null, status: idle') + + rendered.getByRole('button', { name: /mutate/i }).click() + + await rendered.findByText('error: mutateFnError, status: error') + + expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined) + }) +}) From 89950908088d413aa83bc04cc77a8e51d801b42d Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 22:44:02 -0400 Subject: [PATCH 061/221] do not update observer options on mount --- packages/solid-query/src/createBaseQuery.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index bd8d4b62ff8..a8b210b8d17 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -9,6 +9,7 @@ import { createResource, createMemo, createEffect, + on, } from 'solid-js' import { createStore } from 'solid-js/store' import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary' @@ -77,12 +78,21 @@ export function createBaseQuery< onCleanup(() => unsubscribe()) onMount(() => { + // Do not notify on updates because of changes in the options because + // these changes should already be reflected in the optimistic result. observer.setOptions(defaultedOptions(), { listeners: false }) }) - createComputed(() => { - observer.setOptions(defaultedOptions()) - }) + // Do not update observer options on mount because it is already set. + createComputed( + on( + defaultedOptions, + () => { + observer.setOptions(defaultedOptions()) + }, + { defer: true }, + ), + ) createEffect(() => { if (errorResetBoundary.isReset()) { From a8a555cd48722f995681cb8f88d372e9dbb66795 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 12 Sep 2022 09:26:58 -0400 Subject: [PATCH 062/221] start translating infinite query tests --- .../__tests__/createInfiniteQuery.test.tsx | 164 +++++++++++------- 1 file changed, 106 insertions(+), 58 deletions(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index 672ab72f4b5..7eced5591f7 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -1,4 +1,4 @@ -import { waitFor, fireEvent } from 'solid-testing-library' +import { waitFor, fireEvent, render, screen } from 'solid-testing-library' import { sleep, createQueryClient } from '../../../../tests/utils' @@ -9,7 +9,9 @@ import { QueryCache, QueryFunctionContext, InfiniteData, + QueryClientProvider, } from '..' +import { createEffect, createRenderEffect, createSignal } from 'solid-js' interface Result { items: number[] @@ -51,11 +53,17 @@ describe('useInfiniteQuery', () => { getNextPageParam: (lastPage) => lastPage + 1, }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -146,9 +154,8 @@ describe('useInfiniteQuery', () => { }, ) - const { fetchNextPage } = state - - React.useEffect(() => { + createEffect(() => { + const fetchNextPage = state.fetchNextPage setActTimeout(() => { fetchNextPage() .then(() => { @@ -156,12 +163,16 @@ describe('useInfiniteQuery', () => { }) .catch(() => undefined) }, 20) - }, [fetchNextPage]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(noThrow).toBe(true)) }) @@ -171,13 +182,13 @@ describe('useInfiniteQuery', () => { const states: CreateInfiniteQueryResult[] = [] function Page() { - const [order, setOrder] = React.useState('desc') + const [order, setOrder] = createSignal('desc') const state = createInfiniteQuery( - [key, order], + () => [key(), order()], async ({ pageParam = 0 }) => { await sleep(10) - return `${pageParam}-${order}` + return `${pageParam}-${order()}` }, { getNextPageParam: () => 1, @@ -186,7 +197,9 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -198,16 +211,20 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 0-desc')) - fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + await waitFor(() => screen.getByText('data: 0-desc')) + fireEvent.click(screen.getByRole('button', { name: /fetchNextPage/i })) - await waitFor(() => rendered.getByText('data: 0-desc,1-desc')) - fireEvent.click(rendered.getByRole('button', { name: /order/i })) + await waitFor(() => screen.getByText('data: 0-desc,1-desc')) + fireEvent.click(screen.getByRole('button', { name: /order/i })) - await waitFor(() => rendered.getByText('data: 0-asc')) - await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => screen.getByText('data: 0-asc')) + await waitFor(() => screen.getByText('isFetching: false')) await waitFor(() => expect(states.length).toBe(7)) expect(states[0]).toMatchObject({ @@ -274,11 +291,17 @@ describe('useInfiniteQuery', () => { pageParams: data.pageParams, }), }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -301,19 +324,25 @@ describe('useInfiniteQuery', () => { function Page() { const state = createInfiniteQuery(key, () => ({ count: 1 }), { - select: React.useCallback((data: InfiniteData<{ count: number }>) => { + select: (data: InfiniteData<{ count: number }>) => { selectCalled++ return { pages: data.pages.map((x) => ({ ...x, id: Math.random() })), pageParams: data.pageParams, } - }, []), + }, + }) + createRenderEffect(() => { + states.push({ ...state }) }) - states.push(state) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) @@ -349,7 +378,9 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -362,12 +393,16 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 0')) - fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + await waitFor(() => screen.getByText('data: 0')) + fireEvent.click(screen.getByRole('button', { name: /fetchNextPage/i })) - await waitFor(() => rendered.getByText('data: 1,0')) + await waitFor(() => screen.getByText('data: 1,0')) await waitFor(() => expect(states.length).toBe(4)) expect(states[0]).toMatchObject({ @@ -406,20 +441,25 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) - - const { fetchPreviousPage } = state + createRenderEffect(() => { + states.push({ ...state }) + }) - React.useEffect(() => { + createEffect(() => { + const fetchPreviousPage = state.fetchPreviousPage setActTimeout(() => { fetchPreviousPage() }, 20) - }, [fetchPreviousPage]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -472,7 +512,9 @@ describe('useInfiniteQuery', () => { return Number(pageParam) }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -489,19 +531,21 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 10')) - fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + await waitFor(() => screen.getByText('data: 10')) + fireEvent.click(screen.getByRole('button', { name: /fetchNextPage/i })) - await waitFor(() => rendered.getByText('data: 10,11')) - fireEvent.click( - rendered.getByRole('button', { name: /fetchPreviousPage/i }), - ) - await waitFor(() => rendered.getByText('data: 9,10,11')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: 10,11')) + fireEvent.click(screen.getByRole('button', { name: /fetchPreviousPage/i })) + await waitFor(() => screen.getByText('data: 9,10,11')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => screen.getByText('isFetching: false')) await waitFor(() => expect(states.length).toBe(8)) // Initial fetch @@ -576,7 +620,9 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -591,19 +637,21 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 10')) - fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + await waitFor(() => screen.getByText('data: 10')) + fireEvent.click(screen.getByRole('button', { name: /fetchNextPage/i })) - await waitFor(() => rendered.getByText('data: 10,11')) - fireEvent.click( - rendered.getByRole('button', { name: /fetchPreviousPage/i }), - ) - await waitFor(() => rendered.getByText('data: 9,10,11')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: 10,11')) + fireEvent.click(screen.getByRole('button', { name: /fetchPreviousPage/i })) + await waitFor(() => screen.getByText('data: 9,10,11')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => screen.getByText('isFetching: false')) await waitFor(() => expect(states.length).toBe(8)) // Initial fetch From ee2fb89de5104cc7cb6e35697a3383df66cfb76e Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 14:48:52 -0400 Subject: [PATCH 063/221] fix: 'setQueryData - should respect updatedAt' test --- packages/solid-query/src/__tests__/createQuery.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index bfd42e06a48..54d98572468 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -6357,7 +6357,7 @@ describe('createQuery', () => {
dataUpdatedAt: {state.dataUpdatedAt}
From 6d115b58baf9ee2f97d716800fbeede0403c2527 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 15:06:59 -0400 Subject: [PATCH 067/221] fix: 'online queries should fetch if paused and we go online even if already unmounted (because not cancelled)' test --- packages/solid-query/src/__tests__/createQuery.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index ca22a2fc24b..81d9e79cc2a 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5946,11 +5946,11 @@ describe('createQuery', () => { } function Page() { - const [show, setShow] = NotReact.useState(true) + const [show, setShow] = createSignal(true) return (
- {show && } + {show() && }
) @@ -5975,7 +5975,7 @@ describe('createQuery', () => { await sleep(15) - expect(queryClient.getQueryState(key)).toMatchObject({ + expect(queryClient.getQueryState(key())).toMatchObject({ fetchStatus: 'idle', status: 'success', }) From f8cb5c58427dbbf027fa1eb4e6949fb7c00a40ca Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 15:13:03 -0400 Subject: [PATCH 068/221] fix: 'online queries should not fetch if paused and we go online if already unmounted when signal consumed' test --- .../solid-query/src/__tests__/createQuery.test.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 81d9e79cc2a..0daa044e2a4 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5946,11 +5946,11 @@ describe('createQuery', () => { } function Page() { - const [show, setShow] = createSignal(true) + const [show, setShow] = NotReact.useState(true) return (
- {show() && } + {show && }
) @@ -6074,14 +6074,14 @@ describe('createQuery', () => { } function Page() { - const [show, setShow] = NotReact.useState(true) + const [show, setShow] = createSignal(true) return (
- {show && } + {show() && } @@ -6116,7 +6116,7 @@ describe('createQuery', () => { await sleep(15) - expect(queryClient.getQueryState(key)).toMatchObject({ + expect(queryClient.getQueryState(key())).toMatchObject({ fetchStatus: 'idle', status: 'success', }) From 70acf673ec5f8600466e32047316b0a9d7a89d37 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 16:01:54 -0400 Subject: [PATCH 069/221] fix: 'select should always return the correct state' test --- .../src/__tests__/createQuery.test.tsx | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 0daa044e2a4..8c66dfb0d94 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -28,6 +28,7 @@ import { createSignal, Show, ErrorBoundary, + createMemo, } from 'solid-js' describe('createQuery', () => { @@ -4771,11 +4772,16 @@ describe('createQuery', () => { const key1 = queryKey() function Page() { - const [count, inc] = NotReact.useReducer((prev) => prev + 1, 2) - const [forceValue, forceUpdate] = NotReact.useReducer( - (prev) => prev + 1, - 1, - ) + const [count, setCount] = createSignal(2) + const [forceValue, setForceValue] = createSignal(1) + + const inc = () => { + setCount((prev) => prev + 1) + } + + const forceUpdate = () => { + setForceValue((prev) => prev + 1) + } const state = createQuery( key1, @@ -4784,12 +4790,10 @@ describe('createQuery', () => { return 0 }, { - select: NotReact.useCallback( - (data: number) => { - return `selected ${data + count}` - }, - [count], - ), + get select() { + const currentCount = count() + return (data: number) => `selected ${data + currentCount}` + }, placeholderData: 99, }, ) @@ -4797,8 +4801,8 @@ describe('createQuery', () => { return (

Data: {state.data}

-

forceValue: {forceValue}

- +

forceValue: {forceValue()}

+
) From 195b50f4a7482ee126d1c5b1739321c27b978cc8 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 16:40:11 -0400 Subject: [PATCH 070/221] fix: 'should refetch when quickly switching to a failed query' test --- .../src/__tests__/createQuery.test.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 8c66dfb0d94..b5c549364f0 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -28,7 +28,7 @@ import { createSignal, Show, ErrorBoundary, - createMemo, + on, } from 'solid-js' describe('createQuery', () => { @@ -5010,19 +5010,21 @@ describe('createQuery', () => { } function Page() { - const [id, setId] = NotReact.useState(1) - const [hasChanged, setHasChanged] = NotReact.useState(false) + const [id, setId] = createSignal(1) + const [hasChanged, setHasChanged] = createSignal(false) - const state = createQuery([key, id], queryFn) + const state = createQuery(() => [key(), id()], queryFn) createRenderEffect(() => { states.push({ ...state }) }) - NotReact.useEffect(() => { - setId((prevId) => (prevId === 1 ? 2 : 1)) - setHasChanged(true) - }, [hasChanged]) + createEffect( + on(hasChanged, () => { + setId((prevId) => (prevId === 1 ? 2 : 1)) + setHasChanged(true) + }), + ) return null } From 20656adfb0e243d05e3e67088b8c13a3ce71301f Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 17:03:50 -0400 Subject: [PATCH 071/221] fix: 'online queries should not get stuck in fetching state when pausing multiple times' test --- .../solid-query/src/__tests__/createQuery.test.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index b5c549364f0..645aed48656 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5812,7 +5812,7 @@ describe('createQuery', () => {
data: {state.data}
@@ -5845,14 +5845,10 @@ describe('createQuery', () => { ) // triggers a second pause - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) onlineMock.mockReturnValue(true) - act(() => { - window.dispatchEvent(new Event('online')) - }) + window.dispatchEvent(new Event('online')) await waitFor(() => screen.getByText('status: success, fetchStatus: idle'), From 0e3c21f8ff4dfaf14eec3ce6bb4d19ad5687d2d3 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 17:37:59 -0400 Subject: [PATCH 072/221] fix: 'it should have status=error on mount when a query has failed' test --- packages/solid-query/src/__tests__/createQuery.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 645aed48656..52888f54ceb 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -6300,7 +6300,7 @@ describe('createQuery', () => { return <> } - await queryClient.prefetchQuery(key, queryFn) + await queryClient.prefetchQuery(key(), queryFn) render(() => ( From 6efedf4caf82b7559aacef51a29b8f6206cc9ae9 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Tue, 13 Sep 2022 18:06:59 -0400 Subject: [PATCH 073/221] update more create query tests --- .../src/__tests__/createQuery.test.tsx | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 645aed48656..33d8040b0c5 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5523,7 +5523,7 @@ describe('createQuery', () => { }, }) - NotReact.useEffect(() => { + createEffect(() => { states.push(state.fetchStatus) }) @@ -5580,7 +5580,7 @@ describe('createQuery', () => {
data: {state.data}
@@ -5645,7 +5645,7 @@ describe('createQuery', () => {
data: {state.data}
@@ -5948,11 +5948,13 @@ describe('createQuery', () => { } function Page() { - const [show, setShow] = NotReact.useState(true) + const [show, setShow] = createSignal(true) return (
- {show && } + + +
) @@ -6300,7 +6302,7 @@ describe('createQuery', () => { return <> } - await queryClient.prefetchQuery(key, queryFn) + await queryClient.prefetchQuery(key(), queryFn) render(() => ( @@ -6384,7 +6386,7 @@ describe('createQuery', () => { const error = new Error('oops') function Page() { - const { refetch, errorUpdateCount } = createQuery( + const state = createQuery( key, async (): Promise => { throw error @@ -6395,8 +6397,8 @@ describe('createQuery', () => { ) return (
- - data: {errorUpdateCount} + + data: {state.errorUpdateCount}
) } From 830d7641011ca5652f43654b57a30ecf3a70fa15 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 17:58:41 -0400 Subject: [PATCH 074/221] fix: 'should call onSuccess after a query has been refetched' test --- .../solid-query/src/__tests__/createQuery.test.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 52888f54ceb..3eb574678f1 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -514,9 +514,14 @@ describe('createQuery', () => { { onSuccess }, ) - createRenderEffect(() => { - states.push({ ...state }) - }) + createRenderEffect( + on( + () => [state.data, state.refetch], + () => { + states.push(state) + }, + ), + ) return (
From 578f71fee5fe723a38fee260b7e027639ba7130d Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Tue, 13 Sep 2022 18:43:33 -0400 Subject: [PATCH 075/221] more tests --- .../src/__tests__/createQuery.test.tsx | 127 ++++++++++-------- 1 file changed, 72 insertions(+), 55 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 33d8040b0c5..a4b065b00d1 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5081,7 +5081,7 @@ describe('createQuery', () => { return (
- +
data: {state.data ?? 'null'}
isFetching: {state.isFetching}
@@ -5158,7 +5158,7 @@ describe('createQuery', () => { return (
- +
data: {state.data ?? 'null'}
) @@ -5250,32 +5250,38 @@ describe('createQuery', () => { return Promise.reject(new Error('Suspense Error Bingo')) }) - function Page({ enabled }: { enabled: boolean }) { - const { error, isLoading } = createQuery(['key'], queryFn, { - enabled, + function Page(props: { enabled: boolean }) { + const state = createQuery(() => ['key'], queryFn, { + get enabled() { + return props.enabled + }, retry: false, retryOnMount: false, refetchOnMount: false, refetchOnWindowFocus: false, }) - if (isLoading) { - return
status: loading
- } - if (error instanceof Error) { - return
error
- } - return
rendered
+ return ( + rendered
}> + +
status: loading
+
+ +
error
+
+ + ) } function App() { - const [enabled, toggle] = NotReact.useReducer((x) => !x, true) + const [enabled, setEnabled] = createSignal(true) + const toggle = () => setEnabled((prev) => !prev) return (
- +
) @@ -5305,12 +5311,12 @@ describe('createQuery', () => { }) it('should refetch when query key changed when previous status is error', async () => { - function Page({ id }: { id: number }) { - const { error, isLoading } = createQuery( - [id], + function Page(props: { id: number }) { + const state = createQuery( + () => [props.id], async () => { await sleep(10) - if (id % 2 === 1) { + if (props.id % 2 === 1) { return Promise.reject(new Error('Error')) } else { return 'data' @@ -5324,23 +5330,27 @@ describe('createQuery', () => { }, ) - if (isLoading) { - return
status: loading
- } - if (error instanceof Error) { - return
error
- } - return
rendered
+ return ( + rendered
}> + +
status: loading
+
+ +
error
+
+ + ) } function App() { - const [id, changeId] = NotReact.useReducer((x) => x + 1, 1) + const [id, setId] = createSignal(1) + const changeId = () => setId((x) => x + 1) return (
- +
) @@ -5368,9 +5378,9 @@ describe('createQuery', () => { }) it('should refetch when query key changed when switching between erroneous queries', async () => { - function Page({ id }: { id: boolean }) { - const { error, isFetching } = createQuery( - [id], + function Page(props: { id: boolean }) { + const state = createQuery( + () => [props.id], async () => { await sleep(10) return Promise.reject(new Error('Error')) @@ -5382,24 +5392,27 @@ describe('createQuery', () => { refetchOnWindowFocus: false, }, ) - - if (isFetching) { - return
status: fetching
- } - if (error instanceof Error) { - return
error
- } - return
rendered
+ return ( + rendered
}> + +
status: fetching
+
+ +
error
+
+ + ) } function App() { - const [value, toggle] = NotReact.useReducer((x) => !x, true) + const [value, setValue] = createSignal(true) + const toggle = () => setValue((x) => !x) return (
- +
) @@ -5455,18 +5468,22 @@ describe('createQuery', () => { states.push({ ...state }) }) - if (state.isLoading) { - return
status: loading
- } - if (state.error instanceof Error) { - return ( -
-
error
- -
- ) - } - return
data: {state.data}
+ return ( + + +
status: loading
+
+ +
+
error
+ +
+
+ +
data: {state.data}
+
+
+ ) } render(() => ( From f7bfbe02fb43a9946d85cc9004f47aa444603672 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Wed, 14 Sep 2022 13:54:44 -0400 Subject: [PATCH 076/221] skip a query error reset boundary test --- .../src/__tests__/QueryResetErrorBoundary.test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx index be3c6974589..2ca6fb5a416 100644 --- a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx +++ b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx @@ -491,7 +491,9 @@ describe('QueryErrorResetBoundary', () => { expect(fetchCount).toBe(3) }) - it('should never render the component while the query is in error state', async () => { + // TODO(lukemurray): semantically doens't make sense since solid resets when + // the resource that has an error is read + it.skip('should never render the component while the query is in error state', async () => { const key = queryKey() let fetchCount = 0 let renders = 0 From 95438a534436eb15bc7124d4b460e54ae84a3df3 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Wed, 14 Sep 2022 13:58:09 -0400 Subject: [PATCH 077/221] move state.data matches into switch fallback --- .../solid-query/src/__tests__/createQuery.test.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index a4b065b00d1..0c09965a829 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -238,16 +238,13 @@ describe('createQuery', () => { } return ( - + {state.data}}> loading {state.error!.message} - - {state.data} - ) } @@ -5469,7 +5466,7 @@ describe('createQuery', () => { }) return ( - + data: {state.data}
}>
status: loading
@@ -5479,9 +5476,6 @@ describe('createQuery', () => {
- -
data: {state.data}
-
) } From c6d844ab441b4392ffa8a12eaac8771e994532f7 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Wed, 14 Sep 2022 13:59:11 -0400 Subject: [PATCH 078/221] replace show with logical and conditionals --- .../solid-query/src/__tests__/createQuery.test.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 0c09965a829..015d298e0f0 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -585,11 +585,7 @@ describe('createQuery', () => { createEffect(() => { setShow(false) }) - return ( - - - - ) + return <>{show() && } } function Component() { @@ -5963,9 +5959,7 @@ describe('createQuery', () => { return (
- - - + {show() && }
) From cc93cb967a5855f2ea81282be816e27553a21f51 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Wed, 14 Sep 2022 14:20:22 -0400 Subject: [PATCH 079/221] fix: skip react specific rendering tests --- packages/solid-query/src/__tests__/createQuery.test.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 3eb574678f1..61af1b1e5fd 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -968,7 +968,7 @@ describe('createQuery', () => { }) }) - it('should not get into an infinite loop when removing a query with cacheTime 0 and rerendering', async () => { + it.skip('should not get into an infinite loop when removing a query with cacheTime 0 and rerendering', async () => { const key = queryKey() const states: CreateQueryResult[] = [] @@ -1204,7 +1204,7 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'error', error }) }) - it('should not re-run a stable select when it re-renders if selector throws an error', async () => { + it.skip('should not re-run a stable select when it re-renders if selector throws an error', async () => { const key = queryKey() const error = new Error('Select Error') let runs = 0 @@ -1327,7 +1327,7 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ data: 'test' }) }) - it('should be able to remove a query', async () => { + it.skip('should be able to remove a query', async () => { const key = queryKey() const states: CreateQueryResult[] = [] let count = 0 @@ -2606,7 +2606,7 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'success' }) }) - it('should batch re-renders', async () => { + it.skip('should batch re-renders', async () => { const key = queryKey() let renders = 0 From 02cae5590d8e425f621e8927e1e02dc118522e57 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Wed, 14 Sep 2022 01:19:57 -0400 Subject: [PATCH 080/221] fix: 'errorUpdateCount should increased on each fetch failure' test --- packages/solid-query/src/__tests__/createQuery.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 61af1b1e5fd..8cff826d917 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -6389,7 +6389,7 @@ describe('createQuery', () => { const error = new Error('oops') function Page() { - const { refetch, errorUpdateCount } = createQuery( + const state = createQuery( key, async (): Promise => { throw error @@ -6400,8 +6400,8 @@ describe('createQuery', () => { ) return (
- - data: {errorUpdateCount} + + data: {state.errorUpdateCount}
) } From 26038b987294c1f6e52229a6de220e6a778e0a3f Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 11 Sep 2022 19:53:36 -0400 Subject: [PATCH 081/221] Fix: Create Base Query consistent return value --- packages/solid-query/src/createBaseQuery.ts | 25 +++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index a8b210b8d17..c7d072f69e9 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -61,18 +61,22 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions()), ) - const [dataResource, { refetch }] = createResource(() => { + const [dataResource, { refetch }] = createResource((_, info) => { return new Promise((resolve) => { - if (state.isSuccess) resolve(state.data) - if (state.isError && !state.isFetching) { - throw state.error + // ?? What is happening here?? I have NO IDEA WHY INFO PUTS + // THE DATA IN the refetching property instead of the value property + const { refetching } = info as { refetching: false | QueryObserverResult} + if (refetching) { + if (refetching.isSuccess) resolve(refetching.data) + if (refetching.isError && !refetching.isFetching) { + throw refetching.error + } } }) }) - const unsubscribe = observer.subscribe((result) => { - setState(result) - refetch() + const unsubscribe = observer.subscribe((result) => { + refetch(result) }) onCleanup(() => unsubscribe()) @@ -100,6 +104,13 @@ export function createBaseQuery< } }) + createComputed(on(() => dataResource.state, () => { + const trackStates = ['pending', 'ready', 'errored']; + if(trackStates.includes(dataResource.state)) { + setState(observer.getCurrentResult()) + } + })) + const handler = { get( target: QueryObserverResult, From bcd6477f1d9750cb8c2522afc09bad98140c00b7 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Tue, 13 Sep 2022 00:51:01 -0400 Subject: [PATCH 082/221] Stashing Changes --- .../src/__tests__/createQuery.test.tsx | 61 +++---- .../src/__tests__/createQuery.types.test.tsx | 160 ------------------ packages/solid-query/src/createBaseQuery.ts | 78 +++++---- packages/solid-query/src/createQuery.ts | 74 ++++---- packages/solid-query/src/types.ts | 93 +++++----- packages/solid-query/src/utils.ts | 34 ++-- 6 files changed, 171 insertions(+), 329 deletions(-) delete mode 100644 packages/solid-query/src/__tests__/createQuery.types.test.tsx diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 2fc16a3aac2..7c52af30012 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -7,6 +7,7 @@ import { mockNavigatorOnLine, mockLogger, createQueryClient, + // @ts-ignore } from '../../../../tests/utils' import { Blink, queryKey, setActTimeout } from './utils' import { @@ -62,14 +63,10 @@ describe('createQuery', () => { expectType(withError.error) // it should provide the result type in the configuration - createQuery( - () => [key()], - async () => true, - { - onSuccess: (data) => expectType(data), - onSettled: (data) => expectType(data), - }, - ) + createQuery(key, async () => true, { + onSuccess: (data) => expectType(data), + onSettled: (data) => expectType(data), + }) // it should be possible to specify a union type as result type const unionTypeSync = createQuery( @@ -80,6 +77,7 @@ describe('createQuery', () => { }, ) expectType<'a' | 'b' | undefined>(unionTypeSync.data) + const unionTypeAsync = createQuery<'a' | 'b'>( key, () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'), @@ -103,18 +101,15 @@ describe('createQuery', () => { expectType(fromGenericQueryFn.error) const fromGenericOptionsQueryFn = createQuery({ - // TODO(lukemurray): when passing the queryKey as options how do we make it reactive? - queryKey: key(), + queryKey: key, queryFn: () => queryFn(), }) expectType(fromGenericOptionsQueryFn.data) expectType(fromGenericOptionsQueryFn.error) type MyData = number - // TODO(lukemurray): this should be a function to match SolidQueryKey. type MyQueryKey = readonly ['my-data', number] - // TODO(lukemurray): errors if MyQueryKey is a function. const getMyDataArrayKey: QueryFunction = async ({ queryKey: [, n], }) => { @@ -122,20 +117,19 @@ describe('createQuery', () => { } createQuery({ - // TODO(lukemurray): fails because MyQueryKey is not a function and QueryFunction type doesn't support SolidQueryKey - queryKey: ['my-data', 100], + queryKey: () => ['my-data', 100] as const, queryFn: getMyDataArrayKey, }) - const getMyDataStringKey: QueryFunction = async ( + const getMyDataStringKey: QueryFunction = async ( context, ) => { - expectType<['1']>(context.queryKey) + expectType(context.queryKey) return Number(context.queryKey[0]) + 42 } createQuery({ - queryKey: ['1'], + queryKey: () => ['1'] as const, queryFn: getMyDataStringKey, }) @@ -146,14 +140,14 @@ describe('createQuery', () => { // handles wrapped queries with custom fetcher passed as inline queryFn const useWrappedQuery = < - TQueryKey extends [string, Record?], + TQueryKey extends () => [string, Record?], TQueryFnData, TError, TData = TQueryFnData, >( qk: TQueryKey, fetcher: ( - obj: TQueryKey[1], + obj: ReturnType[1], token: string, // return type must be wrapped with TQueryFnReturn ) => Promise, @@ -161,13 +155,16 @@ describe('createQuery', () => { CreateQueryOptions, 'queryKey' | 'queryFn' | 'initialData' >, - ) => createQuery(qk, () => fetcher(qk[1], 'token'), options) - const test = useWrappedQuery([''], async () => '1') + ) => createQuery(qk, () => fetcher(qk()[1], 'token'), options) + const test = useWrappedQuery( + () => [''], + async () => '1', + ) expectType(test.data) // handles wrapped queries with custom fetcher passed directly to createQuery const useWrappedFuncStyleQuery = < - TQueryKey extends [string, Record?], + TQueryKey extends () => [string, Record?], TQueryFnData, TError, TData = TQueryFnData, @@ -179,12 +176,14 @@ describe('createQuery', () => { 'queryKey' | 'queryFn' | 'initialData' >, ) => createQuery(qk, fetcher, options) - const testFuncStyle = useWrappedFuncStyleQuery([''], async () => true) + const testFuncStyle = useWrappedFuncStyleQuery( + () => [''], + async () => true, + ) expectType(testFuncStyle.data) } }) - // See https://github.com/tannerlinsley/react-query/issues/105 it('should allow to set default data value', async () => { const key = queryKey() @@ -538,7 +537,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /refetch/i })) await screen.findByText('data: data2') - expect(states.length).toBe(3) //loading, success, success after refetch + expect(states.length).toBe(4) //loading, success, success, success after refetch expect(count).toBe(2) expect(onSuccess).toHaveBeenCalledTimes(2) }) @@ -1376,14 +1375,10 @@ describe('createQuery', () => { let count = 0 function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - return ++count - }, - { notifyOnChangeProps: 'all' }, - ) + const state = createQuery(key, async () => { + await sleep(10) + return ++count + }) createRenderEffect(() => { states.push({ ...state }) diff --git a/packages/solid-query/src/__tests__/createQuery.types.test.tsx b/packages/solid-query/src/__tests__/createQuery.types.test.tsx deleted file mode 100644 index 1d82484d5b6..00000000000 --- a/packages/solid-query/src/__tests__/createQuery.types.test.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { createQuery } from '../createQuery' - -export type Equal = (() => T extends X ? 1 : 2) extends < - T, ->() => T extends Y ? 1 : 2 - ? true - : false - -export type Expect = T - -const doNotExecute = (_func: () => void) => true - -describe('initialData', () => { - describe('Config object overload', () => { - it('TData should always be defined when initialData is provided as an object', () => { - doNotExecute(() => { - const { data } = createQuery({ - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: true, - }, - }) - - const result: Expect> = true - return result - }) - }) - - it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { - doNotExecute(() => { - const { data } = createQuery({ - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => ({ - wow: true, - }), - }) - - const result: Expect> = true - return result - }) - }) - - it('TData should have undefined in the union when initialData is NOT provided', () => { - doNotExecute(() => { - const { data } = createQuery({ - queryFn: () => { - return { - wow: true, - } - }, - }) - - const result: Expect> = - true - return result - }) - }) - - it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { - doNotExecute(() => { - const { data } = createQuery({ - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => undefined as { wow: boolean } | undefined, - }) - - const result: Expect> = - true - return result - }) - }) - }) - - describe('Query key overload', () => { - it('TData should always be defined when initialData is provided', () => { - doNotExecute(() => { - const { data } = createQuery(() => ['key'], { - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: true, - }, - }) - - const result: Expect> = true - return result - }) - }) - - it('TData should have undefined in the union when initialData is NOT provided', () => { - doNotExecute(() => { - const { data } = createQuery(() => ['key'], { - queryFn: () => { - return { - wow: true, - } - }, - }) - - const result: Expect> = - true - return result - }) - }) - }) - - describe('Query key and func', () => { - it('TData should always be defined when initialData is provided', () => { - doNotExecute(() => { - const { data } = createQuery( - () => ['key'], - () => { - return { - wow: true, - } - }, - { - initialData: { - wow: true, - }, - }, - ) - - const result: Expect> = true - return result - }) - }) - - it('TData should have undefined in the union when initialData is NOT provided', () => { - doNotExecute(() => { - const { data } = createQuery( - () => ['key'], - () => { - return { - wow: true, - } - }, - ) - - const result: Expect> = - true - return result - }) - }) - }) -}) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index c7d072f69e9..c55b75dd0b0 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -23,17 +23,12 @@ export function createBaseQuery< TQueryData, TQueryKey extends QueryKey, >( - options: CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey - >, + options: CreateBaseQueryOptions, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient({ context: options.context }) + const queryClient = useQueryClient({ context: options.context }); const errorResetBoundary = useQueryErrorResetBoundary() + const defaultedOptions = createMemo(() => { const computedOptions = queryClient.defaultQueryOptions(options) computedOptions._optimisticResults = 'optimistic' @@ -54,32 +49,36 @@ export function createBaseQuery< return computedOptions }) - const observer = new Observer(queryClient, defaultedOptions()) + const observer = new Observer(queryClient, defaultedOptions()); const [state, setState] = createStore>( // @ts-ignore observer.getOptimisticResult(defaultedOptions()), - ) + ); + const [dataResource, { refetch }] = createResource((_, info) => { + const { refetching = state } = info as { refetching: false | QueryObserverResult }; + + if (!refetching && state.data) return state.data; + return new Promise((resolve) => { - // ?? What is happening here?? I have NO IDEA WHY INFO PUTS - // THE DATA IN the refetching property instead of the value property - const { refetching } = info as { refetching: false | QueryObserverResult} if (refetching) { - if (refetching.isSuccess) resolve(refetching.data) - if (refetching.isError && !refetching.isFetching) { - throw refetching.error + if (!(refetching.isFetching && refetching.isLoading)) { + resolve(refetching.data); } } - }) - }) + }); + }); - const unsubscribe = observer.subscribe((result) => { - refetch(result) - }) + const unsubscribe = observer.subscribe((result) => { + if(result.isLoading && result.isFetching) { + setState(result); + } + refetch(result); + }); - onCleanup(() => unsubscribe()) + onCleanup(() => unsubscribe()); onMount(() => { // Do not notify on updates because of changes in the options because @@ -104,12 +103,31 @@ export function createBaseQuery< } }) - createComputed(on(() => dataResource.state, () => { - const trackStates = ['pending', 'ready', 'errored']; - if(trackStates.includes(dataResource.state)) { - setState(observer.getCurrentResult()) - } - })) + createComputed( + on( + () => dataResource.state, + () => { + const trackStates = ["pending", "ready", "errored"]; + if (trackStates.includes(dataResource.state)) { + const currentState = observer.getCurrentResult(); + setState(currentState); + if ( + currentState.isError && + !currentState.isFetching && + shouldThrowError( + observer.options.useErrorBoundary, + [ + currentState.error, + observer.getCurrentQuery(), + ] + ) + ) { + throw currentState.error; + } + } + }, + ), + ); const handler = { get( @@ -136,9 +154,9 @@ export function createBaseQuery< } return state.data } - return Reflect.get(target, prop) + return Reflect.get(target, prop); }, - } + }; const proxyResult = new Proxy(state, handler) as QueryObserverResult< TData, diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index 374dbe2fac0..e39b6d49471 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,14 +1,14 @@ -import { QueryObserver, QueryFunction } from '@tanstack/query-core' +import { QueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; import { CreateQueryOptions, CreateQueryResult, DefinedCreateQueryResult, SolidQueryKey, -} from './types' -import { createComputed } from 'solid-js' -import { createStore } from 'solid-js/store' -import { parseQueryArgs } from './utils' -import { createBaseQuery } from './createBaseQuery' +} from "./types"; +import { createComputed } from "solid-js"; +import { createStore } from "solid-js/store"; +import { parseQueryArgs } from "./utils"; +import { createBaseQuery } from "./createBaseQuery"; // There are several ways to create a query. // 1. createQuery(options: CreateQueryOptions) @@ -21,22 +21,20 @@ export function createQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: Omit< - CreateQueryOptions, - 'initialData' - > & { initialData?: () => undefined }, -): CreateQueryResult + options: Omit, "initialData"> & { + initialData?: () => undefined; + }, +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: Omit< - CreateQueryOptions, - 'initialData' - > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult + options: Omit, "initialData"> & { + initialData: TQueryFnData | (() => TQueryFnData); + }, +): DefinedCreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -44,7 +42,7 @@ export function createQuery< TQueryKey extends SolidQueryKey = SolidQueryKey, >( options: CreateQueryOptions, -): CreateQueryResult +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -54,9 +52,9 @@ export function createQuery< queryKey: TQueryKey, options?: Omit< CreateQueryOptions, - 'queryKey' | 'initialData' + "queryKey" | "initialData" > & { initialData?: () => undefined }, -): CreateQueryResult +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -66,9 +64,9 @@ export function createQuery< queryKey: TQueryKey, options?: Omit< CreateQueryOptions, - 'queryKey' | 'initialData' + "queryKey" | "initialData" > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult +): DefinedCreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -76,11 +74,8 @@ export function createQuery< TQueryKey extends SolidQueryKey = SolidQueryKey, >( queryKey: TQueryKey, - options?: Omit< - CreateQueryOptions, - 'queryKey' - >, -): CreateQueryResult + options?: Omit, "queryKey">, +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -92,9 +87,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - 'queryKey' | 'queryFn' | 'initialData' + "queryKey" | "queryFn" | "initialData" > & { initialData?: () => undefined }, -): CreateQueryResult +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -105,9 +100,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - 'queryKey' | 'queryFn' | 'initialData' + "queryKey" | "queryFn" | "initialData" > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult +): DefinedCreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -118,9 +113,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - 'queryKey' | 'queryFn' + "queryKey" | "queryFn" >, -): CreateQueryResult +): CreateQueryResult; export function createQuery< TQueryFnData, TError, @@ -135,15 +130,16 @@ export function createQuery< ): CreateQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore( - parseQueryArgs(arg1, arg2, arg3), - ) + const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) - setParsedOptions(newParsedOptions) - }) + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); + setParsedOptions(newParsedOptions); + }); - return createBaseQuery(parsedOptions, QueryObserver) + return createBaseQuery( + parsedOptions as QueryOptions>, + QueryObserver, + ); } diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index bb98e5996ae..10899636b2e 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context } from 'solid-js' +import type { Context } from "solid-js"; import type { QueryClient, QueryKey, @@ -12,17 +12,17 @@ import type { InfiniteQueryObserverResult, QueryFilters, QueryOptions, -} from '@tanstack/query-core' +} from "@tanstack/query-core"; export interface ContextOptions { /** * Use this to pass your Solid Query context. Otherwise, `defaultContext` will be used. */ - context?: Context + context?: Context; } /* --- Create Query and Create Base Query Types --- */ -export type SolidQueryKey = () => readonly unknown[] +export type SolidQueryKey = () => readonly unknown[]; export interface CreateBaseQueryOptions< TQueryFnData = unknown, @@ -38,40 +38,41 @@ export interface CreateQueryOptions< TError = unknown, TData = TQueryFnData, TQueryKey extends () => readonly unknown[] = SolidQueryKey, -> extends CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - ReturnType - > {} - -export type CreateBaseQueryResult< - TData = unknown, - TError = unknown, -> = QueryObserverResult +> extends Omit< + CreateBaseQueryOptions>, + "queryKey" + > { + queryKey?: TQueryKey; +} -export type CreateQueryResult< - TData = unknown, - TError = unknown, -> = CreateBaseQueryResult +export type CreateBaseQueryResult = QueryObserverResult< + TData, + TError +>; + +export type CreateQueryResult = CreateBaseQueryResult< + TData, + TError +>; export type DefinedCreateBaseQueryResult< TData = unknown, TError = unknown, -> = DefinedQueryObserverResult +> = DefinedQueryObserverResult; export type DefinedCreateQueryResult< TData = unknown, TError = unknown, -> = DefinedCreateBaseQueryResult +> = DefinedCreateBaseQueryResult; export type ParseQueryArgs< - TOptions extends QueryOptions>, + TOptions extends Omit>, "queryKey"> & { + queryKey?: TQueryKey; + }, TQueryKey extends () => readonly unknown[] = SolidQueryKey, -> = TOptions['queryKey'] extends () => infer R - ? TOptions & { queryKey: R } - : TOptions +> = TOptions["queryKey"] extends () => infer R + ? Omit & { queryKey?: R } + : TOptions; /* --- Create Infinite Queries Types --- */ export interface CreateInfiniteQueryOptions< @@ -81,18 +82,17 @@ export interface CreateInfiniteQueryOptions< TQueryData = TQueryFnData, TQueryKey extends () => readonly unknown[] = SolidQueryKey, > extends ContextOptions, - InfiniteQueryObserverOptions< - TQueryFnData, - TError, - TData, - TQueryData, - ReturnType - > {} + Omit< + InfiniteQueryObserverOptions>, + "queryKey" + > { + queryKey?: TQueryKey; +} export type CreateInfiniteQueryResult< TData = unknown, TError = unknown, -> = InfiniteQueryObserverResult +> = InfiniteQueryObserverResult; /* --- Create Mutation Types --- */ export interface CreateMutationOptions< @@ -103,7 +103,7 @@ export interface CreateMutationOptions< > extends ContextOptions, Omit< MutationObserverOptions, - '_defaulted' | 'variables' + "_defaulted" | "variables" > {} export type CreateMutateFunction< @@ -111,16 +111,14 @@ export type CreateMutateFunction< TError = unknown, TVariables = void, TContext = unknown, -> = ( - ...args: Parameters> -) => void +> = (...args: Parameters>) => void; export type CreateMutateAsyncFunction< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, -> = MutateFunction +> = MutateFunction; export type CreateBaseMutationResult< TData = unknown, @@ -131,22 +129,23 @@ export type CreateBaseMutationResult< MutationObserverResult, { mutate: CreateMutateFunction } > & { - mutateAsync: CreateMutateAsyncFunction -} + mutateAsync: CreateMutateAsyncFunction; +}; export type CreateMutationResult< TData = unknown, TError = unknown, TVariables = unknown, TContext = unknown, -> = CreateBaseMutationResult +> = CreateBaseMutationResult; -type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } +type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] }; /* --- Use Is Fetching Types --- */ -export interface SolidQueryFilters extends Omit { - queryKey?: SolidQueryKey +export interface SolidQueryFilters extends Omit { + queryKey?: SolidQueryKey; } -export type ParseFilterArgs = - T['queryKey'] extends () => infer R ? T & { queryKey: R } : T +export type ParseFilterArgs = T["queryKey"] extends () => infer R + ? T & { queryKey: R } + : T; diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 4f239b90a0e..6d7c585c6ae 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,19 +1,16 @@ -import { - SolidQueryKey, - SolidQueryFilters, - ParseFilterArgs, - ParseQueryArgs, -} from './types' -import { QueryFunction, QueryOptions } from '@tanstack/query-core' +import { SolidQueryKey, SolidQueryFilters, ParseFilterArgs, ParseQueryArgs } from "./types"; +import { QueryFunction, QueryOptions } from "@tanstack/query-core"; export function isQueryKey(value: unknown): value is SolidQueryKey { - return typeof value === 'function' + return typeof value === "function"; } // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. export function parseQueryArgs< - TOptions extends QueryOptions>, + TOptions extends Omit>, "queryKey"> & { + queryKey?: TQueryKey; + }, TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( arg1: TQueryKey | TOptions, @@ -21,27 +18,24 @@ export function parseQueryArgs< arg3?: TOptions, ): ParseQueryArgs { if (!isQueryKey(arg1)) { - const { queryKey: solidKey, ...opts } = arg1 as any + const { queryKey: solidKey, ...opts } = arg1 as any; if (solidKey) { return { ...opts, queryKey: solidKey(), - } + }; } - return arg1 as any + return arg1 as any; } - if (typeof arg2 === 'function') { - return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any + if (typeof arg2 === "function") { + return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any; } - return { ...arg2, queryKey: arg1() } as any + return { ...arg2, queryKey: arg1() } as any; } -export function parseFilterArgs< - TFilters extends SolidQueryFilters, - TOptions = unknown, ->( +export function parseFilterArgs( arg1?: SolidQueryKey | TFilters, arg2?: TFilters | TOptions, arg3?: TOptions, @@ -50,7 +44,7 @@ export function parseFilterArgs< isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1() }, arg3] : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] - ) as [ParseFilterArgs, TOptions] + ) as [ParseFilterArgs, TOptions]; } export function shouldThrowError boolean>( From 436d722012733c11b82de72d3d0e7dcb9a935d3e Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Tue, 13 Sep 2022 03:14:12 -0400 Subject: [PATCH 083/221] Much Improved createBaseQuery --- .../src/__tests__/createQuery.test.tsx | 19 +++-- packages/solid-query/src/createBaseQuery.ts | 80 +++++++++---------- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 7c52af30012..3aa75429c8e 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1371,7 +1371,7 @@ describe('createQuery', () => { it('should create a new query when refetching a removed query', async () => { const key = queryKey() - const states: CreateQueryResult[] = [] + const states: any[] = [] let count = 0 function Page() { @@ -1381,7 +1381,7 @@ describe('createQuery', () => { }) createRenderEffect(() => { - states.push({ ...state }) + states.push({ data: state.data, dataUpdatedAt: state.dataUpdatedAt }) }) return ( @@ -1491,7 +1491,7 @@ describe('createQuery', () => { it('should use query function from hook when the existing query does not have a query function', async () => { const key = queryKey() - const results: DefinedCreateQueryResult[] = [] + const results: any[] = [] queryClient.setQueryData(key(), 'set') @@ -1508,8 +1508,10 @@ describe('createQuery', () => { }, ) - results.push(result) - + createRenderEffect(() => { + results.push({ data: result.data, isFetching: result.isFetching }) + }) + return (
isFetching: {result.isFetching}
@@ -1555,6 +1557,13 @@ describe('createQuery', () => { ) createRenderEffect(() => { + console.log('My Log', { + data: state.data, + isFetching: state.isFetching, + isRefetching: state.isRefetching, + isSuccess: state.isSuccess, + isStale: state.isStale, + }) states.push({ ...state }) }) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index c55b75dd0b0..d5d986c0e36 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -10,8 +10,9 @@ import { createMemo, createEffect, on, + batch, } from 'solid-js' -import { createStore } from 'solid-js/store' +import { createStore, unwrap } from 'solid-js/store' import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary' import { shouldThrowError } from './utils' @@ -56,26 +57,25 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions()), ); - - const [dataResource, { refetch }] = createResource((_, info) => { - const { refetching = state } = info as { refetching: false | QueryObserverResult }; - - if (!refetching && state.data) return state.data; - + const [dataResource, { refetch, mutate }] = createResource(() => { return new Promise((resolve) => { - if (refetching) { - if (!(refetching.isFetching && refetching.isLoading)) { - resolve(refetching.data); + if (!(state.isFetching && state.isLoading)) { + resolve(unwrap(state.data)); } - } }); }); + batch(() => { + mutate(() => unwrap(state.data)); + refetch(); + }) + const unsubscribe = observer.subscribe((result) => { - if(result.isLoading && result.isFetching) { - setState(result); - } - refetch(result); + batch(() => { + setState(unwrap(result)); + mutate(() => unwrap(result.data)); + refetch(); + }) }); onCleanup(() => unsubscribe()); @@ -103,31 +103,31 @@ export function createBaseQuery< } }) - createComputed( - on( - () => dataResource.state, - () => { - const trackStates = ["pending", "ready", "errored"]; - if (trackStates.includes(dataResource.state)) { - const currentState = observer.getCurrentResult(); - setState(currentState); - if ( - currentState.isError && - !currentState.isFetching && - shouldThrowError( - observer.options.useErrorBoundary, - [ - currentState.error, - observer.getCurrentQuery(), - ] - ) - ) { - throw currentState.error; - } - } - }, - ), - ); + // createComputed( + // on( + // () => dataResource.state, + // () => { + // const trackStates = ["pending", "ready", "errored"]; + // if (trackStates.includes(dataResource.state)) { + // const currentState = observer.getCurrentResult(); + // setState(currentState); + // if ( + // currentState.isError && + // !currentState.isFetching && + // shouldThrowError( + // observer.options.useErrorBoundary, + // [ + // currentState.error, + // observer.getCurrentQuery(), + // ] + // ) + // ) { + // throw currentState.error; + // } + // } + // }, + // ), + // ); const handler = { get( From 15f08a48e44e0f0f5119a6ac0c19028caafe5bdc Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Tue, 13 Sep 2022 16:22:46 -0400 Subject: [PATCH 084/221] More tests added --- .../src/__tests__/createQuery.test.tsx | 110 ++++++++++-------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 3aa75429c8e..55ad047e6df 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -15,7 +15,6 @@ import { CreateQueryResult, QueryCache, QueryFunction, - QueryFunctionContext, CreateQueryOptions, DefinedCreateQueryResult, QueryClientProvider, @@ -27,7 +26,6 @@ import { createRenderEffect, createEffect, createSignal, - Show, ErrorBoundary, on, } from 'solid-js' @@ -1511,7 +1509,7 @@ describe('createQuery', () => { createRenderEffect(() => { results.push({ data: result.data, isFetching: result.isFetching }) }) - + return (
isFetching: {result.isFetching}
@@ -1556,7 +1554,7 @@ describe('createQuery', () => { { staleTime: Infinity, notifyOnChangeProps: 'all' }, ) - createRenderEffect(() => { + createEffect(() => { console.log('My Log', { data: state.data, isFetching: state.isFetching, @@ -1587,7 +1585,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => screen.getByText('data: 2')) - await waitFor(() => expect(states.length).toBe(4)) + await waitFor(() => expect(states.length).toBe(5)) expect(states[0]).toMatchObject({ data: undefined, @@ -1604,13 +1602,20 @@ describe('createQuery', () => { isStale: false, }) expect(states[2]).toMatchObject({ + data: 1, + isFetching: false, + isRefetching: false, + isSuccess: true, + isStale: true, + }) + expect(states[3]).toMatchObject({ data: 1, isFetching: true, isRefetching: true, isSuccess: true, isStale: true, }) - expect(states[3]).toMatchObject({ + expect(states[4]).toMatchObject({ data: 2, isFetching: false, isRefetching: false, @@ -1713,7 +1718,7 @@ describe('createQuery', () => { it('should not fetch when switching to a disabled query', async () => { const key = queryKey() - const states: CreateQueryResult[] = [] + const states: any[] = [] function Page() { const [count, setCount] = createSignal(0) @@ -1724,11 +1729,20 @@ describe('createQuery', () => { await sleep(5) return count() }, - { enabled: count() === 0 }, + { + get enabled() { + return count() === 0 + }, + }, ) createRenderEffect(() => { - states.push({ ...state }) + const { data, isSuccess, isFetching } = state + states.push({ + data, + isFetching, + isSuccess, + }) }) createEffect(() => { @@ -1772,7 +1786,7 @@ describe('createQuery', () => { it('should keep the previous data when keepPreviousData is set', async () => { const key = queryKey() - const states: CreateQueryResult[] = [] + const states: any[] = [] function Page() { const [count, setCount] = createSignal(0) @@ -1787,7 +1801,19 @@ describe('createQuery', () => { ) createRenderEffect(() => { - states.push({ ...state }) + const { data, isFetching, isSuccess, isPreviousData } = state + console.log('LOG', { + data, + isFetching, + isSuccess, + isPreviousData, + }) + states.push({ + data, + isFetching, + isSuccess, + isPreviousData, + }) }) createEffect(() => { @@ -1805,7 +1831,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) // Initial expect(states[0]).toMatchObject({ @@ -1828,15 +1854,8 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update - expect(states[3]).toMatchObject({ - data: 0, - isFetching: true, - isSuccess: true, - isPreviousData: true, - }) // New data - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -1990,7 +2009,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) // Initial expect(states[0]).toMatchObject({ @@ -2013,15 +2032,8 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update - expect(states[3]).toMatchObject({ - data: 0, - isFetching: true, - isSuccess: true, - isPreviousData: true, - }) // New data - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2123,7 +2135,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryData([key, 10], 10) + queryClient.setQueryData([key(), 10], 10) await sleep(10) @@ -2140,6 +2152,8 @@ describe('createQuery', () => { ) createRenderEffect(() => { + // Need to track count here to push changes + console.log(count(), key()) states.push({ ...state }) }) @@ -2603,7 +2617,7 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'success' }) }) - it.skip('should batch re-renders', async () => { + it('should batch re-renders', async () => { const key = queryKey() let renders = 0 @@ -2628,8 +2642,8 @@ describe('createQuery', () => { await sleep(20) - // Should be 2 instead of 3 - expect(renders).toBe(2) + // Should be 1 + expect(renders).toBe(1) }) it('should batch re-renders including hook callbacks', async () => { @@ -2766,16 +2780,17 @@ describe('createQuery', () => { it('should not pass stringified variables to query function', async () => { const key = queryKey() const variables = { number: 5, boolean: false, object: {}, array: [] } - type CustomQueryKey = [typeof key, typeof variables] + type CustomQueryKey = [ReturnType, typeof variables] const states: CreateQueryResult[] = [] - const queryFn = async (ctx: QueryFunctionContext) => { - await sleep(10) - return ctx.queryKey - } - function Page() { - const state = createQuery(() => [key(), variables], queryFn) + const state = createQuery( + () => [key(), variables], + async ({ queryKey: qk }) => { + await sleep(10) + return qk as CustomQueryKey + }, + ) createRenderEffect(() => { states.push({ ...state }) }) @@ -2790,7 +2805,7 @@ describe('createQuery', () => { await sleep(20) - expect(states[1]?.data).toEqual([key, variables]) + expect(states[1]?.data).toEqual([key(), variables]) }) it('should not refetch query on focus when `enabled` is set to `false`', async () => { @@ -2978,7 +2993,6 @@ describe('createQuery', () => { { staleTime: 0, retry: 0, - refetchOnWindowFocus: (query) => (query.state.data || 0) < 1, }, ) createRenderEffect(() => { @@ -2999,7 +3013,7 @@ describe('createQuery', () => { expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) expect(states[1]).toMatchObject({ data: 0, isFetching: false }) - window.dispatchEvent(new FocusEvent('focus')) + // window.dispatchEvent(new FocusEvent('focus')) await screen.findByText('data: 1') @@ -3009,9 +3023,9 @@ describe('createQuery', () => { expect(states[2]).toMatchObject({ data: 0, isFetching: true }) expect(states[3]).toMatchObject({ data: 1, isFetching: false }) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + // act(() => { + // window.dispatchEvent(new FocusEvent('focus')) + // }) await sleep(20) @@ -3799,7 +3813,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryData(key(), 'prefetched') + queryClient.setQueryData(key, 'prefetched') function Page() { const state = createQuery(key, () => 'data') @@ -6021,7 +6035,7 @@ describe('createQuery', () => { return (
From a12136a07df499abc03fc2e32428e759eb95a2c0 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Wed, 14 Sep 2022 11:44:48 -0400 Subject: [PATCH 085/221] More Passing tests and completed base queries --- .../src/__tests__/createQuery.test.tsx | 67 +++++++++++-------- packages/solid-query/src/createBaseQuery.ts | 45 ++++++------- 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 55ad047e6df..1c89c445ce1 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -28,6 +28,7 @@ import { createSignal, ErrorBoundary, on, + Show, } from 'solid-js' describe('createQuery', () => { @@ -2978,7 +2979,7 @@ describe('createQuery', () => { expect(states[3]).toMatchObject({ data: 1, isFetching: false }) }) - it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => { + it('should calculate focus behaviour for refetchOnWindowFocus depending on function', async () => { const key = queryKey() const states: CreateQueryResult[] = [] let count = 0 @@ -2993,12 +2994,13 @@ describe('createQuery', () => { { staleTime: 0, retry: 0, + refetchOnWindowFocus: (query) => (query.state.data || 0) < 1, }, ) createRenderEffect(() => { states.push({ ...state }) }) - return
data: {String(state.data)}
+ return
data: {state.data}
} render(() => ( @@ -3013,7 +3015,7 @@ describe('createQuery', () => { expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) expect(states[1]).toMatchObject({ data: 0, isFetching: false }) - // window.dispatchEvent(new FocusEvent('focus')) + window.dispatchEvent(new FocusEvent('focus')) await screen.findByText('data: 1') @@ -3023,10 +3025,6 @@ describe('createQuery', () => { expect(states[2]).toMatchObject({ data: 0, isFetching: true }) expect(states[3]).toMatchObject({ data: 1, isFetching: false }) - // act(() => { - // window.dispatchEvent(new FocusEvent('focus')) - // }) - await sleep(20) // no more refetch now @@ -3037,7 +3035,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, () => 'prefetched') + await queryClient.prefetchQuery(key(), () => 'prefetched') function Page() { const state = createQuery(key, () => 'data', { @@ -3075,7 +3073,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, () => 'prefetched') + await queryClient.prefetchQuery(key(), () => 'prefetched') await sleep(10) @@ -3115,7 +3113,7 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const { status, error } = createQuery( + const state = createQuery( key, () => { return Promise.reject('Error test jaylen') @@ -3125,8 +3123,8 @@ describe('createQuery', () => { return (
-

{status}

-

{error}

+

{state.status}

+

{state.error}

) } @@ -3145,7 +3143,7 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const { status, error } = createQuery( + const state = createQuery( key, () => Promise.reject('Error test jaylen'), { retry: false, useErrorBoundary: true }, @@ -3153,8 +3151,8 @@ describe('createQuery', () => { return (
-

{status}

-

{error}

+

{state.status}

+

{state.error}

) } @@ -3202,7 +3200,7 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const { status, error } = createQuery( + const state = createQuery( key, () => Promise.reject('Local Error'), { @@ -3213,8 +3211,8 @@ describe('createQuery', () => { return (
-

{status}

-

{error}

+

{state.status}

+

{state.error}

) } @@ -3235,7 +3233,7 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const { status, error } = createQuery( + const state = createQuery( key, () => Promise.reject(new Error('Remote Error')), { @@ -3246,8 +3244,8 @@ describe('createQuery', () => { return (
-

{status}

-

{error?.message ?? ''}

+

{state.status}

+

{state.error?.message ?? ''}

) } @@ -3299,12 +3297,16 @@ describe('createQuery', () => { } function App() { - const [show, toggle] = NotReact.useReducer((x) => !x, true) + const [showPage, setShowPage] = createSignal(true) + + const toggle = () => setShowPage((s) => !s) return (
- - {show && } + + + +
) } @@ -3351,15 +3353,22 @@ describe('createQuery', () => { } function App() { - const [show, toggle] = NotReact.useReducer((x) => !x, true) + const [showPage, setShowPage] = createSignal(true) + + const toggle = () => setShowPage((s) => !s) return (
- - + - {show && } + + + +
) } @@ -3385,7 +3394,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, () => 'prefetched') + await queryClient.prefetchQuery(key(), () => 'prefetched') function Page() { const state = createQuery(key, () => 'data', { diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index d5d986c0e36..0cac39aaf5f 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -103,31 +103,26 @@ export function createBaseQuery< } }) - // createComputed( - // on( - // () => dataResource.state, - // () => { - // const trackStates = ["pending", "ready", "errored"]; - // if (trackStates.includes(dataResource.state)) { - // const currentState = observer.getCurrentResult(); - // setState(currentState); - // if ( - // currentState.isError && - // !currentState.isFetching && - // shouldThrowError( - // observer.options.useErrorBoundary, - // [ - // currentState.error, - // observer.getCurrentQuery(), - // ] - // ) - // ) { - // throw currentState.error; - // } - // } - // }, - // ), - // ); + createComputed( + on( + () => state.status, + () => { + if ( + state.isError && + !state.isFetching && + shouldThrowError( + observer.options.useErrorBoundary, + [ + state.error, + observer.getCurrentQuery(), + ] + ) + ) { + throw state.error; + } + } + ) + ); const handler = { get( From 6be776d8a82b11186c0114a44df4ee54395a2978 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Wed, 14 Sep 2022 14:04:50 -0400 Subject: [PATCH 086/221] =?UTF-8?q?Prettifying=20stuff=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/solid-query/src/createBaseQuery.ts | 63 +++++++------- packages/solid-query/src/createQuery.ts | 75 ++++++++++------- packages/solid-query/src/types.ts | 92 ++++++++++++--------- packages/solid-query/src/utils.ts | 37 ++++++--- 4 files changed, 157 insertions(+), 110 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 0cac39aaf5f..998fa6d0a7d 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -24,7 +24,13 @@ export function createBaseQuery< TQueryData, TQueryKey extends QueryKey, >( - options: CreateBaseQueryOptions, + options: CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey + >, Observer: typeof QueryObserver, ): QueryObserverResult { const queryClient = useQueryClient({ context: options.context }); @@ -57,28 +63,30 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions()), ); - const [dataResource, { refetch, mutate }] = createResource(() => { - return new Promise((resolve) => { - if (!(state.isFetching && state.isLoading)) { - resolve(unwrap(state.data)); + const [dataResource, { refetch, mutate }] = createResource( + () => { + return new Promise((resolve) => { + if (!(state.isFetching && state.isLoading)) { + resolve(unwrap(state.data)) } - }); - }); + }) + }, + ) batch(() => { - mutate(() => unwrap(state.data)); - refetch(); + mutate(() => unwrap(state.data)) + refetch() }) const unsubscribe = observer.subscribe((result) => { batch(() => { - setState(unwrap(result)); - mutate(() => unwrap(result.data)); - refetch(); + setState(unwrap(result)) + mutate(() => unwrap(result.data)) + refetch() }) - }); + }) - onCleanup(() => unsubscribe()); + onCleanup(() => unsubscribe()) onMount(() => { // Do not notify on updates because of changes in the options because @@ -107,22 +115,19 @@ export function createBaseQuery< on( () => state.status, () => { - if ( - state.isError && + if ( + state.isError && !state.isFetching && - shouldThrowError( - observer.options.useErrorBoundary, - [ - state.error, - observer.getCurrentQuery(), - ] - ) + shouldThrowError(observer.options.useErrorBoundary, [ + state.error, + observer.getCurrentQuery(), + ]) ) { - throw state.error; + throw state.error } - } - ) - ); + }, + ), + ) const handler = { get( @@ -149,9 +154,9 @@ export function createBaseQuery< } return state.data } - return Reflect.get(target, prop); + return Reflect.get(target, prop) }, - }; + } const proxyResult = new Proxy(state, handler) as QueryObserverResult< TData, diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index e39b6d49471..a37982af6b0 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,14 +1,18 @@ -import { QueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; +import { + QueryObserver, + QueryFunction, + QueryOptions, +} from '@tanstack/query-core' import { CreateQueryOptions, CreateQueryResult, DefinedCreateQueryResult, SolidQueryKey, -} from "./types"; -import { createComputed } from "solid-js"; -import { createStore } from "solid-js/store"; -import { parseQueryArgs } from "./utils"; -import { createBaseQuery } from "./createBaseQuery"; +} from './types' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' +import { createBaseQuery } from './createBaseQuery' // There are several ways to create a query. // 1. createQuery(options: CreateQueryOptions) @@ -21,20 +25,26 @@ export function createQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: Omit, "initialData"> & { - initialData?: () => undefined; + options: Omit< + CreateQueryOptions, + 'initialData' + > & { + initialData?: () => undefined }, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: Omit, "initialData"> & { - initialData: TQueryFnData | (() => TQueryFnData); + options: Omit< + CreateQueryOptions, + 'initialData' + > & { + initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult; +): DefinedCreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -42,7 +52,7 @@ export function createQuery< TQueryKey extends SolidQueryKey = SolidQueryKey, >( options: CreateQueryOptions, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -52,9 +62,9 @@ export function createQuery< queryKey: TQueryKey, options?: Omit< CreateQueryOptions, - "queryKey" | "initialData" + 'queryKey' | 'initialData' > & { initialData?: () => undefined }, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -64,9 +74,9 @@ export function createQuery< queryKey: TQueryKey, options?: Omit< CreateQueryOptions, - "queryKey" | "initialData" + 'queryKey' | 'initialData' > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult; +): DefinedCreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -74,8 +84,11 @@ export function createQuery< TQueryKey extends SolidQueryKey = SolidQueryKey, >( queryKey: TQueryKey, - options?: Omit, "queryKey">, -): CreateQueryResult; + options?: Omit< + CreateQueryOptions, + 'queryKey' + >, +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -87,9 +100,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - "queryKey" | "queryFn" | "initialData" + 'queryKey' | 'queryFn' | 'initialData' > & { initialData?: () => undefined }, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -100,9 +113,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - "queryKey" | "queryFn" | "initialData" + 'queryKey' | 'queryFn' | 'initialData' > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult; +): DefinedCreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -113,9 +126,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - "queryKey" | "queryFn" + 'queryKey' | 'queryFn' >, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData, TError, @@ -130,16 +143,18 @@ export function createQuery< ): CreateQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); - setParsedOptions(newParsedOptions); - }); + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) return createBaseQuery( parsedOptions as QueryOptions>, QueryObserver, - ); + ) } diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 10899636b2e..88953261567 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context } from "solid-js"; +import type { Context } from 'solid-js' import type { QueryClient, QueryKey, @@ -12,17 +12,17 @@ import type { InfiniteQueryObserverResult, QueryFilters, QueryOptions, -} from "@tanstack/query-core"; +} from '@tanstack/query-core' export interface ContextOptions { /** * Use this to pass your Solid Query context. Otherwise, `defaultContext` will be used. */ - context?: Context; + context?: Context } /* --- Create Query and Create Base Query Types --- */ -export type SolidQueryKey = () => readonly unknown[]; +export type SolidQueryKey = () => readonly unknown[] export interface CreateBaseQueryOptions< TQueryFnData = unknown, @@ -39,40 +39,49 @@ export interface CreateQueryOptions< TData = TQueryFnData, TQueryKey extends () => readonly unknown[] = SolidQueryKey, > extends Omit< - CreateBaseQueryOptions>, - "queryKey" + CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + ReturnType + >, + 'queryKey' > { - queryKey?: TQueryKey; + queryKey?: TQueryKey } -export type CreateBaseQueryResult = QueryObserverResult< - TData, - TError ->; +export type CreateBaseQueryResult< + TData = unknown, + TError = unknown, +> = QueryObserverResult -export type CreateQueryResult = CreateBaseQueryResult< - TData, - TError ->; +export type CreateQueryResult< + TData = unknown, + TError = unknown, +> = CreateBaseQueryResult export type DefinedCreateBaseQueryResult< TData = unknown, TError = unknown, -> = DefinedQueryObserverResult; +> = DefinedQueryObserverResult export type DefinedCreateQueryResult< TData = unknown, TError = unknown, -> = DefinedCreateBaseQueryResult; +> = DefinedCreateBaseQueryResult export type ParseQueryArgs< - TOptions extends Omit>, "queryKey"> & { - queryKey?: TQueryKey; + TOptions extends Omit< + QueryOptions>, + 'queryKey' + > & { + queryKey?: TQueryKey }, TQueryKey extends () => readonly unknown[] = SolidQueryKey, -> = TOptions["queryKey"] extends () => infer R - ? Omit & { queryKey?: R } - : TOptions; +> = TOptions['queryKey'] extends () => infer R + ? Omit & { queryKey?: R } + : TOptions /* --- Create Infinite Queries Types --- */ export interface CreateInfiniteQueryOptions< @@ -83,16 +92,22 @@ export interface CreateInfiniteQueryOptions< TQueryKey extends () => readonly unknown[] = SolidQueryKey, > extends ContextOptions, Omit< - InfiniteQueryObserverOptions>, - "queryKey" + InfiniteQueryObserverOptions< + TQueryFnData, + TError, + TData, + TQueryData, + ReturnType + >, + 'queryKey' > { - queryKey?: TQueryKey; + queryKey?: TQueryKey } export type CreateInfiniteQueryResult< TData = unknown, TError = unknown, -> = InfiniteQueryObserverResult; +> = InfiniteQueryObserverResult /* --- Create Mutation Types --- */ export interface CreateMutationOptions< @@ -103,7 +118,7 @@ export interface CreateMutationOptions< > extends ContextOptions, Omit< MutationObserverOptions, - "_defaulted" | "variables" + '_defaulted' | 'variables' > {} export type CreateMutateFunction< @@ -111,14 +126,16 @@ export type CreateMutateFunction< TError = unknown, TVariables = void, TContext = unknown, -> = (...args: Parameters>) => void; +> = ( + ...args: Parameters> +) => void export type CreateMutateAsyncFunction< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, -> = MutateFunction; +> = MutateFunction export type CreateBaseMutationResult< TData = unknown, @@ -129,23 +146,22 @@ export type CreateBaseMutationResult< MutationObserverResult, { mutate: CreateMutateFunction } > & { - mutateAsync: CreateMutateAsyncFunction; -}; + mutateAsync: CreateMutateAsyncFunction +} export type CreateMutationResult< TData = unknown, TError = unknown, TVariables = unknown, TContext = unknown, -> = CreateBaseMutationResult; +> = CreateBaseMutationResult -type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] }; +type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } /* --- Use Is Fetching Types --- */ -export interface SolidQueryFilters extends Omit { - queryKey?: SolidQueryKey; +export interface SolidQueryFilters extends Omit { + queryKey?: SolidQueryKey } -export type ParseFilterArgs = T["queryKey"] extends () => infer R - ? T & { queryKey: R } - : T; +export type ParseFilterArgs = + T['queryKey'] extends () => infer R ? T & { queryKey: R } : T diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 6d7c585c6ae..ee8fcc6f570 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,15 +1,23 @@ -import { SolidQueryKey, SolidQueryFilters, ParseFilterArgs, ParseQueryArgs } from "./types"; -import { QueryFunction, QueryOptions } from "@tanstack/query-core"; +import { + SolidQueryKey, + SolidQueryFilters, + ParseFilterArgs, + ParseQueryArgs, +} from './types' +import { QueryFunction, QueryOptions } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { - return typeof value === "function"; + return typeof value === 'function' } // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. export function parseQueryArgs< - TOptions extends Omit>, "queryKey"> & { - queryKey?: TQueryKey; + TOptions extends Omit< + QueryOptions>, + 'queryKey' + > & { + queryKey?: TQueryKey }, TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( @@ -18,24 +26,27 @@ export function parseQueryArgs< arg3?: TOptions, ): ParseQueryArgs { if (!isQueryKey(arg1)) { - const { queryKey: solidKey, ...opts } = arg1 as any; + const { queryKey: solidKey, ...opts } = arg1 as any if (solidKey) { return { ...opts, queryKey: solidKey(), - }; + } } - return arg1 as any; + return arg1 as any } - if (typeof arg2 === "function") { - return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any; + if (typeof arg2 === 'function') { + return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any } - return { ...arg2, queryKey: arg1() } as any; + return { ...arg2, queryKey: arg1() } as any } -export function parseFilterArgs( +export function parseFilterArgs< + TFilters extends SolidQueryFilters, + TOptions = unknown, +>( arg1?: SolidQueryKey | TFilters, arg2?: TFilters | TOptions, arg3?: TOptions, @@ -44,7 +55,7 @@ export function parseFilterArgs, TOptions]; + ) as [ParseFilterArgs, TOptions] } export function shouldThrowError boolean>( From 43c657695b134507a81c5724757c062833ba6e4d Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Thu, 15 Sep 2022 02:10:47 -0400 Subject: [PATCH 087/221] More passing tests --- .../src/__tests__/createQuery.test.tsx | 215 ++++++++++-------- 1 file changed, 126 insertions(+), 89 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 1c89c445ce1..636e37d9eba 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -29,6 +29,7 @@ import { ErrorBoundary, on, Show, + createMemo, } from 'solid-js' describe('createQuery', () => { @@ -1195,27 +1196,32 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'error', error }) }) - it.skip('should not re-run a stable select when it re-renders if selector throws an error', async () => { + it('should not re-run a stable select when it re-renders if selector throws an error', async () => { const key = queryKey() const error = new Error('Select Error') let runs = 0 function Page() { - const [, rerender] = NotReact.useReducer(() => ({}), {}) const state = createQuery( key, () => (runs === 0 ? 'test' : 'test2'), { - select: NotReact.useCallback(() => { + select: () => { runs++ throw error - }, []), + }, }, ) return (
error: {state.error?.message}
- +
) @@ -1370,7 +1376,7 @@ describe('createQuery', () => { it('should create a new query when refetching a removed query', async () => { const key = queryKey() - const states: any[] = [] + const states: Partial>[] = [] let count = 0 function Page() { @@ -1490,7 +1496,7 @@ describe('createQuery', () => { it('should use query function from hook when the existing query does not have a query function', async () => { const key = queryKey() - const results: any[] = [] + const results: Partial>[] = [] queryClient.setQueryData(key(), 'set') @@ -1719,7 +1725,7 @@ describe('createQuery', () => { it('should not fetch when switching to a disabled query', async () => { const key = queryKey() - const states: any[] = [] + const states: Partial>[] = [] function Page() { const [count, setCount] = createSignal(0) @@ -1787,7 +1793,7 @@ describe('createQuery', () => { it('should keep the previous data when keepPreviousData is set', async () => { const key = queryKey() - const states: any[] = [] + const states: Partial>[] = [] function Page() { const [count, setCount] = createSignal(0) @@ -2458,7 +2464,9 @@ describe('createQuery', () => { // 7. Observer options updated // 8. Observer result updated -> stale // 9. Observer options updated - expect(fn).toHaveBeenCalledTimes(9) + // Number 9 wont run in Solid JS + // Number 9 runs in react because the component re-renders after 8 + expect(fn).toHaveBeenCalledTimes(8) }) it('should not re-render when it should only re-render on data changes and the data did not change', async () => { @@ -3597,16 +3605,20 @@ describe('createQuery', () => { const states: DefinedCreateQueryResult<{ count: number }>[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) - const state = createQuery([key, count], () => ({ count: 10 }), { - staleTime: Infinity, - initialData: () => ({ count }), - }) + const [count, setCount] = createSignal(0) + const state = createQuery( + () => ['data', count()], + () => ({ count: 10 }), + { + staleTime: Infinity, + initialData: () => ({ count: count() }), + }, + ) createRenderEffect(() => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setCount(1) }, 10) @@ -3639,15 +3651,15 @@ describe('createQuery', () => { }) function Page() { - const { status, failureCount } = createQuery(key, queryFn, { + const state = createQuery(key, queryFn, { retry: 1, retryDelay: 1, }) return (
-

{status}

-

Failed {failureCount} times

+

{state.status}

+

Failed {state.failureCount} times

) } @@ -3681,20 +3693,16 @@ describe('createQuery', () => { }) function Page() { - const { status, failureCount, error } = createQuery< - unknown, - string, - [string] - >(key, queryFn, { + const state = createQuery(key, queryFn, { retryDelay: 1, retry: (_failureCount, err) => err !== 'NoRetry', }) return (
-

{status}

-

Failed {failureCount} times

-

{error}

+

{state.status}

+

Failed {state.failureCount} times

+

{state.error}

) } @@ -3725,15 +3733,15 @@ describe('createQuery', () => { }) function Page() { - const { status, failureCount } = createQuery(key, queryFn, { + const state = createQuery(key, queryFn, { retry: 1, retryDelay: (_, error: DelayError) => error.delay, }) return (
-

{status}

-

Failed {failureCount} times

+

{state.status}

+

Failed {state.failureCount} times

) } @@ -3799,11 +3807,8 @@ describe('createQuery', () => { await sleep(10) await waitFor(() => screen.getByText('failureCount 1')) - act(() => { - // reset visibilityState to original value - visibilityMock.mockRestore() - window.dispatchEvent(new FocusEvent('focus')) - }) + visibilityMock.mockRestore() + window.dispatchEvent(new FocusEvent('focus')) // Wait for the final result await waitFor(() => screen.getByText('failureCount 4')) @@ -3822,7 +3827,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryData(key, 'prefetched') + queryClient.setQueryData(key(), 'prefetched') function Page() { const state = createQuery(key, () => 'data') @@ -3929,7 +3934,7 @@ describe('createQuery', () => { const prefetchQueryFn = jest.fn() prefetchQueryFn.mockImplementation(() => 'not yet...') - await queryClient.prefetchQuery(key, prefetchQueryFn, { + await queryClient.prefetchQuery(key(), prefetchQueryFn, { staleTime: 10, }) @@ -3967,7 +3972,7 @@ describe('createQuery', () => { return 'not yet...' }) - await queryClient.prefetchQuery(key, prefetchQueryFn, { + await queryClient.prefetchQuery(key(), prefetchQueryFn, { staleTime: 1000, }) @@ -4035,8 +4040,8 @@ describe('createQuery', () => { let count = 0 function Page() { - const [enabled, setEnabled] = NotReact.useState(false) - const [isPrefetched, setPrefetched] = NotReact.useState(false) + const [enabled, setEnabled] = createSignal(false) + const [isPrefetched, setPrefetched] = createSignal(false) const query = createQuery( key, @@ -4046,23 +4051,25 @@ describe('createQuery', () => { return count }, { - enabled, + get enabled() { + return enabled() + }, }, ) - NotReact.useEffect(() => { + createEffect(() => { async function prefetch() { - await queryClient.prefetchQuery(key, () => + await queryClient.prefetchQuery(key(), () => Promise.resolve('prefetched data'), ) - act(() => setPrefetched(true)) + setPrefetched(true) } prefetch() - }, []) + }) return (
- {isPrefetched &&
isPrefetched
} + {isPrefetched() &&
isPrefetched
}
data: {query.data}
@@ -4086,10 +4093,12 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const [shouldFetch, setShouldFetch] = NotReact.useState(false) + const [shouldFetch, setShouldFetch] = createSignal(false) const query = createQuery(key, () => 'data', { - enabled: shouldFetch, + get enabled() { + return shouldFetch() + }, }) return ( @@ -4129,7 +4138,11 @@ describe('createQuery', () => { const result = createQuery(key, () => 'serverData', { initialData: 'data', }) - results.push(result) + + createRenderEffect(() => { + results.push({ ...result }) + }) + return null } @@ -4152,7 +4165,11 @@ describe('createQuery', () => { function Page() { const result = createQuery(key, () => 1, { initialData: 0 }) - results.push(result) + + createRenderEffect(() => { + results.push({ ...result }) + }) + return null } @@ -4175,20 +4192,26 @@ describe('createQuery', () => { const results: DefinedCreateQueryResult[] = [] function Page() { - const [shouldFetch, setShouldFetch] = NotReact.useState(true) + const [shouldFetch, setShouldFetch] = createSignal(true) const result = createQuery(key, () => 'fetched data', { - enabled: shouldFetch, - initialData: shouldFetch ? 'initial' : 'initial falsy', + get enabled() { + return shouldFetch() + }, + get initialData() { + return shouldFetch() ? 'initial' : 'initial falsy' + }, }) - results.push(result) + createRenderEffect(() => { + results.push({ ...result }) + }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setShouldFetch(false) }, 5) - }, []) + }) return null } @@ -4200,10 +4223,10 @@ describe('createQuery', () => { )) await sleep(50) - expect(results.length).toBe(3) + expect(results.length).toBe(2) expect(results[0]).toMatchObject({ data: 'initial', isStale: true }) expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true }) - expect(results[2]).toMatchObject({ data: 'fetched data', isStale: true }) + // Wont render 3rd time, because data is still the same }) it('it should support enabled:false in query object syntax', async () => { @@ -4268,7 +4291,7 @@ describe('createQuery', () => { return
{query.data}
} - render(() => ( + const result = render(() => ( @@ -4276,9 +4299,9 @@ describe('createQuery', () => { await waitFor(() => screen.getByText('fetched data')) - screen.unmount() + result.unmount() - const query = queryCache.find(key) + const query = queryCache.find(key()) // @ts-expect-error expect(query!.cacheTimeout).toBe(undefined) }) @@ -4300,10 +4323,10 @@ describe('createQuery', () => { ) }) - NotReact.useMemo(() => { + createMemo(() => { memoFn() return result.data - }, [result.data]) + }) return (
@@ -4334,18 +4357,20 @@ describe('createQuery', () => { let count = 0 function Page() { - const [int, setInt] = NotReact.useState(200) - const { data } = createQuery(key, () => count++, { - refetchInterval: int, + const [int, setInt] = createSignal(200) + const query = createQuery(key, () => count++, { + get refetchInterval() { + return int() + }, }) - NotReact.useEffect(() => { - if (data === 2) { + createEffect(() => { + if (query.data === 2) { setInt(0) } - }, [data]) + }) - return
count: {data}
+ return
count: {query.data}
} render(() => ( @@ -4377,7 +4402,9 @@ describe('createQuery', () => { }, ) - states.push(queryInfo) + createRenderEffect(() => { + states.push({ ...queryInfo }) + }) return (
@@ -4442,7 +4469,9 @@ describe('createQuery', () => { refetchInterval: 0, }) - states.push(queryInfo) + createRenderEffect(() => { + states.push({ ...queryInfo }) + }) return
count: {queryInfo.data}
} @@ -4475,7 +4504,10 @@ describe('createQuery', () => { it('should accept an empty string as query key', async () => { function Page() { - const result = createQuery([''], (ctx) => ctx.queryKey) + const result = createQuery( + () => [''], + (ctx) => ctx.queryKey, + ) return <>{JSON.stringify(result.data)} } @@ -4490,7 +4522,10 @@ describe('createQuery', () => { it('should accept an object as query key', async () => { function Page() { - const result = createQuery([{ a: 'a' }], (ctx) => ctx.queryKey) + const result = createQuery( + () => [{ a: 'a' }], + (ctx) => ctx.queryKey, + ) return <>{JSON.stringify(result.data)} } @@ -4514,8 +4549,12 @@ describe('createQuery', () => { } function Page() { - const [enabled, setEnabled] = NotReact.useState(false) - const result = createQuery(key, queryFn, { enabled }) + const [enabled, setEnabled] = createSignal(false) + const result = createQuery(key, queryFn, { + get enabled() { + return enabled() + }, + }) return ( <> @@ -4585,18 +4624,22 @@ describe('createQuery', () => { const states: { state: CreateQueryResult; count: number }[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery(key1, () => 'data', { placeholderData: 'placeholder', - enabled: count === 0, + get enabled() { + return count() === 0 + }, }) - states.push({ state, count }) + createRenderEffect(() => { + states.push({ state: { ...state }, count: count() }) + }) - NotReact.useEffect(() => { + createEffect(() => { setCount(1) - }, []) + }) return (
@@ -4719,8 +4762,6 @@ describe('createQuery', () => { )) await waitFor(() => screen.getByText('Data: 2')) - screen.rerender() - expect(states).toMatchObject([ { isSuccess: true, @@ -4732,17 +4773,13 @@ describe('createQuery', () => { isPlaceholderData: false, data: '2', }, - { - isSuccess: true, - isPlaceholderData: false, - data: '2', - }, ]) expect(placeholderFunctionRunCount).toEqual(1) }) - it('select should only run when dependencies change if memoized', async () => { + // React Specific implementation. Not really needed since solid functions are stable + it.skip('select should only run when dependencies change if memoized', async () => { const key1 = queryKey() let selectRun = 0 From 6bfd6c64239578f3761bf107a04f4efe32e3c834 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 10:10:46 -0400 Subject: [PATCH 088/221] fixing merge --- .../src/__tests__/createQuery.test.tsx | 158 +++++++++-------- .../src/__tests__/createQuery.types.test.tsx | 160 ++++++++++++++++++ 2 files changed, 238 insertions(+), 80 deletions(-) create mode 100644 packages/solid-query/src/__tests__/createQuery.types.test.tsx diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 636e37d9eba..3e8b504e967 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -7,7 +7,6 @@ import { mockNavigatorOnLine, mockLogger, createQueryClient, - // @ts-ignore } from '../../../../tests/utils' import { Blink, queryKey, setActTimeout } from './utils' import { @@ -15,6 +14,7 @@ import { CreateQueryResult, QueryCache, QueryFunction, + QueryFunctionContext, CreateQueryOptions, DefinedCreateQueryResult, QueryClientProvider, @@ -63,10 +63,14 @@ describe('createQuery', () => { expectType(withError.error) // it should provide the result type in the configuration - createQuery(key, async () => true, { - onSuccess: (data) => expectType(data), - onSettled: (data) => expectType(data), - }) + createQuery( + () => [key()], + async () => true, + { + onSuccess: (data) => expectType(data), + onSettled: (data) => expectType(data), + }, + ) // it should be possible to specify a union type as result type const unionTypeSync = createQuery( @@ -77,7 +81,6 @@ describe('createQuery', () => { }, ) expectType<'a' | 'b' | undefined>(unionTypeSync.data) - const unionTypeAsync = createQuery<'a' | 'b'>( key, () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'), @@ -184,6 +187,7 @@ describe('createQuery', () => { } }) + // See https://github.com/tannerlinsley/react-query/issues/105 it('should allow to set default data value', async () => { const key = queryKey() @@ -537,7 +541,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /refetch/i })) await screen.findByText('data: data2') - expect(states.length).toBe(4) //loading, success, success, success after refetch + expect(states.length).toBe(3) //loading, success, success after refetch expect(count).toBe(2) expect(onSuccess).toHaveBeenCalledTimes(2) }) @@ -1196,12 +1200,13 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'error', error }) }) - it('should not re-run a stable select when it re-renders if selector throws an error', async () => { + it.skip('should not re-run a stable select when it re-renders if selector throws an error', async () => { const key = queryKey() const error = new Error('Select Error') let runs = 0 function Page() { + const [, rerender] = NotReact.useReducer(() => ({}), {}) const state = createQuery( key, () => (runs === 0 ? 'test' : 'test2'), @@ -1215,13 +1220,7 @@ describe('createQuery', () => { return (
error: {state.error?.message}
- +
) @@ -1380,10 +1379,14 @@ describe('createQuery', () => { let count = 0 function Page() { - const state = createQuery(key, async () => { - await sleep(10) - return ++count - }) + const state = createQuery( + key, + async () => { + await sleep(10) + return ++count + }, + { notifyOnChangeProps: 'all' }, + ) createRenderEffect(() => { states.push({ data: state.data, dataUpdatedAt: state.dataUpdatedAt }) @@ -1561,14 +1564,7 @@ describe('createQuery', () => { { staleTime: Infinity, notifyOnChangeProps: 'all' }, ) - createEffect(() => { - console.log('My Log', { - data: state.data, - isFetching: state.isFetching, - isRefetching: state.isRefetching, - isSuccess: state.isSuccess, - isStale: state.isStale, - }) + createRenderEffect(() => { states.push({ ...state }) }) @@ -1592,7 +1588,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => screen.getByText('data: 2')) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) expect(states[0]).toMatchObject({ data: undefined, @@ -1609,20 +1605,13 @@ describe('createQuery', () => { isStale: false, }) expect(states[2]).toMatchObject({ - data: 1, - isFetching: false, - isRefetching: false, - isSuccess: true, - isStale: true, - }) - expect(states[3]).toMatchObject({ data: 1, isFetching: true, isRefetching: true, isSuccess: true, isStale: true, }) - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 2, isFetching: false, isRefetching: false, @@ -1809,12 +1798,6 @@ describe('createQuery', () => { createRenderEffect(() => { const { data, isFetching, isSuccess, isPreviousData } = state - console.log('LOG', { - data, - isFetching, - isSuccess, - isPreviousData, - }) states.push({ data, isFetching, @@ -1838,7 +1821,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(4)) + await waitFor(() => expect(states.length).toBe(5)) // Initial expect(states[0]).toMatchObject({ @@ -1861,8 +1844,15 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // New data + // Hook state update expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2016,7 +2006,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(4)) + await waitFor(() => expect(states.length).toBe(5)) // Initial expect(states[0]).toMatchObject({ @@ -2039,8 +2029,15 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // New data + // Hook state update expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2159,8 +2156,8 @@ describe('createQuery', () => { ) createRenderEffect(() => { - // Need to track count here to push changes - console.log(count(), key()) + const _trackCount = count() + const _trackKey = key() states.push({ ...state }) }) @@ -2792,12 +2789,14 @@ describe('createQuery', () => { type CustomQueryKey = [ReturnType, typeof variables] const states: CreateQueryResult[] = [] + // TODO(lukemurray): extract the query function to a variable queryFn + function Page() { const state = createQuery( - () => [key(), variables], - async ({ queryKey: qk }) => { + () => [key(), variables] as const, + async (ctx) => { await sleep(10) - return qk as CustomQueryKey + return ctx.queryKey }, ) createRenderEffect(() => { @@ -2987,7 +2986,7 @@ describe('createQuery', () => { expect(states[3]).toMatchObject({ data: 1, isFetching: false }) }) - it('should calculate focus behaviour for refetchOnWindowFocus depending on function', async () => { + it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => { const key = queryKey() const states: CreateQueryResult[] = [] let count = 0 @@ -3033,6 +3032,10 @@ describe('createQuery', () => { expect(states[2]).toMatchObject({ data: 0, isFetching: true }) expect(states[3]).toMatchObject({ data: 1, isFetching: false }) + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + await sleep(20) // no more refetch now @@ -3305,16 +3308,14 @@ describe('createQuery', () => { } function App() { - const [showPage, setShowPage] = createSignal(true) + const [show, setShow] = createSignal(true) - const toggle = () => setShowPage((s) => !s) + const toggle = () => setShow((s) => !s) return (
- - - - + + {show() && }
) } @@ -3361,22 +3362,19 @@ describe('createQuery', () => { } function App() { - const [showPage, setShowPage] = createSignal(true) + const [show, setShow] = createSignal(true) - const toggle = () => setShowPage((s) => !s) + const toggle = () => setShow((s) => !s) return (
- + - - - - + {show() && }
) } @@ -3607,7 +3605,7 @@ describe('createQuery', () => { function Page() { const [count, setCount] = createSignal(0) const state = createQuery( - () => ['data', count()], + () => [key(), count()], () => ({ count: 10 }), { staleTime: Infinity, @@ -4223,10 +4221,10 @@ describe('createQuery', () => { )) await sleep(50) - expect(results.length).toBe(2) + expect(results.length).toBe(3) expect(results[0]).toMatchObject({ data: 'initial', isStale: true }) expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true }) - // Wont render 3rd time, because data is still the same + expect(results[2]).toMatchObject({ data: 'fetched data', isStale: true }) }) it('it should support enabled:false in query object syntax', async () => { @@ -4358,19 +4356,19 @@ describe('createQuery', () => { function Page() { const [int, setInt] = createSignal(200) - const query = createQuery(key, () => count++, { + const state = createQuery(key, () => count++, { get refetchInterval() { return int() }, }) createEffect(() => { - if (query.data === 2) { + if (state.data === 2) { setInt(0) } }) - return
count: {query.data}
+ return
count: {state.data}
} render(() => ( @@ -4391,7 +4389,7 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const queryInfo = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -4403,15 +4401,15 @@ describe('createQuery', () => { ) createRenderEffect(() => { - states.push({ ...queryInfo }) + states.push({ ...state }) }) return (
-

count: {queryInfo.data}

-

status: {queryInfo.status}

-

data: {queryInfo.data}

-

refetch: {queryInfo.isRefetching}

+

count: {state.data}

+

status: {state.status}

+

data: {state.data}

+

refetch: {state.isRefetching}

) } @@ -4465,15 +4463,15 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const queryInfo = createQuery(key, () => 1, { + const state = createQuery(key, () => 1, { refetchInterval: 0, }) createRenderEffect(() => { - states.push({ ...queryInfo }) + states.push({ ...state }) }) - return
count: {queryInfo.data}
+ return
count: {state.data}
} render(() => ( diff --git a/packages/solid-query/src/__tests__/createQuery.types.test.tsx b/packages/solid-query/src/__tests__/createQuery.types.test.tsx new file mode 100644 index 00000000000..1d82484d5b6 --- /dev/null +++ b/packages/solid-query/src/__tests__/createQuery.types.test.tsx @@ -0,0 +1,160 @@ +import { createQuery } from '../createQuery' + +export type Equal = (() => T extends X ? 1 : 2) extends < + T, +>() => T extends Y ? 1 : 2 + ? true + : false + +export type Expect = T + +const doNotExecute = (_func: () => void) => true + +describe('initialData', () => { + describe('Config object overload', () => { + it('TData should always be defined when initialData is provided as an object', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => ({ + wow: true, + }), + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + }) + + const result: Expect> = + true + return result + }) + }) + + it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + }) + + const result: Expect> = + true + return result + }) + }) + }) + + describe('Query key overload', () => { + it('TData should always be defined when initialData is provided', () => { + doNotExecute(() => { + const { data } = createQuery(() => ['key'], { + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery(() => ['key'], { + queryFn: () => { + return { + wow: true, + } + }, + }) + + const result: Expect> = + true + return result + }) + }) + }) + + describe('Query key and func', () => { + it('TData should always be defined when initialData is provided', () => { + doNotExecute(() => { + const { data } = createQuery( + () => ['key'], + () => { + return { + wow: true, + } + }, + { + initialData: { + wow: true, + }, + }, + ) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery( + () => ['key'], + () => { + return { + wow: true, + } + }, + ) + + const result: Expect> = + true + return result + }) + }) + }) +}) From fa5a69020467f7b816c328ccc020d224e76e79e8 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 10:12:30 -0400 Subject: [PATCH 089/221] prettier --- packages/solid-query/src/createBaseQuery.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 998fa6d0a7d..36f9a77af05 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -33,7 +33,7 @@ export function createBaseQuery< >, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient({ context: options.context }); + const queryClient = useQueryClient({ context: options.context }) const errorResetBoundary = useQueryErrorResetBoundary() const defaultedOptions = createMemo(() => { @@ -56,12 +56,12 @@ export function createBaseQuery< return computedOptions }) - const observer = new Observer(queryClient, defaultedOptions()); + const observer = new Observer(queryClient, defaultedOptions()) const [state, setState] = createStore>( // @ts-ignore observer.getOptimisticResult(defaultedOptions()), - ); + ) const [dataResource, { refetch, mutate }] = createResource( () => { From fc2cdcbc6b224d46fe4639f2672bc4507fae03e9 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 10:32:24 -0400 Subject: [PATCH 090/221] more merge fixes --- .../src/__tests__/createQuery.test.tsx | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 3e8b504e967..76fcef1dec3 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -14,7 +14,6 @@ import { CreateQueryResult, QueryCache, QueryFunction, - QueryFunctionContext, CreateQueryOptions, DefinedCreateQueryResult, QueryClientProvider, @@ -28,7 +27,6 @@ import { createSignal, ErrorBoundary, on, - Show, createMemo, } from 'solid-js' @@ -1206,6 +1204,7 @@ describe('createQuery', () => { let runs = 0 function Page() { + //@ts-expect-error -- we skip this test, and no such thing as rerender in solid const [, rerender] = NotReact.useReducer(() => ({}), {}) const state = createQuery( key, @@ -1298,10 +1297,14 @@ describe('createQuery', () => { states.push({ ...state }) }) - createEffect(() => { - const _trackState = { ...state } - renderCount++ - }) + createEffect( + on( + () => ({ ...state }), + () => { + renderCount++ + }, + ), + ) return (
@@ -1329,6 +1332,7 @@ describe('createQuery', () => { let count = 0 function Page() { + //@ts-expect-error -- we skip this test, and no such thing as rerender in solid const [, rerender] = NotReact.useState({}) const state = createQuery(key, () => ++count, { notifyOnChangeProps: 'all', @@ -1860,7 +1864,8 @@ describe('createQuery', () => { }) }) - it('should transition to error state when keepPreviousData is set', async () => { + // this test relies on rerenders which don't exist in solid + it.skip('should transition to error state when keepPreviousData is set', async () => { const key = queryKey() const states: CreateQueryResult[] = [] @@ -1899,8 +1904,10 @@ describe('createQuery', () => { )) await waitFor(() => screen.getByText('data: 0')) + // @ts-expect-error we skip this test and rerenders don't exist in solid act(() => screen.rerender()) await waitFor(() => screen.getByText('data: 1')) + // @ts-expect-error we skip this test and rerenders don't exist in solid act(() => screen.rerender()) await waitFor(() => screen.getByText('error: Error test')) @@ -2155,11 +2162,11 @@ describe('createQuery', () => { { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) - createRenderEffect(() => { - const _trackCount = count() - const _trackKey = key() - states.push({ ...state }) - }) + createRenderEffect( + on([() => ({ ...state }), count], () => { + states.push({ ...state }) + }), + ) createEffect(() => { const refetch = state.refetch @@ -2587,6 +2594,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] + // @ts-expect-error - we skip this test const originalUseEffect = NotReact.useEffect // Try to simulate useEffect timing delay @@ -2612,7 +2620,7 @@ describe('createQuery', () => { )) - queryClient.setQueryData(key, 'data') + queryClient.setQueryData(key(), 'data') await sleep(50) // @ts-ignore @@ -2648,8 +2656,7 @@ describe('createQuery', () => { await sleep(20) - // Should be 1 - expect(renders).toBe(1) + expect(renders).toBe(2) }) it('should batch re-renders including hook callbacks', async () => { @@ -3007,7 +3014,7 @@ describe('createQuery', () => { createRenderEffect(() => { states.push({ ...state }) }) - return
data: {state.data}
+ return
data: {String(state.data)}
} render(() => ( From 4f3f4558aabcdab2d87cdc5c5159f8d73450163e Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 11:42:37 -0400 Subject: [PATCH 091/221] add comment about reactive notifyOnChange props --- packages/solid-query/src/createBaseQuery.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 36f9a77af05..b612afbeea7 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -163,6 +163,7 @@ export function createBaseQuery< TError > + // TODO(lukemurray): is it possible to make this reactive based on defaulted options? return !defaultedOptions().notifyOnChangeProps ? observer.trackResult(proxyResult) : proxyResult From 4ddfc1a5b4e46e2eda61f37eb2ae0616b4b5e643 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 11:42:52 -0400 Subject: [PATCH 092/221] ignore some errors in tests --- .../solid-query/src/__tests__/QueryClientProvider.test.tsx | 4 ++-- packages/solid-query/src/__tests__/createQuery.test.tsx | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx index 509fa0400af..6b4055779da 100644 --- a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -250,8 +250,8 @@ describe('QueryClientProvider', () => { return null } - // TODO(lukemurray): this test doesn't pass because the page function is - // never called. I'm not sure why. + // TODO(lukemurray): fails because renderToString never calls Page + // probably an SSR-testing issue we need to fix. renderToString(() => ( diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 76fcef1dec3..f34f1ba65dd 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -967,6 +967,7 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { + //@ts-expect-error -- skip this test const [, rerender] = NotReact.useState({}) const state = createQuery( @@ -987,6 +988,7 @@ describe('createQuery', () => { const { remove } = state + //@ts-expect-error skip this test NotReact.useEffect(() => { setActTimeout(() => { remove() @@ -4790,6 +4792,7 @@ describe('createQuery', () => { let selectRun = 0 function Page() { + //@ts-expect-error skip this test const [count, inc] = NotReact.useReducer((prev) => prev + 1, 2) const state = createQuery( @@ -4799,6 +4802,7 @@ describe('createQuery', () => { return 0 }, { + //@ts-expect-error skip this test select: NotReact.useCallback( (data: number) => { selectRun++ From 431595826948be67e7d38db5b29a78b17c237fad Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 14:49:02 -0400 Subject: [PATCH 093/221] replace instances of test with it --- .../src/__tests__/QueryClientProvider.test.tsx | 12 ++++++------ .../src/__tests__/createMutation.test.tsx | 6 +++--- .../solid-query/src/__tests__/createQuery.test.tsx | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx index 6b4055779da..28cef444692 100644 --- a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -8,7 +8,7 @@ import { Context, createContext, useContext } from 'solid-js' import { renderToString } from 'solid-js/web' describe('QueryClientProvider', () => { - test('sets a specific cache for all queries to use', async () => { + it('sets a specific cache for all queries to use', async () => { const key = queryKey() const queryCache = new QueryCache() @@ -40,7 +40,7 @@ describe('QueryClientProvider', () => { expect(queryCache.find(key())).toBeDefined() }) - test('allows multiple caches to be partitioned', async () => { + it('allows multiple caches to be partitioned', async () => { const key1 = queryKey() const key2 = queryKey() @@ -95,7 +95,7 @@ describe('QueryClientProvider', () => { expect(queryCache2.find(key2())).toBeDefined() }) - test("uses defaultOptions for queries when they don't provide their own config", async () => { + it("uses defaultOptions for queries when they don't provide their own config", async () => { const key = queryKey() const queryCache = new QueryCache() @@ -192,7 +192,7 @@ describe('QueryClientProvider', () => { }) describe('useQueryClient', () => { - test('should throw an error if no query client has been set', () => { + it('should throw an error if no query client has been set', () => { const consoleMock = jest .spyOn(console, 'error') .mockImplementation(() => undefined) @@ -209,7 +209,7 @@ describe('QueryClientProvider', () => { consoleMock.mockRestore() }) - test('should use window to get the context when contextSharing is true', () => { + it('should use window to get the context when contextSharing is true', () => { const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) @@ -234,7 +234,7 @@ describe('QueryClientProvider', () => { expect(queryClientFromWindow).toEqual(queryClient) }) - test('should not use window to get the context when contextSharing is true and window does not exist', () => { + it('should not use window to get the context when contextSharing is true and window does not exist', () => { const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) diff --git a/packages/solid-query/src/__tests__/createMutation.test.tsx b/packages/solid-query/src/__tests__/createMutation.test.tsx index 5fa388914c3..c8807dd70bf 100644 --- a/packages/solid-query/src/__tests__/createMutation.test.tsx +++ b/packages/solid-query/src/__tests__/createMutation.test.tsx @@ -981,7 +981,7 @@ describe('useMutation', () => { ) }) - test('should go to error state if onSuccess callback errors', async () => { + it('should go to error state if onSuccess callback errors', async () => { const error = new Error('error from onSuccess') const onError = jest.fn() @@ -1016,7 +1016,7 @@ describe('useMutation', () => { expect(onError).toHaveBeenCalledWith(error, 'todo', undefined) }) - test('should go to error state if onError callback errors', async () => { + it('should go to error state if onError callback errors', async () => { const error = new Error('error from onError') const mutateFnError = new Error('mutateFnError') @@ -1052,7 +1052,7 @@ describe('useMutation', () => { await rendered.findByText('error: mutateFnError, status: error') }) - test('should go to error state if onSettled callback errors', async () => { + it('should go to error state if onSettled callback errors', async () => { const error = new Error('error from onSettled') const mutateFnError = new Error('mutateFnError') const onError = jest.fn() diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index f34f1ba65dd..27be5191a2b 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -4262,7 +4262,7 @@ describe('createQuery', () => { }) // See https://github.com/tannerlinsley/react-query/issues/360 - test('should init to status:loading, fetchStatus:idle when enabled is false', async () => { + it('should init to status:loading, fetchStatus:idle when enabled is false', async () => { const key = queryKey() function Page() { @@ -4288,7 +4288,7 @@ describe('createQuery', () => { await waitFor(() => screen.getByText('status: loading, idle')) }) - test('should not schedule garbage collection, if cacheTimeout is set to `Infinity`', async () => { + it('should not schedule garbage collection, if cacheTimeout is set to `Infinity`', async () => { const key = queryKey() function Page() { From 9e055e44974f2a3cc0cf3b88f2a27f6edf600107 Mon Sep 17 00:00:00 2001 From: Luke Murray <34020210+lukesmurray@users.noreply.github.com> Date: Fri, 16 Sep 2022 14:53:05 -0400 Subject: [PATCH 094/221] replace react in comment with solid Co-authored-by: Jen Kaplan --- packages/solid-query/src/QueryClientProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index 9dfd87aaaf4..21987bccab0 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -22,7 +22,7 @@ const QueryClientSharingContext = createContext(false) // If we are given a context, we will use it. // Otherwise, if contextSharing is on, we share the first and at least one // instance of the context across the window -// to ensure that if React Query is used across +// to ensure that if Solid Query is used across // different bundles or microfrontends they will // all use the same **instance** of context, regardless // of module scoping. From 4ae8b1739de6c5aa91ef32704ef091d576a0a23b Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 16 Sep 2022 21:21:02 -0400 Subject: [PATCH 095/221] Completed tests and reviewed PR --- .../src/QueryErrorResetBoundary.tsx | 50 -- .../QueryResetErrorBoundary.test.tsx | 637 ------------------ .../src/__tests__/createQuery.test.tsx | 128 ++-- .../src/__tests__/suspense.test.tsx | 138 +--- .../src/__tests__/useIsFetching.test.tsx | 11 +- .../src/__tests__/useIsMutating.test.tsx | 15 +- packages/solid-query/src/createBaseQuery.ts | 162 ++--- packages/solid-query/src/index.ts | 11 +- 8 files changed, 157 insertions(+), 995 deletions(-) delete mode 100644 packages/solid-query/src/QueryErrorResetBoundary.tsx delete mode 100644 packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx diff --git a/packages/solid-query/src/QueryErrorResetBoundary.tsx b/packages/solid-query/src/QueryErrorResetBoundary.tsx deleted file mode 100644 index 2066f3a6299..00000000000 --- a/packages/solid-query/src/QueryErrorResetBoundary.tsx +++ /dev/null @@ -1,50 +0,0 @@ -// CONTEXT - -import { createContext, createSignal, useContext, JSX } from 'solid-js' - -interface QueryErrorResetBoundaryValue { - clearReset: () => void - isReset: () => boolean - reset: () => void -} - -function createValue(): QueryErrorResetBoundaryValue { - const [isReset, setIsReset] = createSignal(false) - return { - clearReset: () => { - setIsReset(false) - }, - reset: () => { - setIsReset(true) - }, - isReset: () => { - return isReset() - }, - } -} - -const QueryErrorResetBoundaryContext = createContext(createValue()) - -// HOOK - -export const useQueryErrorResetBoundary = () => - useContext(QueryErrorResetBoundaryContext) - -// COMPONENT - -export interface QueryErrorResetBoundaryProps { - children: ((value: QueryErrorResetBoundaryValue) => JSX.Element) | JSX.Element -} - -export const QueryErrorResetBoundary = ( - props: QueryErrorResetBoundaryProps, -) => { - const [value] = createSignal(createValue()) - return ( - - {typeof props.children === 'function' - ? (props.children as Function)(value()) - : props.children} - - ) -} diff --git a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx deleted file mode 100644 index 2ca6fb5a416..00000000000 --- a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx +++ /dev/null @@ -1,637 +0,0 @@ -import { waitFor, fireEvent, render, screen } from 'solid-testing-library' - -import { sleep, createQueryClient } from '../../../../tests/utils' -import { queryKey } from './utils' -import { - createQuery, - QueryCache, - QueryClientProvider, - QueryErrorResetBoundary, -} from '..' -import { createEffect, createSignal, ErrorBoundary, Suspense } from 'solid-js' - -describe('QueryErrorResetBoundary', () => { - const queryCache = new QueryCache() - const queryClient = createQueryClient({ queryCache }) - - it('should retry fetch if the reset error boundary has been reset', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
- , -
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - }) - - it('should not throw error if query is disabled', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - enabled: !succeed, - useErrorBoundary: true, - }, - ) - return ( -
-
status: {state.status}
-
{state.data}
-
- ) - } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('status: error')) - }) - - it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const [enabled, setEnabled] = createSignal(false) - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - enabled: enabled(), - useErrorBoundary: true, - }, - ) - - createEffect(() => { - setEnabled(true) - }) - - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - }) - - it('should throw error if query is disabled and manually refetched', async () => { - const key = queryKey() - - function Page() { - const state = createQuery( - key, - async () => { - throw new Error('Error') - }, - { - retry: false, - enabled: false, - useErrorBoundary: true, - }, - ) - - return ( -
- -
- status: {state.status}, fetchStatus: {state.fetchStatus} -
-
{state.data}
-
- ) - } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('status: loading, fetchStatus: idle')) - fireEvent.click(screen.getByRole('button', { name: /refetch/i })) - await waitFor(() => screen.getByText('error boundary')) - }) - - it('should not retry fetch if the reset error boundary has not been reset', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {() => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - }) - - it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - initialData: 'initial', - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - }) - - it('should not retry fetch if the reset error boundary has not been reset after a previous reset', async () => { - const key = queryKey() - - let succeed = false - let shouldReset = true - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - shouldReset = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - succeed = true - shouldReset = false - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - }) - - it('should throw again on error after the reset error boundary has been reset', async () => { - const key = queryKey() - let fetchCount = 0 - - function Page() { - const state = createQuery( - key, - async () => { - fetchCount++ - await sleep(10) - throw new Error('Error') - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - expect(fetchCount).toBe(3) - }) - - // TODO(lukemurray): semantically doens't make sense since solid resets when - // the resource that has an error is read - it.skip('should never render the component while the query is in error state', async () => { - const key = queryKey() - let fetchCount = 0 - let renders = 0 - - function Page() { - const state = createQuery( - key, - async () => { - fetchCount++ - await sleep(10) - if (fetchCount > 2) { - return 'data' - } else { - throw new Error('Error') - } - }, - { - retry: false, - suspense: true, - }, - ) - renders++ - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - loading
}> - - - - )} - - - )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - expect(fetchCount).toBe(3) - expect(renders).toBe(1) - }) - - it('should render children', async () => { - function Page() { - return ( -
- page -
- ) - } - - render(() => ( - - - - - - )) - - expect(screen.queryByText('page')).not.toBeNull() - }) - - it('should show error boundary when using tracked queries even though we do not track the error field', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - }) -}) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 27be5191a2b..099b3e153b9 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1570,7 +1570,14 @@ describe('createQuery', () => { { staleTime: Infinity, notifyOnChangeProps: 'all' }, ) - createRenderEffect(() => { + createEffect(() => { + console.log('My Log', { + data: state.data, + isFetching: state.isFetching, + isRefetching: state.isRefetching, + isSuccess: state.isSuccess, + isStale: state.isStale, + }) states.push({ ...state }) }) @@ -1594,7 +1601,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => screen.getByText('data: 2')) - await waitFor(() => expect(states.length).toBe(4)) + await waitFor(() => expect(states.length).toBe(5)) expect(states[0]).toMatchObject({ data: undefined, @@ -1611,13 +1618,20 @@ describe('createQuery', () => { isStale: false, }) expect(states[2]).toMatchObject({ + data: 1, + isFetching: false, + isRefetching: false, + isSuccess: true, + isStale: true, + }) + expect(states[3]).toMatchObject({ data: 1, isFetching: true, isRefetching: true, isSuccess: true, isStale: true, }) - expect(states[3]).toMatchObject({ + expect(states[4]).toMatchObject({ data: 2, isFetching: false, isRefetching: false, @@ -1804,6 +1818,12 @@ describe('createQuery', () => { createRenderEffect(() => { const { data, isFetching, isSuccess, isPreviousData } = state + console.log('LOG', { + data, + isFetching, + isSuccess, + isPreviousData, + }) states.push({ data, isFetching, @@ -1827,7 +1847,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) // Initial expect(states[0]).toMatchObject({ @@ -1850,15 +1870,8 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update - expect(states[3]).toMatchObject({ - data: 0, - isFetching: true, - isSuccess: true, - isPreviousData: true, - }) // New data - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2015,7 +2028,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) // Initial expect(states[0]).toMatchObject({ @@ -2038,15 +2051,8 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update - expect(states[3]).toMatchObject({ - data: 0, - isFetching: true, - isSuccess: true, - isPreviousData: true, - }) // New data - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2658,7 +2664,9 @@ describe('createQuery', () => { await sleep(20) - expect(renders).toBe(2) + // Since components are rendered once + // There wiil only be one pass + expect(renders).toBe(1) }) it('should batch re-renders including hook callbacks', async () => { @@ -2995,7 +3003,7 @@ describe('createQuery', () => { expect(states[3]).toMatchObject({ data: 1, isFetching: false }) }) - it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => { + it('should calculate focus behaviour for refetchOnWindowFocus depending on function', async () => { const key = queryKey() const states: CreateQueryResult[] = [] let count = 0 @@ -3016,7 +3024,7 @@ describe('createQuery', () => { createRenderEffect(() => { states.push({ ...state }) }) - return
data: {String(state.data)}
+ return
data: {state.data}
} render(() => ( @@ -3041,10 +3049,6 @@ describe('createQuery', () => { expect(states[2]).toMatchObject({ data: 0, isFetching: true }) expect(states[3]).toMatchObject({ data: 1, isFetching: false }) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) - await sleep(20) // no more refetch now @@ -4230,10 +4234,10 @@ describe('createQuery', () => { )) await sleep(50) - expect(results.length).toBe(3) + expect(results.length).toBe(2) expect(results[0]).toMatchObject({ data: 'initial', isStale: true }) expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true }) - expect(results[2]).toMatchObject({ data: 'fetched data', isStale: true }) + // Wont render 3rd time, because data is still the same }) it('it should support enabled:false in query object syntax', async () => { @@ -4904,10 +4908,7 @@ describe('createQuery', () => { const states: Array> = [] function Page() { - const [forceValue, forceUpdate] = NotReact.useReducer( - (prev) => prev + 1, - 1, - ) + const [forceValue, setForceValue] = createSignal(1) const state = createQuery( key1, @@ -4920,11 +4921,15 @@ describe('createQuery', () => { }, ) - NotReact.useEffect(() => { + createEffect(() => { if (state.data) { states.push(state.data) } - }, [state.data]) + }) + + const forceUpdate = () => { + setForceValue((prev) => prev + 1) + } return (
@@ -4994,7 +4999,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - const queryFn: QueryFunction = async ( + const queryFn: QueryFunction, number]> = async ( ctx, ) => { const [, limit] = ctx.queryKey @@ -5004,7 +5009,7 @@ describe('createQuery', () => { } function Page(props: { limit: number }) { - const state = createQuery([key, props.limit], queryFn) + const state = createQuery(() => ([key(), props.limit] as const), queryFn) states[props.limit] = state return (
@@ -5030,40 +5035,40 @@ describe('createQuery', () => { await waitFor(() => expect(states).toHaveLength(4)) - expect(queryCache.find([key, 0])?.state).toMatchObject({ + expect(queryCache.find([key(), 0])?.state).toMatchObject({ data: 'data 0', status: 'success', dataUpdateCount: 1, }) if (typeof AbortSignal === 'function') { - expect(queryCache.find([key, 1])?.state).toMatchObject({ + expect(queryCache.find([key(), 1])?.state).toMatchObject({ data: undefined, status: 'loading', fetchStatus: 'idle', }) } else { - expect(queryCache.find([key, 1])?.state).toMatchObject({ + expect(queryCache.find([key(), 1])?.state).toMatchObject({ data: 'data 1', status: 'success', dataUpdateCount: 1, }) } - expect(queryCache.find([key, 2])?.state).toMatchObject({ + expect(queryCache.find([key(), 2])?.state).toMatchObject({ data: 'data 2', status: 'success', dataUpdateCount: 1, }) if (typeof AbortSignal === 'function') { - expect(queryCache.find([key, 3])?.state).toMatchObject({ + expect(queryCache.find([key(), 3])?.state).toMatchObject({ data: undefined, status: 'loading', fetchStatus: 'idle', }) } else { - expect(queryCache.find([key, 3])?.state).toMatchObject({ + expect(queryCache.find([key(), 3])?.state).toMatchObject({ data: 'data 3', status: 'success', dataUpdateCount: 1, @@ -5107,24 +5112,15 @@ describe('createQuery', () => { )) await sleep(100) - expect(states.length).toBe(4) + expect(states.length).toBe(2) // Load query 1 expect(states[0]).toMatchObject({ status: 'loading', error: null, }) - // Load query 2 - expect(states[1]).toMatchObject({ - status: 'loading', - error: null, - }) - // Load query 1 - expect(states[2]).toMatchObject({ - status: 'loading', - error: null, - }) + // No rerenders - No state updates // Loaded query 1 - expect(states[3]).toMatchObject({ + expect(states[1]).toMatchObject({ status: 'success', error: null, }) @@ -5147,6 +5143,7 @@ describe('createQuery', () => { ) createRenderEffect(() => { + console.log('LOG', state.data, state.isLoading, state.isFetching, state.isStale) states.push({ ...state }) }) @@ -5206,7 +5203,7 @@ describe('createQuery', () => { it('should update query state and not refetch when resetting a disabled query with resetQueries', async () => { const key = queryKey() - const states: CreateQueryResult[] = [] + const states: Partial>[] = [] let count = 0 function Page() { @@ -5221,7 +5218,15 @@ describe('createQuery', () => { ) createRenderEffect(() => { - states.push({ ...state }) + const { data, isLoading, isFetching, isSuccess, isStale } = state + console.log('LOG', state.data, state.isLoading, state.isFetching, state.isSuccess, state.isStale) + states.push({ + data, + isLoading, + isFetching, + isSuccess, + isStale, + }) }) const { refetch } = state @@ -5294,11 +5299,10 @@ describe('createQuery', () => { } function Page() { - NotReact.useEffect(() => { + const state =createQuery(key, () => 'test', { queryKeyHashFn }) + createEffect(on( () => state.status, () => { renders++ - }) - - createQuery(key, () => 'test', { queryKeyHashFn }) + })) return null } diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index 709a5fd22b0..441052fb489 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -5,9 +5,6 @@ import { queryKey } from './utils' import { createQuery, QueryCache, - QueryErrorResetBoundary, - useQueryErrorResetBoundary, - CreateQueryResult, CreateInfiniteQueryResult, createInfiniteQuery, QueryClientProvider, @@ -17,6 +14,7 @@ import { createSignal, ErrorBoundary, on, + Show, Suspense, } from 'solid-js' @@ -335,19 +333,18 @@ describe("useQuery's in Suspense mode", () => { }, ) - // read state.data to trigger suspense. - createRenderEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense - state.data - }) - - return
rendered
+ // Suspense only triggers if used in JSX + return ( + +
+ rendered +
+
+ ) } render(() => ( - - {({ reset: resetQuery }) => ( (
@@ -355,7 +352,6 @@ describe("useQuery's in Suspense mode", () => { -
- )} - > - - - -
- ) - } - - render(() => ( - - - - )) - - await waitFor(() => screen.getByText('Loading...')) - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('rendered')) - }) - it('should throw errors to the error boundary by default', async () => { const key = queryKey() @@ -861,7 +779,9 @@ describe("useQuery's in Suspense mode", () => { const [enabled, setEnabled] = createSignal(false) const result = createQuery(() => [key()], queryFn, { suspense: true, - enabled: enabled(), + get enabled() { + return enabled() + } }) return ( @@ -881,7 +801,7 @@ describe("useQuery's in Suspense mode", () => { )) expect(queryFn).toHaveBeenCalledTimes(0) - + await sleep(5) fireEvent.click(screen.getByRole('button', { name: /fire/i })) await waitFor(() => { @@ -906,7 +826,7 @@ describe("useQuery's in Suspense mode", () => { if (!succeed) { throw new Error('Suspense Error Bingo') } else { - return nonce + return nonce() } }, { @@ -930,7 +850,6 @@ describe("useQuery's in Suspense mode", () => { } function App() { - const { reset } = useQueryErrorResetBoundary() return (
error boundary
}> @@ -963,11 +882,10 @@ describe("useQuery's in Suspense mode", () => { let succeed = true function Page() { - const [key, rerender] = React.useReducer((x) => x + 1, 0) - const queryKeys = [key, succeed] + const [key, setKey] = createSignal(0) const result = createQuery( - queryKeys, + () => [`${key()}-${succeed}`], async () => { await sleep(10) if (!succeed) { @@ -984,7 +902,7 @@ describe("useQuery's in Suspense mode", () => { return (
rendered {result.data} -
@@ -992,7 +910,6 @@ describe("useQuery's in Suspense mode", () => { } function App() { - const { reset } = useQueryErrorResetBoundary() return (
error boundary
}> @@ -1035,7 +952,9 @@ describe("useQuery's in Suspense mode", () => { { retry: false, suspense: true, - enabled: enabled(), + get enabled() { + return enabled() + } }, ) return ( @@ -1054,7 +973,6 @@ describe("useQuery's in Suspense mode", () => { } function App() { - const { reset } = useQueryErrorResetBoundary() return (
error boundary
}> diff --git a/packages/solid-query/src/__tests__/useIsFetching.test.tsx b/packages/solid-query/src/__tests__/useIsFetching.test.tsx index 96ee1a81e4b..8a0b3670abc 100644 --- a/packages/solid-query/src/__tests__/useIsFetching.test.tsx +++ b/packages/solid-query/src/__tests__/useIsFetching.test.tsx @@ -44,7 +44,9 @@ describe('useIsFetching', () => { return 'test' }, { - enabled: ready(), + get enabled() { + return ready() + } , }, ) @@ -130,7 +132,8 @@ describe('useIsFetching', () => {
)) - await waitFor(() => expect(isFetchings).toEqual([0, 1, 1, 2, 1, 0])) + // unlike react, Updating renderSecond wont cause a rerender for FirstQuery + await waitFor(() => expect(isFetchings).toEqual([0, 1, 2, 1, 0])) }) it('should be able to filter', async () => { @@ -212,7 +215,9 @@ describe('useIsFetching', () => { return 'test' }, { - enabled: ready(), + get enabled() { + return ready() + }, context, }, ) diff --git a/packages/solid-query/src/__tests__/useIsMutating.test.tsx b/packages/solid-query/src/__tests__/useIsMutating.test.tsx index 82d59162963..d95771b41fd 100644 --- a/packages/solid-query/src/__tests__/useIsMutating.test.tsx +++ b/packages/solid-query/src/__tests__/useIsMutating.test.tsx @@ -104,7 +104,8 @@ describe('useIsMutating', () => { )) - await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0])) + // Unlike React, IsMutating Wont re-render twice with mutation2 + await waitFor(() => expect(isMutatings).toEqual([0, 1, 0])) }) it('should filter correctly by predicate', async () => { @@ -145,7 +146,9 @@ describe('useIsMutating', () => { )) - await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0])) + + // Again, No unnecessary re-renders like React + await waitFor(() => expect(isMutatings).toEqual([0, 1, 0])) }) it('should not change state if unmounted', async () => { @@ -215,7 +218,11 @@ describe('useIsMutating', () => { function IsMutating() { const isMutating = useIsMutating(undefined, { context }) - isMutatings.push(isMutating()) + + createRenderEffect(() => { + isMutatings.push(isMutating()) + }) + return null } @@ -252,7 +259,7 @@ describe('useIsMutating', () => { )) - await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0])) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 2, 1, 0])) }) it('should throw if the context is not passed to useIsMutating', async () => { diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index b612afbeea7..635bcdbea6c 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -1,20 +1,10 @@ -import { QueryObserver } from '@tanstack/query-core' -import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' -import { CreateBaseQueryOptions } from './types' -import { useQueryClient } from './QueryClientProvider' -import { - onMount, - onCleanup, - createComputed, - createResource, - createMemo, - createEffect, - on, - batch, -} from 'solid-js' -import { createStore, unwrap } from 'solid-js/store' -import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary' -import { shouldThrowError } from './utils' +import { QueryObserver } from "@tanstack/query-core"; +import type { QueryKey, QueryObserverResult } from "@tanstack/query-core"; +import { CreateBaseQueryOptions } from "./types"; +import { useQueryClient } from "./QueryClientProvider"; +import { onMount, onCleanup, createComputed, createResource, on, batch } from "solid-js"; +import { createStore, unwrap } from "solid-js/store"; +import { shouldThrowError } from "./utils"; // Base Query Function that is used to create the query. export function createBaseQuery< @@ -24,92 +14,51 @@ export function createBaseQuery< TQueryData, TQueryKey extends QueryKey, >( - options: CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey - >, + options: CreateBaseQueryOptions, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient({ context: options.context }) - const errorResetBoundary = useQueryErrorResetBoundary() + const queryClient = useQueryClient({ context: options.context }); - const defaultedOptions = createMemo(() => { - const computedOptions = queryClient.defaultQueryOptions(options) - computedOptions._optimisticResults = 'optimistic' - if (computedOptions.suspense) { - // Always set stale time when using suspense to prevent - // fetching again when directly mounting after suspending - if (typeof computedOptions.staleTime !== 'number') { - computedOptions.staleTime = 1000 - } - } - - if (computedOptions.suspense || computedOptions.useErrorBoundary) { - // Prevent retrying failed query if the error boundary has not been reset yet - if (!errorResetBoundary.isReset()) { - computedOptions.retryOnMount = false - } - } - return computedOptions - }) - - const observer = new Observer(queryClient, defaultedOptions()) + const defaultedOptions = queryClient.defaultQueryOptions(options); + defaultedOptions._optimisticResults = "optimistic"; + const observer = new Observer(queryClient, defaultedOptions); const [state, setState] = createStore>( // @ts-ignore - observer.getOptimisticResult(defaultedOptions()), - ) + observer.getOptimisticResult(defaultedOptions), + ); - const [dataResource, { refetch, mutate }] = createResource( - () => { - return new Promise((resolve) => { - if (!(state.isFetching && state.isLoading)) { - resolve(unwrap(state.data)) - } - }) - }, - ) + const [dataResource, { refetch, mutate }] = createResource(() => { + return new Promise((resolve) => { + if (!(state.isFetching && state.isLoading)) { + resolve(unwrap(state.data)); + } + }); + }); batch(() => { - mutate(() => unwrap(state.data)) - refetch() - }) + mutate(() => unwrap(state.data)); + refetch(); + }); const unsubscribe = observer.subscribe((result) => { batch(() => { - setState(unwrap(result)) - mutate(() => unwrap(result.data)) - refetch() - }) - }) + setState(unwrap(result)); + mutate(() => unwrap(result.data)); + refetch(); + }); + }); - onCleanup(() => unsubscribe()) + onCleanup(() => unsubscribe()); onMount(() => { - // Do not notify on updates because of changes in the options because - // these changes should already be reflected in the optimistic result. - observer.setOptions(defaultedOptions(), { listeners: false }) - }) - - // Do not update observer options on mount because it is already set. - createComputed( - on( - defaultedOptions, - () => { - observer.setOptions(defaultedOptions()) - }, - { defer: true }, - ), - ) + observer.setOptions(defaultedOptions, { listeners: false }); + }); - createEffect(() => { - if (errorResetBoundary.isReset()) { - errorResetBoundary.clearReset() - } - }) + createComputed(() => { + const newDefaultedOptions = queryClient.defaultQueryOptions(options); + observer.setOptions(newDefaultedOptions); + }); createComputed( on( @@ -123,48 +72,23 @@ export function createBaseQuery< observer.getCurrentQuery(), ]) ) { - throw state.error + throw state.error; } }, ), - ) + ); const handler = { get( target: QueryObserverResult, prop: keyof QueryObserverResult, ): any { - if (prop === 'data') { - // handle suspense - const isSuspense = - defaultedOptions().suspense && state.isLoading && state.isFetching - - // handle error boundary - const isErrorBoundary = - state.isError && - !errorResetBoundary.isReset() && - !state.isFetching && - shouldThrowError(defaultedOptions().useErrorBoundary, [ - state.error, - observer.getCurrentQuery(), - ]) - - if (isSuspense || isErrorBoundary) { - return dataResource() - } - return state.data + if (prop === "data") { + return dataResource(); } - return Reflect.get(target, prop) + return Reflect.get(target, prop); }, - } - - const proxyResult = new Proxy(state, handler) as QueryObserverResult< - TData, - TError - > + }; - // TODO(lukemurray): is it possible to make this reactive based on defaulted options? - return !defaultedOptions().notifyOnChangeProps - ? observer.trackResult(proxyResult) - : proxyResult + return new Proxy(state, handler) as QueryObserverResult; } diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 5da9ff50167..3e7f773df26 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -3,8 +3,6 @@ export * from '@tanstack/query-core' // Solid Query export * from './types' -// export { useQueries } from './useQueries' -// export type { QueriesResults, QueriesOptions } from './useQueries' export { createQuery } from './createQuery' export { defaultContext, @@ -12,15 +10,8 @@ export { useQueryClient, } from './QueryClientProvider' export type { QueryClientProviderProps } from './QueryClientProvider' -export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' -// export { useHydrate, Hydrate } from './Hydrate' -// export type { HydrateProps } from './Hydrate' -export { - QueryErrorResetBoundary, - useQueryErrorResetBoundary, -} from './QueryErrorResetBoundary' export { useIsFetching } from './useIsFetching' export { useIsMutating } from './useIsMutating' export { createMutation } from './createMutation' export { createInfiniteQuery } from './createInfiniteQuery' -// export { useIsRestoring, IsRestoringProvider } from './isRestoring' + From 88df6593c950b703a3ba55404290bfb431a04595 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 16 Sep 2022 21:26:00 -0400 Subject: [PATCH 096/221] Prettifying and removing logs --- .../src/__tests__/createQuery.test.tsx | 39 +++----- .../src/__tests__/suspense.test.tsx | 89 ++++++++--------- .../src/__tests__/useIsFetching.test.tsx | 6 +- .../src/__tests__/useIsMutating.test.tsx | 2 +- packages/solid-query/src/createBaseQuery.ts | 97 +++++++++++-------- packages/solid-query/src/index.ts | 1 - 6 files changed, 117 insertions(+), 117 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 099b3e153b9..aa5ff61df9b 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1571,13 +1571,6 @@ describe('createQuery', () => { ) createEffect(() => { - console.log('My Log', { - data: state.data, - isFetching: state.isFetching, - isRefetching: state.isRefetching, - isSuccess: state.isSuccess, - isStale: state.isStale, - }) states.push({ ...state }) }) @@ -1818,12 +1811,6 @@ describe('createQuery', () => { createRenderEffect(() => { const { data, isFetching, isSuccess, isPreviousData } = state - console.log('LOG', { - data, - isFetching, - isSuccess, - isPreviousData, - }) states.push({ data, isFetching, @@ -4999,9 +4986,10 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - const queryFn: QueryFunction, number]> = async ( - ctx, - ) => { + const queryFn: QueryFunction< + string, + readonly [ReturnType, number] + > = async (ctx) => { const [, limit] = ctx.queryKey const value = limit % 2 && ctx.signal ? 'abort' : `data ${limit}` await sleep(25) @@ -5009,7 +4997,7 @@ describe('createQuery', () => { } function Page(props: { limit: number }) { - const state = createQuery(() => ([key(), props.limit] as const), queryFn) + const state = createQuery(() => [key(), props.limit] as const, queryFn) states[props.limit] = state return (
@@ -5143,7 +5131,6 @@ describe('createQuery', () => { ) createRenderEffect(() => { - console.log('LOG', state.data, state.isLoading, state.isFetching, state.isStale) states.push({ ...state }) }) @@ -5219,8 +5206,7 @@ describe('createQuery', () => { createRenderEffect(() => { const { data, isLoading, isFetching, isSuccess, isStale } = state - console.log('LOG', state.data, state.isLoading, state.isFetching, state.isSuccess, state.isStale) - states.push({ + states.push({ data, isLoading, isFetching, @@ -5299,10 +5285,15 @@ describe('createQuery', () => { } function Page() { - const state =createQuery(key, () => 'test', { queryKeyHashFn }) - createEffect(on( () => state.status, () => { - renders++ - })) + const state = createQuery(key, () => 'test', { queryKeyHashFn }) + createEffect( + on( + () => state.status, + () => { + renders++ + }, + ), + ) return null } diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index 441052fb489..7c887df590e 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -336,34 +336,32 @@ describe("useQuery's in Suspense mode", () => { // Suspense only triggers if used in JSX return ( -
- rendered -
+
rendered
) } render(() => ( - ( -
-
error boundary
- -
- )} - > - - - -
+ ( +
+
error boundary
+ +
+ )} + > + + + +
)) @@ -400,37 +398,34 @@ describe("useQuery's in Suspense mode", () => { }, ) - // Suspense only triggers if used in JSX return ( -
- rendered -
+
rendered
) } render(() => ( - ( -
-
error boundary
- -
- )} - > - - - -
+ ( +
+
error boundary
+ +
+ )} + > + + + +
)) @@ -781,7 +776,7 @@ describe("useQuery's in Suspense mode", () => { suspense: true, get enabled() { return enabled() - } + }, }) return ( @@ -902,7 +897,7 @@ describe("useQuery's in Suspense mode", () => { return (
rendered {result.data} -
@@ -954,7 +949,7 @@ describe("useQuery's in Suspense mode", () => { suspense: true, get enabled() { return enabled() - } + }, }, ) return ( diff --git a/packages/solid-query/src/__tests__/useIsFetching.test.tsx b/packages/solid-query/src/__tests__/useIsFetching.test.tsx index 8a0b3670abc..6ee84dedb2f 100644 --- a/packages/solid-query/src/__tests__/useIsFetching.test.tsx +++ b/packages/solid-query/src/__tests__/useIsFetching.test.tsx @@ -46,7 +46,7 @@ describe('useIsFetching', () => { { get enabled() { return ready() - } , + }, }, ) @@ -132,7 +132,7 @@ describe('useIsFetching', () => { )) - // unlike react, Updating renderSecond wont cause a rerender for FirstQuery + // unlike react, Updating renderSecond wont cause a rerender for FirstQuery await waitFor(() => expect(isFetchings).toEqual([0, 1, 2, 1, 0])) }) @@ -216,7 +216,7 @@ describe('useIsFetching', () => { }, { get enabled() { - return ready() + return ready() }, context, }, diff --git a/packages/solid-query/src/__tests__/useIsMutating.test.tsx b/packages/solid-query/src/__tests__/useIsMutating.test.tsx index d95771b41fd..d1985e81963 100644 --- a/packages/solid-query/src/__tests__/useIsMutating.test.tsx +++ b/packages/solid-query/src/__tests__/useIsMutating.test.tsx @@ -222,7 +222,7 @@ describe('useIsMutating', () => { createRenderEffect(() => { isMutatings.push(isMutating()) }) - + return null } diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 635bcdbea6c..3fb4008c271 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -1,10 +1,17 @@ -import { QueryObserver } from "@tanstack/query-core"; -import type { QueryKey, QueryObserverResult } from "@tanstack/query-core"; -import { CreateBaseQueryOptions } from "./types"; -import { useQueryClient } from "./QueryClientProvider"; -import { onMount, onCleanup, createComputed, createResource, on, batch } from "solid-js"; -import { createStore, unwrap } from "solid-js/store"; -import { shouldThrowError } from "./utils"; +import { QueryObserver } from '@tanstack/query-core' +import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' +import { CreateBaseQueryOptions } from './types' +import { useQueryClient } from './QueryClientProvider' +import { + onMount, + onCleanup, + createComputed, + createResource, + on, + batch, +} from 'solid-js' +import { createStore, unwrap } from 'solid-js/store' +import { shouldThrowError } from './utils' // Base Query Function that is used to create the query. export function createBaseQuery< @@ -14,51 +21,59 @@ export function createBaseQuery< TQueryData, TQueryKey extends QueryKey, >( - options: CreateBaseQueryOptions, + options: CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey + >, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient({ context: options.context }); + const queryClient = useQueryClient({ context: options.context }) - const defaultedOptions = queryClient.defaultQueryOptions(options); - defaultedOptions._optimisticResults = "optimistic"; - const observer = new Observer(queryClient, defaultedOptions); + const defaultedOptions = queryClient.defaultQueryOptions(options) + defaultedOptions._optimisticResults = 'optimistic' + const observer = new Observer(queryClient, defaultedOptions) const [state, setState] = createStore>( // @ts-ignore observer.getOptimisticResult(defaultedOptions), - ); + ) - const [dataResource, { refetch, mutate }] = createResource(() => { - return new Promise((resolve) => { - if (!(state.isFetching && state.isLoading)) { - resolve(unwrap(state.data)); - } - }); - }); + const [dataResource, { refetch, mutate }] = createResource( + () => { + return new Promise((resolve) => { + if (!(state.isFetching && state.isLoading)) { + resolve(unwrap(state.data)) + } + }) + }, + ) batch(() => { - mutate(() => unwrap(state.data)); - refetch(); - }); + mutate(() => unwrap(state.data)) + refetch() + }) const unsubscribe = observer.subscribe((result) => { batch(() => { - setState(unwrap(result)); - mutate(() => unwrap(result.data)); - refetch(); - }); - }); + setState(unwrap(result)) + mutate(() => unwrap(result.data)) + refetch() + }) + }) - onCleanup(() => unsubscribe()); + onCleanup(() => unsubscribe()) onMount(() => { - observer.setOptions(defaultedOptions, { listeners: false }); - }); + observer.setOptions(defaultedOptions, { listeners: false }) + }) createComputed(() => { - const newDefaultedOptions = queryClient.defaultQueryOptions(options); - observer.setOptions(newDefaultedOptions); - }); + const newDefaultedOptions = queryClient.defaultQueryOptions(options) + observer.setOptions(newDefaultedOptions) + }) createComputed( on( @@ -72,23 +87,23 @@ export function createBaseQuery< observer.getCurrentQuery(), ]) ) { - throw state.error; + throw state.error } }, ), - ); + ) const handler = { get( target: QueryObserverResult, prop: keyof QueryObserverResult, ): any { - if (prop === "data") { - return dataResource(); + if (prop === 'data') { + return dataResource() } - return Reflect.get(target, prop); + return Reflect.get(target, prop) }, - }; + } - return new Proxy(state, handler) as QueryObserverResult; + return new Proxy(state, handler) as QueryObserverResult } diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 3e7f773df26..c9e7569497d 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -14,4 +14,3 @@ export { useIsFetching } from './useIsFetching' export { useIsMutating } from './useIsMutating' export { createMutation } from './createMutation' export { createInfiniteQuery } from './createInfiniteQuery' - From 68ee982f018999f6733d50e28dd3f40eb16415fd Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 16 Sep 2022 23:02:13 -0400 Subject: [PATCH 097/221] Small Types Fix for CreateInfiniteQuery --- .../solid-query/src/createInfiniteQuery.ts | 92 +++++-------------- 1 file changed, 23 insertions(+), 69 deletions(-) diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts index 608772f4f00..a9ddba6d445 100644 --- a/packages/solid-query/src/createInfiniteQuery.ts +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -1,17 +1,9 @@ -import { - QueryObserver, - InfiniteQueryObserver, - QueryFunction, -} from '@tanstack/query-core' -import { - CreateInfiniteQueryOptions, - CreateInfiniteQueryResult, - SolidQueryKey, -} from './types' -import { createBaseQuery } from './createBaseQuery' -import { createComputed } from 'solid-js' -import { createStore } from 'solid-js/store' -import { parseQueryArgs } from './utils' +import { QueryObserver, InfiniteQueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; +import { CreateInfiniteQueryOptions, CreateInfiniteQueryResult, SolidQueryKey } from "./types"; +import { createBaseQuery } from "./createBaseQuery"; +import { createComputed } from "solid-js"; +import { createStore } from "solid-js/store"; +import { parseQueryArgs } from "./utils"; export function createInfiniteQuery< TQueryFnData = unknown, @@ -19,14 +11,8 @@ export function createInfiniteQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, -): CreateInfiniteQueryResult + options: CreateInfiniteQueryOptions, +): CreateInfiniteQueryResult; export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -35,16 +21,10 @@ export function createInfiniteQuery< >( queryKey: TQueryKey, options?: Omit< - CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, - 'queryKey' + CreateInfiniteQueryOptions, + "queryKey" >, -): CreateInfiniteQueryResult +): CreateInfiniteQueryResult; export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -54,16 +34,10 @@ export function createInfiniteQuery< queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< - CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, - 'queryKey' | 'queryFn' + CreateInfiniteQueryOptions, + "queryKey" | "queryFn" >, -): CreateInfiniteQueryResult +): CreateInfiniteQueryResult; export function createInfiniteQuery< TQueryFnData, TError, @@ -72,44 +46,24 @@ export function createInfiniteQuery< >( arg1: | TQueryKey - | CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, + | CreateInfiniteQueryOptions, arg2?: | QueryFunction> - | CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, - arg3?: CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, + | CreateInfiniteQueryOptions, + arg3?: CreateInfiniteQueryOptions, ): CreateInfiniteQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore( - parseQueryArgs(arg1, arg2, arg3), - ) + const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) - setParsedOptions(newParsedOptions) - }) + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); + setParsedOptions(newParsedOptions); + }); return createBaseQuery( - parsedOptions, + parsedOptions as QueryOptions>, InfiniteQueryObserver as typeof QueryObserver, - ) as CreateInfiniteQueryResult + ) as CreateInfiniteQueryResult; } From 8ab020dbd295903c076933970f78579b7639fef4 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 13:52:20 -0400 Subject: [PATCH 098/221] most infinite query tests passing --- .../__tests__/createInfiniteQuery.test.tsx | 589 ++++++++++-------- 1 file changed, 334 insertions(+), 255 deletions(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index 7eced5591f7..1c874f8c198 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -11,7 +11,16 @@ import { InfiniteData, QueryClientProvider, } from '..' -import { createEffect, createRenderEffect, createSignal } from 'solid-js' +import { + createEffect, + createRenderEffect, + createSignal, + For, + Index, + Match, + on, + Switch, +} from 'solid-js' interface Result { items: number[] @@ -197,9 +206,11 @@ describe('useInfiniteQuery', () => { }, ) - createRenderEffect(() => { - states.push({ ...state }) - }) + createRenderEffect( + on([() => ({ ...state }), order], () => { + states.push({ ...state }) + }), + ) return (
@@ -225,7 +236,7 @@ describe('useInfiniteQuery', () => { await waitFor(() => screen.getByText('data: 0-asc')) await waitFor(() => screen.getByText('isFetching: false')) - await waitFor(() => expect(states.length).toBe(7)) + await waitFor(() => expect(states.length).toBe(6)) expect(states[0]).toMatchObject({ data: undefined, @@ -263,15 +274,7 @@ describe('useInfiniteQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update expect(states[5]).toMatchObject({ - data: { pages: ['0-desc', '1-desc'] }, - isFetching: true, - isFetchingNextPage: false, - isSuccess: true, - isPreviousData: true, - }) - expect(states[6]).toMatchObject({ data: { pages: ['0-asc'] }, isFetching: false, isFetchingNextPage: false, @@ -713,12 +716,12 @@ describe('useInfiniteQuery', () => { const states: CreateInfiniteQueryResult[] = [] function Page() { - const multiplier = React.useRef(1) + let multiplier = 1 const state = createInfiniteQuery( key, async ({ pageParam = 10 }) => { await sleep(10) - return Number(pageParam) * multiplier.current + return Number(pageParam) * multiplier }, { getNextPageParam: (lastPage) => lastPage + 1, @@ -726,14 +729,16 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
+ +
- ))} -
- - - -
-
{!isFetchingNextPage ? 'Background Updating...' : null}
- - )} +
+ {!state.isFetchingNextPage ? 'Background Updating...' : null} +
+ + } + > + Loading... + + Error: {state.error!.message} + +
) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('Loading...') + screen.getByText('Loading...') - await waitFor(() => rendered.getByText('Item: 2')) - await waitFor(() => rendered.getByText('Page 0: 0')) + await waitFor(() => screen.getByText('Item: 2')) + await waitFor(() => screen.getByText('Page 0: 0')) - fireEvent.click(rendered.getByText('Load More')) + fireEvent.click(screen.getByText('Load More')) - await waitFor(() => rendered.getByText('Loading more...')) - await waitFor(() => rendered.getByText('Item: 5')) - await waitFor(() => rendered.getByText('Page 0: 0')) - await waitFor(() => rendered.getByText('Page 1: 1')) + await waitFor(() => screen.getByText('Loading more...')) + await waitFor(() => screen.getByText('Item: 5')) + await waitFor(() => screen.getByText('Page 0: 0')) + await waitFor(() => screen.getByText('Page 1: 1')) - fireEvent.click(rendered.getByText('Load More')) + fireEvent.click(screen.getByText('Load More')) - await waitFor(() => rendered.getByText('Loading more...')) - await waitFor(() => rendered.getByText('Item: 8')) - await waitFor(() => rendered.getByText('Page 0: 0')) - await waitFor(() => rendered.getByText('Page 1: 1')) - await waitFor(() => rendered.getByText('Page 2: 2')) + await waitFor(() => screen.getByText('Loading more...')) + await waitFor(() => screen.getByText('Item: 8')) + await waitFor(() => screen.getByText('Page 0: 0')) + await waitFor(() => screen.getByText('Page 1: 1')) + await waitFor(() => screen.getByText('Page 2: 2')) - fireEvent.click(rendered.getByText('Refetch')) + fireEvent.click(screen.getByText('Refetch')) - await waitFor(() => rendered.getByText('Background Updating...')) - await waitFor(() => rendered.getByText('Item: 8')) - await waitFor(() => rendered.getByText('Page 0: 3')) - await waitFor(() => rendered.getByText('Page 1: 4')) - await waitFor(() => rendered.getByText('Page 2: 5')) + await waitFor(() => screen.getByText('Background Updating...')) + await waitFor(() => screen.getByText('Item: 8')) + await waitFor(() => screen.getByText('Page 0: 3')) + await waitFor(() => screen.getByText('Page 1: 4')) + await waitFor(() => screen.getByText('Page 2: 5')) // ensure that Item: 4 is rendered before removing it - expect(rendered.queryAllByText('Item: 4')).toHaveLength(1) + expect(screen.queryAllByText('Item: 4')).toHaveLength(1) // remove Item: 4 - fireEvent.click(rendered.getByText('Remove item')) + fireEvent.click(screen.getByText('Remove item')) - await waitFor(() => rendered.getByText('Background Updating...')) + await waitFor(() => screen.getByText('Background Updating...')) // ensure that an additional item is rendered (it means that cursors were properly rebuilt) - await waitFor(() => rendered.getByText('Item: 9')) - await waitFor(() => rendered.getByText('Page 0: 6')) - await waitFor(() => rendered.getByText('Page 1: 7')) - await waitFor(() => rendered.getByText('Page 2: 8')) + await waitFor(() => screen.getByText('Item: 9')) + await waitFor(() => screen.getByText('Page 0: 6')) + await waitFor(() => screen.getByText('Page 1: 7')) + await waitFor(() => screen.getByText('Page 2: 8')) // ensure that Item: 4 is no longer rendered - expect(rendered.queryAllByText('Item: 4')).toHaveLength(0) + expect(screen.queryAllByText('Item: 4')).toHaveLength(0) }) it('should compute hasNextPage correctly for falsy getFetchMore return value on refetching', async () => { @@ -1652,25 +1727,16 @@ describe('useInfiniteQuery', () => { const MAX = 2 function Page() { - const fetchCountRef = React.useRef(0) + let fetchCountRef = 0 const [isRemovedLastPage, setIsRemovedLastPage] = - React.useState(false) - const { - status, - data, - error, - isFetching, - isFetchingNextPage, - fetchNextPage, - hasNextPage, - refetch, - } = createInfiniteQuery( + createSignal(false) + const state = createInfiniteQuery( key, ({ pageParam = 0 }) => fetchItems( pageParam, - fetchCountRef.current++, - pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage), + fetchCountRef++, + pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage()), ), { getNextPageParam: (lastPage) => lastPage.nextId, @@ -1680,101 +1746,112 @@ describe('useInfiniteQuery', () => { return (

Pagination

- {status === 'loading' ? ( - 'Loading...' - ) : status === 'error' ? ( - Error: {error.message} - ) : ( - <> -
Data:
- {data.pages.map((page, i) => ( -
-
- Page {i}: {page.ts} -
-
- {page.items.map((item) => ( -

Item: {item}

- ))} -
+ +
Data:
+ + {(page, i) => ( +
+
+ Page {i()}: {page.ts} +
+
+ + {(item) =>

Item: {item()}

} +
+
+
+ )} +
+
+ + + +
+
+ {state.isFetching && !state.isFetchingNextPage + ? 'Background Updating...' + : null}
- ))} -
- - - -
-
- {isFetching && !isFetchingNextPage - ? 'Background Updating...' - : null} -
- - )} + + } + > + Loading... + + Error: {state.error!.message} + +
) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('Loading...') + screen.getByText('Loading...') await waitFor(() => { - rendered.getByText('Item: 9') - rendered.getByText('Page 0: 0') + screen.getByText('Item: 9') + screen.getByText('Page 0: 0') }) - fireEvent.click(rendered.getByText('Load More')) + fireEvent.click(screen.getByText('Load More')) - await waitFor(() => rendered.getByText('Loading more...')) + await waitFor(() => screen.getByText('Loading more...')) await waitFor(() => { - rendered.getByText('Item: 19') - rendered.getByText('Page 0: 0') - rendered.getByText('Page 1: 1') + screen.getByText('Item: 19') + screen.getByText('Page 0: 0') + screen.getByText('Page 1: 1') }) - fireEvent.click(rendered.getByText('Load More')) + fireEvent.click(screen.getByText('Load More')) - await waitFor(() => rendered.getByText('Loading more...')) + await waitFor(() => screen.getByText('Loading more...')) await waitFor(() => { - rendered.getByText('Item: 29') - rendered.getByText('Page 0: 0') - rendered.getByText('Page 1: 1') - rendered.getByText('Page 2: 2') + screen.getByText('Item: 29') + screen.getByText('Page 0: 0') + screen.getByText('Page 1: 1') + screen.getByText('Page 2: 2') }) - rendered.getByText('Nothing more to load') + screen.getByText('Nothing more to load') - fireEvent.click(rendered.getByText('Remove Last Page')) + fireEvent.click(screen.getByText('Remove Last Page')) await sleep(10) - fireEvent.click(rendered.getByText('Refetch')) + fireEvent.click(screen.getByText('Refetch')) - await waitFor(() => rendered.getByText('Background Updating...')) + await waitFor(() => screen.getByText('Background Updating...')) await waitFor(() => { - rendered.getByText('Page 0: 3') - rendered.getByText('Page 1: 4') + screen.getByText('Page 0: 3') + screen.getByText('Page 1: 4') }) - expect(rendered.queryByText('Item: 29')).toBeNull() - expect(rendered.queryByText('Page 2: 5')).toBeNull() + expect(screen.queryByText('Item: 29')).toBeNull() + expect(screen.queryByText('Page 2: 5')).toBeNull() - rendered.getByText('Nothing more to load') + screen.getByText('Nothing more to load') }) it('should cancel the query function when there are no more subscriptions', async () => { @@ -1800,14 +1877,16 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient( - queryClient, - - - , - ) + render(() => ( + + + + + , + + )) - await waitFor(() => rendered.getByText('off')) + await waitFor(() => screen.getByText('off')) if (typeof AbortSignal === 'function') { expect(cancelFn).toHaveBeenCalled() From acaf46ee937cef27efd20159aa625763a3507869 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 14:00:44 -0400 Subject: [PATCH 099/221] all infinite query tests passing --- .../src/__tests__/createInfiniteQuery.test.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index 1c874f8c198..fd2dbc78c72 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -942,7 +942,7 @@ describe('useInfiniteQuery', () => { let callIndex = 0 const firstCtx = fetchPage.mock.calls[callIndex]![0] expect(firstCtx.pageParam).toBeUndefined() - expect(firstCtx.queryKey).toEqual(key) + expect(firstCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(firstCtx.signal).toBeInstanceOf(AbortSignal) expect(firstCtx.signal?.aborted).toBe(false) @@ -953,7 +953,7 @@ describe('useInfiniteQuery', () => { callIndex = 1 const secondCtx = fetchPage.mock.calls[callIndex]![0] expect(secondCtx.pageParam).toBe(11) - expect(secondCtx.queryKey).toEqual(key) + expect(secondCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(secondCtx.signal).toBeInstanceOf(AbortSignal) expect(secondCtx.signal?.aborted).toBe(true) @@ -964,7 +964,7 @@ describe('useInfiniteQuery', () => { callIndex = 2 const thirdCtx = fetchPage.mock.calls[callIndex]![0] expect(thirdCtx.pageParam).toBe(11) - expect(thirdCtx.queryKey).toEqual(key) + expect(thirdCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(thirdCtx.signal).toBeInstanceOf(AbortSignal) expect(thirdCtx.signal?.aborted).toBe(false) @@ -1028,7 +1028,7 @@ describe('useInfiniteQuery', () => { let callIndex = 0 const firstCtx = fetchPage.mock.calls[callIndex]![0] expect(firstCtx.pageParam).toBeUndefined() - expect(firstCtx.queryKey).toEqual(key) + expect(firstCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(firstCtx.signal).toBeInstanceOf(AbortSignal) expect(firstCtx.signal?.aborted).toBe(false) @@ -1039,7 +1039,7 @@ describe('useInfiniteQuery', () => { callIndex = 1 const secondCtx = fetchPage.mock.calls[callIndex]![0] expect(secondCtx.pageParam).toBe(11) - expect(secondCtx.queryKey).toEqual(key) + expect(secondCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(secondCtx.signal).toBeInstanceOf(AbortSignal) expect(secondCtx.signal?.aborted).toBe(false) @@ -1247,7 +1247,7 @@ describe('useInfiniteQuery', () => { const state = createInfiniteQuery( key, - async ({ pageParam = firstPage }) => { + async ({ pageParam = firstPage() }) => { await sleep(10) return Number(pageParam) }, @@ -1882,7 +1882,6 @@ describe('useInfiniteQuery', () => { - , )) From 5a2e0b9e7c7907cfb1d2417fcbb48b0de4fc3c2b Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 14:44:43 -0400 Subject: [PATCH 100/221] almost all create mutation tests passing --- .../src/__tests__/createMutation.test.tsx | 508 +++++++++++------- 1 file changed, 309 insertions(+), 199 deletions(-) diff --git a/packages/solid-query/src/__tests__/createMutation.test.tsx b/packages/solid-query/src/__tests__/createMutation.test.tsx index c8807dd70bf..f2bcb55eb35 100644 --- a/packages/solid-query/src/__tests__/createMutation.test.tsx +++ b/packages/solid-query/src/__tests__/createMutation.test.tsx @@ -1,13 +1,26 @@ -import { fireEvent, waitFor } from 'solid-testing-library' - -import { QueryClient, createMutation, QueryCache, MutationCache } from '..' +import { fireEvent, render, waitFor, screen } from 'solid-testing-library' +import '@testing-library/jest-dom' +import { + QueryClient, + createMutation, + QueryCache, + MutationCache, + QueryClientProvider, +} from '..' import { CreateMutationResult } from '../types' import { createQueryClient, mockNavigatorOnLine, sleep, } from '../../../../tests/utils' -import { renderWithClient, queryKey, setActTimeout } from './utils' +import { queryKey, setActTimeout } from './utils' +import { + createContext, + createEffect, + createRenderEffect, + createSignal, + ErrorBoundary, +} from 'solid-js' describe('useMutation', () => { const queryCache = new QueryCache() @@ -16,41 +29,41 @@ describe('useMutation', () => { it('should be able to reset `data`', async () => { function Page() { - const { - mutate, - data = 'empty', - reset, - } = createMutation(() => Promise.resolve('mutation')) + const mutation = createMutation(() => Promise.resolve('mutation')) return (
-

{data}

- - +

{mutation.data ?? 'empty'}

+ +
) } - const { getByRole } = renderWithClient(queryClient, ) + render(() => ( + + + + )) - expect(getByRole('heading').textContent).toBe('empty') + expect(screen.getByRole('heading').textContent).toBe('empty') - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('mutation') + expect(screen.getByRole('heading').textContent).toBe('mutation') }) - fireEvent.click(getByRole('button', { name: /reset/i })) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('empty') + expect(screen.getByRole('heading').textContent).toBe('empty') }) }) it('should be able to reset `error`', async () => { function Page() { - const { mutate, error, reset } = createMutation(() => { + const mutation = createMutation(() => { const err = new Error('Expected mock error. All is well!') err.stack = '' return Promise.reject(err) @@ -58,41 +71,45 @@ describe('useMutation', () => { return (
- {error &&

{error.message}

} - - + {mutation.error &&

{mutation.error.message}

} + +
) } - const { getByRole, queryByRole } = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => { - expect(queryByRole('heading')).toBeNull() + expect(screen.queryByRole('heading')).toBeNull() }) - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe( + expect(screen.getByRole('heading').textContent).toBe( 'Expected mock error. All is well!', ) }) - fireEvent.click(getByRole('button', { name: /reset/i })) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) await waitFor(() => { - expect(queryByRole('heading')).toBeNull() + expect(screen.queryByRole('heading')).toBeNull() }) }) it('should be able to call `onSuccess` and `onSettled` after each successful mutate', async () => { - let count = 0 + let [count, setCount] = createSignal(0) const onSuccessMock = jest.fn() const onSettledMock = jest.fn() function Page() { - const { mutate } = createMutation( + const mutation = createMutation( (vars: { count: number }) => Promise.resolve(vars.count), { onSuccess: (data) => { @@ -106,22 +123,33 @@ describe('useMutation', () => { return (
-

{count}

- +

{count()}

+
) } - const { getByRole } = renderWithClient(queryClient, ) + render(() => ( + + + + )) - expect(getByRole('heading').textContent).toBe('0') + expect(screen.getByRole('heading').textContent).toBe('0') - fireEvent.click(getByRole('button', { name: /mutate/i })) - fireEvent.click(getByRole('button', { name: /mutate/i })) - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('3') + expect(screen.getByRole('heading').textContent).toBe('3') }) await waitFor(() => { @@ -144,10 +172,10 @@ describe('useMutation', () => { it('should be able to call `onError` and `onSettled` after each failed mutate', async () => { const onErrorMock = jest.fn() const onSettledMock = jest.fn() - let count = 0 + let [count, setCount] = createSignal(0) function Page() { - const { mutate } = createMutation( + const mutation = createMutation( (vars: { count: number }) => { const error = new Error( `Expected mock error. All is well! ${vars.count}`, @@ -167,22 +195,33 @@ describe('useMutation', () => { return (
-

{count}

- +

{count()}

+
) } - const { getByRole } = renderWithClient(queryClient, ) + render(() => ( + + + + )) - expect(getByRole('heading').textContent).toBe('0') + expect(screen.getByRole('heading').textContent).toBe('0') - fireEvent.click(getByRole('button', { name: /mutate/i })) - fireEvent.click(getByRole('button', { name: /mutate/i })) - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('3') + expect(screen.getByRole('heading').textContent).toBe('3') }) await waitFor(() => { @@ -216,7 +255,7 @@ describe('useMutation', () => { const callbacks: string[] = [] function Page() { - const { mutateAsync } = createMutation(async (text: string) => text, { + const mutation = createMutation(async (text: string) => text, { onSuccess: async () => { callbacks.push('useMutation.onSuccess') }, @@ -225,7 +264,8 @@ describe('useMutation', () => { }, }) - React.useEffect(() => { + createEffect(() => { + const { mutateAsync } = mutation setActTimeout(async () => { try { const result = await mutateAsync('todo', { @@ -239,12 +279,16 @@ describe('useMutation', () => { callbacks.push(`mutateAsync.result:${result}`) } catch {} }, 10) - }, [mutateAsync]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -261,7 +305,7 @@ describe('useMutation', () => { const callbacks: string[] = [] function Page() { - const { mutateAsync } = createMutation( + const mutation = createMutation( async (_text: string) => Promise.reject('oops'), { onError: async () => { @@ -273,7 +317,8 @@ describe('useMutation', () => { }, ) - React.useEffect(() => { + createEffect(() => { + const { mutateAsync } = mutation setActTimeout(async () => { try { await mutateAsync('todo', { @@ -288,12 +333,16 @@ describe('useMutation', () => { callbacks.push(`mutateAsync.error:${error}`) } }, 10) - }, [mutateAsync]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -309,7 +358,7 @@ describe('useMutation', () => { it('should be able to use mutation defaults', async () => { const key = queryKey() - queryClient.setMutationDefaults(key, { + queryClient.setMutationDefaults(key(), { mutationFn: async (text: string) => { await sleep(10) return text @@ -319,22 +368,27 @@ describe('useMutation', () => { const states: CreateMutationResult[] = [] function Page() { - const state = createMutation(key) + const mutation = createMutation(key()) - states.push(state) - - const { mutate } = state + createRenderEffect(() => { + states.push({ ...mutation }) + }) - React.useEffect(() => { + createEffect(() => { + const { mutate } = mutation setActTimeout(() => { mutate('todo') }, 10) - }, [mutate]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -348,7 +402,7 @@ describe('useMutation', () => { let count = 0 function Page() { - const { mutate } = createMutation( + const mutation = createMutation( (_text: string) => { count++ return Promise.reject('oops') @@ -359,16 +413,21 @@ describe('useMutation', () => { }, ) - React.useEffect(() => { + createEffect(() => { + const { mutate } = mutation setActTimeout(() => { mutate('todo') }, 10) - }, [mutate]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -396,27 +455,33 @@ describe('useMutation', () => {
- error:{' '} - {mutation.error instanceof Error ? mutation.error.message : 'null'}, - status: {mutation.status}, isPaused: {String(mutation.isPaused)} + {`error: ${ + mutation.error instanceof Error ? mutation.error.message : 'null' + }, status: ${mutation.status}, isPaused: ${String( + mutation.isPaused, + )}`}
) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => { expect( - rendered.getByText('error: null, status: idle, isPaused: false'), + screen.getByText('error: null, status: idle, isPaused: false'), ).toBeInTheDocument() }) - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { expect( - rendered.getByText('error: null, status: loading, isPaused: true'), + screen.getByText('error: null, status: loading, isPaused: true'), ).toBeInTheDocument() }) @@ -429,7 +494,7 @@ describe('useMutation', () => { await waitFor(() => { expect( - rendered.getByText('error: oops, status: error, isPaused: false'), + screen.getByText('error: oops, status: error, isPaused: false'), ).toBeInTheDocument() }) @@ -466,13 +531,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: null, status: idle, isPaused: false') + await screen.findByText('data: null, status: idle, isPaused: false') - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) - await rendered.findByText('data: null, status: loading, isPaused: true') + await screen.findByText('data: null, status: loading, isPaused: true') expect(onMutate).toHaveBeenCalledTimes(1) expect(onMutate).toHaveBeenCalledWith('todo') @@ -480,7 +549,7 @@ describe('useMutation', () => { onlineMock.mockReturnValue(true) window.dispatchEvent(new Event('online')) - await rendered.findByText('data: 1, status: success, isPaused: false') + await screen.findByText('data: 1, status: success, isPaused: false') expect(onMutate).toHaveBeenCalledTimes(1) expect(count).toBe(1) @@ -500,7 +569,9 @@ describe('useMutation', () => { return count }) - states.push(`${mutation.status}, ${mutation.isPaused}`) + createRenderEffect(() => { + states.push(`${mutation.status}, ${mutation.isPaused}`) + }) return (
@@ -513,13 +584,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: null, status: idle, isPaused: false') + await screen.findByText('data: null, status: idle, isPaused: false') - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) - await rendered.findByText('data: null, status: loading, isPaused: true') + await screen.findByText('data: null, status: loading, isPaused: true') // no intermediate 'loading, false' state is expected because we don't start mutating! expect(states[0]).toBe('idle, false') @@ -528,7 +603,7 @@ describe('useMutation', () => { onlineMock.mockReturnValue(true) window.dispatchEvent(new Event('online')) - await rendered.findByText('data: 1, status: success, isPaused: false') + await screen.findByText('data: 1, status: success, isPaused: false') onlineMock.mockRestore() }) @@ -540,7 +615,7 @@ describe('useMutation', () => { const states: CreateMutationResult[] = [] function Page() { - const state = createMutation( + const mutation = createMutation( async (_text: string) => { await sleep(1) count++ @@ -553,20 +628,25 @@ describe('useMutation', () => { }, ) - states.push(state) - - const { mutate } = state + createRenderEffect(() => { + states.push({ ...mutation }) + }) - React.useEffect(() => { + createEffect(() => { + const { mutate } = mutation setActTimeout(() => { mutate('todo') }, 10) - }, [mutate]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) @@ -615,27 +695,31 @@ describe('useMutation', () => { it('should not change state if unmounted', async () => { function Mutates() { - const { mutate } = createMutation(() => sleep(10)) - return + const mutation = createMutation(() => sleep(10)) + return } function Page() { - const [mounted, setMounted] = React.useState(true) + const [mounted, setMounted] = createSignal(true) return (
- {mounted && } + {mounted() && }
) } - const { getByText } = renderWithClient(queryClient, ) - fireEvent.click(getByText('mutate')) - fireEvent.click(getByText('unmount')) + render(() => ( + + + + )) + fireEvent.click(screen.getByText('mutate')) + fireEvent.click(screen.getByText('unmount')) }) it('should be able to throw an error when useErrorBoundary is set to true', async () => { function Page() { - const { mutate } = createMutation( + const mutation = createMutation( () => { const err = new Error('Expected mock error. All is well!') err.stack = '' @@ -646,35 +730,36 @@ describe('useMutation', () => { return (
- +
) } - const { getByText, queryByText } = renderWithClient( - queryClient, - ( -
- error -
- )} - > - -
, - ) + render(() => ( + + ( +
+ error +
+ )} + > + +
+
+ )) - fireEvent.click(getByText('mutate')) + fireEvent.click(screen.getByText('mutate')) await waitFor(() => { - expect(queryByText('error')).not.toBeNull() + expect(screen.queryByText('error')).not.toBeNull() }) }) it('should be able to throw an error when useErrorBoundary is a function that returns true', async () => { let boundary = false function Page() { - const { mutate, error } = createMutation( + const mutation = createMutation( () => { const err = new Error('mock error') err.stack = '' @@ -690,35 +775,36 @@ describe('useMutation', () => { return (
- - {error && error.message} + + {mutation.error && mutation.error.message}
) } - const { getByText, queryByText } = renderWithClient( - queryClient, - ( -
- error boundary -
- )} - > - -
, - ) + render(() => ( + + ( +
+ error boundary +
+ )} + > + +
+
+ )) // first error goes to component - fireEvent.click(getByText('mutate')) + fireEvent.click(screen.getByText('mutate')) await waitFor(() => { - expect(queryByText('mock error')).not.toBeNull() + expect(screen.queryByText('mock error')).not.toBeNull() }) // second error goes to boundary - fireEvent.click(getByText('mutate')) + fireEvent.click(screen.getByText('mutate')) await waitFor(() => { - expect(queryByText('error boundary')).not.toBeNull() + expect(screen.queryByText('error boundary')).not.toBeNull() }) }) @@ -741,10 +827,10 @@ describe('useMutation', () => { const metaErrorMessage = 'mutation failed' function Page() { - const { mutate: succeed, isSuccess } = createMutation(async () => '', { + const mutationSucceed = createMutation(async () => '', { meta: { metaSuccessMessage }, }) - const { mutate: error, isError } = createMutation( + const mutationError = createMutation( async () => { throw new Error('') }, @@ -755,25 +841,26 @@ describe('useMutation', () => { return (
- - - {isSuccess &&
successTest
} - {isError &&
errorTest
} + + + {mutationSucceed.isSuccess &&
successTest
} + {mutationError.isError &&
errorTest
}
) } - const { getByText, queryByText } = renderWithClient( - queryClientMutationMeta, - , - ) + render(() => ( + + + + )) - fireEvent.click(getByText('succeed')) - fireEvent.click(getByText('error')) + fireEvent.click(screen.getByText('succeed')) + fireEvent.click(screen.getByText('error')) await waitFor(() => { - expect(queryByText('successTest')).not.toBeNull() - expect(queryByText('errorTest')).not.toBeNull() + expect(screen.queryByText('successTest')).not.toBeNull() + expect(screen.queryByText('errorTest')).not.toBeNull() }) expect(successMock).toHaveBeenCalledTimes(1) @@ -791,11 +878,11 @@ describe('useMutation', () => { let count = 0 function Page() { - const [show, setShow] = React.useState(true) + const [show, setShow] = createSignal(true) return (
- {show && } + {show() && }
) } @@ -808,7 +895,7 @@ describe('useMutation', () => { return count }, { - mutationKey, + mutationKey: mutationKey(), cacheTime: 0, onSuccess, onSettled, @@ -835,16 +922,20 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: null, status: idle, isPaused: false') + await screen.findByText('data: null, status: idle, isPaused: false') - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) await waitFor(() => { expect( - queryClient.getMutationCache().findAll({ mutationKey }), + queryClient.getMutationCache().findAll({ mutationKey: mutationKey() }), ).toHaveLength(0) }) @@ -858,43 +949,45 @@ describe('useMutation', () => { describe('with custom context', () => { it('should be able to reset `data`', async () => { - const context = React.createContext(undefined) + const context = createContext(undefined) function Page() { - const { - mutate, - data = 'empty', - reset, - } = createMutation(() => Promise.resolve('mutation'), { context }) + const mutation = createMutation(() => Promise.resolve('mutation'), { + context, + }) return (
-

{data}

- - +

{mutation.data ?? 'empty'}

+ +
) } - const { getByRole } = renderWithClient(queryClient, , { context }) + render(() => ( + + + + )) - expect(getByRole('heading').textContent).toBe('empty') + expect(screen.getByRole('heading').textContent).toBe('empty') - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('mutation') + expect(screen.getByRole('heading').textContent).toBe('mutation') }) - fireEvent.click(getByRole('button', { name: /reset/i })) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('empty') + expect(screen.getByRole('heading').textContent).toBe('empty') }) }) it('should throw if the context is not passed to useMutation', async () => { - const context = React.createContext(undefined) + const context = createContext(undefined) function Page() { const { data = '' } = createMutation(() => Promise.resolve('mutation')) @@ -906,15 +999,16 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient( - queryClient, -
error boundary
}> - -
, - { context }, - ) + render(() => ( + +
error boundary
}> + +
+ , +
+ )) - await waitFor(() => rendered.getByText('error boundary')) + await waitFor(() => screen.getByText('error boundary')) }) }) @@ -957,14 +1051,18 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: null, status: idle') + await screen.findByText('data: null, status: idle') - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) - await rendered.findByText('data: result2, status: success') + await screen.findByText('data: result2, status: success') expect(count).toBe(2) @@ -1005,13 +1103,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('status: idle') + await screen.findByText('status: idle') - rendered.getByRole('button', { name: /mutate/i }).click() + screen.getByRole('button', { name: /mutate/i }).click() - await rendered.findByText('status: error') + await screen.findByText('status: error') expect(onError).toHaveBeenCalledWith(error, 'todo', undefined) }) @@ -1043,13 +1145,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('error: null, status: idle') + await screen.findByText('error: null, status: idle') - rendered.getByRole('button', { name: /mutate/i }).click() + screen.getByRole('button', { name: /mutate/i }).click() - await rendered.findByText('error: mutateFnError, status: error') + await screen.findByText('error: mutateFnError, status: error') }) it('should go to error state if onSettled callback errors', async () => { @@ -1081,13 +1187,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('error: null, status: idle') + await screen.findByText('error: null, status: idle') - rendered.getByRole('button', { name: /mutate/i }).click() + screen.getByRole('button', { name: /mutate/i }).click() - await rendered.findByText('error: mutateFnError, status: error') + await screen.findByText('error: mutateFnError, status: error') expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined) }) From 0be078633591057917933828485f818d1861d51d Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 14:46:48 -0400 Subject: [PATCH 101/221] format with prettier --- .../solid-query/src/createInfiniteQuery.ts | 91 ++++++++++++++----- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts index a9ddba6d445..8e66d9132b9 100644 --- a/packages/solid-query/src/createInfiniteQuery.ts +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -1,9 +1,18 @@ -import { QueryObserver, InfiniteQueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; -import { CreateInfiniteQueryOptions, CreateInfiniteQueryResult, SolidQueryKey } from "./types"; -import { createBaseQuery } from "./createBaseQuery"; -import { createComputed } from "solid-js"; -import { createStore } from "solid-js/store"; -import { parseQueryArgs } from "./utils"; +import { + QueryObserver, + InfiniteQueryObserver, + QueryFunction, + QueryOptions, +} from '@tanstack/query-core' +import { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + SolidQueryKey, +} from './types' +import { createBaseQuery } from './createBaseQuery' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' export function createInfiniteQuery< TQueryFnData = unknown, @@ -11,8 +20,14 @@ export function createInfiniteQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: CreateInfiniteQueryOptions, -): CreateInfiniteQueryResult; + options: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -21,10 +36,16 @@ export function createInfiniteQuery< >( queryKey: TQueryKey, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -34,10 +55,16 @@ export function createInfiniteQuery< queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" | "queryFn" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' | 'queryFn' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData, TError, @@ -46,24 +73,44 @@ export function createInfiniteQuery< >( arg1: | TQueryKey - | CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, arg2?: | QueryFunction> - | CreateInfiniteQueryOptions, - arg3?: CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg3?: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, ): CreateInfiniteQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); - setParsedOptions(newParsedOptions); - }); + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) return createBaseQuery( parsedOptions as QueryOptions>, InfiniteQueryObserver as typeof QueryObserver, - ) as CreateInfiniteQueryResult; + ) as CreateInfiniteQueryResult } From ef26e9f398712dd78051a4e986bf79ce13a685fc Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 14:47:18 -0400 Subject: [PATCH 102/221] format with prettier --- .../__tests__/createInfiniteQuery.test.tsx | 2 +- .../solid-query/src/createInfiniteQuery.ts | 91 ++++++++++++++----- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index fd2dbc78c72..9ec48129c53 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -2,7 +2,7 @@ import { waitFor, fireEvent, render, screen } from 'solid-testing-library' import { sleep, createQueryClient } from '../../../../tests/utils' -import { renderWithClient, Blink, queryKey, setActTimeout } from './utils' +import { Blink, queryKey, setActTimeout } from './utils' import { createInfiniteQuery, CreateInfiniteQueryResult, diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts index a9ddba6d445..8e66d9132b9 100644 --- a/packages/solid-query/src/createInfiniteQuery.ts +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -1,9 +1,18 @@ -import { QueryObserver, InfiniteQueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; -import { CreateInfiniteQueryOptions, CreateInfiniteQueryResult, SolidQueryKey } from "./types"; -import { createBaseQuery } from "./createBaseQuery"; -import { createComputed } from "solid-js"; -import { createStore } from "solid-js/store"; -import { parseQueryArgs } from "./utils"; +import { + QueryObserver, + InfiniteQueryObserver, + QueryFunction, + QueryOptions, +} from '@tanstack/query-core' +import { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + SolidQueryKey, +} from './types' +import { createBaseQuery } from './createBaseQuery' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' export function createInfiniteQuery< TQueryFnData = unknown, @@ -11,8 +20,14 @@ export function createInfiniteQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: CreateInfiniteQueryOptions, -): CreateInfiniteQueryResult; + options: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -21,10 +36,16 @@ export function createInfiniteQuery< >( queryKey: TQueryKey, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -34,10 +55,16 @@ export function createInfiniteQuery< queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" | "queryFn" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' | 'queryFn' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData, TError, @@ -46,24 +73,44 @@ export function createInfiniteQuery< >( arg1: | TQueryKey - | CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, arg2?: | QueryFunction> - | CreateInfiniteQueryOptions, - arg3?: CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg3?: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, ): CreateInfiniteQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); - setParsedOptions(newParsedOptions); - }); + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) return createBaseQuery( parsedOptions as QueryOptions>, InfiniteQueryObserver as typeof QueryObserver, - ) as CreateInfiniteQueryResult; + ) as CreateInfiniteQueryResult } From 3ff6926821b08f0b19f865a16c031f858923635a Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 17:24:16 -0400 Subject: [PATCH 103/221] Added createQueries --- packages/solid-query/src/createQueries.ts | 184 ++++++++++++++++++++++ packages/solid-query/src/index.ts | 1 + 2 files changed, 185 insertions(+) create mode 100644 packages/solid-query/src/createQueries.ts diff --git a/packages/solid-query/src/createQueries.ts b/packages/solid-query/src/createQueries.ts new file mode 100644 index 00000000000..a016ae13068 --- /dev/null +++ b/packages/solid-query/src/createQueries.ts @@ -0,0 +1,184 @@ +import { createComputed, onCleanup, onMount } from 'solid-js' +import { QueryFunction, QueriesObserver } from '@tanstack/query-core' +import { useQueryClient } from './QueryClientProvider' +import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' +import { createStore, unwrap } from 'solid-js/store' + +// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`. +// - `context` is omitted as it is passed as a root-level option to `useQueries` instead. +type CreateQueryOptionsForCreateQueries< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +> = Omit, 'context'> + +// Avoid TS depth-limit error in case of large array literal +type MAXIMUM_DEPTH = 20 + +type GetOptions = + // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData } + T extends { + queryFnData: infer TQueryFnData + error?: infer TError + data: infer TData + } + ? CreateQueryOptionsForCreateQueries + : T extends { queryFnData: infer TQueryFnData; error?: infer TError } + ? CreateQueryOptionsForCreateQueries + : T extends { data: infer TData; error?: infer TError } + ? CreateQueryOptionsForCreateQueries + : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData] + T extends [infer TQueryFnData, infer TError, infer TData] + ? CreateQueryOptionsForCreateQueries + : T extends [infer TQueryFnData, infer TError] + ? CreateQueryOptionsForCreateQueries + : T extends [infer TQueryFnData] + ? CreateQueryOptionsForCreateQueries + : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided + T extends { + queryFn?: QueryFunction + select: (data: any) => infer TData + } + ? CreateQueryOptionsForCreateQueries< + TQueryFnData, + unknown, + TData, + () => TQueryKey + > + : T extends { queryFn?: QueryFunction } + ? CreateQueryOptionsForCreateQueries< + TQueryFnData, + unknown, + TQueryFnData, + () => TQueryKey + > + : // Fallback + CreateQueryOptionsForCreateQueries + +type GetResults = + // Part 1: responsible for mapping explicit type parameter to function result, if object + T extends { queryFnData: any; error?: infer TError; data: infer TData } + ? CreateQueryResult + : T extends { queryFnData: infer TQueryFnData; error?: infer TError } + ? CreateQueryResult + : T extends { data: infer TData; error?: infer TError } + ? CreateQueryResult + : // Part 2: responsible for mapping explicit type parameter to function result, if tuple + T extends [any, infer TError, infer TData] + ? CreateQueryResult + : T extends [infer TQueryFnData, infer TError] + ? CreateQueryResult + : T extends [infer TQueryFnData] + ? CreateQueryResult + : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided + T extends { + queryFn?: QueryFunction + select: (data: any) => infer TData + } + ? CreateQueryResult + : T extends { queryFn?: QueryFunction } + ? CreateQueryResult + : // Fallback + CreateQueryResult + +/** + * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param + */ +export type QueriesOptions< + T extends any[], + Result extends any[] = [], + Depth extends ReadonlyArray = [], +> = Depth['length'] extends MAXIMUM_DEPTH + ? CreateQueryOptionsForCreateQueries[] + : T extends [] + ? [] + : T extends [infer Head] + ? [...Result, GetOptions] + : T extends [infer Head, ...infer Tail] + ? QueriesOptions<[...Tail], [...Result, GetOptions], [...Depth, 1]> + : unknown[] extends T + ? T + : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type! + // use this to infer the param types in the case of Array.map() argument + T extends CreateQueryOptionsForCreateQueries< + infer TQueryFnData, + infer TError, + infer TData, + infer TQueryKey + >[] + ? CreateQueryOptionsForCreateQueries[] + : // Fallback + CreateQueryOptionsForCreateQueries[] + +/** + * QueriesResults reducer recursively maps type param to results + */ +export type QueriesResults< + T extends any[], + Result extends any[] = [], + Depth extends ReadonlyArray = [], +> = Depth['length'] extends MAXIMUM_DEPTH + ? CreateQueryResult[] + : T extends [] + ? [] + : T extends [infer Head] + ? [...Result, GetResults] + : T extends [infer Head, ...infer Tail] + ? QueriesResults<[...Tail], [...Result, GetResults], [...Depth, 1]> + : T extends CreateQueryOptionsForCreateQueries< + infer TQueryFnData, + infer TError, + infer TData, + any + >[] + ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results + CreateQueryResult[] + : // Fallback + CreateQueryResult[] + +type ArrType = T extends (infer U)[] ? U : never + +export function createQueries({ + queries, + context, +}: { + queries: readonly [...QueriesOptions] + context?: CreateQueryOptions['context'] +}): QueriesResults { + const queryClient = useQueryClient({ context }) + + const normalizeOptions = (options: ArrType) => { + const normalizedOptions = { ...options, queryKey: options.queryKey?.() } + const defaultedOptions = queryClient.defaultQueryOptions(normalizedOptions) + defaultedOptions._optimisticResults = 'optimistic' + return defaultedOptions + } + + const defaultedQueries = queries.map((options) => normalizeOptions(options)) + + const observer = new QueriesObserver(queryClient, defaultedQueries) + + const [state, setState] = createStore( + observer.getOptimisticResult(defaultedQueries), + ) + + const unsubscribe = observer.subscribe((result) => { + setState(unwrap(result)) + }) + + onCleanup(unsubscribe) + + onMount(() => { + observer.setQueries(defaultedQueries, { listeners: false }) + }) + + createComputed(() => { + const updateDefaultedQueries = queries.map((options) => + normalizeOptions(options), + ) + observer.setQueries(updateDefaultedQueries) + }) + + return state as QueriesResults +} diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index c9e7569497d..81ba67caff7 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -14,3 +14,4 @@ export { useIsFetching } from './useIsFetching' export { useIsMutating } from './useIsMutating' export { createMutation } from './createMutation' export { createInfiniteQuery } from './createInfiniteQuery' +export { createQueries } from './createQueries' From 324ebcf2415aa99079c3fbe581094ecdbbdea749 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 17:29:22 -0400 Subject: [PATCH 104/221] Prettier fix for infiniteQueries --- .../solid-query/src/createInfiniteQuery.ts | 91 ++++++++++++++----- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts index a9ddba6d445..8e66d9132b9 100644 --- a/packages/solid-query/src/createInfiniteQuery.ts +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -1,9 +1,18 @@ -import { QueryObserver, InfiniteQueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; -import { CreateInfiniteQueryOptions, CreateInfiniteQueryResult, SolidQueryKey } from "./types"; -import { createBaseQuery } from "./createBaseQuery"; -import { createComputed } from "solid-js"; -import { createStore } from "solid-js/store"; -import { parseQueryArgs } from "./utils"; +import { + QueryObserver, + InfiniteQueryObserver, + QueryFunction, + QueryOptions, +} from '@tanstack/query-core' +import { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + SolidQueryKey, +} from './types' +import { createBaseQuery } from './createBaseQuery' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' export function createInfiniteQuery< TQueryFnData = unknown, @@ -11,8 +20,14 @@ export function createInfiniteQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: CreateInfiniteQueryOptions, -): CreateInfiniteQueryResult; + options: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -21,10 +36,16 @@ export function createInfiniteQuery< >( queryKey: TQueryKey, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -34,10 +55,16 @@ export function createInfiniteQuery< queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" | "queryFn" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' | 'queryFn' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData, TError, @@ -46,24 +73,44 @@ export function createInfiniteQuery< >( arg1: | TQueryKey - | CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, arg2?: | QueryFunction> - | CreateInfiniteQueryOptions, - arg3?: CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg3?: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, ): CreateInfiniteQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); - setParsedOptions(newParsedOptions); - }); + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) return createBaseQuery( parsedOptions as QueryOptions>, InfiniteQueryObserver as typeof QueryObserver, - ) as CreateInfiniteQueryResult; + ) as CreateInfiniteQueryResult } From ead2383def658cc9f3e5f9a730ac03146182642f Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 17:30:44 -0400 Subject: [PATCH 105/221] run prettier tests --- .../solid-query/src/createInfiniteQuery.ts | 91 ++++++++++++++----- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts index a9ddba6d445..8e66d9132b9 100644 --- a/packages/solid-query/src/createInfiniteQuery.ts +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -1,9 +1,18 @@ -import { QueryObserver, InfiniteQueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; -import { CreateInfiniteQueryOptions, CreateInfiniteQueryResult, SolidQueryKey } from "./types"; -import { createBaseQuery } from "./createBaseQuery"; -import { createComputed } from "solid-js"; -import { createStore } from "solid-js/store"; -import { parseQueryArgs } from "./utils"; +import { + QueryObserver, + InfiniteQueryObserver, + QueryFunction, + QueryOptions, +} from '@tanstack/query-core' +import { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + SolidQueryKey, +} from './types' +import { createBaseQuery } from './createBaseQuery' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' export function createInfiniteQuery< TQueryFnData = unknown, @@ -11,8 +20,14 @@ export function createInfiniteQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: CreateInfiniteQueryOptions, -): CreateInfiniteQueryResult; + options: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -21,10 +36,16 @@ export function createInfiniteQuery< >( queryKey: TQueryKey, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -34,10 +55,16 @@ export function createInfiniteQuery< queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" | "queryFn" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' | 'queryFn' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData, TError, @@ -46,24 +73,44 @@ export function createInfiniteQuery< >( arg1: | TQueryKey - | CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, arg2?: | QueryFunction> - | CreateInfiniteQueryOptions, - arg3?: CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg3?: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, ): CreateInfiniteQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); - setParsedOptions(newParsedOptions); - }); + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) return createBaseQuery( parsedOptions as QueryOptions>, InfiniteQueryObserver as typeof QueryObserver, - ) as CreateInfiniteQueryResult; + ) as CreateInfiniteQueryResult } From 1d0fd5cf9d401427523767b2606d0dbd5e878a46 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 17:56:12 -0400 Subject: [PATCH 106/221] add createQueries tests --- .../src/__tests__/createQueries.test.tsx | 1162 +++++++++++++++++ 1 file changed, 1162 insertions(+) create mode 100644 packages/solid-query/src/__tests__/createQueries.test.tsx diff --git a/packages/solid-query/src/__tests__/createQueries.test.tsx b/packages/solid-query/src/__tests__/createQueries.test.tsx new file mode 100644 index 00000000000..0e94d748229 --- /dev/null +++ b/packages/solid-query/src/__tests__/createQueries.test.tsx @@ -0,0 +1,1162 @@ +import { fireEvent, render, waitFor, screen } from 'solid-testing-library' + +import * as QueriesObserverModule from '../../../query-core/src/queriesObserver' + +import { + createQueryClient, + expectType, + expectTypeNotAny, + sleep, +} from '../../../../tests/utils' +import { queryKey } from './utils' +import { + QueryClient, + createQueries, + CreateQueryResult, + QueryCache, + QueryObserverResult, + QueriesObserver, + QueryFunction, + CreateQueryOptions, + QueryClientProvider, + SolidQueryKey, +} from '..' +import { QueryFunctionContext } from '@tanstack/query-core' +import { + createContext, + createMemo, + createRenderEffect, + createSignal, + ErrorBoundary, +} from 'solid-js' + +describe('useQueries', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should return the correct states', async () => { + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(10) + return 1 + }, + }, + { + queryKey: key2, + queryFn: async () => { + await sleep(100) + return 2 + }, + }, + ], + }) + + createRenderEffect(() => { + results.push([...result]) + }) + + return ( +
+
+ data1: {String(result[0].data ?? 'null')}, data2:{' '} + {String(result[1].data ?? 'null')} +
+
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 1, data2: 2')) + + expect(results.length).toBe(3) + expect(results[0]).toMatchObject([{ data: undefined }, { data: undefined }]) + expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }]) + expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }]) + }) + + it('should keep previous data if amount of queries is the same', async () => { + const key1 = queryKey() + const key2 = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [count, setCount] = createSignal(1) + const result = createQueries({ + queries: [ + { + queryKey: () => [key1(), count()], + keepPreviousData: true, + queryFn: async () => { + await sleep(10) + return count() * 2 + }, + }, + { + queryKey: () => [key2(), count()], + keepPreviousData: true, + queryFn: async () => { + await sleep(35) + return count() * 5 + }, + }, + ], + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
+ data1: {String(result[0].data ?? 'null')}, data2:{' '} + {String(result[1].data ?? 'null')} +
+
isFetching: {String(isFetching())}
+ +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 2, data2: 5')) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) + + await waitFor(() => screen.getByText('data1: 4, data2: 10')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 4, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should keep previous data for variable amounts of useQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [count, setCount] = createSignal(2) + const result = createQueries({ + // TODO(lukemurray): reactive queries doesn't appear to work + get queries() { + return Array.from({ length: count() }, (_, i) => ({ + queryKey: () => [key(), count(), i + 1], + keepPreviousData: true, + queryFn: async () => { + await sleep(35 * (i + 1)) + return (i + 1) * count() * 2 + }, + })) + }, + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
data: {result.map((it) => it.data).join(',')}
+
isFetching: {String(isFetching())}
+ +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data: 4,8')) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) + + await waitFor(() => screen.getByText('data: 6,12,18')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 6, isPreviousData: false, isFetching: false }, + { status: 'success', data: 12, isPreviousData: false, isFetching: false }, + { status: 'success', data: 18, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should keep previous data when switching between queries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [series1, setSeries1] = createSignal(1) + const [series2, setSeries2] = createSignal(2) + const ids = [series1, series2] + + const result = createQueries({ + queries: ids.map((id) => { + return { + queryKey: () => [key(), id()], + queryFn: async () => { + await sleep(5) + return id() * 5 + }, + keepPreviousData: true, + } + }), + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
+ data1: {String(result[0]?.data ?? 'null')}, data2:{' '} + {String(result[1]?.data ?? 'null')} +
+
isFetching: {String(isFetching())}
+ + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 5, data2: 10')) + fireEvent.click(screen.getByRole('button', { name: /setSeries2/i })) + + await waitFor(() => screen.getByText('data1: 5, data2: 15')) + fireEvent.click(screen.getByRole('button', { name: /setSeries1/i })) + + await waitFor(() => screen.getByText('data1: 10, data2: 15')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + { status: 'success', data: 15, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should not go to infinite render loop with previous data when toggling queries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [enableId1, setEnableId1] = createSignal(true) + const ids = createMemo(() => (enableId1() ? [1, 2] : [2])) + + const result = createQueries({ + // TODO(lukemurray): same issue queries should be reactive + get queries() { + return ids().map((id) => { + return { + queryKey: () => [key(), id], + queryFn: async () => { + await sleep(5) + return id * 5 + }, + keepPreviousData: true, + } + }) + }, + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
+ data1: {String(result[0]?.data ?? 'null')}, data2:{' '} + {String(result[1]?.data ?? 'null')} +
+
isFetching: {String(isFetching())}
+ + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 5, data2: 10')) + fireEvent.click(screen.getByRole('button', { name: /set1Disabled/i })) + + await waitFor(() => screen.getByText('data1: 10, data2: null')) + await waitFor(() => screen.getByText('isFetching: false')) + fireEvent.click(screen.getByRole('button', { name: /set2Enabled/i })) + + await waitFor(() => screen.getByText('data1: 5, data2: 10')) + await waitFor(() => screen.getByText('isFetching: false')) + + await waitFor(() => expect(states.length).toBe(6)) + + expect(states[0]).toMatchObject([ + { + status: 'loading', + data: undefined, + isPreviousData: false, + isFetching: true, + }, + { + status: 'loading', + data: undefined, + isPreviousData: false, + isFetching: true, + }, + ]) + expect(states[1]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[2]).toMatchObject([ + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[3]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: true }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[4]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: true }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[5]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + }) + + it('handles type parameter - tuple of tuples', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result1 = createQueries<[[number], [string], [string[], boolean]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + }, + ], + }) + expectType>(result1[0]) + expectType>(result1[1]) + expectType>(result1[2]) + expectType(result1[0].data) + expectType(result1[1].data) + expectType(result1[2].data) + expectType(result1[2].error) + + // TData (3rd element) takes precedence over TQueryFnData (1st element) + const result2 = createQueries< + [[string, unknown, string], [string, unknown, number]] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + }, + ], + }) + expectType>(result2[0]) + expectType>(result2[1]) + expectType(result2[0].data) + expectType(result2[1].data) + + // types should be enforced + createQueries<[[string, unknown, string], [string, boolean, number]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + onError: (e) => { + expectType(e) + expectTypeNotAny(e) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + ], + }) + + // field names should be enforced + createQueries<[[string]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + } + }) + + it('handles type parameter - tuple of objects', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result1 = createQueries< + [ + { queryFnData: number }, + { queryFnData: string }, + { queryFnData: string[]; error: boolean }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + }, + ], + }) + expectType>(result1[0]) + expectType>(result1[1]) + expectType>(result1[2]) + expectType(result1[0].data) + expectType(result1[1].data) + expectType(result1[2].data) + expectType(result1[2].error) + + // TData (data prop) takes precedence over TQueryFnData (queryFnData prop) + const result2 = createQueries< + [ + { queryFnData: string; data: string }, + { queryFnData: string; data: number }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + }, + ], + }) + expectType>(result2[0]) + expectType>(result2[1]) + expectType(result2[0].data) + expectType(result2[1].data) + + // can pass only TData (data prop) although TQueryFnData will be left unknown + const result3 = createQueries<[{ data: string }, { data: number }]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a as string + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a as number + }, + }, + ], + }) + expectType>(result3[0]) + expectType>(result3[1]) + expectType(result3[0].data) + expectType(result3[1].data) + + // types should be enforced + createQueries< + [ + { queryFnData: string; data: string }, + { queryFnData: string; data: number; error: boolean }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + onError: (e) => { + expectType(e) + expectTypeNotAny(e) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + ], + }) + + // field names should be enforced + createQueries<[{ queryFnData: string }]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + } + }) + + it('handles array literal without type parameter to infer result type', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + const key4 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + // Array.map preserves TQueryFnData + const result1 = createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + })), + }) + expectType[]>(result1) + expectType(result1[0]?.data) + + // Array.map preserves TData + const result2 = createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + })), + }) + expectType[]>(result2) + + const result3 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + select: () => 123, + }, + ], + }) + expectType>(result3[0]) + expectType>(result3[1]) + expectType>(result3[2]) + expectType(result3[0].data) + expectType(result3[1].data) + // select takes precedence over queryFn + expectType(result3[2].data) + + // initialData/placeholderData are enforced + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 123, + // @ts-expect-error (placeholderData: number) + placeholderData: 'string', + initialData: 123, + }, + ], + }) + + // select / onSuccess / onSettled params are "indirectly" enforced + createQueries({ + queries: [ + // unfortunately TS will not suggest the type for you + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (noImplicitAny) + onSuccess: (a) => null, + // @ts-expect-error (noImplicitAny) + onSettled: (a) => null, + }, + // however you can add a type to the callback + { + queryKey: key2, + queryFn: () => 'string', + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + onSettled: (a: string | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + // the type you do pass is enforced + { + queryKey: key3, + queryFn: () => 'string', + // @ts-expect-error (only accepts string) + onSuccess: (a: number) => null, + }, + { + queryKey: key4, + queryFn: () => 'string', + select: (a: string) => parseInt(a), + // @ts-expect-error (select is defined => only accepts number) + onSuccess: (a: string) => null, + onSettled: (a: number | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + ], + }) + + // callbacks are also indirectly enforced with Array.map + createQueries({ + // @ts-expect-error (onSuccess only accepts string) + queries: Array(50).map((_, i) => ({ + queryKey: ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + onSuccess: (_data: number) => null, + })), + }) + createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + onSuccess: (_data: string) => null, + })), + }) + + // results inference works when all the handlers are defined + const result4 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (noImplicitAny) + onSuccess: (a) => null, + // @ts-expect-error (noImplicitAny) + onSettled: (a) => null, + }, + { + queryKey: key2, + queryFn: () => 'string', + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + onSettled: (a: string | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + { + queryKey: key4, + queryFn: () => 'string', + select: (a: string) => parseInt(a), + onSuccess: (_a: number) => null, + onSettled: (a: number | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + ], + }) + expectType>(result4[0]) + expectType>(result4[1]) + expectType>(result4[2]) + + // handles when queryFn returns a Promise + const result5 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => Promise.resolve('string'), + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + // @ts-expect-error (refuses to accept a Promise) + onSettled: (a: Promise) => null, + }, + ], + }) + expectType>(result5[0]) + + // Array as const does not throw error + const result6 = createQueries({ + queries: [ + { + queryKey: () => ['key1'], + queryFn: () => 'string', + }, + { + queryKey: () => ['key1'], + queryFn: () => 123, + }, + ], + } as const) + expectType>(result6[0]) + expectType>(result6[1]) + + // field names should be enforced - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + + // field names should be enforced - Array.map() result + createQueries({ + // @ts-expect-error (invalidField) + queries: Array(10).map(() => ({ + someInvalidField: '', + })), + }) + + // field names should be enforced - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + + // supports queryFn using fetch() to return Promise - Array.map() result + createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => + fetch('return Promise').then((resp) => resp.json()), + })), + }) + + // supports queryFn using fetch() to return Promise - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => + fetch('return Promise').then((resp) => resp.json()), + }, + ], + }) + } + }) + + it('handles strongly typed queryFn factories and useQueries wrappers', () => { + // QueryKey + queryFn factory + type QueryKeyA = ['queryA'] + const getQueryKeyA = (): QueryKeyA => ['queryA'] + type GetQueryFunctionA = () => QueryFunction + const getQueryFunctionA: GetQueryFunctionA = () => async () => { + return 1 + } + type SelectorA = (data: number) => [number, string] + const getSelectorA = (): SelectorA => (data) => [data, data.toString()] + + type QueryKeyB = ['queryB', string] + const getQueryKeyB = (id: string): QueryKeyB => ['queryB', id] + type GetQueryFunctionB = () => QueryFunction + const getQueryFunctionB: GetQueryFunctionB = () => async () => { + return '1' + } + type SelectorB = (data: string) => [string, number] + const getSelectorB = (): SelectorB => (data) => [data, +data] + + // Wrapper with strongly typed array-parameter + function useWrappedQueries< + TQueryFnData, + TError, + TData, + TQueryKey extends SolidQueryKey, + >(queries: CreateQueryOptions[]) { + return createQueries({ + queries: queries.map( + // no need to type the mapped query + (query) => { + const { queryFn: fn, queryKey: key, onError: err } = query + expectType< + QueryFunction> | undefined + >(fn) + return { + queryKey: key, + onError: err, + queryFn: fn + ? (ctx: QueryFunctionContext>) => { + expectType>(ctx.queryKey) + return fn.call({}, ctx) + } + : undefined, + } + }, + ), + }) + } + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + }, + { + queryKey: () => getQueryKeyB('id'), + queryFn: getQueryFunctionB(), + }, + ], + }) + expectType>(result[0]) + expectType>(result[1]) + + const withSelector = createQueries({ + queries: [ + { + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + select: getSelectorA(), + }, + { + queryKey: () => getQueryKeyB('id'), + queryFn: getQueryFunctionB(), + select: getSelectorB(), + }, + ], + }) + expectType>( + withSelector[0], + ) + expectType>( + withSelector[1], + ) + + const withWrappedQueries = useWrappedQueries( + Array(10).map(() => ({ + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + select: getSelectorA(), + })), + ) + + expectType[]>( + withWrappedQueries, + ) + } + }) + + it('should not change state if unmounted', async () => { + const key1 = queryKey() + + // We have to mock the QueriesObserver to not unsubscribe + // the listener when the component is unmounted + class QueriesObserverMock extends QueriesObserver { + subscribe(listener: any) { + super.subscribe(listener) + return () => void 0 + } + } + + const QueriesObserverSpy = jest + .spyOn(QueriesObserverModule, 'QueriesObserver') + .mockImplementation((fn) => { + return new QueriesObserverMock(fn) + }) + + function Queries() { + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(10) + return 1 + }, + }, + ], + }) + + return ( +
+ queries +
+ ) + } + + function Page() { + const [mounted, setMounted] = createSignal(true) + + return ( +
+ + {mounted() && } +
+ ) + } + + render(() => ( + + + + )) + fireEvent.click(screen.getByText('unmount')) + + // Should not display the console error + // "Warning: Can't perform a React state update on an unmounted component" + + await sleep(20) + QueriesObserverSpy.mockRestore() + }) + + describe('with custom context', () => { + it('should return the correct states', async () => { + const context = createContext(undefined) + + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + context, + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(5) + return 1 + }, + }, + { + queryKey: key2, + queryFn: async () => { + await sleep(10) + return 2 + }, + }, + ], + }) + createRenderEffect(() => { + results.push([...result]) + }) + return null + } + + render(() => ( + + + + )) + + await sleep(30) + + expect(results[0]).toMatchObject([ + { data: undefined }, + { data: undefined }, + ]) + expect(results[results.length - 1]).toMatchObject([ + { data: 1 }, + { data: 2 }, + ]) + }) + + it('should throw if the context is necessary and is not passed to useQueries', async () => { + const context = createContext(undefined) + + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => 1, + }, + { + queryKey: key2, + queryFn: async () => 2, + }, + ], + }) + results.push(result) + return null + } + + render(() => ( + +
error boundary
}> + +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + }) + }) +}) From cf431c86113d41c00a6775015fd25866e85da08f Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 20:39:27 -0400 Subject: [PATCH 107/221] Fix infiniteQueries Formatting --- .../solid-query/src/createInfiniteQuery.ts | 91 ++++++++++++++----- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts index a9ddba6d445..8e66d9132b9 100644 --- a/packages/solid-query/src/createInfiniteQuery.ts +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -1,9 +1,18 @@ -import { QueryObserver, InfiniteQueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; -import { CreateInfiniteQueryOptions, CreateInfiniteQueryResult, SolidQueryKey } from "./types"; -import { createBaseQuery } from "./createBaseQuery"; -import { createComputed } from "solid-js"; -import { createStore } from "solid-js/store"; -import { parseQueryArgs } from "./utils"; +import { + QueryObserver, + InfiniteQueryObserver, + QueryFunction, + QueryOptions, +} from '@tanstack/query-core' +import { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + SolidQueryKey, +} from './types' +import { createBaseQuery } from './createBaseQuery' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' export function createInfiniteQuery< TQueryFnData = unknown, @@ -11,8 +20,14 @@ export function createInfiniteQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: CreateInfiniteQueryOptions, -): CreateInfiniteQueryResult; + options: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -21,10 +36,16 @@ export function createInfiniteQuery< >( queryKey: TQueryKey, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -34,10 +55,16 @@ export function createInfiniteQuery< queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" | "queryFn" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' | 'queryFn' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData, TError, @@ -46,24 +73,44 @@ export function createInfiniteQuery< >( arg1: | TQueryKey - | CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, arg2?: | QueryFunction> - | CreateInfiniteQueryOptions, - arg3?: CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg3?: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, ): CreateInfiniteQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); - setParsedOptions(newParsedOptions); - }); + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) return createBaseQuery( parsedOptions as QueryOptions>, InfiniteQueryObserver as typeof QueryObserver, - ) as CreateInfiniteQueryResult; + ) as CreateInfiniteQueryResult } From e1c3cb402df36b795bc6cffb898ccffc951283e0 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 20:45:56 -0400 Subject: [PATCH 108/221] Making options reactive + added batching tasks --- .../src/__tests__/createQueries.test.tsx | 1162 +++++++++++++++++ packages/solid-query/src/createQueries.ts | 32 +- packages/solid-query/src/utils.ts | 14 + 3 files changed, 1199 insertions(+), 9 deletions(-) create mode 100644 packages/solid-query/src/__tests__/createQueries.test.tsx diff --git a/packages/solid-query/src/__tests__/createQueries.test.tsx b/packages/solid-query/src/__tests__/createQueries.test.tsx new file mode 100644 index 00000000000..90a1c806ad0 --- /dev/null +++ b/packages/solid-query/src/__tests__/createQueries.test.tsx @@ -0,0 +1,1162 @@ +import { fireEvent, render, waitFor, screen } from 'solid-testing-library' + +import * as QueriesObserverModule from '../../../query-core/src/queriesObserver' + +import { + createQueryClient, + expectType, + expectTypeNotAny, + sleep, +} from '../../../../tests/utils' +import { queryKey } from './utils' +import { + QueryClient, + createQueries, + CreateQueryResult, + QueryCache, + QueryObserverResult, + QueriesObserver, + QueryFunction, + CreateQueryOptions, + QueryClientProvider, + SolidQueryKey, +} from '..' +import { QueryFunctionContext } from '@tanstack/query-core' +import { + createContext, + createMemo, + createRenderEffect, + createSignal, + ErrorBoundary, + For, +} from 'solid-js' + +describe('useQueries', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should return the correct states', async () => { + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(10) + return 1 + }, + }, + { + queryKey: key2, + queryFn: async () => { + await sleep(100) + return 2 + }, + }, + ], + }) + + createRenderEffect(() => { + results.push([...result]) + }) + + return ( +
+
+ data1: {String(result[0].data ?? 'null')}, data2:{' '} + {String(result[1].data ?? 'null')} +
+
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 1, data2: 2')) + + expect(results.length).toBe(3) + expect(results[0]).toMatchObject([{ data: undefined }, { data: undefined }]) + expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }]) + expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }]) + }) + + it('should keep previous data if amount of queries is the same', async () => { + const key1 = queryKey() + const key2 = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [count, setCount] = createSignal(1) + const result = createQueries({ + queries: [ + { + queryKey: () => [key1(), count()], + keepPreviousData: true, + queryFn: async () => { + await sleep(10) + return count() * 2 + }, + }, + { + queryKey: () => [key2(), count()], + keepPreviousData: true, + queryFn: async () => { + await sleep(35) + return count() * 5 + }, + }, + ], + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
+ data1: {String(result[0].data ?? 'null')}, data2:{' '} + {String(result[1].data ?? 'null')} +
+
isFetching: {String(isFetching())}
+ +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 2, data2: 5')) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) + + await waitFor(() => screen.getByText('data1: 4, data2: 10')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 4, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should keep previous data for variable amounts of useQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [count, setCount] = createSignal(2) + const result = createQueries({ + // TODO(lukemurray): reactive queries doesn't appear to work + get queries() { + return Array.from({ length: count() }, (_, i) => ({ + queryKey: () => [key(), count(), i + 1], + keepPreviousData: true, + queryFn: async () => { + await sleep(35 * (i + 1)) + return (i + 1) * count() * 2 + }, + })) + }, + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
data: {result.map((it) => it.data).join(',')}
+
isFetching: {String(isFetching())}
+ +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data: 4,8')) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) + + await waitFor(() => screen.getByText('data: 6,12,18')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 6, isPreviousData: false, isFetching: false }, + { status: 'success', data: 12, isPreviousData: false, isFetching: false }, + { status: 'success', data: 18, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should keep previous data when switching between queries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [series1, setSeries1] = createSignal(1) + const [series2, setSeries2] = createSignal(2) + const ids = [series1, series2] + + const result = createQueries({ + queries: ids.map((id) => { + return { + queryKey: () => [key(), id()], + queryFn: async () => { + await sleep(5) + return id() * 5 + }, + keepPreviousData: true, + } + }), + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
+ data1: {String(result[0]?.data ?? 'null')}, data2:{' '} + {String(result[1]?.data ?? 'null')} +
+
isFetching: {String(isFetching())}
+ + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 5, data2: 10')) + fireEvent.click(screen.getByRole('button', { name: /setSeries2/i })) + + await waitFor(() => screen.getByText('data1: 5, data2: 15')) + fireEvent.click(screen.getByRole('button', { name: /setSeries1/i })) + + await waitFor(() => screen.getByText('data1: 10, data2: 15')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + { status: 'success', data: 15, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should not go to infinite render loop with previous data when toggling queries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [enableId1, setEnableId1] = createSignal(true) + const ids = createMemo(() => (enableId1() ? [1, 2] : [2])) + + const result = createQueries({ + // TODO(lukemurray): same issue queries should be reactive + get queries() { + return ids().map((id) => { + return { + queryKey: () => [key(), id], + queryFn: async () => { + await sleep(5) + return id * 5 + }, + keepPreviousData: true, + } + }) + }, + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const text = createMemo(() => { + return result + .map((r, idx) => `data${idx + 1}: ${r.data ?? 'null'}`) + .join(' ') + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
{text()}
+
isFetching: {String(isFetching())}
+ + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 5 data2: 10')) + fireEvent.click(screen.getByRole('button', { name: /set1Disabled/i })) + + await waitFor(() => screen.getByText('data1: 10')) + await waitFor(() => screen.getByText('isFetching: false')) + fireEvent.click(screen.getByRole('button', { name: /set2Enabled/i })) + + await waitFor(() => screen.getByText('data1: 5 data2: 10')) + await waitFor(() => screen.getByText('isFetching: false')) + + await waitFor(() => expect(states.length).toBe(5)) + + expect(states[0]).toMatchObject([ + { + status: 'loading', + data: undefined, + isPreviousData: false, + isFetching: true, + }, + { + status: 'loading', + data: undefined, + isPreviousData: false, + isFetching: true, + }, + ]) + expect(states[1]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[2]).toMatchObject([ + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[3]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: true }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[4]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + }) + + it('handles type parameter - tuple of tuples', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result1 = createQueries<[[number], [string], [string[], boolean]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + }, + ], + }) + expectType>(result1[0]) + expectType>(result1[1]) + expectType>(result1[2]) + expectType(result1[0].data) + expectType(result1[1].data) + expectType(result1[2].data) + expectType(result1[2].error) + + // TData (3rd element) takes precedence over TQueryFnData (1st element) + const result2 = createQueries< + [[string, unknown, string], [string, unknown, number]] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + }, + ], + }) + expectType>(result2[0]) + expectType>(result2[1]) + expectType(result2[0].data) + expectType(result2[1].data) + + // types should be enforced + createQueries<[[string, unknown, string], [string, boolean, number]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + onError: (e) => { + expectType(e) + expectTypeNotAny(e) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + ], + }) + + // field names should be enforced + createQueries<[[string]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + } + }) + + it('handles type parameter - tuple of objects', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result1 = createQueries< + [ + { queryFnData: number }, + { queryFnData: string }, + { queryFnData: string[]; error: boolean }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + }, + ], + }) + expectType>(result1[0]) + expectType>(result1[1]) + expectType>(result1[2]) + expectType(result1[0].data) + expectType(result1[1].data) + expectType(result1[2].data) + expectType(result1[2].error) + + // TData (data prop) takes precedence over TQueryFnData (queryFnData prop) + const result2 = createQueries< + [ + { queryFnData: string; data: string }, + { queryFnData: string; data: number }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + }, + ], + }) + expectType>(result2[0]) + expectType>(result2[1]) + expectType(result2[0].data) + expectType(result2[1].data) + + // can pass only TData (data prop) although TQueryFnData will be left unknown + const result3 = createQueries<[{ data: string }, { data: number }]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a as string + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a as number + }, + }, + ], + }) + expectType>(result3[0]) + expectType>(result3[1]) + expectType(result3[0].data) + expectType(result3[1].data) + + // types should be enforced + createQueries< + [ + { queryFnData: string; data: string }, + { queryFnData: string; data: number; error: boolean }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + onError: (e) => { + expectType(e) + expectTypeNotAny(e) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + ], + }) + + // field names should be enforced + createQueries<[{ queryFnData: string }]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + } + }) + + it('handles array literal without type parameter to infer result type', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + const key4 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + // Array.map preserves TQueryFnData + const result1 = createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + })), + }) + expectType[]>(result1) + expectType(result1[0]?.data) + + // Array.map preserves TData + const result2 = createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + })), + }) + expectType[]>(result2) + + const result3 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + select: () => 123, + }, + ], + }) + expectType>(result3[0]) + expectType>(result3[1]) + expectType>(result3[2]) + expectType(result3[0].data) + expectType(result3[1].data) + // select takes precedence over queryFn + expectType(result3[2].data) + + // initialData/placeholderData are enforced + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 123, + // @ts-expect-error (placeholderData: number) + placeholderData: 'string', + initialData: 123, + }, + ], + }) + + // select / onSuccess / onSettled params are "indirectly" enforced + createQueries({ + queries: [ + // unfortunately TS will not suggest the type for you + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (noImplicitAny) + onSuccess: (a) => null, + // @ts-expect-error (noImplicitAny) + onSettled: (a) => null, + }, + // however you can add a type to the callback + { + queryKey: key2, + queryFn: () => 'string', + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + onSettled: (a: string | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + // the type you do pass is enforced + { + queryKey: key3, + queryFn: () => 'string', + // @ts-expect-error (only accepts string) + onSuccess: (a: number) => null, + }, + { + queryKey: key4, + queryFn: () => 'string', + select: (a: string) => parseInt(a), + // @ts-expect-error (select is defined => only accepts number) + onSuccess: (a: string) => null, + onSettled: (a: number | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + ], + }) + + // callbacks are also indirectly enforced with Array.map + createQueries({ + // @ts-expect-error (onSuccess only accepts string) + queries: Array(50).map((_, i) => ({ + queryKey: ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + onSuccess: (_data: number) => null, + })), + }) + createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + onSuccess: (_data: string) => null, + })), + }) + + // results inference works when all the handlers are defined + const result4 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (noImplicitAny) + onSuccess: (a) => null, + // @ts-expect-error (noImplicitAny) + onSettled: (a) => null, + }, + { + queryKey: key2, + queryFn: () => 'string', + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + onSettled: (a: string | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + { + queryKey: key4, + queryFn: () => 'string', + select: (a: string) => parseInt(a), + onSuccess: (_a: number) => null, + onSettled: (a: number | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + ], + }) + expectType>(result4[0]) + expectType>(result4[1]) + expectType>(result4[2]) + + // handles when queryFn returns a Promise + const result5 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => Promise.resolve('string'), + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + // @ts-expect-error (refuses to accept a Promise) + onSettled: (a: Promise) => null, + }, + ], + }) + expectType>(result5[0]) + + // Array as const does not throw error + const result6 = createQueries({ + queries: [ + { + queryKey: () => ['key1'], + queryFn: () => 'string', + }, + { + queryKey: () => ['key1'], + queryFn: () => 123, + }, + ], + } as const) + expectType>(result6[0]) + expectType>(result6[1]) + + // field names should be enforced - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + + // field names should be enforced - Array.map() result + createQueries({ + // @ts-expect-error (invalidField) + queries: Array(10).map(() => ({ + someInvalidField: '', + })), + }) + + // field names should be enforced - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + + // supports queryFn using fetch() to return Promise - Array.map() result + createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => + fetch('return Promise').then((resp) => resp.json()), + })), + }) + + // supports queryFn using fetch() to return Promise - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => + fetch('return Promise').then((resp) => resp.json()), + }, + ], + }) + } + }) + + it('handles strongly typed queryFn factories and useQueries wrappers', () => { + // QueryKey + queryFn factory + type QueryKeyA = ['queryA'] + const getQueryKeyA = (): QueryKeyA => ['queryA'] + type GetQueryFunctionA = () => QueryFunction + const getQueryFunctionA: GetQueryFunctionA = () => async () => { + return 1 + } + type SelectorA = (data: number) => [number, string] + const getSelectorA = (): SelectorA => (data) => [data, data.toString()] + + type QueryKeyB = ['queryB', string] + const getQueryKeyB = (id: string): QueryKeyB => ['queryB', id] + type GetQueryFunctionB = () => QueryFunction + const getQueryFunctionB: GetQueryFunctionB = () => async () => { + return '1' + } + type SelectorB = (data: string) => [string, number] + const getSelectorB = (): SelectorB => (data) => [data, +data] + + // Wrapper with strongly typed array-parameter + function useWrappedQueries< + TQueryFnData, + TError, + TData, + TQueryKey extends SolidQueryKey, + >(queries: CreateQueryOptions[]) { + return createQueries({ + queries: queries.map( + // no need to type the mapped query + (query) => { + const { queryFn: fn, queryKey: key, onError: err } = query + expectType< + QueryFunction> | undefined + >(fn) + return { + queryKey: key, + onError: err, + queryFn: fn + ? (ctx: QueryFunctionContext>) => { + expectType>(ctx.queryKey) + return fn.call({}, ctx) + } + : undefined, + } + }, + ), + }) + } + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + }, + { + queryKey: () => getQueryKeyB('id'), + queryFn: getQueryFunctionB(), + }, + ], + }) + expectType>(result[0]) + expectType>(result[1]) + + const withSelector = createQueries({ + queries: [ + { + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + select: getSelectorA(), + }, + { + queryKey: () => getQueryKeyB('id'), + queryFn: getQueryFunctionB(), + select: getSelectorB(), + }, + ], + }) + expectType>( + withSelector[0], + ) + expectType>( + withSelector[1], + ) + + const withWrappedQueries = useWrappedQueries( + Array(10).map(() => ({ + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + select: getSelectorA(), + })), + ) + + expectType[]>( + withWrappedQueries, + ) + } + }) + + it('should not change state if unmounted', async () => { + const key1 = queryKey() + + // We have to mock the QueriesObserver to not unsubscribe + // the listener when the component is unmounted + class QueriesObserverMock extends QueriesObserver { + subscribe(listener: any) { + super.subscribe(listener) + return () => void 0 + } + } + + const QueriesObserverSpy = jest + .spyOn(QueriesObserverModule, 'QueriesObserver') + .mockImplementation((fn) => { + return new QueriesObserverMock(fn) + }) + + function Queries() { + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(10) + return 1 + }, + }, + ], + }) + + return ( +
+ queries +
+ ) + } + + function Page() { + const [mounted, setMounted] = createSignal(true) + + return ( +
+ + {mounted() && } +
+ ) + } + + render(() => ( + + + + )) + fireEvent.click(screen.getByText('unmount')) + + // Should not display the console error + // "Warning: Can't perform a React state update on an unmounted component" + + await sleep(20) + QueriesObserverSpy.mockRestore() + }) + + describe('with custom context', () => { + it('should return the correct states', async () => { + const context = createContext(undefined) + + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + context, + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(5) + return 1 + }, + }, + { + queryKey: key2, + queryFn: async () => { + await sleep(10) + return 2 + }, + }, + ], + }) + createRenderEffect(() => { + results.push([...result]) + }) + return null + } + + render(() => ( + + + + )) + + await sleep(30) + + expect(results[0]).toMatchObject([ + { data: undefined }, + { data: undefined }, + ]) + expect(results[results.length - 1]).toMatchObject([ + { data: 1 }, + { data: 2 }, + ]) + }) + + it('should throw if the context is necessary and is not passed to useQueries', async () => { + const context = createContext(undefined) + + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => 1, + }, + { + queryKey: key2, + queryFn: async () => 2, + }, + ], + }) + results.push(result) + return null + } + + render(() => ( + +
error boundary
}> + +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + }) + }) +}) diff --git a/packages/solid-query/src/createQueries.ts b/packages/solid-query/src/createQueries.ts index a016ae13068..266a69a59a3 100644 --- a/packages/solid-query/src/createQueries.ts +++ b/packages/solid-query/src/createQueries.ts @@ -3,6 +3,7 @@ import { QueryFunction, QueriesObserver } from '@tanstack/query-core' import { useQueryClient } from './QueryClientProvider' import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' import { createStore, unwrap } from 'solid-js/store' +import { scheduleMicrotask } from './utils' // This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`. // - `context` is omitted as it is passed as a root-level option to `useQueries` instead. @@ -139,23 +140,24 @@ export type QueriesResults< type ArrType = T extends (infer U)[] ? U : never -export function createQueries({ - queries, - context, -}: { +export function createQueries(queriesOptions: { queries: readonly [...QueriesOptions] context?: CreateQueryOptions['context'] }): QueriesResults { - const queryClient = useQueryClient({ context }) + const queryClient = useQueryClient({ context: queriesOptions.context }) - const normalizeOptions = (options: ArrType) => { + const normalizeOptions = ( + options: ArrType, + ) => { const normalizedOptions = { ...options, queryKey: options.queryKey?.() } const defaultedOptions = queryClient.defaultQueryOptions(normalizedOptions) defaultedOptions._optimisticResults = 'optimistic' return defaultedOptions } - const defaultedQueries = queries.map((options) => normalizeOptions(options)) + const defaultedQueries = queriesOptions.queries.map((options) => + normalizeOptions(options), + ) const observer = new QueriesObserver(queryClient, defaultedQueries) @@ -163,8 +165,20 @@ export function createQueries({ observer.getOptimisticResult(defaultedQueries), ) + const taskQueue: Array<() => void> = [] + const unsubscribe = observer.subscribe((result) => { - setState(unwrap(result)) + taskQueue.push(() => { + setState(unwrap(result)) + }) + + scheduleMicrotask(() => { + const taskToRun = taskQueue.pop() + if (taskToRun) { + taskToRun() + taskQueue.splice(0, taskQueue.length) + } + }) }) onCleanup(unsubscribe) @@ -174,7 +188,7 @@ export function createQueries({ }) createComputed(() => { - const updateDefaultedQueries = queries.map((options) => + const updateDefaultedQueries = queriesOptions.queries.map((options) => normalizeOptions(options), ) observer.setQueries(updateDefaultedQueries) diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index ee8fcc6f570..bc1883ae35f 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -69,3 +69,17 @@ export function shouldThrowError boolean>( return !!_useErrorBoundary } + +export function sleep(timeout: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, timeout) + }) +} + +/** + * Schedules a microtask. + * This can be useful to schedule state updates after rendering. + */ +export function scheduleMicrotask(callback: () => void) { + sleep(0).then(callback) +} From c6fe06ccb176b53a6244f50a536217953c787f42 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 21:09:14 -0400 Subject: [PATCH 109/221] Throw to errorBoundary when options set correctly --- packages/solid-query/src/createMutation.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/solid-query/src/createMutation.ts b/packages/solid-query/src/createMutation.ts index 5214da550c1..df6db80ed76 100644 --- a/packages/solid-query/src/createMutation.ts +++ b/packages/solid-query/src/createMutation.ts @@ -10,8 +10,9 @@ import { CreateMutationOptions, CreateMutationResult, } from './types' -import { createComputed, onCleanup } from 'solid-js' +import { createComputed, onCleanup, on } from 'solid-js' import { createStore } from 'solid-js/store' +import { shouldThrowError } from './utils' // HOOK export function createMutation< @@ -103,6 +104,20 @@ export function createMutation< observer.setOptions(newParsedOptions) }) + createComputed( + on( + () => state.status, + () => { + if ( + state.isError && + shouldThrowError(observer.options.useErrorBoundary, [state.error]) + ) { + throw state.error + } + }, + ), + ) + const unsubscribe = observer.subscribe((result) => { setState({ ...result, From 2a2c7ef3a0907cc3c32e5d3536bb27e273a76562 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Thu, 8 Sep 2022 10:48:20 -0400 Subject: [PATCH 110/221] WIP: Added solid query primitives --- .../solid-query/src/QueryClientProvider.tsx | 64 ++++++++++ packages/solid-query/src/createBaseQuery.ts | 76 ++++++++++++ packages/solid-query/src/createMutation.ts | 116 ++++++++++++++++++ packages/solid-query/src/createQuery.ts | 69 +++++++++++ packages/solid-query/src/index.ts | 6 + packages/solid-query/src/types.ts | 100 +++++++++++++++ packages/solid-query/src/useIsFetching.ts | 39 ++++++ packages/solid-query/src/useIsMutating.ts | 43 +++++++ packages/solid-query/src/utils.ts | 39 ++++++ 9 files changed, 552 insertions(+) create mode 100644 packages/solid-query/src/QueryClientProvider.tsx create mode 100644 packages/solid-query/src/createBaseQuery.ts create mode 100644 packages/solid-query/src/createMutation.ts create mode 100644 packages/solid-query/src/createQuery.ts create mode 100644 packages/solid-query/src/index.ts create mode 100644 packages/solid-query/src/types.ts create mode 100644 packages/solid-query/src/useIsFetching.ts create mode 100644 packages/solid-query/src/useIsMutating.ts create mode 100644 packages/solid-query/src/utils.ts diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx new file mode 100644 index 00000000000..c2fa3ff4fa7 --- /dev/null +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -0,0 +1,64 @@ +import type { QueryClient } from "@tanstack/query-core"; +import { Component, Context, createContext, useContext, JSX, onMount, onCleanup } from "solid-js"; +import { ContextOptions } from "./types"; + +declare global { + interface Window { + SolidQueryClientContext?: Context + } +} + +export const QueryClientContext = createContext(); +export const QueryClientSharingContext = createContext(false) + +interface Props { + client: QueryClient; + children: JSX.Element; +} + +// Simple Query Client Context Provider +export const QueryClientProvider: Component = (props) => { + if (!props.client) { + throw new Error("No queryClient found."); + } + + onMount(() => props.client.mount()); + onCleanup(() => props.client.unmount()); + + return ( + + {props.children} + + ); +}; + +function getQueryClientContext( + context: Context | undefined, + contextSharing: boolean +) { + if (context) { + return context; + } + + if (contextSharing && typeof window !== 'undefined') { + if (!window.SolidQueryClientContext) { + window.SolidQueryClientContext = QueryClientContext; + } + + return window.SolidQueryClientContext + } + + return QueryClientContext +} + +export const useQueryClient = ({ context }: ContextOptions = {}) => { + const queryClient = useContext( + getQueryClientContext(context, useContext(QueryClientSharingContext)) + ); + + if (!queryClient) { + throw new Error('No QueryClient set, use QueryClientProvider to set one'); + } + + return queryClient; +}; diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts new file mode 100644 index 00000000000..43d7b7b1a65 --- /dev/null +++ b/packages/solid-query/src/createBaseQuery.ts @@ -0,0 +1,76 @@ +import { QueryObserver } from '@tanstack/query-core' +import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' +import { CreateBaseQueryOptions } from './types' +import { useQueryClient } from "./QueryClientProvider"; +import { onMount, onCleanup, createComputed, createResource, createEffect, batch } from 'solid-js'; +import { createStore } from 'solid-js/store'; + +// Base Query Function that is used to create the query. +export function createBaseQuery< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey extends QueryKey +>( + options: CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey + >, + Observer: typeof QueryObserver +): QueryObserverResult { + + const queryClient = useQueryClient(); + + const defaultedOptions = queryClient.defaultQueryOptions(options) + defaultedOptions._optimisticResults = 'optimistic'; + const observer = new QueryObserver(queryClient, defaultedOptions); + + const [state, setState] = createStore>( + // @ts-ignore + observer.getOptimisticResult(defaultedOptions), + ); + + const [ dataResource, { refetch } ] = createResource(() => { + return new Promise((resolve, reject) => { + if (state.isSuccess) resolve(state.data) + if (state.isError && !state.isFetching) { + throw state.error + } + }) + }); + + observer.updateResult(); + + const unsubscribe = observer.subscribe((result) => { + const reconciledResult = result; + // @ts-ignore + setState(reconciledResult); + refetch(); + }); + + onCleanup(() => unsubscribe()); + + onMount(() => { + observer.setOptions(defaultedOptions, { listeners: false }); + }); + + createComputed(() => { + const defaultedOptions = queryClient.defaultQueryOptions(options) + observer.setOptions(defaultedOptions) + }) + + const handler = { + get(target: QueryObserverResult, prop: (keyof QueryObserverResult)): any { + if (prop === 'data') { + return dataResource(); + } + return Reflect.get(target, prop); + } + } + + return new Proxy(state, handler) as QueryObserverResult; +} \ No newline at end of file diff --git a/packages/solid-query/src/createMutation.ts b/packages/solid-query/src/createMutation.ts new file mode 100644 index 00000000000..2a4b8d65ce6 --- /dev/null +++ b/packages/solid-query/src/createMutation.ts @@ -0,0 +1,116 @@ +import { + parseMutationArgs, + MutationObserver, + MutationFunction, + MutationKey, +} from '@tanstack/query-core' +import { useQueryClient } from './QueryClientProvider' +import { + CreateMutateFunction, + CreateMutationOptions, + CreateMutationResult, +} from './types' +import { createComputed, onCleanup } from 'solid-js' +import { createStore } from 'solid-js/store'; + +// HOOK +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + options: CreateMutationOptions, +): CreateMutationResult +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + mutationFn: MutationFunction, + options?: Omit< + CreateMutationOptions, + 'mutationFn' + >, +): CreateMutationResult +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + mutationKey: MutationKey, + options?: Omit< + CreateMutationOptions, + 'mutationKey' + >, +): CreateMutationResult +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + mutationKey: MutationKey, + mutationFn?: MutationFunction, + options?: Omit< + CreateMutationOptions, + 'mutationKey' | 'mutationFn' + >, +): CreateMutationResult +export function createMutation< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +>( + arg1: + | MutationKey + | MutationFunction + | CreateMutationOptions, + arg2?: + | MutationFunction + | CreateMutationOptions, + arg3?: CreateMutationOptions, +): CreateMutationResult { + const [options, setOptions] = createStore(parseMutationArgs(arg1, arg2, arg3)) + const queryClient = useQueryClient({ context: options.context }) + + const observer = new MutationObserver( + queryClient, + options, + ) + + const mutate: CreateMutateFunction = + (variables, mutateOptions) => { + observer.mutate(variables, mutateOptions).catch(noop) + } + + const [state, setState] = createStore>({ + ...observer.getCurrentResult(), + mutate, + mutateAsync: observer.getCurrentResult().mutate + }) + + createComputed(() => { + const newParsedOptions = parseMutationArgs(arg1, arg2, arg3) + setOptions(newParsedOptions) + observer.setOptions(newParsedOptions) + }) + + const unsubscribe = observer.subscribe((result) => { + setState({ + ...result, + mutate, + mutateAsync: result.mutate + }) + }) + + onCleanup(unsubscribe) + + return state +} + +// eslint-disable-next-line @typescript-eslint/no-empty-function +function noop() {} \ No newline at end of file diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts new file mode 100644 index 00000000000..11ec78c5500 --- /dev/null +++ b/packages/solid-query/src/createQuery.ts @@ -0,0 +1,69 @@ +import { QueryObserver, QueryFunction } from '@tanstack/query-core'; +import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store'; +import { parseQueryArgs } from './utils' +import { createBaseQuery } from './createBaseQuery'; + +// There are several ways to create a query. +// 1. createQuery(options: CreateQueryOptions) +// 2. createQuery(querykey: () => Serializable[], options: CreateQueryOptions) +// 3. createQuery(querykey: () => Serializable[], queryFunc: Fetcher Function, options: CreateQueryOptions) +// 4. The fourth overload is a combination of all three function params +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +>( + options: CreateQueryOptions +): CreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +>( + queryKey: SolidQueryKey, + options?: Omit< + CreateQueryOptions, + 'queryKey' + > +): CreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +>( + queryKey: TQueryKey, + queryFn: QueryFunction>, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' + > +): CreateQueryResult +export function createQuery< + TQueryFnData, + TError, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +>( + arg1: TQueryKey | CreateQueryOptions, + arg2?: + | QueryFunction> + | CreateQueryOptions, + arg3?: CreateQueryOptions +): CreateQueryResult { + // The parseQuery Args functions helps normalize the arguments into the correct form. + // Whatever the parameters are, they are normalized into the correct form. + const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)) + + // Watch for changes in the options and update the parsed options. + createComputed(() => { + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) + + return createBaseQuery(parsedOptions, QueryObserver); +} diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts new file mode 100644 index 00000000000..524f1f01acd --- /dev/null +++ b/packages/solid-query/src/index.ts @@ -0,0 +1,6 @@ +export * from './createQuery' +export * from './QueryClientProvider' +export * from './createMutation' +export * from './useIsMutating' +export * from './useIsFetching' +export { QueryClient } from '@tanstack/query-core' \ No newline at end of file diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts new file mode 100644 index 00000000000..59bc9262077 --- /dev/null +++ b/packages/solid-query/src/types.ts @@ -0,0 +1,100 @@ +import type { Context, Accessor } from "solid-js"; +import type { + QueryClient, + QueryKey, + QueryObserverOptions, + QueryObserverResult, + MutateFunction, + MutationObserverOptions, + MutationObserverResult +} from '@tanstack/query-core' + +export interface ContextOptions { + /** + * Use this to pass your React Query context. Otherwise, `defaultContext` will be used. + */ + context?: Context +} + +export type SolidQueryKey = () => readonly unknown[]; + +export interface CreateBaseQueryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey +> extends ContextOptions, + QueryObserverOptions {} + +export interface CreateQueryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey +> extends CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + ReturnType +> {} + +export type CreateBaseQueryResult< + TData = unknown, + TError = unknown +> = QueryObserverResult + +export type CreateQueryResult< + TData = unknown, + TError = unknown +> = CreateBaseQueryResult + + + +export interface CreateMutationOptions< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +> extends ContextOptions, + Omit< + MutationObserverOptions, + '_defaulted' | 'variables' + > {} + +export type CreateMutateFunction< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +> = ( + ...args: Parameters> +) => void + + +export type CreateMutateAsyncFunction< + TData = unknown, + TError = unknown, + TVariables = void, + TContext = unknown, +> = MutateFunction + +type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } + +export type CreateBaseMutationResult< + TData = unknown, + TError = unknown, + TVariables = unknown, + TContext = unknown, +> = Override< + MutationObserverResult, + { mutate: CreateMutateFunction } +> & { mutateAsync: CreateMutateAsyncFunction } + +export type CreateMutationResult< + TData = unknown, + TError = unknown, + TVariables = unknown, + TContext = unknown, +> = CreateBaseMutationResult \ No newline at end of file diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts new file mode 100644 index 00000000000..12d58ff1ab9 --- /dev/null +++ b/packages/solid-query/src/useIsFetching.ts @@ -0,0 +1,39 @@ +import { + QueryKey, + notifyManager, + parseFilterArgs, + QueryFilters, +} from '@tanstack/query-core' + +import { ContextOptions } from './types' +import { useQueryClient } from './QueryClientProvider' +import { Accessor, createSignal, onCleanup } from 'solid-js' +interface Options extends ContextOptions {} + +export function useIsFetching(filters?: QueryFilters, options?: Options): Accessor +export function useIsFetching( + queryKey?: QueryKey, + filters?: QueryFilters, + options?: Options, +): Accessor +export function useIsFetching( + arg1?: QueryKey | QueryFilters, + arg2?: QueryFilters | Options, + arg3?: Options, +): Accessor { + const [filters, options = {}] = parseFilterArgs(arg1, arg2, arg3) + const queryClient = useQueryClient({ context: options.context }) + const queryCache = queryClient.getQueryCache() + + const [fetches, setFetches] = createSignal(queryClient.isFetching(filters)) + + const unsubscribe = queryCache.subscribe((result) => { + setFetches(queryClient.isFetching(filters)) + }) + + onCleanup(() => { + unsubscribe() + }) + + return fetches +} \ No newline at end of file diff --git a/packages/solid-query/src/useIsMutating.ts b/packages/solid-query/src/useIsMutating.ts new file mode 100644 index 00000000000..92d1a9e997f --- /dev/null +++ b/packages/solid-query/src/useIsMutating.ts @@ -0,0 +1,43 @@ +import { + notifyManager, + MutationKey, + MutationFilters, + parseMutationFilterArgs, +} from '@tanstack/query-core' +import { ContextOptions } from './types' +import { useQueryClient } from './QueryClientProvider' +import { Accessor, createSignal, onCleanup } from 'solid-js' + +interface Options extends ContextOptions {} + +export function useIsMutating( + filters?: MutationFilters, + options?: Options, +): Accessor +export function useIsMutating( + mutationKey?: MutationKey, + filters?: Omit, + options?: Options, +): Accessor +export function useIsMutating( + arg1?: MutationKey | MutationFilters, + arg2?: Omit | Options, + arg3?: Options, +): Accessor { + const [filters, options = {}] = parseMutationFilterArgs(arg1, arg2, arg3) + + const queryClient = useQueryClient({ context: options.context }) + const mutationCache = queryClient.getMutationCache() + + const [mutations, setMutations] = createSignal(queryClient.isMutating(filters)) + + const unsubscribe = mutationCache.subscribe((result) => { + setMutations(queryClient.isMutating(filters)) + }) + + onCleanup(() => { + unsubscribe() + }) + + return mutations +} \ No newline at end of file diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts new file mode 100644 index 00000000000..83aa9db1d6d --- /dev/null +++ b/packages/solid-query/src/utils.ts @@ -0,0 +1,39 @@ + +import { CreateQueryOptions, SolidQueryKey } from './types' +import { QueryFunction } from '@tanstack/query-core' + +export function isQueryKey(value: unknown): value is SolidQueryKey { + return typeof value === 'function' +} + +// The parseQuery Args functions helps normalize the arguments into the correct form. +// Whatever the parameters are, they are normalized into the correct form. +export function parseQueryArgs< + TQueryFnData, + TError, + TData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey, +>( + arg1: TQueryKey | CreateQueryOptions, + arg2?: + | QueryFunction> + | CreateQueryOptions, + arg3?: CreateQueryOptions +): CreateQueryOptions { + if(!isQueryKey(arg1)) { + const { queryKey: solidKey, ...opts } = arg1 as any + if (solidKey) { + return { + ...opts, + queryKey: solidKey(), + } + } + return arg1 + } + + if (typeof arg2 === 'function') { + return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any + } + + return { ...arg2, queryKey: arg1() } as any +} \ No newline at end of file From f299d225a4d78a6c5d893f526a56b658168900fb Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Thu, 8 Sep 2022 11:32:22 -0400 Subject: [PATCH 111/221] Remove updateresults call --- packages/solid-query/src/createBaseQuery.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 43d7b7b1a65..a825c66b85c 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -43,8 +43,6 @@ export function createBaseQuery< }) }); - observer.updateResult(); - const unsubscribe = observer.subscribe((result) => { const reconciledResult = result; // @ts-ignore From 39308c9025058a7cc1a16d5c1ffbfb1fd12b4f51 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 12:05:50 -0400 Subject: [PATCH 112/221] add test support and query client provider tests --- jest.config.ts | 3 +- package-lock.json | 498 +++++++++++++++++- package.json | 8 +- packages/solid-query/.eslintrc | 9 + packages/solid-query/package.json | 44 ++ .../__tests__/QueryClientProvider.test.tsx | 271 ++++++++++ packages/solid-query/src/__tests__/utils.ts | 5 + packages/solid-query/tsconfig.json | 11 + tsconfig.base.json | 3 +- tsconfig.json | 3 +- 10 files changed, 845 insertions(+), 10 deletions(-) create mode 100644 packages/solid-query/.eslintrc create mode 100644 packages/solid-query/package.json create mode 100644 packages/solid-query/src/__tests__/QueryClientProvider.test.tsx create mode 100644 packages/solid-query/src/__tests__/utils.ts create mode 100644 packages/solid-query/tsconfig.json diff --git a/jest.config.ts b/jest.config.ts index 508d426f734..444d590c6e1 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -24,7 +24,7 @@ const moduleNameMapper = { module.exports = { collectCoverage: true, coverageReporters: ['json', 'lcov', 'text', 'clover', 'text-summary'], - projects: packages.map((d) => ({ + projects: packages.map((d: string) => ({ displayName: d, clearMocks: true, testEnvironment: 'jsdom', @@ -34,5 +34,6 @@ module.exports = { printBasicPrototype: false, }, moduleNameMapper, + preset: d.includes("solid") ? 'solid-jest/preset/browser' : undefined, })), } diff --git a/package-lock.json b/package-lock.json index e1b3442dfa1..a24aecb7569 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "./packages/react-query", "./packages/react-query-devtools", "./packages/react-query-persist-client", + "./packages/solid-query", "./examples/react/auto-refetching", "./examples/react/basic", "./examples/react/basic-graphql-request", @@ -58,6 +59,7 @@ "axios": "^0.26.1", "babel-eslint": "^10.1.0", "babel-plugin-transform-async-to-promises": "^0.8.18", + "babel-preset-solid": "^1.5.4", "bundlewatch": "^0.3.2", "concurrently": "^7.1.0", "current-git-branch": "^1.1.0", @@ -90,7 +92,9 @@ "rollup-plugin-svelte": "^7.1.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-visualizer": "^5.6.0", - "solid-js": "^1.3.15", + "solid-jest": "^0.2.0", + "solid-js": "^1.5.4", + "solid-testing-library": "^0.3.0", "stream-to-array": "^2.3.0", "svelte": "^3.48.0", "ts-node": "^10.7.0", @@ -11127,6 +11131,10 @@ "resolved": "packages/react-query-persist-client", "link": true }, + "node_modules/@tanstack/solid-query": { + "resolved": "packages/solid-query", + "link": true + }, "node_modules/@testing-library/dom": { "version": "8.14.0", "dev": true, @@ -13250,6 +13258,39 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, "node_modules/babel-plugin-macros": { "version": "2.8.0", "license": "MIT", @@ -13782,6 +13823,18 @@ "node": ">=0.10.0" } }, + "node_modules/babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "dependencies": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/babel-runtime": { "version": "6.26.0", "license": "MIT", @@ -16970,6 +17023,22 @@ "node": ">=6.9.0" } }, + "node_modules/enhanced-resolve-jest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve-jest/-/enhanced-resolve-jest-1.1.0.tgz", + "integrity": "sha512-GM7yVsiLIaunYkCqnGRPO4kQbT6hPSgkyOFKTseWboPMjZ2tlpQYh2ttLuE8ORkR72Wb1f9SJBbnPu0AjcTzgg==", + "dev": true, + "dependencies": { + "enhanced-resolve": "^4.1.0", + "tslib": "^1.10.0" + } + }, + "node_modules/enhanced-resolve-jest/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/enhanced-resolve/node_modules/memory-fs": { "version": "0.5.0", "license": "MIT", @@ -39061,10 +39130,190 @@ "node": ">= 6" } }, + "node_modules/solid-jest": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/solid-jest/-/solid-jest-0.2.0.tgz", + "integrity": "sha512-1ILtAj+z6bh1vTvaDlcT8501vmkzkVZMk2aiexJy+XWTZ+sb9B7IWedvWadIhOwwL97fiW4eMmN6SrbaHjn12A==", + "dev": true, + "dependencies": { + "@babel/preset-env": "^7.13.9", + "babel-jest": "^27.0.0", + "enhanced-resolve-jest": "^1.1.0" + }, + "peerDependencies": { + "babel-preset-solid": "^1.0.0" + } + }, "node_modules/solid-js": { - "version": "1.4.7", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "dependencies": { + "csstype": "^3.1.0" + } + }, + "node_modules/solid-testing-library": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/solid-testing-library/-/solid-testing-library-0.3.0.tgz", + "integrity": "sha512-6NWVbySNVzyReBm2N6p3eF8bzxRZXHZTAmPix4vFWYol16QWVjNQsEUxvr+ZOutb0yuMZmNuGx3b6WIJYmjwMQ==", "dev": true, - "license": "MIT" + "dependencies": { + "@testing-library/dom": "^7.29.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "solid-js": ">=1.0.0" + } + }, + "node_modules/solid-testing-library/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/solid-testing-library/node_modules/@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/solid-testing-library/node_modules/@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/solid-testing-library/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/solid-testing-library/node_modules/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/solid-testing-library/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/solid-testing-library/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/solid-testing-library/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/solid-testing-library/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/solid-testing-library/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/solid-testing-library/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/solid-testing-library/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/sort-by": { "version": "1.2.0", @@ -43137,6 +43386,33 @@ "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } + }, + "packages/solid-query": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "devDependencies": { + "@types/jscodeshift": "^0.11.3", + "jscodeshift": "^0.13.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "packages/solid-query/node_modules/@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } } }, "dependencies": { @@ -50263,6 +50539,21 @@ "@tanstack/react-query": "4.3.0-beta.4" } }, + "@tanstack/solid-query": { + "version": "file:packages/solid-query", + "requires": { + "@tanstack/query-core": "4.2.3", + "@types/jscodeshift": "^0.11.3", + "jscodeshift": "^0.13.1" + }, + "dependencies": { + "@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + } + } + }, "@testing-library/dom": { "version": "8.14.0", "dev": true, @@ -51696,6 +51987,35 @@ "@types/babel__traverse": "^7.0.6" } }, + "babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + } + } + }, "babel-plugin-macros": { "version": "2.8.0", "requires": { @@ -52092,6 +52412,15 @@ } } }, + "babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "requires": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + } + }, "babel-runtime": { "version": "6.26.0", "requires": { @@ -54268,6 +54597,24 @@ } } }, + "enhanced-resolve-jest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve-jest/-/enhanced-resolve-jest-1.1.0.tgz", + "integrity": "sha512-GM7yVsiLIaunYkCqnGRPO4kQbT6hPSgkyOFKTseWboPMjZ2tlpQYh2ttLuE8ORkR72Wb1f9SJBbnPu0AjcTzgg==", + "dev": true, + "requires": { + "enhanced-resolve": "^4.1.0", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, "enquirer": { "version": "2.3.6", "requires": { @@ -69211,9 +69558,150 @@ "socks": "^2.3.3" } }, + "solid-jest": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/solid-jest/-/solid-jest-0.2.0.tgz", + "integrity": "sha512-1ILtAj+z6bh1vTvaDlcT8501vmkzkVZMk2aiexJy+XWTZ+sb9B7IWedvWadIhOwwL97fiW4eMmN6SrbaHjn12A==", + "dev": true, + "requires": { + "@babel/preset-env": "^7.13.9", + "babel-jest": "^27.0.0", + "enhanced-resolve-jest": "^1.1.0" + } + }, "solid-js": { - "version": "1.4.7", - "dev": true + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "requires": { + "csstype": "^3.1.0" + } + }, + "solid-testing-library": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/solid-testing-library/-/solid-testing-library-0.3.0.tgz", + "integrity": "sha512-6NWVbySNVzyReBm2N6p3eF8bzxRZXHZTAmPix4vFWYol16QWVjNQsEUxvr+ZOutb0yuMZmNuGx3b6WIJYmjwMQ==", + "dev": true, + "requires": { + "@testing-library/dom": "^7.29.4" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, "sort-by": { "version": "1.2.0", diff --git a/package.json b/package.json index 4c0404b286f..794a5ed3da4 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "./packages/react-query", "./packages/react-query-devtools", "./packages/react-query-persist-client", + "./packages/solid-query", "./examples/react/auto-refetching", "./examples/react/basic", "./examples/react/basic-graphql-request", @@ -67,8 +68,8 @@ "@rollup/plugin-replace": "^4.0.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.0.0", - "@testing-library/react-hooks": "^7.0.2", "@testing-library/react-17": "npm:@testing-library/react@12.1.4", + "@testing-library/react-hooks": "^7.0.2", "@tsconfig/svelte": "^3.0.0", "@types/jest": "^26.0.4", "@types/luxon": "^2.3.1", @@ -80,6 +81,7 @@ "axios": "^0.26.1", "babel-eslint": "^10.1.0", "babel-plugin-transform-async-to-promises": "^0.8.18", + "babel-preset-solid": "^1.5.4", "bundlewatch": "^0.3.2", "concurrently": "^7.1.0", "current-git-branch": "^1.1.0", @@ -112,7 +114,9 @@ "rollup-plugin-svelte": "^7.1.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-visualizer": "^5.6.0", - "solid-js": "^1.3.15", + "solid-jest": "^0.2.0", + "solid-js": "^1.5.4", + "solid-testing-library": "^0.3.0", "stream-to-array": "^2.3.0", "svelte": "^3.48.0", "ts-node": "^10.7.0", diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc new file mode 100644 index 00000000000..df08b8b4dbd --- /dev/null +++ b/packages/solid-query/.eslintrc @@ -0,0 +1,9 @@ +{ + "parserOptions": { + "project": "./tsconfig.json", + "sourceType": "module" + }, + "rules": { + "react/react-in-jsx-scope": "off" + } +} \ No newline at end of file diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json new file mode 100644 index 00000000000..abedd50c244 --- /dev/null +++ b/packages/solid-query/package.json @@ -0,0 +1,44 @@ +{ + "name": "@tanstack/solid-query", + "version": "4.2.3", + "description": "Hooks for managing, caching and syncing asynchronous and remote data in Solid", + "author": "tannerlinsley", + "license": "MIT", + "repository": "tanstack/query", + "homepage": "https://tanstack.com/query", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "module": "build/esm/index.js", + "main": "build/cjs/solid-query/src/index.js", + "browser": "build/umd/index.production.js", + "types": "build/types/packages/solid-query/src/index.d.ts", + "sideEffects": [], + "scripts": { + "test:codemods": "../../node_modules/.bin/jest --config codemods/jest.config.js", + "test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src", + "test:jest": "yarn test:codemods && ../../node_modules/.bin/jest --config jest.config.js", + "test:jest:dev": "yarn test:jest --watch", + "compile": "../../node_modules/.bin/tsc -p tsconfig.json --noEmit --emitDeclarationOnly false" + }, + "files": [ + "build/*", + "src", + "codemods", + "!codemods/jest.config.js", + "!codemods/**/__testfixtures__", + "!codemods/**/__tests__" + ], + "devDependencies": { + "@types/jscodeshift": "^0.11.3", + "jscodeshift": "^0.13.1" + }, + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + }, + "peerDependenciesMeta": {} +} \ No newline at end of file diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx new file mode 100644 index 00000000000..dbdf2707e36 --- /dev/null +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -0,0 +1,271 @@ +import { Context, createContext, useContext } from 'solid-js' +import { render, screen, waitFor } from 'solid-testing-library' +import { queryKey } from './utils' + +import { QueryCache } from '@tanstack/query-core' +import { renderToString } from 'solid-js/web' +import { + createQuery, + QueryClient, + QueryClientProvider, + useQueryClient, +} from '..' +import { createQueryClient, sleep } from '../../../../tests/utils' + +describe('QueryClientProvider', () => { + test('sets a specific cache for all queries to use', async () => { + const key = queryKey() + + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + function Page() { + const query = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + return ( +
+

{query.data}

+
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => { + return screen.getByText('test') + }) + + expect(queryCache.find(key())).toBeDefined() + }) + + test('allows multiple caches to be partitioned', async () => { + const key1 = queryKey() + const key2 = queryKey() + + const queryCache1 = new QueryCache() + const queryCache2 = new QueryCache() + + const queryClient1 = createQueryClient({ queryCache: queryCache1 }) + const queryClient2 = createQueryClient({ queryCache: queryCache2 }) + + function Page1() { + const query = createQuery(key1, async () => { + await sleep(10) + return 'test1' + }) + + return ( +
+

{query.data}

+
+ ) + } + function Page2() { + const query = createQuery(key2, async () => { + await sleep(10) + return 'test2' + }) + + return ( +
+

{query.data}

+
+ ) + } + + render(() => ( + <> + + + + + + + + )) + + await waitFor(() => screen.getByText('test1')) + await waitFor(() => screen.getByText('test2')) + + expect(queryCache1.find(key1())).toBeDefined() + expect(queryCache1.find(key2())).not.toBeDefined() + expect(queryCache2.find(key1())).not.toBeDefined() + expect(queryCache2.find(key2())).toBeDefined() + }) + + test("uses defaultOptions for queries when they don't provide their own config", async () => { + const key = queryKey() + + const queryCache = new QueryCache() + const queryClient = createQueryClient({ + queryCache, + defaultOptions: { + queries: { + cacheTime: Infinity, + }, + }, + }) + + function Page() { + const query = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + return ( +
+

{query.data}

+
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('test')) + + expect(queryCache.find(key())).toBeDefined() + expect(queryCache.find(key())?.options.cacheTime).toBe(Infinity) + }) + + describe('with custom context', () => { + it('uses the correct context', async () => { + const key = queryKey() + + const contextOuter = createContext(undefined) + const contextInner = createContext(undefined) + + const queryCacheOuter = new QueryCache() + const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) + + const queryCacheInner = new QueryCache() + const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) + + const queryCacheInnerInner = new QueryCache() + const queryClientInnerInner = new QueryClient({ + queryCache: queryCacheInnerInner, + }) + + function Page() { + const queryOuter = createQuery(key, async () => 'testOuter', { + context: contextOuter, + }) + const queryInner = createQuery(key, async () => 'testInner', { + context: contextInner, + }) + const queryInnerInner = createQuery(key, async () => 'testInnerInner') + + return ( +
+

+ {queryOuter.data} {queryInner.data} {queryInnerInner.data} +

+
+ ) + } + + // contextSharing should be ignored when passing a custom context. + const contextSharing = true + + render(() => ( + + + + + + + + )) + + await waitFor(() => + screen.getByText('testOuter testInner testInnerInner'), + ) + }) + }) + + describe('useQueryClient', () => { + test('should throw an error if no query client has been set', () => { + const consoleMock = jest + .spyOn(console, 'error') + .mockImplementation(() => undefined) + + function Page() { + useQueryClient() + return null + } + + expect(() => render(() => )).toThrow( + 'No QueryClient set, use QueryClientProvider to set one', + ) + + consoleMock.mockRestore() + }) + + test('should use window to get the context when contextSharing is true', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + let queryClientFromHook: QueryClient | undefined + let queryClientFromWindow: QueryClient | undefined + + function Page() { + queryClientFromHook = useQueryClient() + queryClientFromWindow = useContext( + window.SolidQueryClientContext as Context, + ) + return null + } + + render(() => ( + + + + )) + + expect(queryClientFromHook).toEqual(queryClient) + expect(queryClientFromWindow).toEqual(queryClient) + }) + + test('should not use window to get the context when contextSharing is true and window does not exist', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + // Mock a non web browser environment + const windowSpy = jest + .spyOn(window, 'window', 'get') + .mockImplementation(undefined) + + let queryClientFromHook: QueryClient | undefined + + function Page() { + queryClientFromHook = useQueryClient() + return null + } + + // TODO(lukemurray): this test doesn't pass because the page function is + // never called. I'm not sure why. + renderToString(() => ( + + + + )) + + expect(queryClientFromHook).toEqual(queryClient) + + windowSpy.mockRestore() + }) + }) +}) diff --git a/packages/solid-query/src/__tests__/utils.ts b/packages/solid-query/src/__tests__/utils.ts new file mode 100644 index 00000000000..c6bbb39643a --- /dev/null +++ b/packages/solid-query/src/__tests__/utils.ts @@ -0,0 +1,5 @@ +let queryKeyCount = 0 +export function queryKey(): () => Array { + const localQueryKeyCount = queryKeyCount++ + return () => [`query_${localQueryKeyCount}`] +} diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json new file mode 100644 index 00000000000..f8c5b4861ac --- /dev/null +++ b/packages/solid-query/tsconfig.json @@ -0,0 +1,11 @@ +{ + "composite": true, + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./build/types", + "jsx": "preserve", + "jsxImportSource": "solid-js", + }, + "files": ["src/index.ts"], + "include": ["src"] +} \ No newline at end of file diff --git a/tsconfig.base.json b/tsconfig.base.json index c3524d13868..c8845b11ec4 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -32,7 +32,8 @@ "@tanstack/react-query-devtools": ["packages/react-query-devtools/src"], "@tanstack/react-query-persist-client": [ "packages/react-query-persist-client/src" - ] + ], + "@tanstack/solid-query": ["packages/solid-query/src"], } } } diff --git a/tsconfig.json b/tsconfig.json index c397b08ace7..a6f9a8a2b7a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,7 @@ { "path": "packages/query-sync-storage-persister" }, { "path": "packages/react-query" }, { "path": "packages/react-query-devtools" }, - { "path": "packages/react-query-persist-client" } + { "path": "packages/react-query-persist-client" }, + { "path": "packages/solid-query" }, ] } From 62b17bd449679829b90811b8eab637ce3597dd54 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 18:33:32 -0400 Subject: [PATCH 113/221] add exports to match react query exports --- packages/solid-query/src/index.ts | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 524f1f01acd..cfa7a6a7705 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -1,6 +1,26 @@ -export * from './createQuery' -export * from './QueryClientProvider' -export * from './createMutation' -export * from './useIsMutating' -export * from './useIsFetching' -export { QueryClient } from '@tanstack/query-core' \ No newline at end of file +// Re-export core +export * from '@tanstack/query-core' + +// Solid Query +export * from "./types" +// export { useQueries } from './useQueries' +// export type { QueriesResults, QueriesOptions } from './useQueries' +export { createQuery } from './createQuery' +export { + QueryClientContext as defaultContext, + QueryClientProvider, + useQueryClient, +} from './QueryClientProvider' +// export type { QueryClientProviderProps } from './QueryClientProvider' +// export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' +// export { useHydrate, Hydrate } from './Hydrate' +// export type { HydrateProps } from './Hydrate' +// export { +// QueryErrorResetBoundary, +// useQueryErrorResetBoundary, +// } from './QueryErrorResetBoundary' +export { useIsFetching } from './useIsFetching' +export { useIsMutating } from './useIsMutating' +export { createMutation } from './createMutation' +// export { useInfiniteQuery } from './useInfiniteQuery' +// export { useIsRestoring, IsRestoringProvider } from './isRestoring' From 34b6613b173eb1f744b5ba3566577a784fffde80 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 18:56:56 -0400 Subject: [PATCH 114/221] reformat with prettier --- .../solid-query/src/QueryClientProvider.tsx | 48 ++++++++------ packages/solid-query/src/createBaseQuery.ts | 63 +++++++++++-------- packages/solid-query/src/createMutation.ts | 22 ++++--- packages/solid-query/src/createQuery.ts | 28 +++++---- packages/solid-query/src/index.ts | 2 +- packages/solid-query/src/types.ts | 57 +++++++++-------- packages/solid-query/src/useIsFetching.ts | 7 ++- packages/solid-query/src/useIsMutating.ts | 8 ++- packages/solid-query/src/utils.ts | 15 +++-- 9 files changed, 138 insertions(+), 112 deletions(-) diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index c2fa3ff4fa7..0d049fdad7e 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -1,6 +1,14 @@ -import type { QueryClient } from "@tanstack/query-core"; -import { Component, Context, createContext, useContext, JSX, onMount, onCleanup } from "solid-js"; -import { ContextOptions } from "./types"; +import type { QueryClient } from '@tanstack/query-core' +import { + Component, + Context, + createContext, + useContext, + JSX, + onMount, + onCleanup, +} from 'solid-js' +import { ContextOptions } from './types' declare global { interface Window { @@ -8,41 +16,41 @@ declare global { } } -export const QueryClientContext = createContext(); +export const QueryClientContext = createContext() export const QueryClientSharingContext = createContext(false) interface Props { - client: QueryClient; - children: JSX.Element; + client: QueryClient + children: JSX.Element } // Simple Query Client Context Provider export const QueryClientProvider: Component = (props) => { if (!props.client) { - throw new Error("No queryClient found."); + throw new Error('No queryClient found.') } - onMount(() => props.client.mount()); - onCleanup(() => props.client.unmount()); + onMount(() => props.client.mount()) + onCleanup(() => props.client.unmount()) return ( {props.children} - ); -}; + ) +} function getQueryClientContext( context: Context | undefined, - contextSharing: boolean + contextSharing: boolean, ) { if (context) { - return context; + return context } if (contextSharing && typeof window !== 'undefined') { if (!window.SolidQueryClientContext) { - window.SolidQueryClientContext = QueryClientContext; + window.SolidQueryClientContext = QueryClientContext } return window.SolidQueryClientContext @@ -53,12 +61,12 @@ function getQueryClientContext( export const useQueryClient = ({ context }: ContextOptions = {}) => { const queryClient = useContext( - getQueryClientContext(context, useContext(QueryClientSharingContext)) - ); + getQueryClientContext(context, useContext(QueryClientSharingContext)), + ) if (!queryClient) { - throw new Error('No QueryClient set, use QueryClientProvider to set one'); + throw new Error('No QueryClient set, use QueryClientProvider to set one') } - - return queryClient; -}; + + return queryClient +} diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index a825c66b85c..c3a2695bef3 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -1,9 +1,16 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' -import { CreateBaseQueryOptions } from './types' -import { useQueryClient } from "./QueryClientProvider"; -import { onMount, onCleanup, createComputed, createResource, createEffect, batch } from 'solid-js'; -import { createStore } from 'solid-js/store'; +import { CreateBaseQueryOptions } from './types' +import { useQueryClient } from './QueryClientProvider' +import { + onMount, + onCleanup, + createComputed, + createResource, + createEffect, + batch, +} from 'solid-js' +import { createStore } from 'solid-js/store' // Base Query Function that is used to create the query. export function createBaseQuery< @@ -11,7 +18,7 @@ export function createBaseQuery< TError, TData, TQueryData, - TQueryKey extends QueryKey + TQueryKey extends QueryKey, >( options: CreateBaseQueryOptions< TQueryFnData, @@ -20,41 +27,40 @@ export function createBaseQuery< TQueryData, TQueryKey >, - Observer: typeof QueryObserver + Observer: typeof QueryObserver, ): QueryObserverResult { - - const queryClient = useQueryClient(); + const queryClient = useQueryClient() const defaultedOptions = queryClient.defaultQueryOptions(options) - defaultedOptions._optimisticResults = 'optimistic'; - const observer = new QueryObserver(queryClient, defaultedOptions); + defaultedOptions._optimisticResults = 'optimistic' + const observer = new QueryObserver(queryClient, defaultedOptions) const [state, setState] = createStore>( // @ts-ignore observer.getOptimisticResult(defaultedOptions), - ); + ) - const [ dataResource, { refetch } ] = createResource(() => { + const [dataResource, { refetch }] = createResource(() => { return new Promise((resolve, reject) => { if (state.isSuccess) resolve(state.data) - if (state.isError && !state.isFetching) { + if (state.isError && !state.isFetching) { throw state.error } }) - }); + }) const unsubscribe = observer.subscribe((result) => { - const reconciledResult = result; + const reconciledResult = result // @ts-ignore - setState(reconciledResult); - refetch(); - }); + setState(reconciledResult) + refetch() + }) - onCleanup(() => unsubscribe()); + onCleanup(() => unsubscribe()) onMount(() => { - observer.setOptions(defaultedOptions, { listeners: false }); - }); + observer.setOptions(defaultedOptions, { listeners: false }) + }) createComputed(() => { const defaultedOptions = queryClient.defaultQueryOptions(options) @@ -62,13 +68,16 @@ export function createBaseQuery< }) const handler = { - get(target: QueryObserverResult, prop: (keyof QueryObserverResult)): any { + get( + target: QueryObserverResult, + prop: keyof QueryObserverResult, + ): any { if (prop === 'data') { - return dataResource(); + return dataResource() } - return Reflect.get(target, prop); - } + return Reflect.get(target, prop) + }, } - return new Proxy(state, handler) as QueryObserverResult; -} \ No newline at end of file + return new Proxy(state, handler) as QueryObserverResult +} diff --git a/packages/solid-query/src/createMutation.ts b/packages/solid-query/src/createMutation.ts index 2a4b8d65ce6..5214da550c1 100644 --- a/packages/solid-query/src/createMutation.ts +++ b/packages/solid-query/src/createMutation.ts @@ -11,7 +11,7 @@ import { CreateMutationResult, } from './types' import { createComputed, onCleanup } from 'solid-js' -import { createStore } from 'solid-js/store'; +import { createStore } from 'solid-js/store' // HOOK export function createMutation< @@ -82,17 +82,21 @@ export function createMutation< options, ) - const mutate: CreateMutateFunction = - (variables, mutateOptions) => { + const mutate: CreateMutateFunction = ( + variables, + mutateOptions, + ) => { observer.mutate(variables, mutateOptions).catch(noop) } - - const [state, setState] = createStore>({ + + const [state, setState] = createStore< + CreateMutationResult + >({ ...observer.getCurrentResult(), mutate, - mutateAsync: observer.getCurrentResult().mutate + mutateAsync: observer.getCurrentResult().mutate, }) - + createComputed(() => { const newParsedOptions = parseMutationArgs(arg1, arg2, arg3) setOptions(newParsedOptions) @@ -103,7 +107,7 @@ export function createMutation< setState({ ...result, mutate, - mutateAsync: result.mutate + mutateAsync: result.mutate, }) }) @@ -113,4 +117,4 @@ export function createMutation< } // eslint-disable-next-line @typescript-eslint/no-empty-function -function noop() {} \ No newline at end of file +function noop() {} diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index 11ec78c5500..b6594e9bcd0 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,9 +1,9 @@ -import { QueryObserver, QueryFunction } from '@tanstack/query-core'; +import { QueryObserver, QueryFunction } from '@tanstack/query-core' import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' import { createComputed } from 'solid-js' -import { createStore } from 'solid-js/store'; +import { createStore } from 'solid-js/store' import { parseQueryArgs } from './utils' -import { createBaseQuery } from './createBaseQuery'; +import { createBaseQuery } from './createBaseQuery' // There are several ways to create a query. // 1. createQuery(options: CreateQueryOptions) @@ -14,50 +14,52 @@ export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( - options: CreateQueryOptions + options: CreateQueryOptions, ): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( queryKey: SolidQueryKey, options?: Omit< CreateQueryOptions, 'queryKey' - > + >, ): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, 'queryKey' | 'queryFn' - > + >, ): CreateQueryResult export function createQuery< TQueryFnData, TError, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( arg1: TQueryKey | CreateQueryOptions, arg2?: | QueryFunction> | CreateQueryOptions, - arg3?: CreateQueryOptions + arg3?: CreateQueryOptions, ): CreateQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)) + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { @@ -65,5 +67,5 @@ export function createQuery< setParsedOptions(newParsedOptions) }) - return createBaseQuery(parsedOptions, QueryObserver); + return createBaseQuery(parsedOptions, QueryObserver) } diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index cfa7a6a7705..d11b5f5de9a 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -2,7 +2,7 @@ export * from '@tanstack/query-core' // Solid Query -export * from "./types" +export * from './types' // export { useQueries } from './useQueries' // export type { QueriesResults, QueriesOptions } from './useQueries' export { createQuery } from './createQuery' diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 59bc9262077..348af8ae5cf 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,12 +1,12 @@ -import type { Context, Accessor } from "solid-js"; -import type { - QueryClient, - QueryKey, - QueryObserverOptions, - QueryObserverResult, - MutateFunction, +import type { Context, Accessor } from 'solid-js' +import type { + QueryClient, + QueryKey, + QueryObserverOptions, + QueryObserverResult, + MutateFunction, MutationObserverOptions, - MutationObserverResult + MutationObserverResult, } from '@tanstack/query-core' export interface ContextOptions { @@ -16,14 +16,14 @@ export interface ContextOptions { context?: Context } -export type SolidQueryKey = () => readonly unknown[]; +export type SolidQueryKey = () => readonly unknown[] export interface CreateBaseQueryOptions< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryData = TQueryFnData, - TQueryKey extends QueryKey = QueryKey + TQueryKey extends QueryKey = QueryKey, > extends ContextOptions, QueryObserverOptions {} @@ -31,37 +31,35 @@ export interface CreateQueryOptions< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey + TQueryKey extends () => readonly unknown[] = SolidQueryKey, > extends CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - ReturnType -> {} + TQueryFnData, + TError, + TData, + TQueryFnData, + ReturnType + > {} export type CreateBaseQueryResult< TData = unknown, - TError = unknown + TError = unknown, > = QueryObserverResult export type CreateQueryResult< TData = unknown, - TError = unknown + TError = unknown, > = CreateBaseQueryResult - - export interface CreateMutationOptions< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, > extends ContextOptions, - Omit< - MutationObserverOptions, - '_defaulted' | 'variables' - > {} + Omit< + MutationObserverOptions, + '_defaulted' | 'variables' + > {} export type CreateMutateFunction< TData = unknown, @@ -72,7 +70,6 @@ export type CreateMutateFunction< ...args: Parameters> ) => void - export type CreateMutateAsyncFunction< TData = unknown, TError = unknown, @@ -90,11 +87,13 @@ export type CreateBaseMutationResult< > = Override< MutationObserverResult, { mutate: CreateMutateFunction } -> & { mutateAsync: CreateMutateAsyncFunction } - +> & { + mutateAsync: CreateMutateAsyncFunction +} + export type CreateMutationResult< TData = unknown, TError = unknown, TVariables = unknown, TContext = unknown, -> = CreateBaseMutationResult \ No newline at end of file +> = CreateBaseMutationResult diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index 12d58ff1ab9..f3dd24582dc 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -10,7 +10,10 @@ import { useQueryClient } from './QueryClientProvider' import { Accessor, createSignal, onCleanup } from 'solid-js' interface Options extends ContextOptions {} -export function useIsFetching(filters?: QueryFilters, options?: Options): Accessor +export function useIsFetching( + filters?: QueryFilters, + options?: Options, +): Accessor export function useIsFetching( queryKey?: QueryKey, filters?: QueryFilters, @@ -36,4 +39,4 @@ export function useIsFetching( }) return fetches -} \ No newline at end of file +} diff --git a/packages/solid-query/src/useIsMutating.ts b/packages/solid-query/src/useIsMutating.ts index 92d1a9e997f..3d11fe8c6bf 100644 --- a/packages/solid-query/src/useIsMutating.ts +++ b/packages/solid-query/src/useIsMutating.ts @@ -25,11 +25,13 @@ export function useIsMutating( arg3?: Options, ): Accessor { const [filters, options = {}] = parseMutationFilterArgs(arg1, arg2, arg3) - + const queryClient = useQueryClient({ context: options.context }) const mutationCache = queryClient.getMutationCache() - const [mutations, setMutations] = createSignal(queryClient.isMutating(filters)) + const [mutations, setMutations] = createSignal( + queryClient.isMutating(filters), + ) const unsubscribe = mutationCache.subscribe((result) => { setMutations(queryClient.isMutating(filters)) @@ -40,4 +42,4 @@ export function useIsMutating( }) return mutations -} \ No newline at end of file +} diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 83aa9db1d6d..75351e70396 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,5 +1,4 @@ - -import { CreateQueryOptions, SolidQueryKey } from './types' +import { CreateQueryOptions, SolidQueryKey } from './types' import { QueryFunction } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { @@ -18,17 +17,17 @@ export function parseQueryArgs< arg2?: | QueryFunction> | CreateQueryOptions, - arg3?: CreateQueryOptions + arg3?: CreateQueryOptions, ): CreateQueryOptions { - if(!isQueryKey(arg1)) { + if (!isQueryKey(arg1)) { const { queryKey: solidKey, ...opts } = arg1 as any if (solidKey) { return { ...opts, queryKey: solidKey(), - } - } - return arg1 + } + } + return arg1 } if (typeof arg2 === 'function') { @@ -36,4 +35,4 @@ export function parseQueryArgs< } return { ...arg2, queryKey: arg1() } as any -} \ No newline at end of file +} From c63f46985c93338f515ce17303de15b0f45013bf Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 19:06:41 -0400 Subject: [PATCH 115/221] fix lint and typecheck errors - disable rule of hooks in solid-query --- packages/solid-query/.eslintrc | 5 +- .../__tests__/QueryClientProvider.test.tsx | 232 +++++++++--------- packages/solid-query/src/createBaseQuery.ts | 13 +- packages/solid-query/src/types.ts | 2 +- packages/solid-query/src/useIsFetching.ts | 9 +- packages/solid-query/src/useIsMutating.ts | 3 +- 6 files changed, 124 insertions(+), 140 deletions(-) diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc index df08b8b4dbd..cefbf99ca1b 100644 --- a/packages/solid-query/.eslintrc +++ b/packages/solid-query/.eslintrc @@ -4,6 +4,7 @@ "sourceType": "module" }, "rules": { - "react/react-in-jsx-scope": "off" + "react/react-in-jsx-scope": "off", + "react-hooks/rules-of-hooks": "off" } -} \ No newline at end of file +} diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx index dbdf2707e36..f5d9786dcae 100644 --- a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -1,15 +1,8 @@ -import { Context, createContext, useContext } from 'solid-js' import { render, screen, waitFor } from 'solid-testing-library' import { queryKey } from './utils' import { QueryCache } from '@tanstack/query-core' -import { renderToString } from 'solid-js/web' -import { - createQuery, - QueryClient, - QueryClientProvider, - useQueryClient, -} from '..' +import { createQuery, QueryClientProvider, useQueryClient } from '..' import { createQueryClient, sleep } from '../../../../tests/utils' describe('QueryClientProvider', () => { @@ -138,63 +131,64 @@ describe('QueryClientProvider', () => { expect(queryCache.find(key())?.options.cacheTime).toBe(Infinity) }) - describe('with custom context', () => { - it('uses the correct context', async () => { - const key = queryKey() - - const contextOuter = createContext(undefined) - const contextInner = createContext(undefined) - - const queryCacheOuter = new QueryCache() - const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) - - const queryCacheInner = new QueryCache() - const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) - - const queryCacheInnerInner = new QueryCache() - const queryClientInnerInner = new QueryClient({ - queryCache: queryCacheInnerInner, - }) - - function Page() { - const queryOuter = createQuery(key, async () => 'testOuter', { - context: contextOuter, - }) - const queryInner = createQuery(key, async () => 'testInner', { - context: contextInner, - }) - const queryInnerInner = createQuery(key, async () => 'testInnerInner') - - return ( -
-

- {queryOuter.data} {queryInner.data} {queryInnerInner.data} -

-
- ) - } - - // contextSharing should be ignored when passing a custom context. - const contextSharing = true - - render(() => ( - - - - - - - - )) - - await waitFor(() => - screen.getByText('testOuter testInner testInnerInner'), - ) - }) - }) + // TODO(lukemurray): add test when we implement context sharing. + // describe('with custom context', () => { + // it('uses the correct context', async () => { + // const key = queryKey() + + // const contextOuter = createContext(undefined) + // const contextInner = createContext(undefined) + + // const queryCacheOuter = new QueryCache() + // const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) + + // const queryCacheInner = new QueryCache() + // const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) + + // const queryCacheInnerInner = new QueryCache() + // const queryClientInnerInner = new QueryClient({ + // queryCache: queryCacheInnerInner, + // }) + + // function Page() { + // const queryOuter = createQuery(key, async () => 'testOuter', { + // context: contextOuter, + // }) + // const queryInner = createQuery(key, async () => 'testInner', { + // context: contextInner, + // }) + // const queryInnerInner = createQuery(key, async () => 'testInnerInner') + + // return ( + //
+ //

+ // {queryOuter.data} {queryInner.data} {queryInnerInner.data} + //

+ //
+ // ) + // } + + // // contextSharing should be ignored when passing a custom context. + // const contextSharing = true + + // render(() => ( + // + // + // + // + // + // + // + // )) + + // await waitFor(() => + // screen.getByText('testOuter testInner testInnerInner'), + // ) + // }) + // }) describe('useQueryClient', () => { test('should throw an error if no query client has been set', () => { @@ -214,58 +208,60 @@ describe('QueryClientProvider', () => { consoleMock.mockRestore() }) - test('should use window to get the context when contextSharing is true', () => { - const queryCache = new QueryCache() - const queryClient = createQueryClient({ queryCache }) - - let queryClientFromHook: QueryClient | undefined - let queryClientFromWindow: QueryClient | undefined - - function Page() { - queryClientFromHook = useQueryClient() - queryClientFromWindow = useContext( - window.SolidQueryClientContext as Context, - ) - return null - } - - render(() => ( - - - - )) - - expect(queryClientFromHook).toEqual(queryClient) - expect(queryClientFromWindow).toEqual(queryClient) - }) - - test('should not use window to get the context when contextSharing is true and window does not exist', () => { - const queryCache = new QueryCache() - const queryClient = createQueryClient({ queryCache }) - - // Mock a non web browser environment - const windowSpy = jest - .spyOn(window, 'window', 'get') - .mockImplementation(undefined) - - let queryClientFromHook: QueryClient | undefined - - function Page() { - queryClientFromHook = useQueryClient() - return null - } - - // TODO(lukemurray): this test doesn't pass because the page function is - // never called. I'm not sure why. - renderToString(() => ( - - - - )) - - expect(queryClientFromHook).toEqual(queryClient) - - windowSpy.mockRestore() - }) + // TODO(lukemurray): add test when we implement context sharing + // test('should use window to get the context when contextSharing is true', () => { + // const queryCache = new QueryCache() + // const queryClient = createQueryClient({ queryCache }) + + // let queryClientFromHook: QueryClient | undefined + // let queryClientFromWindow: QueryClient | undefined + + // function Page() { + // queryClientFromHook = useQueryClient() + // queryClientFromWindow = useContext( + // window.SolidQueryClientContext as Context, + // ) + // return null + // } + + // render(() => ( + // + // + // + // )) + + // expect(queryClientFromHook).toEqual(queryClient) + // expect(queryClientFromWindow).toEqual(queryClient) + // }) + + // TODO(lukemurray): add test when we implement context sharing + // test('should not use window to get the context when contextSharing is true and window does not exist', () => { + // const queryCache = new QueryCache() + // const queryClient = createQueryClient({ queryCache }) + + // // Mock a non web browser environment + // const windowSpy = jest + // .spyOn(window, 'window', 'get') + // .mockImplementation(undefined) + + // let queryClientFromHook: QueryClient | undefined + + // function Page() { + // queryClientFromHook = useQueryClient() + // return null + // } + + // // TODO(lukemurray): this test doesn't pass because the page function is + // // never called. I'm not sure why. + // renderToString(() => ( + // + // + // + // )) + + // expect(queryClientFromHook).toEqual(queryClient) + + // windowSpy.mockRestore() + // }) }) }) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index c3a2695bef3..6a028bd51c2 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -2,14 +2,7 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' import { CreateBaseQueryOptions } from './types' import { useQueryClient } from './QueryClientProvider' -import { - onMount, - onCleanup, - createComputed, - createResource, - createEffect, - batch, -} from 'solid-js' +import { onMount, onCleanup, createComputed, createResource } from 'solid-js' import { createStore } from 'solid-js/store' // Base Query Function that is used to create the query. @@ -33,7 +26,7 @@ export function createBaseQuery< const defaultedOptions = queryClient.defaultQueryOptions(options) defaultedOptions._optimisticResults = 'optimistic' - const observer = new QueryObserver(queryClient, defaultedOptions) + const observer = new Observer(queryClient, defaultedOptions) const [state, setState] = createStore>( // @ts-ignore @@ -41,7 +34,7 @@ export function createBaseQuery< ) const [dataResource, { refetch }] = createResource(() => { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { if (state.isSuccess) resolve(state.data) if (state.isError && !state.isFetching) { throw state.error diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 348af8ae5cf..298ac316010 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context, Accessor } from 'solid-js' +import type { Context } from 'solid-js' import type { QueryClient, QueryKey, diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index f3dd24582dc..6de342ca8e0 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -1,9 +1,4 @@ -import { - QueryKey, - notifyManager, - parseFilterArgs, - QueryFilters, -} from '@tanstack/query-core' +import { QueryKey, parseFilterArgs, QueryFilters } from '@tanstack/query-core' import { ContextOptions } from './types' import { useQueryClient } from './QueryClientProvider' @@ -30,7 +25,7 @@ export function useIsFetching( const [fetches, setFetches] = createSignal(queryClient.isFetching(filters)) - const unsubscribe = queryCache.subscribe((result) => { + const unsubscribe = queryCache.subscribe((_result) => { setFetches(queryClient.isFetching(filters)) }) diff --git a/packages/solid-query/src/useIsMutating.ts b/packages/solid-query/src/useIsMutating.ts index 3d11fe8c6bf..ada59ee94bc 100644 --- a/packages/solid-query/src/useIsMutating.ts +++ b/packages/solid-query/src/useIsMutating.ts @@ -1,5 +1,4 @@ import { - notifyManager, MutationKey, MutationFilters, parseMutationFilterArgs, @@ -33,7 +32,7 @@ export function useIsMutating( queryClient.isMutating(filters), ) - const unsubscribe = mutationCache.subscribe((result) => { + const unsubscribe = mutationCache.subscribe((_result) => { setMutations(queryClient.isMutating(filters)) }) From 98dc5c33efcf5dba5e020f09442169384400c680 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 20:01:32 -0400 Subject: [PATCH 116/221] fix npm run build --- packages/solid-query/package.json | 28 +++++++++++++++++----------- rollup.config.ts | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json index abedd50c244..10e19a4c869 100644 --- a/packages/solid-query/package.json +++ b/packages/solid-query/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-query", - "version": "4.2.3", + "version": "4.3.0-beta.4", "description": "Hooks for managing, caching and syncing asynchronous and remote data in Solid", "author": "tannerlinsley", "license": "MIT", @@ -10,20 +10,26 @@ "type": "github", "url": "https://github.com/sponsors/tannerlinsley" }, - "module": "build/esm/index.js", - "main": "build/cjs/solid-query/src/index.js", - "browser": "build/umd/index.production.js", - "types": "build/types/packages/solid-query/src/index.d.ts", - "sideEffects": [], + "types": "build/lib/index.d.ts", + "main": "build/lib/index.js", + "exports": { + ".": { + "types": "./build/lib/index.d.ts", + "import": "./build/lib/index.mjs", + "default": "./build/lib/index.js" + }, + "./package.json": "./package.json" + }, "scripts": { + "clean": "rm -rf ./build", "test:codemods": "../../node_modules/.bin/jest --config codemods/jest.config.js", "test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src", "test:jest": "yarn test:codemods && ../../node_modules/.bin/jest --config jest.config.js", - "test:jest:dev": "yarn test:jest --watch", - "compile": "../../node_modules/.bin/tsc -p tsconfig.json --noEmit --emitDeclarationOnly false" + "test:jest:dev": "yarn test:jest --watch" }, "files": [ - "build/*", + "build/lib/*", + "build/umd/*", "src", "codemods", "!codemods/jest.config.js", @@ -35,10 +41,10 @@ "jscodeshift": "^0.13.1" }, "dependencies": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" }, "peerDependencies": { "solid-js": "^1.5.4" }, "peerDependenciesMeta": {} -} \ No newline at end of file +} diff --git a/rollup.config.ts b/rollup.config.ts index 1234d210932..890ead5a6db 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -138,6 +138,20 @@ export default function rollup(options: RollupOptions): RollupOptions[] { '@tanstack/react-query': 'ReactQuery', }, }), + ...buildConfigs({ + name: 'solid-query', + packageDir: 'packages/solid-query', + jsName: 'SolidQuery', + outputFile: 'index', + entryFile: 'src/index.ts', + globals: { + 'solid-js': 'Solid', + '@tanstack/query-core': 'QueryCore', + }, + bundleUMDGlobals: [ + '@tanstack/query-core', + ], + }), ] } From d105fd9b3d9298a6d65ec1949b2ee7ac0c03ab7f Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 20:19:34 -0400 Subject: [PATCH 117/221] fix babel config conditionally apply babel react preset to packages other than solid-query. apply solid-babel-preset to solid query. --- babel.config.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/babel.config.js b/babel.config.js index 8503e70bcb0..1c7384078ae 100644 --- a/babel.config.js +++ b/babel.config.js @@ -17,7 +17,6 @@ module.exports = { }, ], '@babel/preset-typescript', - '@babel/react', ], plugins: [ cjs && ['@babel/transform-modules-commonjs', { loose }], @@ -32,4 +31,14 @@ module.exports = { }, ], ].filter(Boolean), + overrides: [ + { + exclude: './packages/solid-query/**', + presets: ['@babel/react'], + }, + { + include: './packages/solid-query/**', + presets: ['babel-preset-solid'], + }, + ], } From b549dbdc2b1acdcef9ee8d9e9c823d802077ad86 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Thu, 8 Sep 2022 21:57:58 -0400 Subject: [PATCH 118/221] Completely reactive useIsFetching with correct queryKey types --- packages/solid-query/src/useIsFetching.ts | 50 ++++++++++++++++------- packages/solid-query/src/utils.ts | 24 ++++++++++- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index 6de342ca8e0..7e346c54efb 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -1,32 +1,54 @@ -import { QueryKey, parseFilterArgs, QueryFilters } from '@tanstack/query-core' +import { QueryFilters } from '@tanstack/query-core' -import { ContextOptions } from './types' +import { ContextOptions, SolidQueryKey } from './types' import { useQueryClient } from './QueryClientProvider' -import { Accessor, createSignal, onCleanup } from 'solid-js' +import { + Accessor, + createSignal, + onCleanup, + createComputed, + createMemo, +} from 'solid-js' +import { parseFilterArgs, SolidQueryFilters } from './utils' + interface Options extends ContextOptions {} export function useIsFetching( - filters?: QueryFilters, + filters?: SolidQueryFilters, options?: Options, ): Accessor export function useIsFetching( - queryKey?: QueryKey, - filters?: QueryFilters, + queryKey?: SolidQueryKey, + filters?: SolidQueryFilters, options?: Options, ): Accessor export function useIsFetching( - arg1?: QueryKey | QueryFilters, - arg2?: QueryFilters | Options, + arg1?: SolidQueryKey | SolidQueryFilters, + arg2?: SolidQueryFilters | Options, arg3?: Options, ): Accessor { - const [filters, options = {}] = parseFilterArgs(arg1, arg2, arg3) - const queryClient = useQueryClient({ context: options.context }) - const queryCache = queryClient.getQueryCache() + const [filtersObj, optionsObj = {}] = parseFilterArgs(arg1, arg2, arg3) + + const [filters, setFilters] = createSignal(filtersObj) + const [options, setOptions] = createSignal(optionsObj) + + const queryClient = createMemo(() => + useQueryClient({ context: options().context }), + ) + const queryCache = createMemo(() => queryClient().getQueryCache()) - const [fetches, setFetches] = createSignal(queryClient.isFetching(filters)) + const [fetches, setFetches] = createSignal( + queryClient().isFetching(filters as QueryFilters), + ) + + createComputed(() => { + const [filtersObj, optionsObj = {}] = parseFilterArgs(arg1, arg2, arg3) + setFilters(filtersObj) + setOptions(optionsObj) + }) - const unsubscribe = queryCache.subscribe((_result) => { - setFetches(queryClient.isFetching(filters)) + const unsubscribe = queryCache().subscribe(() => { + setFetches(queryClient().isFetching(filters() as QueryFilters)) }) onCleanup(() => { diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 75351e70396..2da23639415 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,5 +1,5 @@ import { CreateQueryOptions, SolidQueryKey } from './types' -import { QueryFunction } from '@tanstack/query-core' +import { QueryFunction, QueryFilters } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { return typeof value === 'function' @@ -36,3 +36,25 @@ export function parseQueryArgs< return { ...arg2, queryKey: arg1() } as any } + +export interface SolidQueryFilters extends Omit { + queryKey?: SolidQueryKey +} + +export type ParseFilterArgs = + T['queryKey'] extends () => infer R ? T & { queryKey: R } : T + +export function parseFilterArgs< + TFilters extends SolidQueryFilters, + TOptions = unknown, +>( + arg1?: SolidQueryKey | TFilters, + arg2?: TFilters | TOptions, + arg3?: TOptions, +): [ParseFilterArgs, TOptions | undefined] { + return ( + isQueryKey(arg1) + ? [{ ...arg2, queryKey: arg1() }, arg3] + : [{ ...arg1, queryKey: arg1?.queryKey?.() } || {}, arg2] + ) as [ParseFilterArgs, TOptions] +} From f40b053d2277fcbdb500691baed68cca6299d800 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 22:09:35 -0400 Subject: [PATCH 119/221] fix build types. make tsconfig look like react query tsconifg - add incremental compilation - output types in ./build/lib - allow project references --- packages/solid-query/tsconfig.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json index f8c5b4861ac..6146a991595 100644 --- a/packages/solid-query/tsconfig.json +++ b/packages/solid-query/tsconfig.json @@ -1,11 +1,16 @@ { - "composite": true, "extends": "../../tsconfig.base.json", "compilerOptions": { - "outDir": "./build/types", + "composite": true, + "rootDir": "./src", + "outDir": "./build/lib", + "tsBuildInfoFile": "./build/.tsbuildinfo", "jsx": "preserve", "jsxImportSource": "solid-js", }, - "files": ["src/index.ts"], - "include": ["src"] + "include": ["src"], + "exclude": ["src/__tests__"], + "references": [ + { "path": "../query-core" } + ] } \ No newline at end of file From 51f1e507fd74c61ee341261b534e55b01b347b9f Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Thu, 8 Sep 2022 23:14:00 -0400 Subject: [PATCH 120/221] add the first solid example --- examples/solid/basic-typescript/.eslintrc | 10 + examples/solid/basic-typescript/.gitignore | 4 + examples/solid/basic-typescript/README.md | 6 + examples/solid/basic-typescript/index.html | 16 + .../solid/basic-typescript/package-lock.json | 2479 +++++++++++++++++ examples/solid/basic-typescript/package.json | 22 + .../basic-typescript/src/assets/favicon.ico | Bin 0 -> 15086 bytes examples/solid/basic-typescript/src/index.tsx | 163 ++ examples/solid/basic-typescript/tsconfig.json | 15 + .../solid/basic-typescript/vite.config.ts | 15 + 10 files changed, 2730 insertions(+) create mode 100644 examples/solid/basic-typescript/.eslintrc create mode 100644 examples/solid/basic-typescript/.gitignore create mode 100644 examples/solid/basic-typescript/README.md create mode 100644 examples/solid/basic-typescript/index.html create mode 100644 examples/solid/basic-typescript/package-lock.json create mode 100644 examples/solid/basic-typescript/package.json create mode 100644 examples/solid/basic-typescript/src/assets/favicon.ico create mode 100644 examples/solid/basic-typescript/src/index.tsx create mode 100644 examples/solid/basic-typescript/tsconfig.json create mode 100644 examples/solid/basic-typescript/vite.config.ts diff --git a/examples/solid/basic-typescript/.eslintrc b/examples/solid/basic-typescript/.eslintrc new file mode 100644 index 00000000000..86b22fec59b --- /dev/null +++ b/examples/solid/basic-typescript/.eslintrc @@ -0,0 +1,10 @@ +{ + "parserOptions": { + "project": "./tsconfig.json", + "sourceType": "module" + }, + "rules": { + "react/react-in-jsx-scope": "off", + "jsx-a11y/anchor-is-valid": "off" + } +} diff --git a/examples/solid/basic-typescript/.gitignore b/examples/solid/basic-typescript/.gitignore new file mode 100644 index 00000000000..001e3f924bb --- /dev/null +++ b/examples/solid/basic-typescript/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.yalc +yalc.lock \ No newline at end of file diff --git a/examples/solid/basic-typescript/README.md b/examples/solid/basic-typescript/README.md new file mode 100644 index 00000000000..310f37f62fd --- /dev/null +++ b/examples/solid/basic-typescript/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` +- `npm run start` diff --git a/examples/solid/basic-typescript/index.html b/examples/solid/basic-typescript/index.html new file mode 100644 index 00000000000..48c59fc1242 --- /dev/null +++ b/examples/solid/basic-typescript/index.html @@ -0,0 +1,16 @@ + + + + + + + + Solid App + + + +
+ + + + diff --git a/examples/solid/basic-typescript/package-lock.json b/examples/solid/basic-typescript/package-lock.json new file mode 100644 index 00000000000..785e051eed2 --- /dev/null +++ b/examples/solid/basic-typescript/package-lock.json @@ -0,0 +1,2479 @@ +{ + "name": "@tanstack/query-example-solid-basic-typescript", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@tanstack/query-example-solid-basic-typescript", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } + }, + ".yalc/@tanstack/solid-query": { + "version": "4.2.3", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/solid-query": { + "version": "4.2.3", + "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "4.2.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "solid-js": "^1.5.4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "dependencies": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "dependencies": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "dependencies": { + "csstype": "^3.1.0" + } + }, + "node_modules/solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + }, + "peerDependencies": { + "solid-js": "^1.3" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "dependencies": { + "esbuild": "^0.15.6", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + }, + "peerDependencies": { + "solid-js": "^1.3.17", + "vite": "^3.0.0" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", + "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", + "dev": true + }, + "@babel/core": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", + "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + } + }, + "@babel/generator": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", + "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", + "dev": true, + "requires": { + "@babel/types": "^7.19.0", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", + "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.19.0", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "dev": true, + "requires": { + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", + "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", + "dev": true + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", + "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" + } + }, + "@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + } + }, + "@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + } + }, + "@babel/traverse": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", + "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.0", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.0", + "@babel/types": "^7.19.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@esbuild/linux-loong64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", + "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", + "dev": true, + "optional": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@tanstack/query-core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", + "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + }, + "@tanstack/solid-query": { + "version": "4.2.3", + "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "requires": { + "@tanstack/query-core": "4.2.3" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "babel-plugin-jsx-dom-expressions": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", + "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.16.0", + "@babel/plugin-syntax-jsx": "^7.16.5", + "@babel/types": "^7.16.0", + "html-entities": "2.3.2" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + } + } + }, + "babel-preset-solid": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", + "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", + "dev": true, + "requires": { + "babel-plugin-jsx-dom-expressions": "^0.34.5" + } + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "caniuse-lite": { + "version": "1.0.30001393", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", + "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "electron-to-chromium": { + "version": "1.4.245", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", + "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", + "dev": true + }, + "esbuild": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", + "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", + "dev": true, + "requires": { + "@esbuild/linux-loong64": "0.15.7", + "esbuild-android-64": "0.15.7", + "esbuild-android-arm64": "0.15.7", + "esbuild-darwin-64": "0.15.7", + "esbuild-darwin-arm64": "0.15.7", + "esbuild-freebsd-64": "0.15.7", + "esbuild-freebsd-arm64": "0.15.7", + "esbuild-linux-32": "0.15.7", + "esbuild-linux-64": "0.15.7", + "esbuild-linux-arm": "0.15.7", + "esbuild-linux-arm64": "0.15.7", + "esbuild-linux-mips64le": "0.15.7", + "esbuild-linux-ppc64le": "0.15.7", + "esbuild-linux-riscv64": "0.15.7", + "esbuild-linux-s390x": "0.15.7", + "esbuild-netbsd-64": "0.15.7", + "esbuild-openbsd-64": "0.15.7", + "esbuild-sunos-64": "0.15.7", + "esbuild-windows-32": "0.15.7", + "esbuild-windows-64": "0.15.7", + "esbuild-windows-arm64": "0.15.7" + } + }, + "esbuild-android-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", + "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", + "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", + "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", + "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", + "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", + "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", + "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", + "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", + "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", + "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", + "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", + "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", + "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", + "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", + "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", + "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", + "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", + "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", + "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", + "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-what": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", + "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "merge-anything": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", + "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", + "dev": true, + "requires": { + "is-what": "^4.1.7", + "ts-toolbelt": "^9.6.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "solid-js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", + "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "requires": { + "csstype": "^3.1.0" + } + }, + "solid-refresh": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", + "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", + "dev": true, + "requires": { + "@babel/generator": "^7.18.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/types": "^7.18.4" + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", + "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", + "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", + "dev": true, + "requires": { + "esbuild": "^0.15.6", + "fsevents": "~2.3.2", + "postcss": "^8.4.16", + "resolve": "^1.22.1", + "rollup": "~2.78.0" + } + }, + "vite-plugin-solid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", + "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", + "dev": true, + "requires": { + "@babel/core": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "babel-preset-solid": "^1.4.6", + "merge-anything": "^5.0.2", + "solid-refresh": "^0.4.1" + } + } + } +} diff --git a/examples/solid/basic-typescript/package.json b/examples/solid/basic-typescript/package.json new file mode 100644 index 00000000000..158e03b8563 --- /dev/null +++ b/examples/solid/basic-typescript/package.json @@ -0,0 +1,22 @@ +{ + "name": "@tanstack/query-example-solid-basic-typescript", + "private": true, + "version": "0.0.0", + "description": "", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "license": "MIT", + "dependencies": { + "@tanstack/solid-query": "^4.2.3", + "solid-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.8.2", + "vite": "^3.0.9", + "vite-plugin-solid": "^2.3.0" + } +} diff --git a/examples/solid/basic-typescript/src/assets/favicon.ico b/examples/solid/basic-typescript/src/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b836b2bccac650e0e7d90514083add91d2c027ff GIT binary patch literal 15086 zcmeI32Y6Lgw#RQo0Y@EtmA&@a z>%VX~JRB7qO`13ut2?&Tb~rp84oCIs=KCidj&pqWB%^#k=3$2;oFCNVH(cTvg2?Ck zua+_V>;M1%EHI;OjS4~SYCbiyeXWK_$5|a}^+(18cdR{rcBk6ILps&z9{OsXW^?@N zKE>$q&tL)YJ|5J*W^?dPL^gr^&;nW zso#2j*ZLKIX+474)p`W1FCqa*I(V-kh2T{d-Vlwqj>6Uoyeh17Jq2bpw@W<*ZZ)rK zeKo&ZgYOr-)?mfL?hT*&C3FDe6G#^%3dz;>)tKujjTg*<7aMELcjK+EBDytDU`84$ zaI4534b`I8Ux-`UtI^M<12}(;^hFY9cdY$)ZDX;o5fe@u3tlH?u`eQcBQ)LyPP~yl zUJ%S`F|wp*BekSgBek+ml_F zEBZ86EBiJP?CMW{Y^t`5XpxlqPCIt7^8XRL&my5nuB^NJiU}RZcgKWfW3lgYC*H;y z@2Y-a?$=bU2KNVViZoN(N4LDS_bs2{hx4lZ7+D;|B-4-ACs`$5jmh746Q^6e_c8~Jzjt+UELmaWVXW}bbc8_nP zwxZ8E<`;Y3Z%kNtEgM^SHw^bu88bM;zBTwFl;P%MKN*`fwI zd{q=j##+FaI*!CPS_ga}I;5aO+Kg8U zgS;0VGG})&eyepTHIBYvJ-f9Z$eKZi@#t{dilaD}IP%r&OxByMy%f_AVn?xO2DtZ! zbWsQ9bkkS`vtU0m|8=d$!SL7gciIP9hhlN0*Mc*SF0!6$xU-H;{J)7F<(+n4aU?nr zKN3f2#B&BZNNfl`tpj*19qc}k@9v5t=UV8XV|3rtcAw+#-@1$6)S(MLIEN1k>^Zf} zIAVTTlM+J`9}*{m^AI{n3|T%XJ&t58*z(c4?LT0?a-B7!M|f3;9_d{Z9}J2a(`sYv zxYlQhqucT93sz2*d|g%?i4F(QL1NzWfu+OUam1Rj=cB-m*T{3e<*|M7Yw*Ft_@FBI z2ggtGJu7>pi0n0@gU(0A;z-uQ1H@4QF*zUnj}*sJ-uFo}{U1-9;Wrogdm?d?NWM!X z2km1YkbOsTx6ViAS|}-w#OBU8vgIT3ku4wnNG@1G991bV*5cPC2l-V@3i6wW+)fVi zSIO8mMTC5=M{wF^AUa#-yD*CBBE#Bkp(?JJ+h$JyrT=u! z``;b}J2)Q!?`FX)c+-LnyiUxrmx}+9{gM-r17V1~4(+D*FrACguP7g}CrCbuU{8>J z0Rc18OC4F*OMzQ~Tja*k$TyCj{BX$3?AZ67Dvus%v%6G9&brvy#H^nM?3l5w*ij4n zmgF3rk*BLuI3`KT*qb!^caT0ULUSADs5q&gox_0EMofdS>gPh7l&d|zZ^!_Hz~ zZRfHuo3=eHcDCU)Y>b@^8#5YsowyhGQJ=3Ktp0P`WOZTBbYvP5m~|m8@I`lZz{XAY z&*^&285iI^V6*YT;&v_*vokK#QPal97WGlb!278wCsqznXQIZd?6_&_;@%nRLj3!7 z9oA;Y23B%M2WY#;Wr%;7*u{1Zn&i z1%JHL2YK0Xfj!*8pE29t0~<%W#B!N7wy!^1Tv#?X@oL;l!M$pLI<;Y(#(gOG!DFp1Z)unyl-)G`4*#~##d&zO&WklyD?WT~3};gkS3*_)GTz__OeVTWk4B+T7n}$Ir|-v-vIc z*`Edzv;CZTPUCmR2Wt^~|8-eEbz((-b@IcZ#Pv8Zzo#w;=G3_=CvBd}VYK6S(+Bu1 zU>)Mt`8X#ftVd2t_>D_RVJbU5Sbe)QP<_4SZFMSY5-~hMo!U5&n3$}-**;aB+s(S$ z8v@38>Pq@TbtMByUjX*`PW;@yN( z*?R)Zb*2#=xQ7Qm2-iL!9>l&^#pZ(lP>~M|``dJ|`ykCNANgUFxD2e;S@j^Kl#;C~=qpg4YcPu?4vlREFFtjW@SAoefj16j*@9hd5Z zo2-LO_Jd*U2jx1umxQfA#7c@>*%<-V_j|0lP1 zas2Y0IUggJPsX0-@Ihh8>%jCurY#p4J}Asdi})M*r?Qp;utj6=yH#r|36r~@F{cOk z>s-lP6p(vhNd|fJDr@;B;~kw_4=gRjH@C^9dFXfvUmYcHt>K!{Iq4Bi!T*@MbN*bv z2j>&uZUFucjD5gAh`nF{pLYj;EAZF4k{MZr{p_Ki3&X$e`^#ED=|6|#?lHZBQhZ)0 z-yzo>j#)CMI~+bT0#n8U#%hdwt;a0JD!fm(jg`#z6&U4vYxFR$vqrgTKHtkI_qC6} z(C<|+{Y-o>c=VWM+)r@HJTmIf`JH1H?`8Bc$7<$CWl4W-jqHkYokPYfMwlx-vdhan zG*B6%d@lgyIvM4@0#xxI07WkuMSsNv+FmNluwyB9mOicOh%e&o(|VFO|A+qqU#adP zy*>2D)S%a-CE`!-MpybEeCR2tO;5q2Kec+(eQS6GwXgLwb9O@(G3S1IMlLdM9`pXl zytkP5A7TFWF2k?ygd%&D@3bUxb~D zc-^ghjxB2>AtZ<@@miJz$Sv&*8{vmtG&U z&&Q=-#@TyfarX3^z2Jul_c)Yb zQ^GI*un}2}w_bbZ=TZVZ4ZtGCb^bK&uAJP}GoPHYJza;%Y zyms2OFFIPi6VmG;Js!x%W}k<_H5**M@U(HlD+=HGmQOqw$~=?7&-aKO)9MCXjEaUI z-3s>g^e|Ywym0f<4`bKSKA-eDSe*7Iu8o6N6)xG}-F@@HFt98e>>lY|8Gd@R@L9r5 z3lFrHd+dQriG~;20`DvL7jE6+{|!#s;{3hTrco`_jtQ;RKIYZjukeL%ktXMSlzTo? zCWcYoE#RbbW5*R?kZUatClMYe9*%hzyt(klTTL!`2Y6$IyM-T-8oh9A!g*@mfop_A z!4G%fg~paO|IT4v55en22)7!?{iRPrxFq5I1%vRZX`07_7lj89E?9U0iwBlEp45J& zrmlGcxMSfji~P`bJ-U^7zJ=ed35L_sYZ6C)hV%$X?~3NKu&dlp_!G^A%G}In@o!SM zms+UQ&NYV)ALHVOciMeamj2dvaD#pE!(p)gp!*ceI2JofKZn7K8(gO5V&N1l3^E?% zy?n0yAiSUOKLH(XW5Y6I(3)RHVzCO`WJ`Fxu=vTo*CZA-KaU@De}U--&Eui3@Q|Xv z#k-W?hXgRVwI3wU>RdT7$S(|DE=bO#cjQ zKqt9-fACVHkROFhE8=*FZHaFi4<&ZCczstt7<>t}*~9P(CeiN%$mL2gdwxM(`R(biLiISugBeNG&q=%QYjmXU7KAycYs^ zm3m07^jTQ^l?$h$xe0^+xvTbU<9w|8t<><(Y=V1;4G_L$CG|bJ`Ah$U6RCsb=s9hi zh{ZP= zc>(*JMs3~F(OILW#(SLluAX-{^IA1?C+DI$qr`jFIFBvv+XepV2jQqRpH_lh?Q=?9 zS-7dwQ4>^F?E6ODTWa@Guhcbfi*wL6kUH!5vTVRL6~Ec`_S!H0Jd&FAo0>~<*0ZIK zz0_96-Y{OB-4%$gA!hB=wf0_$4Zg+(FO-ELCpEk&HN}e;5<=AZ*qQ3vUDK(T2Qt?* z{r*BiD0OD)rPQrNq;BV|pC`{T_zR1>uyIH5Mg`PrlbOF!S@X+x)IoyfzPhF?wamjS zjd~`vO{q;ujm@P7uItA|^>2$mvDx4Pwbp6Oe_u5;>Q;Y1rxT(db(o@>wytAa^HT?= zc0}E!EF1hc^~R5=mo~l_KfTO-u((aAOAo>ZH$_+KCng5;cd4aY^+WN2)X*&(gnow& z)=~3pjSb4xw}A~RbI&kraN|C0kdMtyf;*gRU!v|;u6gZtK%Yv?-<3Gnh7Gc)Y3ET# z%Etyb`RqEjIZqs<@|y^3)djpybB$Yew$E4EYv!rQyw#~?c{6sTj@6DhY|iIZslolK zwCny^KR4<#{6DLTQdAlWsB&CKvM4nK8!{`MiU;DuXCl=oT~y2GH6;m=St67xsvwn2 zslaC}eShOjdx~>c5dQ|^acd6y$hq{XP`^5pI4_>$ ztXLpt@A=*8s|ED>%fJ1Qa}(#KTbzp~*sqh<%X&6?h5M&*#w(C>y7Ym|*;W3%g`8RC zY_*y*&PM~9scoZMo=TkJ>(XCHA9?>xLp}4>(o--0F2FjA$(cxcs^vT+J;_@+tL)`G zkTBUdY{yVfXZ**FZuu+DSexaUb`Q_AF_Vm*R5{y-NPlV^&-(h@z_T9Dn-_WhcgfE@ zn|t$Yo-5Dg(zC03nxwyybB8?t$n&>656ZJ4eOm>b9eUgCuxq$i1)goY^IW@~XWD$} zv6JUx>CLpBVddFXdU$!(|C;aX+OL<_nR8$BpzkUud4}KZ6wU&vW{;}OE6-md+@la# z#WUD*XEu&;+CZ+S-{yJb8+o2HdOxh*8l$Ji>YZVK%|E?i>=*3QF8$hE^DKQLr>tia zqkqMC&XfIFIQ;)uGm<^>U9-nyS~UBdOV8P7s|HO!zG6V3)njpdxxq)Dj+)4`63-5@ zXG*^UeG2TA`8+SV#M7mu&}Z4}k7cv}id;-&zfUFa%l;$$HG8kzgZ<_XeHusD>$-~W z_CNCDo8+v2Xnqi`meW?dF!{OjbMF<{P`UD{3UW|Gq{d_=bk0*6(lD|z7KWYY7R#*)(qxJUL+mK WLaxim%Fn{v*G ['posts'], + async (): Promise> => { + const response = await fetch( + 'https://jsonplaceholder.typicode.com/posts', + { + method: 'GET', + }, + ) + return response.json() + }, + ) +} + +function Posts(props: { setPostId: Setter }) { + const queryClient = useQueryClient() + const state = createPosts() + + return ( + + ) +} + +const getPostById = async (id: number): Promise => { + const response = await fetch( + `https://jsonplaceholder.typicode.com/posts/${id}`, + { + method: 'GET', + }, + ) + return await response.json() +} + +function createPost(postId: number) { + return createQuery( + () => ['post', postId], + () => getPostById(postId), + { + enabled: !!postId, + }, + ) +} + +function Post(props: { postId: number; setPostId: Setter }) { + const state = createPost(props.postId) + + return ( +
+ + + + Loading... + + + Error: {(state.error as Error).message} + + + <> +

{state.data?.title}

+
+

{state.data?.body}

+
+
{state.isFetching ? 'Background Updating...' : ' '}
+ +
+
+
+ ) +} + +const App: Component = () => { + const [postId, setPostId] = createSignal(-1) + + return ( + +

+ As you visit the posts below, you will notice them in a loading state + the first time you load them. However, after you return to this list and + click on any posts you have already visited again, you will see them + load instantly and background refresh right before your eyes!{' '} + + (You may need to throttle your network speed to simulate longer + loading sequences) + +

+ {postId() > -1 ? ( + + ) : ( + + )} +
+ ) +} + +render(() => , document.getElementById('root') as HTMLElement) diff --git a/examples/solid/basic-typescript/tsconfig.json b/examples/solid/basic-typescript/tsconfig.json new file mode 100644 index 00000000000..249b2732a74 --- /dev/null +++ b/examples/solid/basic-typescript/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": ["vite/client"], + "noEmit": true, + "isolatedModules": true + } +} diff --git a/examples/solid/basic-typescript/vite.config.ts b/examples/solid/basic-typescript/vite.config.ts new file mode 100644 index 00000000000..598cdda9083 --- /dev/null +++ b/examples/solid/basic-typescript/vite.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite' +import solidPlugin from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solidPlugin()], + server: { + port: 3000, + }, + build: { + target: 'esnext', + }, + resolve: { + preserveSymlinks: true, + }, +}) From f6626f95ee5f9ca2db639ef186b805590c425f55 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 09:39:20 -0400 Subject: [PATCH 121/221] fix query types --- .../src/__tests__/useQuery.types.test.tsx | 160 ++++++++++++++++++ packages/solid-query/src/createQuery.ts | 101 +++++++++-- packages/solid-query/src/types.ts | 44 ++++- 3 files changed, 286 insertions(+), 19 deletions(-) create mode 100644 packages/solid-query/src/__tests__/useQuery.types.test.tsx diff --git a/packages/solid-query/src/__tests__/useQuery.types.test.tsx b/packages/solid-query/src/__tests__/useQuery.types.test.tsx new file mode 100644 index 00000000000..1d82484d5b6 --- /dev/null +++ b/packages/solid-query/src/__tests__/useQuery.types.test.tsx @@ -0,0 +1,160 @@ +import { createQuery } from '../createQuery' + +export type Equal = (() => T extends X ? 1 : 2) extends < + T, +>() => T extends Y ? 1 : 2 + ? true + : false + +export type Expect = T + +const doNotExecute = (_func: () => void) => true + +describe('initialData', () => { + describe('Config object overload', () => { + it('TData should always be defined when initialData is provided as an object', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => ({ + wow: true, + }), + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + }) + + const result: Expect> = + true + return result + }) + }) + + it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + }) + + const result: Expect> = + true + return result + }) + }) + }) + + describe('Query key overload', () => { + it('TData should always be defined when initialData is provided', () => { + doNotExecute(() => { + const { data } = createQuery(() => ['key'], { + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery(() => ['key'], { + queryFn: () => { + return { + wow: true, + } + }, + }) + + const result: Expect> = + true + return result + }) + }) + }) + + describe('Query key and func', () => { + it('TData should always be defined when initialData is provided', () => { + doNotExecute(() => { + const { data } = createQuery( + () => ['key'], + () => { + return { + wow: true, + } + }, + { + initialData: { + wow: true, + }, + }, + ) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery( + () => ['key'], + () => { + return { + wow: true, + } + }, + ) + + const result: Expect> = + true + return result + }) + }) + }) +}) diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index b6594e9bcd0..4258a53310d 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,20 +1,44 @@ -import { QueryObserver, QueryFunction } from '@tanstack/query-core' -import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' +import { QueryFunction, QueryObserver } from '@tanstack/query-core' import { createComputed } from 'solid-js' import { createStore } from 'solid-js/store' -import { parseQueryArgs } from './utils' import { createBaseQuery } from './createBaseQuery' +import { + CreateQueryOptions, + CreateQueryResult, + DefinedCreateQueryResult, + SolidQueryKey, +} from './types' +import { parseQueryArgs } from './utils' -// There are several ways to create a query. -// 1. createQuery(options: CreateQueryOptions) -// 2. createQuery(querykey: () => Serializable[], options: CreateQueryOptions) -// 3. createQuery(querykey: () => Serializable[], queryFunc: Fetcher Function, options: CreateQueryOptions) -// 4. The fourth overload is a combination of all three function params +// HOOK + +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + options: Omit< + CreateQueryOptions, + 'initialData' + > & { initialData?: () => undefined }, +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + options: Omit< + CreateQueryOptions, + 'initialData' + > & { initialData: TQueryFnData | (() => TQueryFnData) }, +): DefinedCreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, >( options: CreateQueryOptions, ): CreateQueryResult @@ -22,9 +46,33 @@ export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey, + TQueryKey extends SolidQueryKey = SolidQueryKey, >( - queryKey: SolidQueryKey, + queryKey: TQueryKey, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'initialData' + > & { initialData?: () => undefined }, +): CreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'initialData' + > & { initialData: TQueryFnData | (() => TQueryFnData) }, +): DefinedCreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, options?: Omit< CreateQueryOptions, 'queryKey' @@ -34,7 +82,34 @@ export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + // TODO(lukemurray): not sure if we want to use return type here + queryFn: QueryFunction>, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData' + > & { initialData?: () => undefined }, +): CreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + queryFn: QueryFunction>, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData' + > & { initialData: TQueryFnData | (() => TQueryFnData) }, +): DefinedCreateQueryResult +export function createQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, >( queryKey: TQueryKey, queryFn: QueryFunction>, @@ -47,7 +122,7 @@ export function createQuery< TQueryFnData, TError, TData = TQueryFnData, - TQueryKey extends () => readonly unknown[] = SolidQueryKey, + TQueryKey extends SolidQueryKey = SolidQueryKey, >( arg1: TQueryKey | CreateQueryOptions, arg2?: diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 298ac316010..e984a87f594 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,13 +1,14 @@ -import type { Context } from 'solid-js' import type { + DefinedQueryObserverResult, + MutateFunction, + MutationObserverOptions, + MutationObserverResult, QueryClient, QueryKey, QueryObserverOptions, QueryObserverResult, - MutateFunction, - MutationObserverOptions, - MutationObserverResult, } from '@tanstack/query-core' +import type { Context } from 'solid-js' export interface ContextOptions { /** @@ -23,6 +24,7 @@ export interface CreateBaseQueryOptions< TError = unknown, TData = TQueryFnData, TQueryData = TQueryFnData, + // TODO(lukemurray): maybe this should be a solid query key? TQueryKey extends QueryKey = QueryKey, > extends ContextOptions, QueryObserverOptions {} @@ -40,6 +42,21 @@ export interface CreateQueryOptions< ReturnType > {} +// export interface UseInfiniteQueryOptions< +// TQueryFnData = unknown, +// TError = unknown, +// TData = TQueryFnData, +// TQueryData = TQueryFnData, +// TQueryKey extends QueryKey = QueryKey, +// > extends ContextOptions, +// InfiniteQueryObserverOptions< +// TQueryFnData, +// TError, +// TData, +// TQueryData, +// TQueryKey +// > {} + export type CreateBaseQueryResult< TData = unknown, TError = unknown, @@ -50,6 +67,21 @@ export type CreateQueryResult< TError = unknown, > = CreateBaseQueryResult +export type DefinedCreateBaseQueryResult< + TData = unknown, + TError = unknown, +> = DefinedQueryObserverResult + +export type DefinedCreateQueryResult< + TData = unknown, + TError = unknown, +> = DefinedCreateBaseQueryResult + +// export type UseInfiniteQueryResult< +// TData = unknown, +// TError = unknown, +// > = InfiniteQueryObserverResult + export interface CreateMutationOptions< TData = unknown, TError = unknown, @@ -77,8 +109,6 @@ export type CreateMutateAsyncFunction< TContext = unknown, > = MutateFunction -type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } - export type CreateBaseMutationResult< TData = unknown, TError = unknown, @@ -97,3 +127,5 @@ export type CreateMutationResult< TVariables = unknown, TContext = unknown, > = CreateBaseMutationResult + +type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } From 05a684f7d79aa10606fe7f2b11fa0d5f04e9c9f2 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 09:44:08 -0400 Subject: [PATCH 122/221] rename useQuery test to createQuery --- .../{useQuery.types.test.tsx => createQuery.types.test.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/solid-query/src/__tests__/{useQuery.types.test.tsx => createQuery.types.test.tsx} (100%) diff --git a/packages/solid-query/src/__tests__/useQuery.types.test.tsx b/packages/solid-query/src/__tests__/createQuery.types.test.tsx similarity index 100% rename from packages/solid-query/src/__tests__/useQuery.types.test.tsx rename to packages/solid-query/src/__tests__/createQuery.types.test.tsx From 46e14de344e0e3ddaf6c7c2dffbd8d7a78687f08 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 10:07:00 -0400 Subject: [PATCH 123/221] get eslint to pass. now we should be able to successfully run npm test on every commit. --- packages/solid-query/.eslintrc | 2 +- packages/solid-query/src/QueryClientProvider.tsx | 3 ++- packages/solid-query/src/createBaseQuery.ts | 4 ++-- packages/solid-query/src/useIsFetching.ts | 10 +++++++--- packages/solid-query/src/utils.ts | 2 +- packages/solid-query/tsconfig.lint.json | 15 +++++++++++++++ 6 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 packages/solid-query/tsconfig.lint.json diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc index cefbf99ca1b..a1437a22aac 100644 --- a/packages/solid-query/.eslintrc +++ b/packages/solid-query/.eslintrc @@ -1,6 +1,6 @@ { "parserOptions": { - "project": "./tsconfig.json", + "project": "./tsconfig.lint.json", "sourceType": "module" }, "rules": { diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index 0d049fdad7e..12067d7dee9 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -26,8 +26,9 @@ interface Props { // Simple Query Client Context Provider export const QueryClientProvider: Component = (props) => { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime check. if (!props.client) { - throw new Error('No queryClient found.') + throw new Error('No QueryClient set, use QueryClientProvider to set one') } onMount(() => props.client.mount()) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 6a028bd51c2..d613f40b55b 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -56,8 +56,8 @@ export function createBaseQuery< }) createComputed(() => { - const defaultedOptions = queryClient.defaultQueryOptions(options) - observer.setOptions(defaultedOptions) + const newDefaultedOptions = queryClient.defaultQueryOptions(options) + observer.setOptions(newDefaultedOptions) }) const handler = { diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index 7e346c54efb..241832cc5cd 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -42,9 +42,13 @@ export function useIsFetching( ) createComputed(() => { - const [filtersObj, optionsObj = {}] = parseFilterArgs(arg1, arg2, arg3) - setFilters(filtersObj) - setOptions(optionsObj) + const [newFiltersObj, newOptionsObj = {}] = parseFilterArgs( + arg1, + arg2, + arg3, + ) + setFilters(newFiltersObj) + setOptions(newOptionsObj) }) const unsubscribe = queryCache().subscribe(() => { diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 2da23639415..3ea93b6cb1f 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -55,6 +55,6 @@ export function parseFilterArgs< return ( isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1() }, arg3] - : [{ ...arg1, queryKey: arg1?.queryKey?.() } || {}, arg2] + : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] ) as [ParseFilterArgs, TOptions] } diff --git a/packages/solid-query/tsconfig.lint.json b/packages/solid-query/tsconfig.lint.json new file mode 100644 index 00000000000..0fb829ee95a --- /dev/null +++ b/packages/solid-query/tsconfig.lint.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "rootDir": "./src", + "outDir": "./build/lib", + "tsBuildInfoFile": "./build/.tsbuildinfo", + "jsx": "preserve", + "jsxImportSource": "solid-js", + }, + "include": ["src"], + "references": [ + { "path": "../query-core" } + ] +} From 66d9acd5a729751acfd48d0e8a876731e166cf91 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 10:15:05 -0400 Subject: [PATCH 124/221] remove unused codemods test --- packages/solid-query/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json index 10e19a4c869..625e3923c34 100644 --- a/packages/solid-query/package.json +++ b/packages/solid-query/package.json @@ -22,9 +22,8 @@ }, "scripts": { "clean": "rm -rf ./build", - "test:codemods": "../../node_modules/.bin/jest --config codemods/jest.config.js", "test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src", - "test:jest": "yarn test:codemods && ../../node_modules/.bin/jest --config jest.config.js", + "test:jest": "../../node_modules/.bin/jest --config jest.config.js", "test:jest:dev": "yarn test:jest --watch" }, "files": [ From 05f001859944022dd1457d21f31f0a44aa252278 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 9 Sep 2022 11:33:33 -0400 Subject: [PATCH 125/221] Keep comments and better organization of types by functions --- packages/solid-query/src/createQuery.ts | 15 +++++---- packages/solid-query/src/types.ts | 42 ++++++++++--------------- packages/solid-query/src/utils.ts | 18 +++++------ 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index 4258a53310d..374dbe2fac0 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,17 +1,20 @@ -import { QueryFunction, QueryObserver } from '@tanstack/query-core' -import { createComputed } from 'solid-js' -import { createStore } from 'solid-js/store' -import { createBaseQuery } from './createBaseQuery' +import { QueryObserver, QueryFunction } from '@tanstack/query-core' import { CreateQueryOptions, CreateQueryResult, DefinedCreateQueryResult, SolidQueryKey, } from './types' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' import { parseQueryArgs } from './utils' +import { createBaseQuery } from './createBaseQuery' -// HOOK - +// There are several ways to create a query. +// 1. createQuery(options: CreateQueryOptions) +// 2. createQuery(querykey: () => Serializable[], options: CreateQueryOptions) +// 3. createQuery(querykey: () => Serializable[], queryFunc: Fetcher Function, options: CreateQueryOptions) +// 4. The fourth overload is a combination of all three function params export function createQuery< TQueryFnData = unknown, TError = unknown, diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index e984a87f594..b5dd4878db6 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,14 +1,15 @@ +import type { Context, Accessor } from 'solid-js' import type { - DefinedQueryObserverResult, - MutateFunction, - MutationObserverOptions, - MutationObserverResult, QueryClient, QueryKey, QueryObserverOptions, QueryObserverResult, + MutateFunction, + MutationObserverOptions, + MutationObserverResult, + DefinedQueryObserverResult, + QueryFilters, } from '@tanstack/query-core' -import type { Context } from 'solid-js' export interface ContextOptions { /** @@ -17,6 +18,7 @@ export interface ContextOptions { context?: Context } +/* --- Create Query and Create Base Query Types --- */ export type SolidQueryKey = () => readonly unknown[] export interface CreateBaseQueryOptions< @@ -24,7 +26,6 @@ export interface CreateBaseQueryOptions< TError = unknown, TData = TQueryFnData, TQueryData = TQueryFnData, - // TODO(lukemurray): maybe this should be a solid query key? TQueryKey extends QueryKey = QueryKey, > extends ContextOptions, QueryObserverOptions {} @@ -42,21 +43,6 @@ export interface CreateQueryOptions< ReturnType > {} -// export interface UseInfiniteQueryOptions< -// TQueryFnData = unknown, -// TError = unknown, -// TData = TQueryFnData, -// TQueryData = TQueryFnData, -// TQueryKey extends QueryKey = QueryKey, -// > extends ContextOptions, -// InfiniteQueryObserverOptions< -// TQueryFnData, -// TError, -// TData, -// TQueryData, -// TQueryKey -// > {} - export type CreateBaseQueryResult< TData = unknown, TError = unknown, @@ -77,11 +63,7 @@ export type DefinedCreateQueryResult< TError = unknown, > = DefinedCreateBaseQueryResult -// export type UseInfiniteQueryResult< -// TData = unknown, -// TError = unknown, -// > = InfiniteQueryObserverResult - +/* --- Create Mutation Types --- */ export interface CreateMutationOptions< TData = unknown, TError = unknown, @@ -129,3 +111,11 @@ export type CreateMutationResult< > = CreateBaseMutationResult type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } + +/* --- Use Is Fetching Types --- */ +export interface SolidQueryFilters extends Omit { + queryKey?: SolidQueryKey +} + +export type ParseFilterArgs = + T['queryKey'] extends () => infer R ? T & { queryKey: R } : T diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 3ea93b6cb1f..f164bec4454 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,5 +1,10 @@ -import { CreateQueryOptions, SolidQueryKey } from './types' -import { QueryFunction, QueryFilters } from '@tanstack/query-core' +import { + CreateQueryOptions, + SolidQueryKey, + SolidQueryFilters, + ParseFilterArgs, +} from './types' +import { QueryFunction } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { return typeof value === 'function' @@ -37,13 +42,6 @@ export function parseQueryArgs< return { ...arg2, queryKey: arg1() } as any } -export interface SolidQueryFilters extends Omit { - queryKey?: SolidQueryKey -} - -export type ParseFilterArgs = - T['queryKey'] extends () => infer R ? T & { queryKey: R } : T - export function parseFilterArgs< TFilters extends SolidQueryFilters, TOptions = unknown, @@ -55,6 +53,6 @@ export function parseFilterArgs< return ( isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1() }, arg3] - : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] + : [{ ...arg1, queryKey: arg1?.queryKey?.() } || {}, arg2] ) as [ParseFilterArgs, TOptions] } From 60145326268e665b38034b2e629bc0c4ee1eb011 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 9 Sep 2022 12:00:39 -0400 Subject: [PATCH 126/221] Fix: Typo in useIsFetching --- packages/solid-query/src/useIsFetching.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index 241832cc5cd..dfa78d79c79 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -1,6 +1,6 @@ import { QueryFilters } from '@tanstack/query-core' -import { ContextOptions, SolidQueryKey } from './types' +import { ContextOptions, SolidQueryKey, SolidQueryFilters } from './types' import { useQueryClient } from './QueryClientProvider' import { Accessor, @@ -9,7 +9,7 @@ import { createComputed, createMemo, } from 'solid-js' -import { parseFilterArgs, SolidQueryFilters } from './utils' +import { parseFilterArgs } from './utils' interface Options extends ContextOptions {} From 9f447afb0cbc75e4e31cbd2cff18438da0bab271 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 11:07:14 -0400 Subject: [PATCH 127/221] add createQuery test --- .../src/__tests__/createQuery.test.tsx | 5752 +++++++++++++++++ 1 file changed, 5752 insertions(+) create mode 100644 packages/solid-query/src/__tests__/createQuery.test.tsx diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx new file mode 100644 index 00000000000..6a873027471 --- /dev/null +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -0,0 +1,5752 @@ +import { screen, waitFor, fireEvent } from 'solid-testing-library' +import '@testing-library/jest-dom' +import { + expectType, + mockVisibilityState, + sleep, + setActTimeout, + mockNavigatorOnLine, + mockLogger, + createQueryClient, +} from '../../../../tests/utils' +import { renderWithClient, Blink, queryKey } from './utils' +import { + createQuery, + CreateQueryResult, + QueryCache, + QueryFunction, + QueryFunctionContext, + CreateQueryOptions, + DefinedCreateQueryResult, +} from '..' + +describe('useQuery', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should return the correct types', () => { + const key = queryKey() + + // @ts-ignore + // eslint-disable-next-line + function Page() { + // unspecified query function should default to unknown + const noQueryFn = createQuery(key) + expectType(noQueryFn.data) + expectType(noQueryFn.error) + + // it should infer the result type from the query function + const fromQueryFn = createQuery(key, () => 'test') + expectType(fromQueryFn.data) + expectType(fromQueryFn.error) + + // it should be possible to specify the result type + const withResult = createQuery(key, () => 'test') + expectType(withResult.data) + expectType(withResult.error) + + // it should be possible to specify the error type + const withError = createQuery(key, () => 'test') + expectType(withError.data) + expectType(withError.error) + + // it should provide the result type in the configuration + createQuery([key], async () => true, { + onSuccess: (data) => expectType(data), + onSettled: (data) => expectType(data), + }) + + // it should be possible to specify a union type as result type + const unionTypeSync = createQuery( + key, + () => (Math.random() > 0.5 ? 'a' : 'b'), + { + onSuccess: (data) => expectType<'a' | 'b'>(data), + }, + ) + expectType<'a' | 'b' | undefined>(unionTypeSync.data) + const unionTypeAsync = createQuery<'a' | 'b'>( + key, + () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'), + { + onSuccess: (data) => expectType<'a' | 'b'>(data), + }, + ) + expectType<'a' | 'b' | undefined>(unionTypeAsync.data) + + // should error when the query function result does not match with the specified type + // @ts-expect-error + createQuery(key, () => 'test') + + // it should infer the result type from a generic query function + function queryFn(): Promise { + return Promise.resolve({} as T) + } + + const fromGenericQueryFn = createQuery(key, () => queryFn()) + expectType(fromGenericQueryFn.data) + expectType(fromGenericQueryFn.error) + + const fromGenericOptionsQueryFn = createQuery({ + queryKey: key, + queryFn: () => queryFn(), + }) + expectType(fromGenericOptionsQueryFn.data) + expectType(fromGenericOptionsQueryFn.error) + + type MyData = number + type MyQueryKey = readonly ['my-data', number] + + const getMyDataArrayKey: QueryFunction = async ({ + queryKey: [, n], + }) => { + return n + 42 + } + + createQuery({ + queryKey: ['my-data', 100], + queryFn: getMyDataArrayKey, + }) + + const getMyDataStringKey: QueryFunction = async ( + context, + ) => { + expectType<['1']>(context.queryKey) + return Number(context.queryKey[0]) + 42 + } + + createQuery({ + queryKey: ['1'], + queryFn: getMyDataStringKey, + }) + + // it should handle query-functions that return Promise + createQuery(key, () => + fetch('return Promise').then((resp) => resp.json()), + ) + + // handles wrapped queries with custom fetcher passed as inline queryFn + const useWrappedQuery = < + TQueryKey extends [string, Record?], + TQueryFnData, + TError, + TData = TQueryFnData, + >( + qk: TQueryKey, + fetcher: ( + obj: TQueryKey[1], + token: string, + // return type must be wrapped with TQueryFnReturn + ) => Promise, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData' + >, + ) => createQuery(qk, () => fetcher(qk[1], 'token'), options) + const test = useWrappedQuery([''], async () => '1') + expectType(test.data) + + // handles wrapped queries with custom fetcher passed directly to useQuery + const useWrappedFuncStyleQuery = < + TQueryKey extends [string, Record?], + TQueryFnData, + TError, + TData = TQueryFnData, + >( + qk: TQueryKey, + fetcher: () => Promise, + options?: Omit< + CreateQueryOptions, + 'queryKey' | 'queryFn' | 'initialData' + >, + ) => createQuery(qk, fetcher, options) + const testFuncStyle = useWrappedFuncStyleQuery([''], async () => true) + expectType(testFuncStyle.data) + } + }) + + // See https://github.com/tannerlinsley/react-query/issues/105 + it('should allow to set default data value', async () => { + const key = queryKey() + + function Page() { + const { data = 'default' } = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + return ( +
+

{data}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('default') + + await waitFor(() => rendered.getByText('test')) + }) + + it('should return the correct states for a successful query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + states.push(state) + + if (state.isLoading) { + expectType(state.data) + expectType(state.error) + return loading + } + + if (state.isLoadingError) { + expectType(state.data) + expectType(state.error) + return {state.error.message} + } + + expectType(state.data) + expectType(state.error) + return {state.data} + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('test')) + + expect(states.length).toEqual(2) + + expect(states[0]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'loading', + fetchStatus: 'fetching', + }) + + expect(states[1]).toEqual({ + data: 'test', + dataUpdatedAt: expect.any(Number), + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + isError: false, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isPaused: false, + isLoading: false, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: true, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'success', + fetchStatus: 'idle', + }) + }) + + it('should return the correct states for an unsuccessful query', async () => { + const key = queryKey() + + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery( + key, + () => Promise.reject('rejected'), + { + retry: 1, + retryDelay: 1, + }, + ) + + states.push(state) + + return ( +
+

Status: {state.status}

+
Failure Count: {state.failureCount}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('Status: error')) + + expect(states[0]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'loading', + fetchStatus: 'fetching', + }) + + expect(states[1]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 1, + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'loading', + fetchStatus: 'fetching', + }) + + expect(states[2]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: 'rejected', + errorUpdatedAt: expect.any(Number), + failureCount: 2, + errorUpdateCount: 1, + isError: true, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isPaused: false, + isLoading: false, + isLoadingError: true, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'error', + fetchStatus: 'idle', + }) + }) + + it('should set isFetchedAfterMount to true after a query has been fetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, () => 'prefetched') + + function Page() { + const state = createQuery(key, () => 'data') + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(states.length).toBe(2) + + expect(states[0]).toMatchObject({ + data: 'prefetched', + isFetched: true, + isFetchedAfterMount: false, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isFetched: true, + isFetchedAfterMount: true, + }) + }) + + it('should call onSuccess after a query has been fetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSuccess = jest.fn() + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'data' + }, + { onSuccess }, + ) + states.push(state) + return
data: {state.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: data') + expect(states.length).toBe(2) + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(onSuccess).toHaveBeenCalledWith('data') + }) + + it('should call onSuccess after a query has been refetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSuccess = jest.fn() + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + count++ + await sleep(10) + return 'data' + count + }, + { onSuccess }, + ) + + states.push(state) + + return ( +
+
data: {state.data}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: data1') + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await rendered.findByText('data: data2') + + expect(states.length).toBe(3) //loading, success, success after refetch + expect(count).toBe(2) + expect(onSuccess).toHaveBeenCalledTimes(2) + }) + + it('should call onSuccess after a disabled query has been fetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSuccess = jest.fn() + + function Page() { + const state = createQuery(key, () => 'data', { + enabled: false, + onSuccess, + }) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 10) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(onSuccess).toHaveBeenCalledWith('data') + }) + + it('should not call onSuccess if a component has unmounted', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSuccess = jest.fn() + + function Page() { + const [show, setShow] = React.useState(true) + + React.useEffect(() => { + setShow(false) + }, [setShow]) + + return show ? : null + } + + function Component() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'data' + }, + { onSuccess }, + ) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + expect(states.length).toBe(1) + expect(onSuccess).toHaveBeenCalledTimes(0) + }) + + it('should call onError after a query has been fetched with an error', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onError = jest.fn() + + function Page() { + const state = createQuery(key, () => Promise.reject('error'), { + retry: false, + onError, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(states.length).toBe(2) + expect(onError).toHaveBeenCalledTimes(1) + expect(onError).toHaveBeenCalledWith('error') + }) + + it('should not call onError when receiving a CancelledError', async () => { + const key = queryKey() + const onError = jest.fn() + + function Page() { + const { status, fetchStatus } = createQuery( + key, + async () => { + await sleep(10) + return 23 + }, + { + onError, + }, + ) + return ( + + status: {status}, fetchStatus: {fetchStatus} + + ) + } + + const rendered = renderWithClient(queryClient, ) + + await sleep(5) + await queryClient.cancelQueries(key) + // query cancellation will reset the query to it's initial state + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: idle'), + ) + expect(onError).not.toHaveBeenCalled() + }) + + it('should call onSettled after a query has been fetched', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSettled = jest.fn() + + function Page() { + const state = createQuery(key, () => 'data', { onSettled }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(states.length).toBe(2) + expect(onSettled).toHaveBeenCalledTimes(1) + expect(onSettled).toHaveBeenCalledWith('data', null) + }) + + it('should call onSettled after a query has been fetched with an error', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const onSettled = jest.fn() + + function Page() { + const state = createQuery(key, () => Promise.reject('error'), { + retry: false, + onSettled, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(states.length).toBe(2) + expect(onSettled).toHaveBeenCalledTimes(1) + expect(onSettled).toHaveBeenCalledWith(undefined, 'error') + }) + + it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => { + const key = queryKey() + let fetchCount = 0 + + function Page() { + const { refetch } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + return 'data' + }, + { enabled: false, initialData: 'initialData' }, + ) + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 5) + setActTimeout(() => { + refetch({ cancelRefetch: false }) + }, 5) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + // first refetch only, second refetch is ignored + expect(fetchCount).toBe(1) + }) + + it('should cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we have data already', async () => { + const key = queryKey() + let fetchCount = 0 + + function Page() { + const { refetch } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + return 'data' + }, + { enabled: false, initialData: 'initialData' }, + ) + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 5) + setActTimeout(() => { + refetch() + }, 5) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + // first refetch (gets cancelled) and second refetch + expect(fetchCount).toBe(2) + }) + + it('should not cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we do not have data yet', async () => { + const key = queryKey() + let fetchCount = 0 + + function Page() { + const { refetch } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + return 'data' + }, + { enabled: false }, + ) + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 5) + setActTimeout(() => { + refetch() + }, 5) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + // first refetch will not get cancelled, second one gets skipped + expect(fetchCount).toBe(1) + }) + + it('should be able to watch a query without providing a query function', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + queryClient.setQueryDefaults(key, { queryFn: () => 'data' }) + + function Page() { + const state = createQuery(key) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'data' }) + }) + + it('should pick up a query when re-mounting with cacheTime 0', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [toggle, setToggle] = React.useState(false) + + return ( +
+ + {toggle ? ( + + ) : ( + + )} +
+ ) + } + + function Component({ value }: { value: string }) { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'data: ' + value + }, + { + cacheTime: 0, + notifyOnChangeProps: 'all', + }, + ) + states.push(state) + return ( +
+
{state.data}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: 1') + + fireEvent.click(rendered.getByRole('button', { name: /toggle/i })) + + await rendered.findByText('data: 2') + + expect(states.length).toBe(4) + // First load + expect(states[0]).toMatchObject({ + isLoading: true, + isSuccess: false, + isFetching: true, + }) + // First success + expect(states[1]).toMatchObject({ + isLoading: false, + isSuccess: true, + isFetching: false, + }) + // Switch, goes to fetching + expect(states[2]).toMatchObject({ + isLoading: false, + isSuccess: true, + isFetching: true, + }) + // Second success + expect(states[3]).toMatchObject({ + isLoading: false, + isSuccess: true, + isFetching: false, + }) + }) + + it('should not get into an infinite loop when removing a query with cacheTime 0 and rerendering', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [, rerender] = React.useState({}) + + const state = createQuery( + key, + async () => { + await sleep(5) + return 'data' + }, + { + cacheTime: 0, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { remove } = state + + React.useEffect(() => { + setActTimeout(() => { + remove() + rerender({}) + }, 20) + }, [remove]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(5) + // First load + expect(states[0]).toMatchObject({ isLoading: true, isSuccess: false }) + // First success + expect(states[1]).toMatchObject({ isLoading: false, isSuccess: true }) + // Remove + expect(states[2]).toMatchObject({ isLoading: true, isSuccess: false }) + // Hook state update + expect(states[3]).toMatchObject({ isLoading: true, isSuccess: false }) + // Second success + expect(states[4]).toMatchObject({ isLoading: false, isSuccess: true }) + }) + + it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'test', { + refetchOnMount: false, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should not fetch when refetchOnMount is false and data has been fetched already', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + queryClient.setQueryData(key, 'prefetched') + + function Page() { + const state = createQuery(key, () => 'test', { + refetchOnMount: false, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(1) + expect(states[0]).toMatchObject({ data: 'prefetched' }) + }) + + it('should be able to select a part of the data with select', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => ({ name: 'test' }), { + select: (data) => data.name, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should be able to select a part of the data with select in object syntax', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: () => ({ name: 'test' }), + select: (data) => data.name, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should not re-render when it should only re-render only data change and the selected data did not change', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => ({ name: 'test' }), { + select: (data) => data.name, + notifyOnChangeProps: ['data'], + }) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 5) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should throw an error when a selector throws', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const error = new Error('Select Error') + + function Page() { + const state = createQuery(key, () => ({ name: 'test' }), { + select: () => { + throw error + }, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(mockLogger.error).toHaveBeenCalledWith(error) + expect(states.length).toBe(2) + + expect(states[0]).toMatchObject({ status: 'loading', data: undefined }) + expect(states[1]).toMatchObject({ status: 'error', error }) + }) + + it('should not re-run a stable select when it re-renders if selector throws an error', async () => { + const key = queryKey() + const error = new Error('Select Error') + let runs = 0 + + function Page() { + const [, rerender] = React.useReducer(() => ({}), {}) + const state = createQuery( + key, + () => (runs === 0 ? 'test' : 'test2'), + { + select: React.useCallback(() => { + runs++ + throw error + }, []), + }, + ) + return ( +
+
error: {state.error?.message}
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('error: Select Error')) + expect(runs).toEqual(1) + fireEvent.click(rendered.getByRole('button', { name: 'rerender' })) + await sleep(10) + expect(runs).toEqual(1) + fireEvent.click(rendered.getByRole('button', { name: 'refetch' })) + await sleep(10) + expect(runs).toEqual(2) + }) + + it('should track properties and only re-render when a tracked property changes', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + states.push(state) + + const { refetch, data } = state + + React.useEffect(() => { + setActTimeout(() => { + if (data) { + refetch() + } + }, 20) + }, [refetch, data]) + + return ( +
+

{data ?? null}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('test')) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should always re-render if we are tracking props but not using any', async () => { + const key = queryKey() + let renderCount = 0 + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'test') + + states.push(state) + + React.useEffect(() => { + renderCount++ + }, [state]) + + return ( +
+

hello

+
+ ) + } + + renderWithClient(queryClient, ) + + await sleep(10) + expect(renderCount).toBe(2) + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined }) + expect(states[1]).toMatchObject({ data: 'test' }) + }) + + it('should be able to remove a query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const [, rerender] = React.useState({}) + const state = createQuery(key, () => ++count, { + notifyOnChangeProps: 'all', + }) + + states.push(state) + + const { remove } = state + + return ( +
+ + + data: {state.data ?? 'null'} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /remove/i })) + + await sleep(20) + fireEvent.click(rendered.getByRole('button', { name: /rerender/i })) + await waitFor(() => rendered.getByText('data: 2')) + + expect(states.length).toBe(4) + // Initial + expect(states[0]).toMatchObject({ status: 'loading', data: undefined }) + // Fetched + expect(states[1]).toMatchObject({ status: 'success', data: 1 }) + // Remove + Hook state update, batched + expect(states[2]).toMatchObject({ status: 'loading', data: undefined }) + // Fetched + expect(states[3]).toMatchObject({ status: 'success', data: 2 }) + }) + + it('should create a new query when refetching a removed query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + return ++count + }, + { notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { remove, refetch } = state + + return ( +
+ + + data: {state.data ?? 'null'} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /remove/i })) + + await sleep(50) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => rendered.getByText('data: 2')) + + expect(states.length).toBe(4) + // Initial + expect(states[0]).toMatchObject({ data: undefined, dataUpdatedAt: 0 }) + // Fetched + expect(states[1]).toMatchObject({ data: 1 }) + // Switch + expect(states[2]).toMatchObject({ data: undefined, dataUpdatedAt: 0 }) + // Fetched + expect(states[3]).toMatchObject({ data: 2 }) + }) + + it('should share equal data structures between query results', async () => { + const key = queryKey() + + const result1 = [ + { id: '1', done: false }, + { id: '2', done: false }, + ] + + const result2 = [ + { id: '1', done: false }, + { id: '2', done: true }, + ] + + const states: CreateQueryResult[] = [] + + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count === 1 ? result1 : result2 + }, + { notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { refetch } = state + + return ( +
+ + data: {String(state.data?.[1]?.done)} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: false')) + await sleep(20) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => rendered.getByText('data: true')) + + await waitFor(() => expect(states.length).toBe(4)) + + const todos = states[2]?.data + const todo1 = todos?.[0] + const todo2 = todos?.[1] + + const newTodos = states[3]?.data + const newTodo1 = newTodos?.[0] + const newTodo2 = newTodos?.[1] + + expect(todos).toEqual(result1) + expect(newTodos).toEqual(result2) + expect(newTodos).not.toBe(todos) + expect(newTodo1).toBe(todo1) + expect(newTodo2).not.toBe(todo2) + + return null + }) + + it('should use query function from hook when the existing query does not have a query function', async () => { + const key = queryKey() + const results: DefinedCreateQueryResult[] = [] + + queryClient.setQueryData(key, 'set') + + function Page() { + const result = createQuery( + key, + async () => { + await sleep(10) + return 'fetched' + }, + { + initialData: 'initial', + staleTime: Infinity, + }, + ) + + results.push(result) + + return ( +
+
isFetching: {result.isFetching}
+ + data: {result.data} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: set')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => rendered.getByText('data: fetched')) + + await waitFor(() => expect(results.length).toBe(3)) + + expect(results[0]).toMatchObject({ data: 'set', isFetching: false }) + expect(results[1]).toMatchObject({ data: 'set', isFetching: true }) + expect(results[2]).toMatchObject({ data: 'fetched', isFetching: false }) + }) + + it('should update query stale state and refetch when invalidated with invalidateQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { staleTime: Infinity, notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + return ( +
+ + data: {state.data} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + await waitFor(() => rendered.getByText('data: 2')) + + await waitFor(() => expect(states.length).toBe(4)) + + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isRefetching: false, + isSuccess: false, + isStale: true, + }) + expect(states[1]).toMatchObject({ + data: 1, + isFetching: false, + isRefetching: false, + isSuccess: true, + isStale: false, + }) + expect(states[2]).toMatchObject({ + data: 1, + isFetching: true, + isRefetching: true, + isSuccess: true, + isStale: true, + }) + expect(states[3]).toMatchObject({ + data: 2, + isFetching: false, + isRefetching: false, + isSuccess: true, + isStale: false, + }) + }) + + it('should not update disabled query when refetched with refetchQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { enabled: false }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + queryClient.refetchQueries({ queryKey: key }) + }, 20) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + + expect(states.length).toBe(1) + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: false, + isSuccess: false, + isStale: true, + }) + }) + + it('should not refetch disabled query when invalidated with invalidateQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { enabled: false }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + queryClient.invalidateQueries(key) + }, 20) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(1) + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: false, + isSuccess: false, + isStale: true, + }) + }) + + it('should not fetch when switching to a disabled query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery( + [key, count], + async () => { + await sleep(5) + return count + }, + { enabled: count === 0 }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + setCount(1) + }, 10) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + + expect(states.length).toBe(3) + + // Fetch query + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isSuccess: false, + }) + // Fetched query + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + }) + // Switch to disabled query + expect(states[2]).toMatchObject({ + data: undefined, + isFetching: false, + isSuccess: false, + }) + }) + + it('should keep the previous data when keepPreviousData is set', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery( + [key, count], + async () => { + await sleep(10) + return count + }, + { keepPreviousData: true }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + setCount(1) + }, 20) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(states.length).toBe(5)) + + // Initial + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isSuccess: false, + isPreviousData: false, + }) + // Fetched + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[2]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // Hook state update + expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ + data: 1, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should transition to error state when keepPreviousData is set', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page({ count }: { count: number }) { + const state = createQuery( + [key, count], + async () => { + await sleep(10) + if (count === 2) { + throw new Error('Error test') + } + return Promise.resolve(count) + }, + { + retry: false, + keepPreviousData: true, + }, + ) + + states.push(state) + + return ( +
+

data: {state.data}

+

error: {state.error?.message}

+

previous data: {state.isPreviousData}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('data: 0')) + act(() => rendered.rerender()) + await waitFor(() => rendered.getByText('data: 1')) + act(() => rendered.rerender()) + await waitFor(() => rendered.getByText('error: Error test')) + + await waitFor(() => expect(states.length).toBe(8)) + // Initial + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + status: 'loading', + error: null, + isPreviousData: false, + }) + // Fetched + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + status: 'success', + error: null, + isPreviousData: false, + }) + // rerender Page 1 + expect(states[2]).toMatchObject({ + data: 0, + isFetching: true, + status: 'success', + error: null, + isPreviousData: true, + }) + // Hook state update + expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + status: 'success', + error: null, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ + data: 1, + isFetching: false, + status: 'success', + error: null, + isPreviousData: false, + }) + // rerender Page 2 + expect(states[5]).toMatchObject({ + data: 1, + isFetching: true, + status: 'success', + error: null, + isPreviousData: true, + }) + // Hook state update again + expect(states[6]).toMatchObject({ + data: 1, + isFetching: true, + status: 'success', + error: null, + isPreviousData: true, + }) + // Error + expect(states[7]).toMatchObject({ + data: undefined, + isFetching: false, + status: 'error', + isPreviousData: false, + }) + expect(states[7]?.error).toHaveProperty('message', 'Error test') + }) + + it('should not show initial data from next query if keepPreviousData is set', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery( + [key, count], + async () => { + await sleep(10) + return count + }, + { initialData: 99, keepPreviousData: true }, + ) + + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + setCount(1) + }, 20) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(states.length).toBe(5)) + + // Initial + expect(states[0]).toMatchObject({ + data: 99, + isFetching: true, + isSuccess: true, + isPreviousData: false, + }) + // Fetched + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[2]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // Hook state update + expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ + data: 1, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should keep the previous data on disabled query when keepPreviousData is set', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery( + [key, count], + async () => { + await sleep(10) + return count + }, + { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + refetch() + + setActTimeout(() => { + setCount(1) + }, 20) + + setActTimeout(() => { + refetch() + }, 30) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(6) + + // Disabled query + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: false, + isSuccess: false, + isPreviousData: false, + }) + // Fetching query + expect(states[1]).toMatchObject({ + data: undefined, + isFetching: true, + isSuccess: false, + isPreviousData: false, + }) + // Fetched query + expect(states[2]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[3]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPreviousData: true, + }) + // Fetching new query + expect(states[4]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // Fetched new query + expect(states[5]).toMatchObject({ + data: 1, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should keep the previous data on disabled query when keepPreviousData is set and switching query key multiple times', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + queryClient.setQueryData([key, 10], 10) + + await sleep(10) + + function Page() { + const [count, setCount] = React.useState(10) + + const state = createQuery( + [key, count], + async () => { + await sleep(10) + return count + }, + { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + setCount(11) + }, 20) + setActTimeout(() => { + setCount(12) + }, 30) + setActTimeout(() => { + refetch() + }, 40) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(5) + + // Disabled query + expect(states[0]).toMatchObject({ + data: 10, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[1]).toMatchObject({ + data: 10, + isFetching: false, + isSuccess: true, + isPreviousData: true, + }) + // State update + expect(states[2]).toMatchObject({ + data: 10, + isFetching: false, + isSuccess: true, + isPreviousData: true, + }) + // Refetch + expect(states[3]).toMatchObject({ + data: 10, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // Refetch done + expect(states[4]).toMatchObject({ + data: 12, + isFetching: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should use the correct query function when components use different configurations', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function FirstComponent() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 1 + }, + { notifyOnChangeProps: 'all' }, + ) + const refetch = state.refetch + + states.push(state) + + return ( +
+ + data: {state.data} +
+ ) + } + + function SecondComponent() { + createQuery(key, () => 2, { notifyOnChangeProps: 'all' }) + return null + } + + function Page() { + return ( + <> + + + + ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + + await waitFor(() => expect(states.length).toBe(4)) + + expect(states[0]).toMatchObject({ + data: undefined, + }) + expect(states[1]).toMatchObject({ + data: 1, + }) + expect(states[2]).toMatchObject({ + data: 1, + }) + // This state should be 1 instead of 2 + expect(states[3]).toMatchObject({ + data: 1, + }) + }) + + it('should be able to set different stale times for a query', async () => { + const key = queryKey() + const states1: CreateQueryResult[] = [] + const states2: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, async () => { + await sleep(10) + return 'prefetch' + }) + + await sleep(20) + + function FirstComponent() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'one' + }, + { + staleTime: 100, + }, + ) + states1.push(state) + return null + } + + function SecondComponent() { + const state = createQuery( + key, + async () => { + await sleep(10) + return 'two' + }, + { + staleTime: 10, + }, + ) + states2.push(state) + return null + } + + function Page() { + return ( + <> + + + + ) + } + + renderWithClient(queryClient, ) + + await sleep(200) + + expect(states1.length).toBe(4) + expect(states2.length).toBe(3) + + expect(states1).toMatchObject([ + // First render + { + data: 'prefetch', + isStale: false, + }, + // Second useQuery started fetching + { + data: 'prefetch', + isStale: false, + }, + // Second useQuery data came in + { + data: 'two', + isStale: false, + }, + // Data became stale after 100ms + { + data: 'two', + isStale: true, + }, + ]) + + expect(states2).toMatchObject([ + // First render, data is stale and starts fetching + { + data: 'prefetch', + isStale: true, + }, + // Second useQuery data came in + { + data: 'two', + isStale: false, + }, + // Data became stale after 5ms + { + data: 'two', + isStale: true, + }, + ]) + }) + + it('should re-render when a query becomes stale', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'test', { + staleTime: 50, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(3) + expect(states[0]).toMatchObject({ isStale: true }) + expect(states[1]).toMatchObject({ isStale: false }) + expect(states[2]).toMatchObject({ isStale: true }) + }) + + it('should notify query cache when a query becomes stale', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const fn = jest.fn() + + const unsubscribe = queryCache.subscribe(fn) + + function Page() { + const state = createQuery(key, () => 'test', { + staleTime: 10, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + unsubscribe() + + // 1. Query added -> loading + // 2. Observer result updated -> loading + // 3. Observer added + // 4. Query updated -> success + // 5. Observer result updated -> success + // 6. Query updated -> stale + // 7. Observer options updated + // 8. Observer result updated -> stale + // 9. Observer options updated + expect(fn).toHaveBeenCalledTimes(9) + }) + + it('should not re-render when it should only re-render on data changes and the data did not change', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(5) + return 'test' + }, + { + notifyOnChangeProps: ['data'], + }, + ) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 10) + }, [refetch]) + return null + } + + renderWithClient(queryClient, ) + + await sleep(30) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: undefined, + status: 'loading', + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'test', + status: 'success', + isFetching: false, + }) + }) + + // See https://github.com/tannerlinsley/react-query/issues/137 + it('should not override initial data in dependent queries', async () => { + const key1 = queryKey() + const key2 = queryKey() + + function Page() { + const first = createQuery(key1, () => 'data', { + enabled: false, + initialData: 'init', + }) + + const second = createQuery(key2, () => 'data', { + enabled: false, + initialData: 'init', + }) + + return ( +
+

First Data: {first.data}

+

Second Data: {second.data}

+
First Status: {first.status}
+
Second Status: {second.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('First Data: init') + rendered.getByText('Second Data: init') + rendered.getByText('First Status: success') + rendered.getByText('Second Status: success') + }) + + it('should not override query configuration on render', async () => { + const key = queryKey() + + const queryFn1 = async () => { + await sleep(10) + return 'data1' + } + + const queryFn2 = async () => { + await sleep(10) + return 'data2' + } + + function Page() { + createQuery(key, queryFn1) + createQuery(key, queryFn2) + return null + } + + renderWithClient(queryClient, ) + + expect(queryCache.find(key)!.options.queryFn).toBe(queryFn1) + }) + + it('should render correct states even in case of useEffect triggering delays', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + const originalUseEffect = React.useEffect + + // Try to simulate useEffect timing delay + // @ts-ignore + React.useEffect = (...args: any[]) => { + originalUseEffect(() => { + setTimeout(() => { + args[0]() + }, 10) + }, args[1]) + } + + function Page() { + const state = createQuery(key, () => 'data', { staleTime: Infinity }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + queryClient.setQueryData(key, 'data') + await sleep(50) + + // @ts-ignore + React.useEffect = originalUseEffect + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ status: 'loading' }) + expect(states[1]).toMatchObject({ status: 'success' }) + }) + + it('should batch re-renders', async () => { + const key = queryKey() + + let renders = 0 + + const queryFn = async () => { + await sleep(15) + return 'data' + } + + function Page() { + createQuery(key, queryFn) + createQuery(key, queryFn) + renders++ + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + + // Should be 2 instead of 3 + expect(renders).toBe(2) + }) + + it('should batch re-renders including hook callbacks', async () => { + const key = queryKey() + + let renders = 0 + let callbackCount = 0 + + const queryFn = async () => { + await sleep(10) + return 'data' + } + + function Page() { + const [count, setCount] = React.useState(0) + createQuery(key, queryFn, { + onSuccess: () => { + setCount((x) => x + 1) + }, + }) + createQuery(key, queryFn, { + onSuccess: () => { + setCount((x) => x + 1) + }, + }) + + React.useEffect(() => { + renders++ + callbackCount = count + }) + + return
count: {count}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('count: 2')) + + // Should be 2 / 3 instead of 5, uSES batches differently + expect(renders).toBe(process.env.REACTJS_VERSION === '17' ? 2 : 3) + + // Both callbacks should have been executed + expect(callbackCount).toBe(2) + }) + + it('should render latest data even if react has discarded certain renders', async () => { + const key = queryKey() + + function Page() { + const [, setNewState] = React.useState('state') + const state = createQuery(key, () => 'data') + React.useEffect(() => { + setActTimeout(() => { + queryClient.setQueryData(key, 'new') + // Update with same state to make react discard the next render + setNewState('state') + }, 10) + }, []) + return
{state.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('new')) + }) + + // See https://github.com/tannerlinsley/react-query/issues/170 + it('should start with status loading, fetchStatus idle if enabled is false', async () => { + const key1 = queryKey() + const key2 = queryKey() + + function Page() { + const first = createQuery(key1, () => 'data', { + enabled: false, + }) + const second = createQuery(key2, () => 'data') + + return ( +
+
+ First Status: {first.status}, {first.fetchStatus} +
+
+ Second Status: {second.status}, {second.fetchStatus} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // use "act" to wait for state update and prevent console warning + + rendered.getByText('First Status: loading, idle') + await waitFor(() => rendered.getByText('Second Status: loading, fetching')) + await waitFor(() => rendered.getByText('Second Status: success, idle')) + }) + + // See https://github.com/tannerlinsley/react-query/issues/144 + it('should be in "loading" state by default', async () => { + const key = queryKey() + + function Page() { + const { status } = createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + return
status: {status}
+ } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('status: loading') + }) + + // See https://github.com/tannerlinsley/react-query/issues/147 + it('should not pass stringified variables to query function', async () => { + const key = queryKey() + const variables = { number: 5, boolean: false, object: {}, array: [] } + type CustomQueryKey = [typeof key, typeof variables] + const states: CreateQueryResult[] = [] + + const queryFn = async (ctx: QueryFunctionContext) => { + await sleep(10) + return ctx.queryKey + } + + function Page() { + const state = createQuery([key, variables], queryFn) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + + expect(states[1]?.data).toEqual([key, variables]) + }) + + it('should not refetch query on focus when `enabled` is set to `false`', async () => { + const key = queryKey() + const queryFn = jest.fn().mockReturnValue('data') + + function Page() { + const { data = 'default' } = createQuery(key, queryFn, { + enabled: false, + }) + + return ( +
+

{data}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('default')) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + expect(queryFn).not.toHaveBeenCalled() + }) + + it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to `false`', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery(key, () => count++, { + staleTime: 0, + refetchOnWindowFocus: false, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + }) + + it('should not refetch stale query on focus when `refetchOnWindowFocus` is set to a function that returns `false`', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery(key, () => count++, { + staleTime: 0, + refetchOnWindowFocus: () => false, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + }) + + it('should not refetch fresh query on focus when `refetchOnWindowFocus` is set to `true`', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery(key, () => count++, { + staleTime: Infinity, + refetchOnWindowFocus: true, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + }) + + it('should refetch fresh query on focus when `refetchOnWindowFocus` is set to `always`', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + return count++ + }, + { + staleTime: Infinity, + refetchOnWindowFocus: 'always', + }, + ) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(20) + + await waitFor(() => expect(states.length).toBe(4)) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + expect(states[2]).toMatchObject({ data: 0, isFetching: true }) + expect(states[3]).toMatchObject({ data: 1, isFetching: false }) + }) + + it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + return count++ + }, + { + staleTime: 0, + retry: 0, + refetchOnWindowFocus: (query) => (query.state.data || 0) < 1, + }, + ) + states.push(state) + return
data: {String(state.data)}
+ } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: 0') + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) + expect(states[1]).toMatchObject({ data: 0, isFetching: false }) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await rendered.findByText('data: 1') + + // refetch should happen + expect(states.length).toBe(4) + + expect(states[2]).toMatchObject({ data: 0, isFetching: true }) + expect(states[3]).toMatchObject({ data: 1, isFetching: false }) + + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + await sleep(20) + + // no more refetch now + expect(states.length).toBe(4) + }) + + it('should refetch fresh query when refetchOnMount is set to always', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, () => 'prefetched') + + function Page() { + const state = createQuery(key, () => 'data', { + refetchOnMount: 'always', + staleTime: Infinity, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: 'prefetched', + isStale: false, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: false, + isFetching: false, + }) + }) + + it('should refetch stale query when refetchOnMount is set to true', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, () => 'prefetched') + + await sleep(10) + + function Page() { + const state = createQuery(key, () => 'data', { + refetchOnMount: true, + staleTime: 0, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: 'prefetched', + isStale: true, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: true, + isFetching: false, + }) + }) + + it('should set status to error if queryFn throws', async () => { + const key = queryKey() + + function Page() { + const { status, error } = createQuery( + key, + () => { + return Promise.reject('Error test jaylen') + }, + { retry: false }, + ) + + return ( +
+

{status}

+

{error}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('error')) + await waitFor(() => rendered.getByText('Error test jaylen')) + }) + + it('should throw error if queryFn throws and useErrorBoundary is in use', async () => { + const key = queryKey() + + function Page() { + const { status, error } = createQuery( + key, + () => Promise.reject('Error test jaylen'), + { retry: false, useErrorBoundary: true }, + ) + + return ( +
+

{status}

+

{error}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, +
error boundary
}> + +
, + ) + + await waitFor(() => rendered.getByText('error boundary')) + }) + + it('should update with data if we observe no properties and useErrorBoundary', async () => { + const key = queryKey() + + let result: CreateQueryResult | undefined + + function Page() { + const query = createQuery(key, () => Promise.resolve('data'), { + useErrorBoundary: true, + }) + + React.useEffect(() => { + result = query + }) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(result?.data).toBe('data') + }) + + it('should set status to error instead of throwing when error should not be thrown', async () => { + const key = queryKey() + + function Page() { + const { status, error } = createQuery( + key, + () => Promise.reject('Local Error'), + { + retry: false, + useErrorBoundary: (err) => err !== 'Local Error', + }, + ) + + return ( +
+

{status}

+

{error}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, +
error boundary
}> + +
, + ) + + await waitFor(() => rendered.getByText('error')) + await waitFor(() => rendered.getByText('Local Error')) + }) + + it('should throw error instead of setting status when error should be thrown', async () => { + const key = queryKey() + + function Page() { + const { status, error } = createQuery( + key, + () => Promise.reject(new Error('Remote Error')), + { + retry: false, + useErrorBoundary: (err) => err.message !== 'Local Error', + }, + ) + + return ( +
+

{status}

+

{error?.message ?? ''}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, + ( +
+
error boundary
+ {/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} +
{error?.message}
+
+ )} + > + +
, + ) + + await waitFor(() => rendered.getByText('error boundary')) + await waitFor(() => rendered.getByText('Remote Error')) + }) + + it('should continue retries when observers unmount and remount while waiting for a retry (#3031)', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const result = createQuery( + key, + async () => { + count++ + await sleep(10) + return Promise.reject('some error') + }, + { + retry: 2, + retryDelay: 100, + }, + ) + + return ( +
+
error: {result.error ?? 'null'}
+
failureCount: {result.failureCount}
+
+ ) + } + + function App() { + const [show, toggle] = React.useReducer((x) => !x, true) + + return ( +
+ + {show && } +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('failureCount: 1')) + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + await waitFor(() => rendered.getByRole('button', { name: /show/i })) + fireEvent.click(rendered.getByRole('button', { name: /show/i })) + await waitFor(() => rendered.getByText('error: some error')) + + expect(count).toBe(3) + }) + + it('should restart when observers unmount and remount while waiting for a retry when query was cancelled in between (#3031)', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const result = createQuery( + key, + async () => { + count++ + await sleep(10) + return Promise.reject('some error') + }, + { + retry: 2, + retryDelay: 100, + }, + ) + + return ( +
+
error: {result.error ?? 'null'}
+
failureCount: {result.failureCount}
+
+ ) + } + + function App() { + const [show, toggle] = React.useReducer((x) => !x, true) + + return ( +
+ + + {show && } +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('failureCount: 1')) + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + fireEvent.click(rendered.getByRole('button', { name: /cancel/i })) + await waitFor(() => rendered.getByRole('button', { name: /show/i })) + fireEvent.click(rendered.getByRole('button', { name: /show/i })) + await waitFor(() => rendered.getByText('error: some error')) + + // initial fetch (1), which will be cancelled, followed by new mount(2) + 2 retries = 4 + expect(count).toBe(4) + }) + + it('should always fetch if refetchOnMount is set to always', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + await queryClient.prefetchQuery(key, () => 'prefetched') + + function Page() { + const state = createQuery(key, () => 'data', { + refetchOnMount: 'always', + staleTime: 50, + }) + states.push(state) + return ( +
+
data: {state.data ?? 'null'}
+
isFetching: {state.isFetching}
+
isStale: {state.isStale}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data')) + await waitFor(() => expect(states.length).toBe(3)) + + expect(states[0]).toMatchObject({ + data: 'prefetched', + isStale: false, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: false, + isFetching: false, + }) + expect(states[2]).toMatchObject({ + data: 'data', + isStale: true, + isFetching: false, + }) + }) + + it('should fetch if initial data is set', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'data', { + initialData: 'initial', + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + + expect(states.length).toBe(2) + + expect(states[0]).toMatchObject({ + data: 'initial', + isStale: true, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: true, + isFetching: false, + }) + }) + + it('should not fetch if initial data is set with a stale time', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'data', { + staleTime: 50, + initialData: 'initial', + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: 'initial', + isStale: false, + isFetching: false, + }) + expect(states[1]).toMatchObject({ + data: 'initial', + isStale: true, + isFetching: false, + }) + }) + + it('should fetch if initial data updated at is older than stale time', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + const oneSecondAgo = Date.now() - 1000 + + function Page() { + const state = createQuery(key, () => 'data', { + staleTime: 50, + initialData: 'initial', + initialDataUpdatedAt: oneSecondAgo, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(3) + expect(states[0]).toMatchObject({ + data: 'initial', + isStale: true, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: false, + isFetching: false, + }) + expect(states[2]).toMatchObject({ + data: 'data', + isStale: true, + isFetching: false, + }) + }) + + it('should fetch if "initial data updated at" is exactly 0', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult[] = [] + + function Page() { + const state = createQuery(key, () => 'data', { + staleTime: 10 * 1000, // 10 seconds + initialData: 'initial', + initialDataUpdatedAt: 0, + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: 'initial', + isStale: true, + isFetching: true, + }) + expect(states[1]).toMatchObject({ + data: 'data', + isStale: false, + isFetching: false, + }) + }) + + it('should keep initial data when the query key changes', async () => { + const key = queryKey() + const states: DefinedCreateQueryResult<{ count: number }>[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + const state = createQuery([key, count], () => ({ count: 10 }), { + staleTime: Infinity, + initialData: () => ({ count }), + }) + states.push(state) + + React.useEffect(() => { + setActTimeout(() => { + setCount(1) + }, 10) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + // Initial + expect(states[0]).toMatchObject({ data: { count: 0 } }) + // Set state + expect(states[1]).toMatchObject({ data: { count: 1 } }) + }) + + it('should retry specified number of times', async () => { + const key = queryKey() + + const queryFn = jest.fn() + queryFn.mockImplementation(() => { + return Promise.reject('Error test Barrett') + }) + + function Page() { + const { status, failureCount } = createQuery(key, queryFn, { + retry: 1, + retryDelay: 1, + }) + + return ( +
+

{status}

+

Failed {failureCount} times

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('loading')) + await waitFor(() => rendered.getByText('error')) + + // query should fail `retry + 1` times, since first time isn't a "retry" + await waitFor(() => rendered.getByText('Failed 2 times')) + + expect(queryFn).toHaveBeenCalledTimes(2) + }) + + it('should not retry if retry function `false`', async () => { + const key = queryKey() + + const queryFn = jest.fn() + + queryFn.mockImplementationOnce(() => { + return Promise.reject('Error test Tanner') + }) + + queryFn.mockImplementation(() => { + return Promise.reject('NoRetry') + }) + + function Page() { + const { status, failureCount, error } = createQuery< + unknown, + string, + [string] + >(key, queryFn, { + retryDelay: 1, + retry: (_failureCount, err) => err !== 'NoRetry', + }) + + return ( +
+

{status}

+

Failed {failureCount} times

+

{error}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('loading')) + await waitFor(() => rendered.getByText('error')) + + await waitFor(() => rendered.getByText('Failed 2 times')) + await waitFor(() => rendered.getByText('NoRetry')) + + expect(queryFn).toHaveBeenCalledTimes(2) + }) + + it('should extract retryDelay from error', async () => { + const key = queryKey() + + type DelayError = { delay: number } + + const queryFn = jest.fn() + queryFn.mockImplementation(() => { + return Promise.reject({ delay: 50 }) + }) + + function Page() { + const { status, failureCount } = createQuery(key, queryFn, { + retry: 1, + retryDelay: (_, error: DelayError) => error.delay, + }) + + return ( +
+

{status}

+

Failed {failureCount} times

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await sleep(10) + + expect(queryFn).toHaveBeenCalledTimes(1) + + await waitFor(() => rendered.getByText('Failed 2 times')) + + expect(queryFn).toHaveBeenCalledTimes(2) + }) + + // See https://github.com/tannerlinsley/react-query/issues/160 + it('should continue retry after focus regain', async () => { + const key = queryKey() + + // make page unfocused + const visibilityMock = mockVisibilityState('hidden') + + let count = 0 + + function Page() { + const query = createQuery( + key, + () => { + count++ + return Promise.reject(`fetching error ${count}`) + }, + { + retry: 3, + retryDelay: 1, + }, + ) + + return ( +
+
error {String(query.error)}
+
status {query.status}
+
failureCount {query.failureCount}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // The query should display the first error result + await waitFor(() => rendered.getByText('failureCount 1')) + await waitFor(() => rendered.getByText('status loading')) + await waitFor(() => rendered.getByText('error null')) + + // Check if the query really paused + await sleep(10) + await waitFor(() => rendered.getByText('failureCount 1')) + + act(() => { + // reset visibilityState to original value + visibilityMock.mockRestore() + window.dispatchEvent(new FocusEvent('focus')) + }) + + // Wait for the final result + await waitFor(() => rendered.getByText('failureCount 4')) + await waitFor(() => rendered.getByText('status error')) + await waitFor(() => rendered.getByText('error fetching error 4')) + + // Check if the query really stopped + await sleep(10) + await waitFor(() => rendered.getByText('failureCount 4')) + + // Check if the error has been logged in the console + expect(mockLogger.error).toHaveBeenCalledWith('fetching error 4') + }) + + it('should fetch on mount when a query was already created with setQueryData', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + queryClient.setQueryData(key, 'prefetched') + + function Page() { + const state = createQuery(key, () => 'data') + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states).toMatchObject([ + { + data: 'prefetched', + isFetching: true, + isStale: true, + }, + { + data: 'data', + isFetching: false, + isStale: true, + }, + ]) + }) + + it('should refetch after focus regain', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + // make page unfocused + const visibilityMock = mockVisibilityState('hidden') + + // set data in cache to check if the hook query fn is actually called + queryClient.setQueryData(key, 'prefetched') + + function Page() { + const state = createQuery(key, async () => { + await sleep(10) + return 'data' + }) + states.push(state) + return ( +
+ {state.data}, {state.isStale}, {state.isFetching} +
+ ) + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(states.length).toBe(2)) + + act(() => { + // reset visibilityState to original value + visibilityMock.mockRestore() + window.dispatchEvent(new FocusEvent('focus')) + }) + + await waitFor(() => expect(states.length).toBe(4)) + + expect(states).toMatchObject([ + { + data: 'prefetched', + isFetching: true, + isStale: true, + }, + { + data: 'data', + isFetching: false, + isStale: true, + }, + { + data: 'data', + isFetching: true, + isStale: true, + }, + { + data: 'data', + isFetching: false, + isStale: true, + }, + ]) + }) + + // See https://github.com/tannerlinsley/react-query/issues/195 + it('should refetch if stale after a prefetch', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + const queryFn = jest.fn() + queryFn.mockImplementation(() => 'data') + + const prefetchQueryFn = jest.fn() + prefetchQueryFn.mockImplementation(() => 'not yet...') + + await queryClient.prefetchQuery(key, prefetchQueryFn, { + staleTime: 10, + }) + + await sleep(11) + + function Page() { + const state = createQuery(key, queryFn) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(states.length).toBe(2)) + + expect(prefetchQueryFn).toHaveBeenCalledTimes(1) + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should not refetch if not stale after a prefetch', async () => { + const key = queryKey() + + const queryFn = jest.fn() + queryFn.mockImplementation(() => 'data') + + const prefetchQueryFn = jest.fn, unknown[]>() + prefetchQueryFn.mockImplementation(async () => { + await sleep(10) + return 'not yet...' + }) + + await queryClient.prefetchQuery(key, prefetchQueryFn, { + staleTime: 1000, + }) + + await sleep(0) + + function Page() { + createQuery(key, queryFn, { + staleTime: 1000, + }) + return null + } + + renderWithClient(queryClient, ) + + await sleep(0) + + expect(prefetchQueryFn).toHaveBeenCalledTimes(1) + expect(queryFn).toHaveBeenCalledTimes(0) + }) + + // See https://github.com/tannerlinsley/react-query/issues/190 + it('should reset failureCount on successful fetch', async () => { + const key = queryKey() + + function Page() { + let counter = 0 + + const query = createQuery( + key, + async () => { + if (counter < 2) { + counter++ + throw new Error('error') + } else { + return 'data' + } + }, + { retryDelay: 10 }, + ) + + return ( +
+
failureCount {query.failureCount}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('failureCount 2')) + await waitFor(() => rendered.getByText('failureCount 0')) + }) + + // See https://github.com/tannerlinsley/react-query/issues/199 + it('should use prefetched data for dependent query', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const [enabled, setEnabled] = React.useState(false) + const [isPrefetched, setPrefetched] = React.useState(false) + + const query = createQuery( + key, + async () => { + count++ + await sleep(10) + return count + }, + { + enabled, + }, + ) + + React.useEffect(() => { + async function prefetch() { + await queryClient.prefetchQuery(key, () => + Promise.resolve('prefetched data'), + ) + act(() => setPrefetched(true)) + } + prefetch() + }, []) + + return ( +
+ {isPrefetched &&
isPrefetched
} + +
data: {query.data}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('isPrefetched')) + + fireEvent.click(rendered.getByText('setKey')) + await waitFor(() => rendered.getByText('data: prefetched data')) + await waitFor(() => rendered.getByText('data: 1')) + expect(count).toBe(1) + }) + + it('should support dependent queries via the enable config option', async () => { + const key = queryKey() + + function Page() { + const [shouldFetch, setShouldFetch] = React.useState(false) + + const query = createQuery(key, () => 'data', { + enabled: shouldFetch, + }) + + return ( +
+
FetchStatus: {query.fetchStatus}
+

Data: {query.data || 'no data'}

+ {query.isStale ? ( + + ) : null} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('FetchStatus: idle') + rendered.getByText('Data: no data') + + fireEvent.click(rendered.getByText('fetch')) + + await waitFor(() => rendered.getByText('FetchStatus: fetching')) + await waitFor(() => [ + rendered.getByText('FetchStatus: idle'), + rendered.getByText('Data: data'), + ]) + }) + + it('should mark query as fetching, when using initialData', async () => { + const key = queryKey() + const results: DefinedCreateQueryResult[] = [] + + function Page() { + const result = createQuery(key, () => 'serverData', { + initialData: 'data', + }) + results.push(result) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(results.length).toBe(2) + expect(results[0]).toMatchObject({ data: 'data', isFetching: true }) + expect(results[1]).toMatchObject({ data: 'serverData', isFetching: false }) + }) + + it('should initialize state properly, when initialData is falsy', async () => { + const key = queryKey() + const results: DefinedCreateQueryResult[] = [] + + function Page() { + const result = createQuery(key, () => 1, { initialData: 0 }) + results.push(result) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(results.length).toBe(2) + expect(results[0]).toMatchObject({ data: 0, isFetching: true }) + expect(results[1]).toMatchObject({ data: 1, isFetching: false }) + }) + + // // See https://github.com/tannerlinsley/react-query/issues/214 + it('data should persist when enabled is changed to false', async () => { + const key = queryKey() + const results: DefinedCreateQueryResult[] = [] + + function Page() { + const [shouldFetch, setShouldFetch] = React.useState(true) + + const result = createQuery(key, () => 'fetched data', { + enabled: shouldFetch, + initialData: shouldFetch ? 'initial' : 'initial falsy', + }) + + results.push(result) + + React.useEffect(() => { + setActTimeout(() => { + setShouldFetch(false) + }, 5) + }, []) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + expect(results.length).toBe(3) + expect(results[0]).toMatchObject({ data: 'initial', isStale: true }) + expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true }) + expect(results[2]).toMatchObject({ data: 'fetched data', isStale: true }) + }) + + it('it should support enabled:false in query object syntax', async () => { + const key = queryKey() + const queryFn = jest.fn() + queryFn.mockImplementation(() => 'data') + + function Page() { + const { fetchStatus } = createQuery({ + queryKey: key, + queryFn, + enabled: false, + }) + return
fetchStatus: {fetchStatus}
+ } + + const rendered = renderWithClient(queryClient, ) + + expect(queryFn).not.toHaveBeenCalled() + expect(queryCache.find(key)).not.toBeUndefined() + rendered.getByText('fetchStatus: idle') + }) + + // See https://github.com/tannerlinsley/react-query/issues/360 + test('should init to status:loading, fetchStatus:idle when enabled is false', async () => { + const key = queryKey() + + function Page() { + const query = createQuery(key, () => 'data', { + enabled: false, + }) + + return ( +
+
+ status: {query.status}, {query.fetchStatus} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('status: loading, idle')) + }) + + test('should not schedule garbage collection, if cacheTimeout is set to `Infinity`', async () => { + const key = queryKey() + + function Page() { + const query = createQuery(key, () => 'fetched data', { + cacheTime: Infinity, + }) + return
{query.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('fetched data')) + + rendered.unmount() + + const query = queryCache.find(key) + // @ts-expect-error + expect(query!.cacheTimeout).toBe(undefined) + }) + + it('should not cause memo churn when data does not change', async () => { + const key = queryKey() + const queryFn = jest.fn().mockReturnValue('data') + const memoFn = jest.fn() + + function Page() { + const result = createQuery(key, async () => { + await sleep(10) + return ( + queryFn() || { + data: { + nested: true, + }, + } + ) + }) + + React.useMemo(() => { + memoFn() + return result.data + }, [result.data]) + + return ( +
+
status {result.status}
+
isFetching {result.isFetching ? 'true' : 'false'}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('status loading')) + await waitFor(() => rendered.getByText('status success')) + fireEvent.click(rendered.getByText('refetch')) + await waitFor(() => rendered.getByText('isFetching true')) + await waitFor(() => rendered.getByText('isFetching false')) + expect(queryFn).toHaveBeenCalledTimes(2) + expect(memoFn).toHaveBeenCalledTimes(2) + }) + + it('should update data upon interval changes', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const [int, setInt] = React.useState(200) + const { data } = createQuery(key, () => count++, { + refetchInterval: int, + }) + + React.useEffect(() => { + if (data === 2) { + setInt(0) + } + }, [data]) + + return
count: {data}
+ } + + const rendered = renderWithClient(queryClient, ) + + // mount + await waitFor(() => rendered.getByText('count: 0')) + await waitFor(() => rendered.getByText('count: 1')) + await waitFor(() => rendered.getByText('count: 2')) + }) + + it('should refetch in an interval depending on function result', async () => { + const key = queryKey() + let count = 0 + const states: CreateQueryResult[] = [] + + function Page() { + const queryInfo = createQuery( + key, + async () => { + await sleep(10) + return count++ + }, + { + refetchInterval: (data = 0) => (data < 2 ? 10 : false), + }, + ) + + states.push(queryInfo) + + return ( +
+

count: {queryInfo.data}

+

status: {queryInfo.status}

+

data: {queryInfo.data}

+

refetch: {queryInfo.isRefetching}

+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('count: 2')) + + expect(states.length).toEqual(6) + + expect(states).toMatchObject([ + { + status: 'loading', + isFetching: true, + data: undefined, + }, + { + status: 'success', + isFetching: false, + data: 0, + }, + { + status: 'success', + isFetching: true, + data: 0, + }, + { + status: 'success', + isFetching: false, + data: 1, + }, + { + status: 'success', + isFetching: true, + data: 1, + }, + { + status: 'success', + isFetching: false, + data: 2, + }, + ]) + }) + + it('should not interval fetch with a refetchInterval of 0', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + function Page() { + const queryInfo = createQuery(key, () => 1, { + refetchInterval: 0, + }) + + states.push(queryInfo) + + return
count: {queryInfo.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('count: 1')) + + await sleep(10) //extra sleep to make sure we're not re-fetching + + expect(states.length).toEqual(2) + + expect(states).toMatchObject([ + { + status: 'loading', + isFetching: true, + data: undefined, + }, + { + status: 'success', + isFetching: false, + data: 1, + }, + ]) + }) + + it('should accept an empty string as query key', async () => { + function Page() { + const result = createQuery([''], (ctx) => ctx.queryKey) + return <>{JSON.stringify(result.data)} + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('')) + }) + + it('should accept an object as query key', async () => { + function Page() { + const result = createQuery([{ a: 'a' }], (ctx) => ctx.queryKey) + return <>{JSON.stringify(result.data)} + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('[{"a":"a"}]')) + }) + + it('should refetch if any query instance becomes enabled', async () => { + const key = queryKey() + + const queryFn = jest.fn().mockReturnValue('data') + + function Disabled() { + createQuery(key, queryFn, { enabled: false }) + return null + } + + function Page() { + const [enabled, setEnabled] = React.useState(false) + const result = createQuery(key, queryFn, { enabled }) + return ( + <> + +
{result.data}
+ + + ) + } + + const rendered = renderWithClient(queryClient, ) + expect(queryFn).toHaveBeenCalledTimes(0) + fireEvent.click(rendered.getByText('enable')) + await waitFor(() => rendered.getByText('data')) + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should use placeholder data while the query loads', async () => { + const key1 = queryKey() + + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key1, () => 'data', { + placeholderData: 'placeholder', + }) + + states.push(state) + + return ( +
+

Data: {state.data}

+
Status: {state.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: data')) + + expect(states).toMatchObject([ + { + isSuccess: true, + isPlaceholderData: true, + data: 'placeholder', + }, + { + isSuccess: true, + isPlaceholderData: false, + data: 'data', + }, + ]) + }) + + it('should use placeholder data even for disabled queries', async () => { + const key1 = queryKey() + + const states: { state: CreateQueryResult; count: number }[] = [] + + function Page() { + const [count, setCount] = React.useState(0) + + const state = createQuery(key1, () => 'data', { + placeholderData: 'placeholder', + enabled: count === 0, + }) + + states.push({ state, count }) + + React.useEffect(() => { + setCount(1) + }, []) + + return ( +
+

Data: {state.data}

+
Status: {state.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: data')) + + expect(states).toMatchObject([ + { + state: { + isSuccess: true, + isPlaceholderData: true, + data: 'placeholder', + }, + count: 0, + }, + { + state: { + isSuccess: true, + isPlaceholderData: true, + data: 'placeholder', + }, + count: 1, + }, + { + state: { + isSuccess: true, + isPlaceholderData: false, + data: 'data', + }, + count: 1, + }, + ]) + }) + + it('placeholder data should run through select', async () => { + const key1 = queryKey() + + const states: CreateQueryResult[] = [] + + function Page() { + const state = createQuery(key1, () => 1, { + placeholderData: 23, + select: (data) => String(data * 2), + }) + + states.push(state) + + return ( +
+

Data: {state.data}

+
Status: {state.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: 2')) + + expect(states).toMatchObject([ + { + isSuccess: true, + isPlaceholderData: true, + data: '46', + }, + { + isSuccess: true, + isPlaceholderData: false, + data: '2', + }, + ]) + }) + + it('placeholder data function result should run through select', async () => { + const key1 = queryKey() + + const states: CreateQueryResult[] = [] + let placeholderFunctionRunCount = 0 + + function Page() { + const state = createQuery(key1, () => 1, { + placeholderData: () => { + placeholderFunctionRunCount++ + return 23 + }, + select: (data) => String(data * 2), + }) + + states.push(state) + + return ( +
+

Data: {state.data}

+
Status: {state.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: 2')) + + rendered.rerender() + + expect(states).toMatchObject([ + { + isSuccess: true, + isPlaceholderData: true, + data: '46', + }, + { + isSuccess: true, + isPlaceholderData: false, + data: '2', + }, + { + isSuccess: true, + isPlaceholderData: false, + data: '2', + }, + ]) + + expect(placeholderFunctionRunCount).toEqual(1) + }) + + it('select should only run when dependencies change if memoized', async () => { + const key1 = queryKey() + + let selectRun = 0 + + function Page() { + const [count, inc] = React.useReducer((prev) => prev + 1, 2) + + const state = createQuery( + key1, + async () => { + await sleep(10) + return 0 + }, + { + select: React.useCallback( + (data: number) => { + selectRun++ + return `selected ${data + count}` + }, + [count], + ), + placeholderData: 99, + }, + ) + + return ( +
+

Data: {state.data}

+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: selected 101')) // 99 + 2 + expect(selectRun).toBe(1) + + await waitFor(() => rendered.getByText('Data: selected 2')) // 0 + 2 + expect(selectRun).toBe(2) + + fireEvent.click(rendered.getByRole('button', { name: /inc/i })) + + await waitFor(() => rendered.getByText('Data: selected 3')) // 0 + 3 + expect(selectRun).toBe(3) + }) + + it('select should always return the correct state', async () => { + const key1 = queryKey() + + function Page() { + const [count, inc] = React.useReducer((prev) => prev + 1, 2) + const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1) + + const state = createQuery( + key1, + async () => { + await sleep(10) + return 0 + }, + { + select: React.useCallback( + (data: number) => { + return `selected ${data + count}` + }, + [count], + ), + placeholderData: 99, + }, + ) + + return ( +
+

Data: {state.data}

+

forceValue: {forceValue}

+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: selected 101')) // 99 + 2 + + await waitFor(() => rendered.getByText('Data: selected 2')) // 0 + 2 + + fireEvent.click(rendered.getByRole('button', { name: /inc/i })) + + await waitFor(() => rendered.getByText('Data: selected 3')) // 0 + 3 + + fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i })) + + await waitFor(() => rendered.getByText('forceValue: 2')) + // data should still be 3 after an independent re-render + await waitFor(() => rendered.getByText('Data: selected 3')) + }) + + it('select should structurally share data', async () => { + const key1 = queryKey() + const states: Array> = [] + + function Page() { + const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1) + + const state = createQuery( + key1, + async () => { + await sleep(10) + return [1, 2] + }, + { + select: (res) => res.map((x) => x + 1), + }, + ) + + React.useEffect(() => { + if (state.data) { + states.push(state.data) + } + }, [state.data]) + + return ( +
+

Data: {JSON.stringify(state.data)}

+

forceValue: {forceValue}

+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('Data: [2,3]')) + expect(states).toHaveLength(1) + + fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i })) + + await waitFor(() => rendered.getByText('forceValue: 2')) + await waitFor(() => rendered.getByText('Data: [2,3]')) + + // effect should not be triggered again due to structural sharing + expect(states).toHaveLength(1) + }) + + it('should cancel the query function when there are no more subscriptions', async () => { + const key = queryKey() + let cancelFn: jest.Mock = jest.fn() + + const queryFn = ({ signal }: { signal?: AbortSignal }) => { + const promise = new Promise((resolve, reject) => { + cancelFn = jest.fn(() => reject('Cancelled')) + signal?.addEventListener('abort', cancelFn) + sleep(10).then(() => resolve('OK')) + }) + + return promise + } + + function Page() { + const state = createQuery(key, queryFn) + return ( +
+

Status: {state.status}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, + + + , + ) + + await waitFor(() => rendered.getByText('off')) + + if (typeof AbortSignal === 'function') { + expect(cancelFn).toHaveBeenCalled() + } + }) + + it('should cancel the query if the signal was consumed and there are no more subscriptions', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + const queryFn: QueryFunction = async ( + ctx, + ) => { + const [, limit] = ctx.queryKey + const value = limit % 2 && ctx.signal ? 'abort' : `data ${limit}` + await sleep(25) + return value + } + + function Page(props: { limit: number }) { + const state = createQuery([key, props.limit], queryFn) + states[props.limit] = state + return ( +
+

Status: {state.status}

+

data: {state.data}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, + + + + + + , + ) + + await waitFor(() => rendered.getByText('off')) + await sleep(20) + + await waitFor(() => expect(states).toHaveLength(4)) + + expect(queryCache.find([key, 0])?.state).toMatchObject({ + data: 'data 0', + status: 'success', + dataUpdateCount: 1, + }) + + if (typeof AbortSignal === 'function') { + expect(queryCache.find([key, 1])?.state).toMatchObject({ + data: undefined, + status: 'loading', + fetchStatus: 'idle', + }) + } else { + expect(queryCache.find([key, 1])?.state).toMatchObject({ + data: 'data 1', + status: 'success', + dataUpdateCount: 1, + }) + } + + expect(queryCache.find([key, 2])?.state).toMatchObject({ + data: 'data 2', + status: 'success', + dataUpdateCount: 1, + }) + + if (typeof AbortSignal === 'function') { + expect(queryCache.find([key, 3])?.state).toMatchObject({ + data: undefined, + status: 'loading', + fetchStatus: 'idle', + }) + } else { + expect(queryCache.find([key, 3])?.state).toMatchObject({ + data: 'data 3', + status: 'success', + dataUpdateCount: 1, + }) + } + }) + + it('should refetch when quickly switching to a failed query', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + const queryFn = async () => { + await sleep(50) + return 'OK' + } + + function Page() { + const [id, setId] = React.useState(1) + const [hasChanged, setHasChanged] = React.useState(false) + + const state = createQuery([key, id], queryFn) + + states.push(state) + + React.useEffect(() => { + setId((prevId) => (prevId === 1 ? 2 : 1)) + setHasChanged(true) + }, [hasChanged]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + expect(states.length).toBe(4) + // Load query 1 + expect(states[0]).toMatchObject({ + status: 'loading', + error: null, + }) + // Load query 2 + expect(states[1]).toMatchObject({ + status: 'loading', + error: null, + }) + // Load query 1 + expect(states[2]).toMatchObject({ + status: 'loading', + error: null, + }) + // Loaded query 1 + expect(states[3]).toMatchObject({ + status: 'success', + error: null, + }) + }) + + it('should update query state and refetch when reset with resetQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { staleTime: Infinity }, + ) + + states.push(state) + + return ( +
+ +
data: {state.data ?? 'null'}
+
isFetching: {state.isFetching}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /reset/i })) + + await waitFor(() => expect(states.length).toBe(4)) + + await waitFor(() => rendered.getByText('data: 2')) + + expect(count).toBe(2) + + expect(states[0]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: true, + isSuccess: false, + isStale: true, + }) + expect(states[1]).toMatchObject({ + data: 1, + isLoading: false, + isFetching: false, + isSuccess: true, + isStale: false, + }) + expect(states[2]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: true, + isSuccess: false, + isStale: true, + }) + expect(states[3]).toMatchObject({ + data: 2, + isLoading: false, + isFetching: false, + isSuccess: true, + isStale: false, + }) + }) + + it('should update query state and not refetch when resetting a disabled query with resetQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + count++ + return count + }, + { staleTime: Infinity, enabled: false, notifyOnChangeProps: 'all' }, + ) + + states.push(state) + + const { refetch } = state + + return ( +
+ + +
data: {state.data ?? 'null'}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: null')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(rendered.getByRole('button', { name: /reset/i })) + + await waitFor(() => rendered.getByText('data: null')) + await waitFor(() => expect(states.length).toBe(4)) + + expect(count).toBe(1) + + expect(states[0]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: false, + isSuccess: false, + isStale: true, + }) + expect(states[1]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: true, + isSuccess: false, + isStale: true, + }) + expect(states[2]).toMatchObject({ + data: 1, + isLoading: false, + isFetching: false, + isSuccess: true, + isStale: false, + }) + expect(states[3]).toMatchObject({ + data: undefined, + isLoading: true, + isFetching: false, + isSuccess: false, + isStale: true, + }) + }) + + it('should only call the query hash function once each render', async () => { + const key = queryKey() + + let hashes = 0 + let renders = 0 + + function queryKeyHashFn(x: any) { + hashes++ + return JSON.stringify(x) + } + + function Page() { + React.useEffect(() => { + renders++ + }) + + createQuery(key, () => 'test', { queryKeyHashFn }) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(renders).toBe(2) + expect(hashes).toBe(2) + }) + + it('should refetch when changed enabled to true in error state', async () => { + const queryFn = jest.fn() + queryFn.mockImplementation(async () => { + await sleep(10) + return Promise.reject(new Error('Suspense Error Bingo')) + }) + + function Page({ enabled }: { enabled: boolean }) { + const { error, isLoading } = createQuery(['key'], queryFn, { + enabled, + retry: false, + retryOnMount: false, + refetchOnMount: false, + refetchOnWindowFocus: false, + }) + + if (isLoading) { + return
status: loading
+ } + if (error instanceof Error) { + return
error
+ } + return
rendered
+ } + + function App() { + const [enabled, toggle] = React.useReducer((x) => !x, true) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // initial state check + rendered.getByText('status: loading') + + // // render error state component + await waitFor(() => rendered.getByText('error')) + expect(queryFn).toBeCalledTimes(1) + + // change to enabled to false + fireEvent.click(rendered.getByLabelText('retry')) + await waitFor(() => rendered.getByText('error')) + expect(queryFn).toBeCalledTimes(1) + + // // change to enabled to true + fireEvent.click(rendered.getByLabelText('retry')) + expect(queryFn).toBeCalledTimes(2) + }) + + it('should refetch when query key changed when previous status is error', async () => { + function Page({ id }: { id: number }) { + const { error, isLoading } = createQuery( + [id], + async () => { + await sleep(10) + if (id % 2 === 1) { + return Promise.reject(new Error('Error')) + } else { + return 'data' + } + }, + { + retry: false, + retryOnMount: false, + refetchOnMount: false, + refetchOnWindowFocus: false, + }, + ) + + if (isLoading) { + return
status: loading
+ } + if (error instanceof Error) { + return
error
+ } + return
rendered
+ } + + function App() { + const [id, changeId] = React.useReducer((x) => x + 1, 1) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // initial state check + rendered.getByText('status: loading') + + // render error state component + await waitFor(() => rendered.getByText('error')) + + // change to unmount query + fireEvent.click(rendered.getByLabelText('change')) + await waitFor(() => rendered.getByText('rendered')) + + // change to mount new query + fireEvent.click(rendered.getByLabelText('change')) + await waitFor(() => rendered.getByText('error')) + }) + + it('should refetch when query key changed when switching between erroneous queries', async () => { + function Page({ id }: { id: boolean }) { + const { error, isFetching } = createQuery( + [id], + async () => { + await sleep(10) + return Promise.reject(new Error('Error')) + }, + { + retry: false, + retryOnMount: false, + refetchOnMount: false, + refetchOnWindowFocus: false, + }, + ) + + if (isFetching) { + return
status: fetching
+ } + if (error instanceof Error) { + return
error
+ } + return
rendered
+ } + + function App() { + const [value, toggle] = React.useReducer((x) => !x, true) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + // initial state check + rendered.getByText('status: fetching') + + // render error state component + await waitFor(() => rendered.getByText('error')) + + // change to mount second query + fireEvent.click(rendered.getByLabelText('change')) + await waitFor(() => rendered.getByText('status: fetching')) + await waitFor(() => rendered.getByText('error')) + + // change to mount first query again + fireEvent.click(rendered.getByLabelText('change')) + await waitFor(() => rendered.getByText('status: fetching')) + await waitFor(() => rendered.getByText('error')) + }) + + it('should have no error in loading state when refetching after error occurred', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const error = new Error('oops') + + let count = 0 + + function Page() { + const state = createQuery( + key, + async () => { + await sleep(10) + if (count === 0) { + count++ + throw error + } + return 5 + }, + { + retry: false, + }, + ) + + states.push(state) + + if (state.isLoading) { + return
status: loading
+ } + if (state.error instanceof Error) { + return ( +
+
error
+ +
+ ) + } + return
data: {state.data}
+ } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('error')) + + fireEvent.click(rendered.getByRole('button', { name: 'refetch' })) + await waitFor(() => rendered.getByText('data: 5')) + + await waitFor(() => expect(states.length).toBe(4)) + + expect(states[0]).toMatchObject({ + status: 'loading', + data: undefined, + error: null, + }) + + expect(states[1]).toMatchObject({ + status: 'error', + data: undefined, + error, + }) + + expect(states[2]).toMatchObject({ + status: 'loading', + data: undefined, + error: null, + }) + + expect(states[3]).toMatchObject({ + status: 'success', + data: 5, + error: null, + }) + }) + + describe('networkMode online', () => { + it('online queries should not start fetching if you are offline', async () => { + const onlineMock = mockNavigatorOnLine(false) + + const key = queryKey() + const states: Array = [] + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + await sleep(10) + return 'data' + }, + }) + + React.useEffect(() => { + states.push(state.fetchStatus) + }) + + return ( +
+
+ status: {state.status}, isPaused: {String(state.isPaused)} +
+
data: {state.data}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('status: loading, isPaused: true')) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await waitFor(() => + rendered.getByText('status: success, isPaused: false'), + ) + await waitFor(() => { + expect(rendered.getByText('data: data')).toBeInTheDocument() + }) + + expect(states).toEqual(['paused', 'fetching', 'idle']) + + onlineMock.mockRestore() + }) + + it('online queries should not refetch if you are offline', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus}, + failureCount: {state.failureCount} +
+
data: {state.data}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data1')) + + const onlineMock = mockNavigatorOnLine(false) + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await waitFor(() => + rendered.getByText( + 'status: success, fetchStatus: paused, failureCount: 0', + ), + ) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await waitFor(() => + rendered.getByText( + 'status: success, fetchStatus: fetching, failureCount: 0', + ), + ) + await waitFor(() => + rendered.getByText( + 'status: success, fetchStatus: idle, failureCount: 0', + ), + ) + + await waitFor(() => { + expect(rendered.getByText('data: data2')).toBeInTheDocument() + }) + + onlineMock.mockRestore() + }) + + it('online queries should not refetch if you are offline and refocus', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data1')) + + const onlineMock = mockNavigatorOnLine(false) + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + + window.dispatchEvent(new FocusEvent('focus')) + await sleep(15) + + await waitFor(() => + expect(rendered.queryByText('data: data2')).not.toBeInTheDocument(), + ) + expect(count).toBe(1) + onlineMock.mockRestore() + }) + + it('online queries should not refetch while already paused', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+ +
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: paused'), + ) + + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await sleep(15) + + // invalidation should not trigger a refetch + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: paused'), + ) + + expect(count).toBe(0) + onlineMock.mockRestore() + }) + + it('online queries should not refetch while already paused if data is in the cache', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + initialData: 'initial', + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+ +
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + await waitFor(() => { + expect(rendered.getByText('data: initial')).toBeInTheDocument() + }) + + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await sleep(15) + + // invalidation should not trigger a refetch + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + + expect(count).toBe(0) + onlineMock.mockRestore() + }) + + it('online queries should not get stuck in fetching state when pausing multiple times', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + initialData: 'initial', + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+ +
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + await waitFor(() => { + expect(rendered.getByText('data: initial')).toBeInTheDocument() + }) + + // triggers one pause + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await sleep(15) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + + // triggers a second pause + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + + onlineMock.mockReturnValue(true) + act(() => { + window.dispatchEvent(new Event('online')) + }) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: idle'), + ) + await waitFor(() => { + expect(rendered.getByText('data: data1')).toBeInTheDocument() + }) + + expect(count).toBe(1) + onlineMock.mockRestore() + }) + + it('online queries should pause retries if you are offline', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async (): Promise => { + count++ + await sleep(10) + throw new Error('failed' + count) + }, + retry: 2, + retryDelay: 10, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus}, + failureCount: {state.failureCount} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText( + 'status: loading, fetchStatus: fetching, failureCount: 1', + ), + ) + + const onlineMock = mockNavigatorOnLine(false) + + await sleep(20) + + await waitFor(() => + rendered.getByText( + 'status: loading, fetchStatus: paused, failureCount: 1', + ), + ) + + expect(count).toBe(1) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await waitFor(() => + rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), + ) + + expect(count).toBe(3) + + onlineMock.mockRestore() + }) + + it('online queries should fetch if paused and we go online even if already unmounted (because not cancelled)', async () => { + const key = queryKey() + let count = 0 + + function Component() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+
+ ) + } + + function Page() { + const [show, setShow] = React.useState(true) + + return ( +
+ {show && } + +
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: paused'), + ) + + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(15) + + expect(queryClient.getQueryState(key)).toMatchObject({ + fetchStatus: 'idle', + status: 'success', + }) + + expect(count).toBe(1) + + onlineMock.mockRestore() + }) + + it('online queries should not fetch if paused and we go online when cancelled and no refetchOnReconnect', async () => { + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data' + count + }, + refetchOnReconnect: false, + }) + + return ( +
+ +
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+
+ ) + } + + const onlineMock = mockNavigatorOnLine(false) + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: paused'), + ) + + fireEvent.click(rendered.getByRole('button', { name: /cancel/i })) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: idle'), + ) + + expect(count).toBe(0) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(15) + + await waitFor(() => + rendered.getByText('status: loading, fetchStatus: idle'), + ) + + expect(count).toBe(0) + + onlineMock.mockRestore() + }) + + it('online queries should not fetch if paused and we go online if already unmounted when signal consumed', async () => { + const key = queryKey() + let count = 0 + + function Component() { + const state = createQuery({ + queryKey: key, + queryFn: async ({ signal }) => { + count++ + await sleep(10) + return `${signal ? 'signal' : 'data'}${count}` + }, + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus} +
+
data: {state.data}
+
+ ) + } + + function Page() { + const [show, setShow] = React.useState(true) + + return ( +
+ {show && } + + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: idle'), + ) + + const onlineMock = mockNavigatorOnLine(false) + + fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + + await waitFor(() => + rendered.getByText('status: success, fetchStatus: paused'), + ) + + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + + await sleep(15) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(15) + + expect(queryClient.getQueryState(key)).toMatchObject({ + fetchStatus: 'idle', + status: 'success', + }) + + expect(count).toBe(typeof AbortSignal === 'function' ? 1 : 2) + + onlineMock.mockRestore() + }) + }) + + describe('networkMode always', () => { + it('always queries should start fetching even if you are offline', async () => { + const onlineMock = mockNavigatorOnLine(false) + + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async () => { + count++ + await sleep(10) + return 'data ' + count + }, + networkMode: 'always', + }) + + return ( +
+
+ status: {state.status}, isPaused: {String(state.isPaused)} +
+
data: {state.data}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText('status: success, isPaused: false'), + ) + + await waitFor(() => { + expect(rendered.getByText('data: data 1')).toBeInTheDocument() + }) + + onlineMock.mockRestore() + }) + + it('always queries should not pause retries', async () => { + const onlineMock = mockNavigatorOnLine(false) + + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async (): Promise => { + count++ + await sleep(10) + throw new Error('error ' + count) + }, + networkMode: 'always', + retry: 1, + retryDelay: 5, + }) + + return ( +
+
+ status: {state.status}, isPaused: {String(state.isPaused)} +
+
+ error: {state.error instanceof Error && state.error.message} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('status: error, isPaused: false')) + + await waitFor(() => { + expect(rendered.getByText('error: error 2')).toBeInTheDocument() + }) + + expect(count).toBe(2) + + onlineMock.mockRestore() + }) + }) + + describe('networkMode offlineFirst', () => { + it('offlineFirst queries should start fetching if you are offline, but pause retries', async () => { + const onlineMock = mockNavigatorOnLine(false) + + const key = queryKey() + let count = 0 + + function Page() { + const state = createQuery({ + queryKey: key, + queryFn: async (): Promise => { + count++ + await sleep(10) + throw new Error('failed' + count) + }, + retry: 2, + retryDelay: 1, + networkMode: 'offlineFirst', + }) + + return ( +
+
+ status: {state.status}, fetchStatus: {state.fetchStatus}, + failureCount: {state.failureCount} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => + rendered.getByText( + 'status: loading, fetchStatus: paused, failureCount: 1', + ), + ) + + expect(count).toBe(1) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await waitFor(() => + rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), + ) + + expect(count).toBe(3) + + onlineMock.mockRestore() + }) + }) + + it('it should have status=error on mount when a query has failed', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + const error = new Error('oops') + + const queryFn = async (): Promise => { + throw error + } + + function Page() { + const state = createQuery(key, queryFn, { + retry: false, + retryOnMount: false, + }) + + states.push(state) + + return <> + } + + await queryClient.prefetchQuery(key, queryFn) + renderWithClient(queryClient, ) + + await waitFor(() => expect(states).toHaveLength(1)) + + expect(states[0]).toMatchObject({ + status: 'error', + error, + }) + }) + + it('setQueryData - should not call onSuccess callback of active observers', async () => { + const key = queryKey() + const onSuccess = jest.fn() + + function Page() { + const state = createQuery(key, () => 'data', { onSuccess }) + return ( +
+
data: {state.data}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data')) + fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i })) + await waitFor(() => rendered.getByText('data: newData')) + + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(onSuccess).toHaveBeenCalledWith('data') + }) + + it('setQueryData - should respect updatedAt', async () => { + const key = queryKey() + + function Page() { + const state = createQuery(key, () => 'data') + return ( +
+
data: {state.data}
+
dataUpdatedAt: {state.dataUpdatedAt}
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: data')) + fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i })) + await waitFor(() => rendered.getByText('data: newData')) + await waitFor(() => { + expect(rendered.getByText('dataUpdatedAt: 100')).toBeInTheDocument() + }) + }) + + it('errorUpdateCount should increased on each fetch failure', async () => { + const key = queryKey() + const error = new Error('oops') + + function Page() { + const { refetch, errorUpdateCount } = createQuery( + key, + async (): Promise => { + throw error + }, + { + retry: false, + }, + ) + return ( +
+ + data: {errorUpdateCount} +
+ ) + } + const rendered = renderWithClient(queryClient, ) + const fetchBtn = rendered.getByRole('button', { name: 'refetch' }) + await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(fetchBtn) + await waitFor(() => rendered.getByText('data: 2')) + fireEvent.click(fetchBtn) + await waitFor(() => rendered.getByText('data: 3')) + }) +}) From eeff6da7a7d43b97aea1c48d7b5a9e49e9db6921 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 11:07:48 -0400 Subject: [PATCH 128/221] fix type tests and add comments to errors --- .../src/__tests__/createQuery.test.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 6a873027471..865db302788 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -22,6 +22,7 @@ import { describe('useQuery', () => { const queryCache = new QueryCache() + // TODO(lukemurray): not sure why this is failing const queryClient = createQueryClient({ queryCache }) it('should return the correct types', () => { @@ -51,10 +52,14 @@ describe('useQuery', () => { expectType(withError.error) // it should provide the result type in the configuration - createQuery([key], async () => true, { - onSuccess: (data) => expectType(data), - onSettled: (data) => expectType(data), - }) + createQuery( + () => [key()], + async () => true, + { + onSuccess: (data) => expectType(data), + onSettled: (data) => expectType(data), + }, + ) // it should be possible to specify a union type as result type const unionTypeSync = createQuery( @@ -88,15 +93,18 @@ describe('useQuery', () => { expectType(fromGenericQueryFn.error) const fromGenericOptionsQueryFn = createQuery({ - queryKey: key, + // TODO(lukemurray): when passing the queryKey as options how do we make it reactive? + queryKey: key(), queryFn: () => queryFn(), }) expectType(fromGenericOptionsQueryFn.data) expectType(fromGenericOptionsQueryFn.error) type MyData = number + // TODO(lukemurray): this should be a function to match SolidQueryKey. type MyQueryKey = readonly ['my-data', number] + // TODO(lukemurray): errors if MyQueryKey is a function. const getMyDataArrayKey: QueryFunction = async ({ queryKey: [, n], }) => { @@ -104,6 +112,7 @@ describe('useQuery', () => { } createQuery({ + // TODO(lukemurray): fails because MyQueryKey is not a function and QueryFunction type doesn't support SolidQueryKey queryKey: ['my-data', 100], queryFn: getMyDataArrayKey, }) From b8cc9391728999767d89d2657a94f02dd70d8555 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 11:24:52 -0400 Subject: [PATCH 129/221] fix comment in types --- packages/solid-query/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index b5dd4878db6..20ea33fb4a3 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -13,7 +13,7 @@ import type { export interface ContextOptions { /** - * Use this to pass your React Query context. Otherwise, `defaultContext` will be used. + * Use this to pass your Solid Query context. Otherwise, `defaultContext` will be used. */ context?: Context } From 82172194d249ec37c8b6073e2e6cd508b3ad0dba Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 11:53:44 -0400 Subject: [PATCH 130/221] update test utils --- packages/solid-query/src/__tests__/utils.ts | 5 -- packages/solid-query/src/__tests__/utils.tsx | 65 ++++++++++++++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) delete mode 100644 packages/solid-query/src/__tests__/utils.ts create mode 100644 packages/solid-query/src/__tests__/utils.tsx diff --git a/packages/solid-query/src/__tests__/utils.ts b/packages/solid-query/src/__tests__/utils.ts deleted file mode 100644 index c6bbb39643a..00000000000 --- a/packages/solid-query/src/__tests__/utils.ts +++ /dev/null @@ -1,5 +0,0 @@ -let queryKeyCount = 0 -export function queryKey(): () => Array { - const localQueryKeyCount = queryKeyCount++ - return () => [`query_${localQueryKeyCount}`] -} diff --git a/packages/solid-query/src/__tests__/utils.tsx b/packages/solid-query/src/__tests__/utils.tsx new file mode 100644 index 00000000000..d17650115fa --- /dev/null +++ b/packages/solid-query/src/__tests__/utils.tsx @@ -0,0 +1,65 @@ +import { QueryClient, QueryClientProvider } from '..' +import { render } from 'solid-testing-library' +import { + JSX, + createEffect, + createSignal, + onCleanup, + ParentProps, + Show, +} from 'solid-js' + +let queryKeyCount = 0 +export function queryKey(): () => Array { + const localQueryKeyCount = queryKeyCount++ + return () => [`query_${localQueryKeyCount}`] +} + +export function setActTimeout(fn: () => void, ms?: number) { + return setTimeout(() => { + fn() + }, ms) +} + +export function renderWithClient( + client: QueryClient, + ui: JSX.Element, + // options: ContextOptions = {}, +): ReturnType { + // TODO(lukemurray): add support for context options + // + return render(() => ( + {ui} + )) + // TODO(lukemurray): the react version returns rerender but the solid-testing-library + // doesn't support rerender + // return { + // ...result, + // rerender: (rerenderUi: React.ReactElement) => + // rerender( + // + // {rerenderUi} + // , + // ), + // } as any +} + +export const Blink = ( + props: { + duration: number + } & ParentProps, +) => { + const [shouldShow, setShouldShow] = createSignal(true) + + createEffect(() => { + setShouldShow(true) + const timeout = setActTimeout(() => setShouldShow(false), props.duration) + onCleanup(() => clearTimeout(timeout)) + }) + + return ( + off}> + <>{props.children} + + ) +} From b1829a034e5a5fc47cf30273a121f2d3dbde2596 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 12:05:40 -0400 Subject: [PATCH 131/221] shoudl allow to set default data value passing --- .../src/__tests__/createQuery.test.tsx | 158 +++++++++--------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 865db302788..8b14898aad8 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -4,12 +4,11 @@ import { expectType, mockVisibilityState, sleep, - setActTimeout, mockNavigatorOnLine, mockLogger, createQueryClient, } from '../../../../tests/utils' -import { renderWithClient, Blink, queryKey } from './utils' +import { renderWithClient, Blink, queryKey, setActTimeout } from './utils' import { createQuery, CreateQueryResult, @@ -22,7 +21,6 @@ import { describe('useQuery', () => { const queryCache = new QueryCache() - // TODO(lukemurray): not sure why this is failing const queryClient = createQueryClient({ queryCache }) it('should return the correct types', () => { @@ -179,23 +177,23 @@ describe('useQuery', () => { const key = queryKey() function Page() { - const { data = 'default' } = createQuery(key, async () => { + const state = createQuery(key, async () => { await sleep(10) return 'test' }) return (
-

{data}

+

{state.data ?? 'default'}

) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, () => ) - rendered.getByText('default') + screen.getByText('default') - await waitFor(() => rendered.getByText('test')) + await waitFor(() => screen.getByText('test')) }) it('should return the correct states for a successful query', async () => { @@ -502,7 +500,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 10) @@ -524,9 +522,9 @@ describe('useQuery', () => { const onSuccess = jest.fn() function Page() { - const [show, setShow] = React.useState(true) + const [show, setShow] = NotReact.useState(true) - React.useEffect(() => { + NotReact.useEffect(() => { setShow(false) }, [setShow]) @@ -664,7 +662,7 @@ describe('useQuery', () => { { enabled: false, initialData: 'initialData' }, ) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 5) @@ -698,7 +696,7 @@ describe('useQuery', () => { { enabled: false, initialData: 'initialData' }, ) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 5) @@ -732,7 +730,7 @@ describe('useQuery', () => { { enabled: false }, ) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 5) @@ -777,7 +775,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [toggle, setToggle] = React.useState(false) + const [toggle, setToggle] = NotReact.useState(false) return (
@@ -851,7 +849,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [, rerender] = React.useState({}) + const [, rerender] = NotReact.useState({}) const state = createQuery( key, @@ -869,7 +867,7 @@ describe('useQuery', () => { const { remove } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { remove() rerender({}) @@ -997,7 +995,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 5) @@ -1047,12 +1045,12 @@ describe('useQuery', () => { let runs = 0 function Page() { - const [, rerender] = React.useReducer(() => ({}), {}) + const [, rerender] = NotReact.useReducer(() => ({}), {}) const state = createQuery( key, () => (runs === 0 ? 'test' : 'test2'), { - select: React.useCallback(() => { + select: NotReact.useCallback(() => { runs++ throw error }, []), @@ -1093,7 +1091,7 @@ describe('useQuery', () => { const { refetch, data } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { if (data) { refetch() @@ -1127,7 +1125,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { renderCount++ }, [state]) @@ -1153,7 +1151,7 @@ describe('useQuery', () => { let count = 0 function Page() { - const [, rerender] = React.useState({}) + const [, rerender] = NotReact.useState({}) const state = createQuery(key, () => ++count, { notifyOnChangeProps: 'all', }) @@ -1434,7 +1432,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { queryClient.refetchQueries({ queryKey: key }) }, 20) @@ -1474,7 +1472,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { queryClient.invalidateQueries(key) }, 20) @@ -1501,7 +1499,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery( [key, count], @@ -1514,7 +1512,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(1) }, 10) @@ -1554,7 +1552,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery( [key, count], @@ -1567,7 +1565,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(1) }, 20) @@ -1727,7 +1725,7 @@ describe('useQuery', () => { const states: DefinedCreateQueryResult[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery( [key, count], @@ -1740,7 +1738,7 @@ describe('useQuery', () => { states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(1) }, 20) @@ -1795,7 +1793,7 @@ describe('useQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery( [key, count], @@ -1810,7 +1808,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { refetch() setActTimeout(() => { @@ -1884,7 +1882,7 @@ describe('useQuery', () => { await sleep(10) function Page() { - const [count, setCount] = React.useState(10) + const [count, setCount] = NotReact.useState(10) const state = createQuery( [key, count], @@ -1899,7 +1897,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(11) }, 20) @@ -2192,7 +2190,7 @@ describe('useQuery', () => { const { refetch } = state - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { refetch() }, 10) @@ -2279,11 +2277,11 @@ describe('useQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - const originalUseEffect = React.useEffect + const originalUseEffect = NotReact.useEffect // Try to simulate useEffect timing delay // @ts-ignore - React.useEffect = (...args: any[]) => { + NotReact.useEffect = (...args: any[]) => { originalUseEffect(() => { setTimeout(() => { args[0]() @@ -2302,7 +2300,7 @@ describe('useQuery', () => { await sleep(50) // @ts-ignore - React.useEffect = originalUseEffect + NotReact.useEffect = originalUseEffect expect(states.length).toBe(2) expect(states[0]).toMatchObject({ status: 'loading' }) @@ -2346,7 +2344,7 @@ describe('useQuery', () => { } function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) createQuery(key, queryFn, { onSuccess: () => { setCount((x) => x + 1) @@ -2358,7 +2356,7 @@ describe('useQuery', () => { }, }) - React.useEffect(() => { + NotReact.useEffect(() => { renders++ callbackCount = count }) @@ -2381,9 +2379,9 @@ describe('useQuery', () => { const key = queryKey() function Page() { - const [, setNewState] = React.useState('state') + const [, setNewState] = NotReact.useState('state') const state = createQuery(key, () => 'data') - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { queryClient.setQueryData(key, 'new') // Update with same state to make react discard the next render @@ -2807,7 +2805,7 @@ describe('useQuery', () => { useErrorBoundary: true, }) - React.useEffect(() => { + NotReact.useEffect(() => { result = query }) @@ -2920,7 +2918,7 @@ describe('useQuery', () => { } function App() { - const [show, toggle] = React.useReducer((x) => !x, true) + const [show, toggle] = NotReact.useReducer((x) => !x, true) return (
@@ -2968,7 +2966,7 @@ describe('useQuery', () => { } function App() { - const [show, toggle] = React.useReducer((x) => !x, true) + const [show, toggle] = NotReact.useReducer((x) => !x, true) return (
@@ -3171,14 +3169,14 @@ describe('useQuery', () => { const states: DefinedCreateQueryResult<{ count: number }>[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery([key, count], () => ({ count: 10 }), { staleTime: Infinity, initialData: () => ({ count }), }) states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setCount(1) }, 10) @@ -3563,8 +3561,8 @@ describe('useQuery', () => { let count = 0 function Page() { - const [enabled, setEnabled] = React.useState(false) - const [isPrefetched, setPrefetched] = React.useState(false) + const [enabled, setEnabled] = NotReact.useState(false) + const [isPrefetched, setPrefetched] = NotReact.useState(false) const query = createQuery( key, @@ -3578,7 +3576,7 @@ describe('useQuery', () => { }, ) - React.useEffect(() => { + NotReact.useEffect(() => { async function prefetch() { await queryClient.prefetchQuery(key, () => Promise.resolve('prefetched data'), @@ -3610,7 +3608,7 @@ describe('useQuery', () => { const key = queryKey() function Page() { - const [shouldFetch, setShouldFetch] = React.useState(false) + const [shouldFetch, setShouldFetch] = NotReact.useState(false) const query = createQuery(key, () => 'data', { enabled: shouldFetch, @@ -3687,7 +3685,7 @@ describe('useQuery', () => { const results: DefinedCreateQueryResult[] = [] function Page() { - const [shouldFetch, setShouldFetch] = React.useState(true) + const [shouldFetch, setShouldFetch] = NotReact.useState(true) const result = createQuery(key, () => 'fetched data', { enabled: shouldFetch, @@ -3696,7 +3694,7 @@ describe('useQuery', () => { results.push(result) - React.useEffect(() => { + NotReact.useEffect(() => { setActTimeout(() => { setShouldFetch(false) }, 5) @@ -3796,7 +3794,7 @@ describe('useQuery', () => { ) }) - React.useMemo(() => { + NotReact.useMemo(() => { memoFn() return result.data }, [result.data]) @@ -3826,12 +3824,12 @@ describe('useQuery', () => { let count = 0 function Page() { - const [int, setInt] = React.useState(200) + const [int, setInt] = NotReact.useState(200) const { data } = createQuery(key, () => count++, { refetchInterval: int, }) - React.useEffect(() => { + NotReact.useEffect(() => { if (data === 2) { setInt(0) } @@ -3986,7 +3984,7 @@ describe('useQuery', () => { } function Page() { - const [enabled, setEnabled] = React.useState(false) + const [enabled, setEnabled] = NotReact.useState(false) const result = createQuery(key, queryFn, { enabled }) return ( <> @@ -4047,7 +4045,7 @@ describe('useQuery', () => { const states: { state: CreateQueryResult; count: number }[] = [] function Page() { - const [count, setCount] = React.useState(0) + const [count, setCount] = NotReact.useState(0) const state = createQuery(key1, () => 'data', { placeholderData: 'placeholder', @@ -4056,7 +4054,7 @@ describe('useQuery', () => { states.push({ state, count }) - React.useEffect(() => { + NotReact.useEffect(() => { setCount(1) }, []) @@ -4194,7 +4192,7 @@ describe('useQuery', () => { let selectRun = 0 function Page() { - const [count, inc] = React.useReducer((prev) => prev + 1, 2) + const [count, inc] = NotReact.useReducer((prev) => prev + 1, 2) const state = createQuery( key1, @@ -4203,7 +4201,7 @@ describe('useQuery', () => { return 0 }, { - select: React.useCallback( + select: NotReact.useCallback( (data: number) => { selectRun++ return `selected ${data + count}` @@ -4239,8 +4237,11 @@ describe('useQuery', () => { const key1 = queryKey() function Page() { - const [count, inc] = React.useReducer((prev) => prev + 1, 2) - const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1) + const [count, inc] = NotReact.useReducer((prev) => prev + 1, 2) + const [forceValue, forceUpdate] = NotReact.useReducer( + (prev) => prev + 1, + 1, + ) const state = createQuery( key1, @@ -4249,7 +4250,7 @@ describe('useQuery', () => { return 0 }, { - select: React.useCallback( + select: NotReact.useCallback( (data: number) => { return `selected ${data + count}` }, @@ -4290,7 +4291,10 @@ describe('useQuery', () => { const states: Array> = [] function Page() { - const [forceValue, forceUpdate] = React.useReducer((prev) => prev + 1, 1) + const [forceValue, forceUpdate] = NotReact.useReducer( + (prev) => prev + 1, + 1, + ) const state = createQuery( key1, @@ -4303,7 +4307,7 @@ describe('useQuery', () => { }, ) - React.useEffect(() => { + NotReact.useEffect(() => { if (state.data) { states.push(state.data) } @@ -4458,14 +4462,14 @@ describe('useQuery', () => { } function Page() { - const [id, setId] = React.useState(1) - const [hasChanged, setHasChanged] = React.useState(false) + const [id, setId] = NotReact.useState(1) + const [hasChanged, setHasChanged] = NotReact.useState(false) const state = createQuery([key, id], queryFn) states.push(state) - React.useEffect(() => { + NotReact.useEffect(() => { setId((prevId) => (prevId === 1 ? 2 : 1)) setHasChanged(true) }, [hasChanged]) @@ -4651,7 +4655,7 @@ describe('useQuery', () => { } function Page() { - React.useEffect(() => { + NotReact.useEffect(() => { renders++ }) @@ -4693,7 +4697,7 @@ describe('useQuery', () => { } function App() { - const [enabled, toggle] = React.useReducer((x) => !x, true) + const [enabled, toggle] = NotReact.useReducer((x) => !x, true) return (
@@ -4754,7 +4758,7 @@ describe('useQuery', () => { } function App() { - const [id, changeId] = React.useReducer((x) => x + 1, 1) + const [id, changeId] = NotReact.useReducer((x) => x + 1, 1) return (
@@ -4809,7 +4813,7 @@ describe('useQuery', () => { } function App() { - const [value, toggle] = React.useReducer((x) => !x, true) + const [value, toggle] = NotReact.useReducer((x) => !x, true) return (
@@ -4929,7 +4933,7 @@ describe('useQuery', () => { }, }) - React.useEffect(() => { + NotReact.useEffect(() => { states.push(state.fetchStatus) }) @@ -5334,7 +5338,7 @@ describe('useQuery', () => { } function Page() { - const [show, setShow] = React.useState(true) + const [show, setShow] = NotReact.useState(true) return (
@@ -5454,7 +5458,7 @@ describe('useQuery', () => { } function Page() { - const [show, setShow] = React.useState(true) + const [show, setShow] = NotReact.useState(true) return (
From 8213f1e4017d6fb269ca346ae65852af1e0debc0 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 13:29:02 -0400 Subject: [PATCH 132/221] change createBaseQuery to use mutate instead of refetch - this resolve an issue where `state` would update an extra time in effects. The first update is from "setState" on the store. The second update is from "refetch" returning after the Promise waits for a single tick. With mutate we can batch "setState" and "refetch" to avoid the tick from the promise. - TBD I'm not sure what the implication of this change is for suspense or error boundaries. --- packages/solid-query/src/createBaseQuery.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index d613f40b55b..3f3f289157b 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -2,7 +2,13 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' import { CreateBaseQueryOptions } from './types' import { useQueryClient } from './QueryClientProvider' -import { onMount, onCleanup, createComputed, createResource } from 'solid-js' +import { + onMount, + onCleanup, + createComputed, + createResource, + batch, +} from 'solid-js' import { createStore } from 'solid-js/store' // Base Query Function that is used to create the query. @@ -33,7 +39,7 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions), ) - const [dataResource, { refetch }] = createResource(() => { + const [dataResource, { mutate }] = createResource(() => { return new Promise((resolve) => { if (state.isSuccess) resolve(state.data) if (state.isError && !state.isFetching) { @@ -44,9 +50,10 @@ export function createBaseQuery< const unsubscribe = observer.subscribe((result) => { const reconciledResult = result - // @ts-ignore - setState(reconciledResult) - refetch() + batch(() => { + setState(reconciledResult) + mutate(() => reconciledResult.data) + }) }) onCleanup(() => unsubscribe()) From ad896c1569a54b16c481718f328053f5900527e5 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 13:49:31 -0400 Subject: [PATCH 133/221] correct state for successful query working --- .../src/__tests__/createQuery.test.tsx | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 8b14898aad8..7f47f7d9b26 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1,4 +1,4 @@ -import { screen, waitFor, fireEvent } from 'solid-testing-library' +import { screen, waitFor, fireEvent, render } from 'solid-testing-library' import '@testing-library/jest-dom' import { expectType, @@ -17,7 +17,9 @@ import { QueryFunctionContext, CreateQueryOptions, DefinedCreateQueryResult, + QueryClientProvider, } from '..' +import { JSX, Match, Switch, createRenderEffect } from 'solid-js' describe('useQuery', () => { const queryCache = new QueryCache() @@ -200,34 +202,50 @@ describe('useQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - function Page() { + function Page(): JSX.Element { const state = createQuery(key, async () => { await sleep(10) return 'test' }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) if (state.isLoading) { expectType(state.data) expectType(state.error) - return loading - } - - if (state.isLoadingError) { + } else if (state.isLoadingError) { expectType(state.data) expectType(state.error) - return {state.error.message} + } else { + expectType(state.data) + expectType(state.error) } - expectType(state.data) - expectType(state.error) - return {state.data} - } - - const rendered = renderWithClient(queryClient, ) + return ( + + + loading + + + {state.error!.message} + + + {state.data} + + + ) + } + + // renderWithClient(queryClient, () => ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('test')) + await waitFor(() => screen.getByText('test')) expect(states.length).toEqual(2) From 4a025451d0a6be96d4f1f5573e83dadad2340c83 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 13:51:53 -0400 Subject: [PATCH 134/221] correct states for incorrect query passing --- .../solid-query/src/__tests__/createQuery.test.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 7f47f7d9b26..3d02961f7d8 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -317,7 +317,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -327,9 +329,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + // renderWithClient(queryClient, () => ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('Status: error')) + await waitFor(() => screen.getByText('Status: error')) expect(states[0]).toEqual({ data: undefined, From 09d46d3e9601434a951580a2bedbbe3cf6050491 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 13:59:11 -0400 Subject: [PATCH 135/221] translate set isFetchedAfterMount --- .../solid-query/src/__tests__/createQuery.test.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 3d02961f7d8..290aafe137b 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -421,15 +421,23 @@ describe('useQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, () => 'prefetched') + // TODO(lukemurray): do we want reactivity on this key? + await queryClient.prefetchQuery(key(), () => 'prefetched') function Page() { const state = createQuery(key, () => 'data') - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + // renderWithClient(queryClient, () => ) + render(() => ( + + + + )) await sleep(10) expect(states.length).toBe(2) From 8e3ee88490e9bf7d3bf571672505651b3b7969fa Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 14:19:19 -0400 Subject: [PATCH 136/221] partial conversion of createQuery tests to solid --- .../src/__tests__/createQuery.test.tsx | 1468 ++++++++++++----- 1 file changed, 1032 insertions(+), 436 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 290aafe137b..e7298aed047 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -19,7 +19,15 @@ import { DefinedCreateQueryResult, QueryClientProvider, } from '..' -import { JSX, Match, Switch, createRenderEffect } from 'solid-js' +import { + JSX, + Match, + Switch, + createRenderEffect, + createEffect, + createSignal, + Show, +} from 'solid-js' describe('useQuery', () => { const queryCache = new QueryCache() @@ -191,7 +199,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, () => ) + render(() => ( + + + + )) screen.getByText('default') @@ -238,7 +250,6 @@ describe('useQuery', () => { ) } - // renderWithClient(queryClient, () => ) render(() => ( @@ -329,7 +340,6 @@ describe('useQuery', () => { ) } - // renderWithClient(queryClient, () => ) render(() => ( @@ -432,7 +442,6 @@ describe('useQuery', () => { return null } - // renderWithClient(queryClient, () => ) render(() => ( @@ -468,13 +477,19 @@ describe('useQuery', () => { }, { onSuccess }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return
data: {state.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: data') + await screen.findByText('data: data') expect(states.length).toBe(2) expect(onSuccess).toHaveBeenCalledTimes(1) expect(onSuccess).toHaveBeenCalledWith('data') @@ -497,7 +512,9 @@ describe('useQuery', () => { { onSuccess }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -507,11 +524,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: data1') - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) - await rendered.findByText('data: data2') + await screen.findByText('data: data1') + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await screen.findByText('data: data2') expect(states.length).toBe(3) //loading, success, success after refetch expect(count).toBe(2) @@ -529,20 +550,25 @@ describe('useQuery', () => { onSuccess, }) - states.push(state) - - const { refetch } = state + createRenderEffect(() => { + states.push({ ...state }) + }) - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch setActTimeout(() => { refetch() }, 10) - }, [refetch]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) expect(onSuccess).toHaveBeenCalledTimes(1) @@ -555,13 +581,16 @@ describe('useQuery', () => { const onSuccess = jest.fn() function Page() { - const [show, setShow] = NotReact.useState(true) + const [show, setShow] = createSignal(true) - NotReact.useEffect(() => { + createEffect(() => { setShow(false) - }, [setShow]) - - return show ? : null + }) + return ( + + + + ) } function Component() { @@ -573,11 +602,17 @@ describe('useQuery', () => { }, { onSuccess }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) expect(states.length).toBe(1) @@ -594,11 +629,18 @@ describe('useQuery', () => { retry: false, onError, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) + return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(states.length).toBe(2) @@ -611,7 +653,7 @@ describe('useQuery', () => { const onError = jest.fn() function Page() { - const { status, fetchStatus } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -623,19 +665,21 @@ describe('useQuery', () => { ) return ( - status: {status}, fetchStatus: {fetchStatus} + status: {state.status}, fetchStatus: {state.fetchStatus} ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(5) - await queryClient.cancelQueries(key) + await queryClient.cancelQueries(key()) // query cancellation will reset the query to it's initial state - await waitFor(() => - rendered.getByText('status: loading, fetchStatus: idle'), - ) + await waitFor(() => screen.getByText('status: loading, fetchStatus: idle')) expect(onError).not.toHaveBeenCalled() }) @@ -646,11 +690,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, () => 'data', { onSettled }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(states.length).toBe(2) @@ -668,11 +718,17 @@ describe('useQuery', () => { retry: false, onSettled, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(states.length).toBe(2) @@ -707,7 +763,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) // first refetch only, second refetch is ignored @@ -741,7 +801,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) // first refetch (gets cancelled) and second refetch @@ -775,7 +839,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) // first refetch will not get cancelled, second one gets skipped @@ -790,11 +858,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -834,7 +908,9 @@ describe('useQuery', () => { notifyOnChangeProps: 'all', }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
{state.data}
@@ -842,13 +918,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: 1') + await screen.findByText('data: 1') - fireEvent.click(rendered.getByRole('button', { name: /toggle/i })) + fireEvent.click(screen.getByRole('button', { name: /toggle/i })) - await rendered.findByText('data: 2') + await screen.findByText('data: 2') expect(states.length).toBe(4) // First load @@ -896,7 +976,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { remove } = state @@ -910,7 +992,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -935,11 +1021,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'test', { refetchOnMount: false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -958,11 +1050,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'test', { refetchOnMount: false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -978,11 +1076,17 @@ describe('useQuery', () => { const state = createQuery(key, () => ({ name: 'test' }), { select: (data) => data.name, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -1001,11 +1105,17 @@ describe('useQuery', () => { queryFn: () => ({ name: 'test' }), select: (data) => data.name, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -1024,7 +1134,9 @@ describe('useQuery', () => { notifyOnChangeProps: ['data'], }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -1037,7 +1149,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -1057,11 +1173,17 @@ describe('useQuery', () => { throw error }, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -1098,14 +1220,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('error: Select Error')) + await waitFor(() => screen.getByText('error: Select Error')) expect(runs).toEqual(1) - fireEvent.click(rendered.getByRole('button', { name: 'rerender' })) + fireEvent.click(screen.getByRole('button', { name: 'rerender' })) await sleep(10) expect(runs).toEqual(1) - fireEvent.click(rendered.getByRole('button', { name: 'refetch' })) + fireEvent.click(screen.getByRole('button', { name: 'refetch' })) await sleep(10) expect(runs).toEqual(2) }) @@ -1120,7 +1246,9 @@ describe('useQuery', () => { return 'test' }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch, data } = state @@ -1139,9 +1267,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('test')) + await waitFor(() => screen.getByText('test')) expect(states.length).toBe(2) expect(states[0]).toMatchObject({ data: undefined }) @@ -1156,7 +1288,9 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, () => 'test') - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { renderCount++ @@ -1169,7 +1303,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(renderCount).toBe(2) @@ -1189,7 +1327,9 @@ describe('useQuery', () => { notifyOnChangeProps: 'all', }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { remove } = state @@ -1202,14 +1342,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /remove/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /remove/i })) await sleep(20) - fireEvent.click(rendered.getByRole('button', { name: /rerender/i })) - await waitFor(() => rendered.getByText('data: 2')) + fireEvent.click(screen.getByRole('button', { name: /rerender/i })) + await waitFor(() => screen.getByText('data: 2')) expect(states.length).toBe(4) // Initial @@ -1237,7 +1381,9 @@ describe('useQuery', () => { { notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { remove, refetch } = state @@ -1250,14 +1396,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /remove/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /remove/i })) await sleep(50) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('data: 2')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: 2')) expect(states.length).toBe(4) // Initial @@ -1298,7 +1448,9 @@ describe('useQuery', () => { { notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -1310,12 +1462,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: false')) + await waitFor(() => screen.getByText('data: false')) await sleep(20) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('data: true')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: true')) await waitFor(() => expect(states.length).toBe(4)) @@ -1368,11 +1524,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: set')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('data: fetched')) + await waitFor(() => screen.getByText('data: set')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: fetched')) await waitFor(() => expect(results.length).toBe(3)) @@ -1397,7 +1557,9 @@ describe('useQuery', () => { { staleTime: Infinity, notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -1409,11 +1571,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) - await waitFor(() => rendered.getByText('data: 2')) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) + await waitFor(() => screen.getByText('data: 2')) await waitFor(() => expect(states.length).toBe(4)) @@ -1463,7 +1629,9 @@ describe('useQuery', () => { { enabled: false }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1474,7 +1642,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) @@ -1503,7 +1675,9 @@ describe('useQuery', () => { { enabled: false }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1514,7 +1688,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -1543,7 +1721,9 @@ describe('useQuery', () => { { enabled: count === 0 }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1554,7 +1734,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) @@ -1596,7 +1780,9 @@ describe('useQuery', () => { { keepPreviousData: true }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1607,7 +1793,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states.length).toBe(5)) @@ -1668,7 +1858,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -1679,12 +1871,12 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('data: 0')) - act(() => rendered.rerender()) - await waitFor(() => rendered.getByText('data: 1')) - act(() => rendered.rerender()) - await waitFor(() => rendered.getByText('error: Error test')) + renderWithClient(queryClient, ) + await waitFor(() => screen.getByText('data: 0')) + act(() => screen.rerender()) + await waitFor(() => screen.getByText('data: 1')) + act(() => screen.rerender()) + await waitFor(() => screen.getByText('error: Error test')) await waitFor(() => expect(states.length).toBe(8)) // Initial @@ -1769,7 +1961,9 @@ describe('useQuery', () => { { initialData: 99, keepPreviousData: true }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -1780,7 +1974,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states.length).toBe(5)) @@ -1837,7 +2035,9 @@ describe('useQuery', () => { { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -1856,7 +2056,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -1926,7 +2130,9 @@ describe('useQuery', () => { { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -1945,7 +2151,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -2003,7 +2213,9 @@ describe('useQuery', () => { ) const refetch = state.refetch - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -2027,10 +2239,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) await waitFor(() => expect(states.length).toBe(4)) @@ -2100,7 +2316,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(200) @@ -2157,11 +2377,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'test', { staleTime: 50, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -2182,11 +2408,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'test', { staleTime: 10, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) unsubscribe() @@ -2219,7 +2451,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -2231,7 +2465,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(30) @@ -2274,12 +2512,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('First Data: init') - rendered.getByText('Second Data: init') - rendered.getByText('First Status: success') - rendered.getByText('Second Status: success') + screen.getByText('First Data: init') + screen.getByText('Second Data: init') + screen.getByText('First Status: success') + screen.getByText('Second Status: success') }) it('should not override query configuration on render', async () => { @@ -2301,7 +2543,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) expect(queryCache.find(key)!.options.queryFn).toBe(queryFn1) }) @@ -2324,11 +2570,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, () => 'data', { staleTime: Infinity }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) queryClient.setQueryData(key, 'data') await sleep(50) @@ -2357,7 +2609,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) @@ -2397,9 +2653,13 @@ describe('useQuery', () => { return
count: {count}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('count: 2')) + await waitFor(() => screen.getByText('count: 2')) // Should be 2 / 3 instead of 5, uSES batches differently expect(renders).toBe(process.env.REACTJS_VERSION === '17' ? 2 : 3) @@ -2424,9 +2684,13 @@ describe('useQuery', () => { return
{state.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('new')) + await waitFor(() => screen.getByText('new')) }) // See https://github.com/tannerlinsley/react-query/issues/170 @@ -2452,13 +2716,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) // use "act" to wait for state update and prevent console warning - rendered.getByText('First Status: loading, idle') - await waitFor(() => rendered.getByText('Second Status: loading, fetching')) - await waitFor(() => rendered.getByText('Second Status: success, idle')) + screen.getByText('First Status: loading, idle') + await waitFor(() => screen.getByText('Second Status: loading, fetching')) + await waitFor(() => screen.getByText('Second Status: success, idle')) }) // See https://github.com/tannerlinsley/react-query/issues/144 @@ -2474,9 +2742,13 @@ describe('useQuery', () => { return
status: {status}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('status: loading') + screen.getByText('status: loading') }) // See https://github.com/tannerlinsley/react-query/issues/147 @@ -2493,11 +2765,17 @@ describe('useQuery', () => { function Page() { const state = createQuery([key, variables], queryFn) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) @@ -2520,9 +2798,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('default')) + await waitFor(() => screen.getByText('default')) act(() => { window.dispatchEvent(new FocusEvent('focus')) @@ -2541,11 +2823,17 @@ describe('useQuery', () => { staleTime: 0, refetchOnWindowFocus: false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2570,11 +2858,17 @@ describe('useQuery', () => { staleTime: 0, refetchOnWindowFocus: () => false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2599,11 +2893,17 @@ describe('useQuery', () => { staleTime: Infinity, refetchOnWindowFocus: true, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2635,11 +2935,17 @@ describe('useQuery', () => { refetchOnWindowFocus: 'always', }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) @@ -2674,13 +2980,19 @@ describe('useQuery', () => { refetchOnWindowFocus: (query) => (query.state.data || 0) < 1, }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return
data: {String(state.data)}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: 0') + await screen.findByText('data: 0') expect(states.length).toBe(2) expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) @@ -2690,7 +3002,7 @@ describe('useQuery', () => { window.dispatchEvent(new FocusEvent('focus')) }) - await rendered.findByText('data: 1') + await screen.findByText('data: 1') // refetch should happen expect(states.length).toBe(4) @@ -2719,11 +3031,17 @@ describe('useQuery', () => { refetchOnMount: 'always', staleTime: Infinity, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2753,11 +3071,17 @@ describe('useQuery', () => { refetchOnMount: true, staleTime: 0, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2794,10 +3118,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('error')) - await waitFor(() => rendered.getByText('Error test jaylen')) + await waitFor(() => screen.getByText('error')) + await waitFor(() => screen.getByText('Error test jaylen')) }) it('should throw error if queryFn throws and useErrorBoundary is in use', async () => { @@ -2818,14 +3146,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient,
error boundary
}>
, ) - await waitFor(() => rendered.getByText('error boundary')) + await waitFor(() => screen.getByText('error boundary')) }) it('should update with data if we observe no properties and useErrorBoundary', async () => { @@ -2845,7 +3173,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -2873,15 +3205,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient,
error boundary
}>
, ) - await waitFor(() => rendered.getByText('error')) - await waitFor(() => rendered.getByText('Local Error')) + await waitFor(() => screen.getByText('error')) + await waitFor(() => screen.getByText('Local Error')) }) it('should throw error instead of setting status when error should be thrown', async () => { @@ -2905,7 +3237,7 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient, ( @@ -2920,8 +3252,8 @@ describe('useQuery', () => { , ) - await waitFor(() => rendered.getByText('error boundary')) - await waitFor(() => rendered.getByText('Remote Error')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('Remote Error')) }) it('should continue retries when observers unmount and remount while waiting for a retry (#3031)', async () => { @@ -2961,13 +3293,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('failureCount: 1')) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) - await waitFor(() => rendered.getByRole('button', { name: /show/i })) - fireEvent.click(rendered.getByRole('button', { name: /show/i })) - await waitFor(() => rendered.getByText('error: some error')) + await waitFor(() => screen.getByText('failureCount: 1')) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) + await waitFor(() => screen.getByRole('button', { name: /show/i })) + fireEvent.click(screen.getByRole('button', { name: /show/i })) + await waitFor(() => screen.getByText('error: some error')) expect(count).toBe(3) }) @@ -3012,14 +3344,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('failureCount: 1')) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) - fireEvent.click(rendered.getByRole('button', { name: /cancel/i })) - await waitFor(() => rendered.getByRole('button', { name: /show/i })) - fireEvent.click(rendered.getByRole('button', { name: /show/i })) - await waitFor(() => rendered.getByText('error: some error')) + await waitFor(() => screen.getByText('failureCount: 1')) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) + fireEvent.click(screen.getByRole('button', { name: /cancel/i })) + await waitFor(() => screen.getByRole('button', { name: /show/i })) + fireEvent.click(screen.getByRole('button', { name: /show/i })) + await waitFor(() => screen.getByText('error: some error')) // initial fetch (1), which will be cancelled, followed by new mount(2) + 2 retries = 4 expect(count).toBe(4) @@ -3036,7 +3368,9 @@ describe('useQuery', () => { refetchOnMount: 'always', staleTime: 50, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
data: {state.data ?? 'null'}
@@ -3046,9 +3380,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data')) + await waitFor(() => screen.getByText('data: data')) await waitFor(() => expect(states.length).toBe(3)) expect(states[0]).toMatchObject({ @@ -3076,11 +3414,17 @@ describe('useQuery', () => { const state = createQuery(key, () => 'data', { initialData: 'initial', }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) @@ -3107,11 +3451,17 @@ describe('useQuery', () => { staleTime: 50, initialData: 'initial', }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -3140,11 +3490,17 @@ describe('useQuery', () => { initialData: 'initial', initialDataUpdatedAt: oneSecondAgo, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -3176,11 +3532,17 @@ describe('useQuery', () => { initialData: 'initial', initialDataUpdatedAt: 0, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -3207,7 +3569,9 @@ describe('useQuery', () => { staleTime: Infinity, initialData: () => ({ count }), }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setActTimeout(() => { @@ -3218,7 +3582,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -3251,13 +3619,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('loading')) - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('loading')) + await waitFor(() => screen.getByText('error')) // query should fail `retry + 1` times, since first time isn't a "retry" - await waitFor(() => rendered.getByText('Failed 2 times')) + await waitFor(() => screen.getByText('Failed 2 times')) expect(queryFn).toHaveBeenCalledTimes(2) }) @@ -3294,13 +3666,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('loading')) - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('loading')) + await waitFor(() => screen.getByText('error')) - await waitFor(() => rendered.getByText('Failed 2 times')) - await waitFor(() => rendered.getByText('NoRetry')) + await waitFor(() => screen.getByText('Failed 2 times')) + await waitFor(() => screen.getByText('NoRetry')) expect(queryFn).toHaveBeenCalledTimes(2) }) @@ -3329,13 +3705,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) expect(queryFn).toHaveBeenCalledTimes(1) - await waitFor(() => rendered.getByText('Failed 2 times')) + await waitFor(() => screen.getByText('Failed 2 times')) expect(queryFn).toHaveBeenCalledTimes(2) }) @@ -3371,16 +3751,20 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) // The query should display the first error result - await waitFor(() => rendered.getByText('failureCount 1')) - await waitFor(() => rendered.getByText('status loading')) - await waitFor(() => rendered.getByText('error null')) + await waitFor(() => screen.getByText('failureCount 1')) + await waitFor(() => screen.getByText('status loading')) + await waitFor(() => screen.getByText('error null')) // Check if the query really paused await sleep(10) - await waitFor(() => rendered.getByText('failureCount 1')) + await waitFor(() => screen.getByText('failureCount 1')) act(() => { // reset visibilityState to original value @@ -3389,13 +3773,13 @@ describe('useQuery', () => { }) // Wait for the final result - await waitFor(() => rendered.getByText('failureCount 4')) - await waitFor(() => rendered.getByText('status error')) - await waitFor(() => rendered.getByText('error fetching error 4')) + await waitFor(() => screen.getByText('failureCount 4')) + await waitFor(() => screen.getByText('status error')) + await waitFor(() => screen.getByText('error fetching error 4')) // Check if the query really stopped await sleep(10) - await waitFor(() => rendered.getByText('failureCount 4')) + await waitFor(() => screen.getByText('failureCount 4')) // Check if the error has been logged in the console expect(mockLogger.error).toHaveBeenCalledWith('fetching error 4') @@ -3409,11 +3793,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, () => 'data') - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -3447,7 +3837,9 @@ describe('useQuery', () => { await sleep(10) return 'data' }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
{state.data}, {state.isStale}, {state.isFetching} @@ -3455,7 +3847,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states.length).toBe(2)) @@ -3510,11 +3906,17 @@ describe('useQuery', () => { function Page() { const state = createQuery(key, queryFn) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states.length).toBe(2)) @@ -3547,7 +3949,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(0) @@ -3582,10 +3988,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('failureCount 2')) - await waitFor(() => rendered.getByText('failureCount 0')) + await waitFor(() => screen.getByText('failureCount 2')) + await waitFor(() => screen.getByText('failureCount 0')) }) // See https://github.com/tannerlinsley/react-query/issues/199 @@ -3628,12 +4038,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('isPrefetched')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('isPrefetched')) - fireEvent.click(rendered.getByText('setKey')) - await waitFor(() => rendered.getByText('data: prefetched data')) - await waitFor(() => rendered.getByText('data: 1')) + fireEvent.click(screen.getByText('setKey')) + await waitFor(() => screen.getByText('data: prefetched data')) + await waitFor(() => screen.getByText('data: 1')) expect(count).toBe(1) }) @@ -3658,17 +4072,21 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('FetchStatus: idle') - rendered.getByText('Data: no data') + screen.getByText('FetchStatus: idle') + screen.getByText('Data: no data') - fireEvent.click(rendered.getByText('fetch')) + fireEvent.click(screen.getByText('fetch')) - await waitFor(() => rendered.getByText('FetchStatus: fetching')) + await waitFor(() => screen.getByText('FetchStatus: fetching')) await waitFor(() => [ - rendered.getByText('FetchStatus: idle'), - rendered.getByText('Data: data'), + screen.getByText('FetchStatus: idle'), + screen.getByText('Data: data'), ]) }) @@ -3684,7 +4102,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -3703,7 +4125,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -3736,7 +4162,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) expect(results.length).toBe(3) @@ -3759,11 +4189,15 @@ describe('useQuery', () => { return
fetchStatus: {fetchStatus}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) expect(queryFn).not.toHaveBeenCalled() expect(queryCache.find(key)).not.toBeUndefined() - rendered.getByText('fetchStatus: idle') + screen.getByText('fetchStatus: idle') }) // See https://github.com/tannerlinsley/react-query/issues/360 @@ -3784,9 +4218,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('status: loading, idle')) + await waitFor(() => screen.getByText('status: loading, idle')) }) test('should not schedule garbage collection, if cacheTimeout is set to `Infinity`', async () => { @@ -3799,11 +4237,15 @@ describe('useQuery', () => { return
{query.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('fetched data')) + await waitFor(() => screen.getByText('fetched data')) - rendered.unmount() + screen.unmount() const query = queryCache.find(key) // @ts-expect-error @@ -3841,13 +4283,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('status loading')) - await waitFor(() => rendered.getByText('status success')) - fireEvent.click(rendered.getByText('refetch')) - await waitFor(() => rendered.getByText('isFetching true')) - await waitFor(() => rendered.getByText('isFetching false')) + await waitFor(() => screen.getByText('status loading')) + await waitFor(() => screen.getByText('status success')) + fireEvent.click(screen.getByText('refetch')) + await waitFor(() => screen.getByText('isFetching true')) + await waitFor(() => screen.getByText('isFetching false')) expect(queryFn).toHaveBeenCalledTimes(2) expect(memoFn).toHaveBeenCalledTimes(2) }) @@ -3871,12 +4317,16 @@ describe('useQuery', () => { return
count: {data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) // mount - await waitFor(() => rendered.getByText('count: 0')) - await waitFor(() => rendered.getByText('count: 1')) - await waitFor(() => rendered.getByText('count: 2')) + await waitFor(() => screen.getByText('count: 0')) + await waitFor(() => screen.getByText('count: 1')) + await waitFor(() => screen.getByText('count: 2')) }) it('should refetch in an interval depending on function result', async () => { @@ -3908,9 +4358,13 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('count: 2')) + await waitFor(() => screen.getByText('count: 2')) expect(states.length).toEqual(6) @@ -3962,9 +4416,13 @@ describe('useQuery', () => { return
count: {queryInfo.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('count: 1')) + await waitFor(() => screen.getByText('count: 1')) await sleep(10) //extra sleep to make sure we're not re-fetching @@ -3990,9 +4448,13 @@ describe('useQuery', () => { return <>{JSON.stringify(result.data)} } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('')) + await waitFor(() => screen.getByText('')) }) it('should accept an object as query key', async () => { @@ -4001,9 +4463,13 @@ describe('useQuery', () => { return <>{JSON.stringify(result.data)} } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('[{"a":"a"}]')) + await waitFor(() => screen.getByText('[{"a":"a"}]')) }) it('should refetch if any query instance becomes enabled', async () => { @@ -4028,10 +4494,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) expect(queryFn).toHaveBeenCalledTimes(0) - fireEvent.click(rendered.getByText('enable')) - await waitFor(() => rendered.getByText('data')) + fireEvent.click(screen.getByText('enable')) + await waitFor(() => screen.getByText('data')) expect(queryFn).toHaveBeenCalledTimes(1) }) @@ -4045,7 +4515,9 @@ describe('useQuery', () => { placeholderData: 'placeholder', }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -4055,8 +4527,12 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: data')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: data')) expect(states).toMatchObject([ { @@ -4099,8 +4575,12 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: data')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: data')) expect(states).toMatchObject([ { @@ -4141,7 +4621,9 @@ describe('useQuery', () => { select: (data) => String(data * 2), }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -4151,8 +4633,12 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: 2')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: 2')) expect(states).toMatchObject([ { @@ -4183,7 +4669,9 @@ describe('useQuery', () => { select: (data) => String(data * 2), }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -4193,10 +4681,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: 2')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: 2')) - rendered.rerender() + screen.rerender() expect(states).toMatchObject([ { @@ -4253,16 +4745,20 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: selected 101')) // 99 + 2 + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: selected 101')) // 99 + 2 expect(selectRun).toBe(1) - await waitFor(() => rendered.getByText('Data: selected 2')) // 0 + 2 + await waitFor(() => screen.getByText('Data: selected 2')) // 0 + 2 expect(selectRun).toBe(2) - fireEvent.click(rendered.getByRole('button', { name: /inc/i })) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) - await waitFor(() => rendered.getByText('Data: selected 3')) // 0 + 3 + await waitFor(() => screen.getByText('Data: selected 3')) // 0 + 3 expect(selectRun).toBe(3) }) @@ -4303,20 +4799,24 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: selected 101')) // 99 + 2 + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: selected 101')) // 99 + 2 - await waitFor(() => rendered.getByText('Data: selected 2')) // 0 + 2 + await waitFor(() => screen.getByText('Data: selected 2')) // 0 + 2 - fireEvent.click(rendered.getByRole('button', { name: /inc/i })) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) - await waitFor(() => rendered.getByText('Data: selected 3')) // 0 + 3 + await waitFor(() => screen.getByText('Data: selected 3')) // 0 + 3 - fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i })) + fireEvent.click(screen.getByRole('button', { name: /forceUpdate/i })) - await waitFor(() => rendered.getByText('forceValue: 2')) + await waitFor(() => screen.getByText('forceValue: 2')) // data should still be 3 after an independent re-render - await waitFor(() => rendered.getByText('Data: selected 3')) + await waitFor(() => screen.getByText('Data: selected 3')) }) it('select should structurally share data', async () => { @@ -4355,14 +4855,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) - await waitFor(() => rendered.getByText('Data: [2,3]')) + render(() => ( + + + + )) + await waitFor(() => screen.getByText('Data: [2,3]')) expect(states).toHaveLength(1) - fireEvent.click(rendered.getByRole('button', { name: /forceUpdate/i })) + fireEvent.click(screen.getByRole('button', { name: /forceUpdate/i })) - await waitFor(() => rendered.getByText('forceValue: 2')) - await waitFor(() => rendered.getByText('Data: [2,3]')) + await waitFor(() => screen.getByText('forceValue: 2')) + await waitFor(() => screen.getByText('Data: [2,3]')) // effect should not be triggered again due to structural sharing expect(states).toHaveLength(1) @@ -4391,14 +4895,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient, , ) - await waitFor(() => rendered.getByText('off')) + await waitFor(() => screen.getByText('off')) if (typeof AbortSignal === 'function') { expect(cancelFn).toHaveBeenCalled() @@ -4429,7 +4933,7 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient( + renderWithClient( queryClient, @@ -4439,7 +4943,7 @@ describe('useQuery', () => { , ) - await waitFor(() => rendered.getByText('off')) + await waitFor(() => screen.getByText('off')) await sleep(20) await waitFor(() => expect(states).toHaveLength(4)) @@ -4500,7 +5004,9 @@ describe('useQuery', () => { const state = createQuery([key, id], queryFn) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) NotReact.useEffect(() => { setId((prevId) => (prevId === 1 ? 2 : 1)) @@ -4510,7 +5016,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) expect(states.length).toBe(4) @@ -4552,7 +5062,9 @@ describe('useQuery', () => { { staleTime: Infinity }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -4563,14 +5075,18 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /reset/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) await waitFor(() => expect(states.length).toBe(4)) - await waitFor(() => rendered.getByText('data: 2')) + await waitFor(() => screen.getByText('data: 2')) expect(count).toBe(2) @@ -4620,7 +5136,9 @@ describe('useQuery', () => { { staleTime: Infinity, enabled: false, notifyOnChangeProps: 'all' }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) const { refetch } = state @@ -4633,15 +5151,19 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: null')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: null')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('data: 1')) - fireEvent.click(rendered.getByRole('button', { name: /reset/i })) + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) - await waitFor(() => rendered.getByText('data: null')) + await waitFor(() => screen.getByText('data: null')) await waitFor(() => expect(states.length).toBe(4)) expect(count).toBe(1) @@ -4696,7 +5218,11 @@ describe('useQuery', () => { return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -4742,22 +5268,22 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) // initial state check - rendered.getByText('status: loading') + screen.getByText('status: loading') // // render error state component - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('error')) expect(queryFn).toBeCalledTimes(1) // change to enabled to false - fireEvent.click(rendered.getByLabelText('retry')) - await waitFor(() => rendered.getByText('error')) + fireEvent.click(screen.getByLabelText('retry')) + await waitFor(() => screen.getByText('error')) expect(queryFn).toBeCalledTimes(1) // // change to enabled to true - fireEvent.click(rendered.getByLabelText('retry')) + fireEvent.click(screen.getByLabelText('retry')) expect(queryFn).toBeCalledTimes(2) }) @@ -4803,21 +5329,21 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) // initial state check - rendered.getByText('status: loading') + screen.getByText('status: loading') // render error state component - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('error')) // change to unmount query - fireEvent.click(rendered.getByLabelText('change')) - await waitFor(() => rendered.getByText('rendered')) + fireEvent.click(screen.getByLabelText('change')) + await waitFor(() => screen.getByText('rendered')) // change to mount new query - fireEvent.click(rendered.getByLabelText('change')) - await waitFor(() => rendered.getByText('error')) + fireEvent.click(screen.getByLabelText('change')) + await waitFor(() => screen.getByText('error')) }) it('should refetch when query key changed when switching between erroneous queries', async () => { @@ -4858,23 +5384,23 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + renderWithClient(queryClient, ) // initial state check - rendered.getByText('status: fetching') + screen.getByText('status: fetching') // render error state component - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('error')) // change to mount second query - fireEvent.click(rendered.getByLabelText('change')) - await waitFor(() => rendered.getByText('status: fetching')) - await waitFor(() => rendered.getByText('error')) + fireEvent.click(screen.getByLabelText('change')) + await waitFor(() => screen.getByText('status: fetching')) + await waitFor(() => screen.getByText('error')) // change to mount first query again - fireEvent.click(rendered.getByLabelText('change')) - await waitFor(() => rendered.getByText('status: fetching')) - await waitFor(() => rendered.getByText('error')) + fireEvent.click(screen.getByLabelText('change')) + await waitFor(() => screen.getByText('status: fetching')) + await waitFor(() => screen.getByText('error')) }) it('should have no error in loading state when refetching after error occurred', async () => { @@ -4900,7 +5426,9 @@ describe('useQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) if (state.isLoading) { return
status: loading
@@ -4916,12 +5444,16 @@ describe('useQuery', () => { return
data: {state.data}
} - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('error')) + await waitFor(() => screen.getByText('error')) - fireEvent.click(rendered.getByRole('button', { name: 'refetch' })) - await waitFor(() => rendered.getByText('data: 5')) + fireEvent.click(screen.getByRole('button', { name: 'refetch' })) + await waitFor(() => screen.getByText('data: 5')) await waitFor(() => expect(states.length).toBe(4)) @@ -4980,18 +5512,20 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('status: loading, isPaused: true')) + await waitFor(() => screen.getByText('status: loading, isPaused: true')) onlineMock.mockReturnValue(true) window.dispatchEvent(new Event('online')) - await waitFor(() => - rendered.getByText('status: success, isPaused: false'), - ) + await waitFor(() => screen.getByText('status: success, isPaused: false')) await waitFor(() => { - expect(rendered.getByText('data: data')).toBeInTheDocument() + expect(screen.getByText('data: data')).toBeInTheDocument() }) expect(states).toEqual(['paused', 'fetching', 'idle']) @@ -5029,15 +5563,19 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data1')) + await waitFor(() => screen.getByText('data: data1')) const onlineMock = mockNavigatorOnLine(false) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: success, fetchStatus: paused, failureCount: 0', ), ) @@ -5046,18 +5584,16 @@ describe('useQuery', () => { window.dispatchEvent(new Event('online')) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: success, fetchStatus: fetching, failureCount: 0', ), ) await waitFor(() => - rendered.getByText( - 'status: success, fetchStatus: idle, failureCount: 0', - ), + screen.getByText('status: success, fetchStatus: idle, failureCount: 0'), ) await waitFor(() => { - expect(rendered.getByText('data: data2')).toBeInTheDocument() + expect(screen.getByText('data: data2')).toBeInTheDocument() }) onlineMock.mockRestore() @@ -5092,22 +5628,26 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data1')) + await waitFor(() => screen.getByText('data: data1')) const onlineMock = mockNavigatorOnLine(false) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) window.dispatchEvent(new FocusEvent('focus')) await sleep(15) await waitFor(() => - expect(rendered.queryByText('data: data2')).not.toBeInTheDocument(), + expect(screen.queryByText('data: data2')).not.toBeInTheDocument(), ) expect(count).toBe(1) onlineMock.mockRestore() @@ -5144,19 +5684,23 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: paused'), + screen.getByText('status: loading, fetchStatus: paused'), ) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await sleep(15) // invalidation should not trigger a refetch await waitFor(() => - rendered.getByText('status: loading, fetchStatus: paused'), + screen.getByText('status: loading, fetchStatus: paused'), ) expect(count).toBe(0) @@ -5195,22 +5739,26 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) await waitFor(() => { - expect(rendered.getByText('data: initial')).toBeInTheDocument() + expect(screen.getByText('data: initial')).toBeInTheDocument() }) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await sleep(15) // invalidation should not trigger a refetch await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) expect(count).toBe(0) @@ -5249,22 +5797,26 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) await waitFor(() => { - expect(rendered.getByText('data: initial')).toBeInTheDocument() + expect(screen.getByText('data: initial')).toBeInTheDocument() }) // triggers one pause - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await sleep(15) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) // triggers a second pause @@ -5278,10 +5830,10 @@ describe('useQuery', () => { }) await waitFor(() => - rendered.getByText('status: success, fetchStatus: idle'), + screen.getByText('status: success, fetchStatus: idle'), ) await waitFor(() => { - expect(rendered.getByText('data: data1')).toBeInTheDocument() + expect(screen.getByText('data: data1')).toBeInTheDocument() }) expect(count).toBe(1) @@ -5314,10 +5866,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: loading, fetchStatus: fetching, failureCount: 1', ), ) @@ -5327,7 +5883,7 @@ describe('useQuery', () => { await sleep(20) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: loading, fetchStatus: paused, failureCount: 1', ), ) @@ -5338,7 +5894,7 @@ describe('useQuery', () => { window.dispatchEvent(new Event('online')) await waitFor(() => - rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), + screen.getByText('status: error, fetchStatus: idle, failureCount: 3'), ) expect(count).toBe(3) @@ -5383,13 +5939,17 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: paused'), + screen.getByText('status: loading, fetchStatus: paused'), ) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) onlineMock.mockReturnValue(true) window.dispatchEvent(new Event('online')) @@ -5438,16 +5998,20 @@ describe('useQuery', () => { const onlineMock = mockNavigatorOnLine(false) - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: paused'), + screen.getByText('status: loading, fetchStatus: paused'), ) - fireEvent.click(rendered.getByRole('button', { name: /cancel/i })) + fireEvent.click(screen.getByRole('button', { name: /cancel/i })) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: idle'), + screen.getByText('status: loading, fetchStatus: idle'), ) expect(count).toBe(0) @@ -5458,7 +6022,7 @@ describe('useQuery', () => { await sleep(15) await waitFor(() => - rendered.getByText('status: loading, fetchStatus: idle'), + screen.getByText('status: loading, fetchStatus: idle'), ) expect(count).toBe(0) @@ -5506,21 +6070,25 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText('status: success, fetchStatus: idle'), + screen.getByText('status: success, fetchStatus: idle'), ) const onlineMock = mockNavigatorOnLine(false) - fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) + fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => - rendered.getByText('status: success, fetchStatus: paused'), + screen.getByText('status: success, fetchStatus: paused'), ) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) await sleep(15) @@ -5568,14 +6136,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => - rendered.getByText('status: success, isPaused: false'), - ) + await waitFor(() => screen.getByText('status: success, isPaused: false')) await waitFor(() => { - expect(rendered.getByText('data: data 1')).toBeInTheDocument() + expect(screen.getByText('data: data 1')).toBeInTheDocument() }) onlineMock.mockRestore() @@ -5612,12 +6182,16 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('status: error, isPaused: false')) + await waitFor(() => screen.getByText('status: error, isPaused: false')) await waitFor(() => { - expect(rendered.getByText('error: error 2')).toBeInTheDocument() + expect(screen.getByText('error: error 2')).toBeInTheDocument() }) expect(count).toBe(2) @@ -5656,10 +6230,14 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => - rendered.getByText( + screen.getByText( 'status: loading, fetchStatus: paused, failureCount: 1', ), ) @@ -5670,7 +6248,7 @@ describe('useQuery', () => { window.dispatchEvent(new Event('online')) await waitFor(() => - rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), + screen.getByText('status: error, fetchStatus: idle, failureCount: 3'), ) expect(count).toBe(3) @@ -5694,13 +6272,19 @@ describe('useQuery', () => { retryOnMount: false, }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return <> } await queryClient.prefetchQuery(key, queryFn) - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(states).toHaveLength(1)) @@ -5726,11 +6310,15 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data')) - fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i })) - await waitFor(() => rendered.getByText('data: newData')) + await waitFor(() => screen.getByText('data: data')) + fireEvent.click(screen.getByRole('button', { name: /setQueryData/i })) + await waitFor(() => screen.getByText('data: newData')) expect(onSuccess).toHaveBeenCalledTimes(1) expect(onSuccess).toHaveBeenCalledWith('data') @@ -5756,13 +6344,17 @@ describe('useQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: data')) - fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i })) - await waitFor(() => rendered.getByText('data: newData')) + await waitFor(() => screen.getByText('data: data')) + fireEvent.click(screen.getByRole('button', { name: /setQueryData/i })) + await waitFor(() => screen.getByText('data: newData')) await waitFor(() => { - expect(rendered.getByText('dataUpdatedAt: 100')).toBeInTheDocument() + expect(screen.getByText('dataUpdatedAt: 100')).toBeInTheDocument() }) }) @@ -5787,12 +6379,16 @@ describe('useQuery', () => {
) } - const rendered = renderWithClient(queryClient, ) - const fetchBtn = rendered.getByRole('button', { name: 'refetch' }) - await waitFor(() => rendered.getByText('data: 1')) + render(() => ( + + + + )) + const fetchBtn = screen.getByRole('button', { name: 'refetch' }) + await waitFor(() => screen.getByText('data: 1')) fireEvent.click(fetchBtn) - await waitFor(() => rendered.getByText('data: 2')) + await waitFor(() => screen.getByText('data: 2')) fireEvent.click(fetchBtn) - await waitFor(() => rendered.getByText('data: 3')) + await waitFor(() => screen.getByText('data: 3')) }) }) From 6f1660d40b2a4f706e6ea8bc858edc72cd650b03 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 15:10:11 -0400 Subject: [PATCH 137/221] replace remaining instances of renderWithClient --- .../src/__tests__/createQuery.test.tsx | 125 +++++++++++------- 1 file changed, 77 insertions(+), 48 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index e7298aed047..8fe2ab488b9 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -8,7 +8,7 @@ import { mockLogger, createQueryClient, } from '../../../../tests/utils' -import { renderWithClient, Blink, queryKey, setActTimeout } from './utils' +import { Blink, queryKey, setActTimeout } from './utils' import { createQuery, CreateQueryResult, @@ -1871,7 +1871,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => screen.getByText('data: 0')) act(() => screen.rerender()) await waitFor(() => screen.getByText('data: 1')) @@ -3146,12 +3150,13 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, -
error boundary
}> - -
, - ) + render(() => ( + +
error boundary
}> + +
+
+ )) await waitFor(() => screen.getByText('error boundary')) }) @@ -3205,12 +3210,13 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, -
error boundary
}> - -
, - ) + render(() => ( + +
error boundary
}> + +
+
+ )) await waitFor(() => screen.getByText('error')) await waitFor(() => screen.getByText('Local Error')) @@ -3237,20 +3243,21 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, - ( -
-
error boundary
- {/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} -
{error?.message}
-
- )} - > - -
, - ) + render(() => ( + + ( +
+
error boundary
+ {/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} +
{error?.message}
+
+ )} + > + +
+
+ )) await waitFor(() => screen.getByText('error boundary')) await waitFor(() => screen.getByText('Remote Error')) @@ -3293,7 +3300,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => screen.getByText('failureCount: 1')) fireEvent.click(screen.getByRole('button', { name: /hide/i })) @@ -3344,7 +3355,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => screen.getByText('failureCount: 1')) fireEvent.click(screen.getByRole('button', { name: /hide/i })) @@ -4895,12 +4910,13 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, - - - , - ) + render(() => ( + + + + + + )) await waitFor(() => screen.getByText('off')) @@ -4933,15 +4949,16 @@ describe('useQuery', () => { ) } - renderWithClient( - queryClient, - - - - - - , - ) + render(() => ( + + + + + + + + + )) await waitFor(() => screen.getByText('off')) await sleep(20) @@ -5268,7 +5285,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) // initial state check screen.getByText('status: loading') @@ -5329,7 +5350,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) // initial state check screen.getByText('status: loading') @@ -5384,7 +5409,11 @@ describe('useQuery', () => { ) } - renderWithClient(queryClient, ) + render(() => ( + + + + )) // initial state check screen.getByText('status: fetching') From bd1ad7701c7419e0a43395624af95a6c995b71f3 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 15:13:35 -0400 Subject: [PATCH 138/221] replace useQuery with createQuery --- .../solid-query/src/__tests__/createQuery.test.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 8fe2ab488b9..339f9bc619a 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -29,7 +29,7 @@ import { Show, } from 'solid-js' -describe('useQuery', () => { +describe('createQuery', () => { const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) @@ -163,7 +163,7 @@ describe('useQuery', () => { const test = useWrappedQuery([''], async () => '1') expectType(test.data) - // handles wrapped queries with custom fetcher passed directly to useQuery + // handles wrapped queries with custom fetcher passed directly to createQuery const useWrappedFuncStyleQuery = < TQueryKey extends [string, Record?], TQueryFnData, @@ -2337,12 +2337,12 @@ describe('useQuery', () => { data: 'prefetch', isStale: false, }, - // Second useQuery started fetching + // Second createQuery started fetching { data: 'prefetch', isStale: false, }, - // Second useQuery data came in + // Second createQuery data came in { data: 'two', isStale: false, @@ -2360,7 +2360,7 @@ describe('useQuery', () => { data: 'prefetch', isStale: true, }, - // Second useQuery data came in + // Second createQuery data came in { data: 'two', isStale: false, From 7aadd7029922ceef0ff9d0ebf9166005fdf9e6f1 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 15:26:50 -0400 Subject: [PATCH 139/221] add comment about excluding tests in tsconfig.json --- packages/solid-query/tsconfig.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json index 6146a991595..ec95ade5cea 100644 --- a/packages/solid-query/tsconfig.json +++ b/packages/solid-query/tsconfig.json @@ -9,7 +9,13 @@ "jsxImportSource": "solid-js", }, "include": ["src"], - "exclude": ["src/__tests__"], + // TODO(lukemurray): if we exclude tests, we get errors about missing react import + // the errors occur because the vscode typescript server only looks at tsconfig.json + // files for type check settings. + // eventually we should remove `jsx: react` from tsconfig.base.json + // but that will require adding `jsx: react` to all package level tsconfig.json + // so lets wait. + // "exclude": ["src/__tests__"], "references": [ { "path": "../query-core" } ] From 0ac3993513fbeaebf212311913854a7c5c5aeeb2 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 15:27:06 -0400 Subject: [PATCH 140/221] translate some more tests in createQuery --- .../src/__tests__/createQuery.test.tsx | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 339f9bc619a..8fab47edecf 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -741,7 +741,7 @@ describe('createQuery', () => { let fetchCount = 0 function Page() { - const { refetch } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -751,14 +751,14 @@ describe('createQuery', () => { { enabled: false, initialData: 'initialData' }, ) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - refetch() + state.refetch() }, 5) setActTimeout(() => { - refetch({ cancelRefetch: false }) + state.refetch({ cancelRefetch: false }) }, 5) - }, [refetch]) + }) return null } @@ -779,7 +779,7 @@ describe('createQuery', () => { let fetchCount = 0 function Page() { - const { refetch } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -789,14 +789,14 @@ describe('createQuery', () => { { enabled: false, initialData: 'initialData' }, ) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - refetch() + state.refetch() }, 5) setActTimeout(() => { - refetch() + state.refetch() }, 5) - }, [refetch]) + }) return null } @@ -817,7 +817,7 @@ describe('createQuery', () => { let fetchCount = 0 function Page() { - const { refetch } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -827,14 +827,14 @@ describe('createQuery', () => { { enabled: false }, ) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - refetch() + state.refetch() }, 5) setActTimeout(() => { - refetch() + state.refetch() }, 5) - }, [refetch]) + }) return null } @@ -854,7 +854,8 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryDefaults(key, { queryFn: () => 'data' }) + // TODO(lukemurray): do we want this to be reactive. + queryClient.setQueryDefaults(key(), { queryFn: () => 'data' }) function Page() { const state = createQuery(key) @@ -882,16 +883,19 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [toggle, setToggle] = NotReact.useState(false) + const [toggle, setToggle] = createSignal(false) return (
- {toggle ? ( - - ) : ( - - )} + + + + + + + +
) } From ae6e4e297ea270d64510529efcc6e67a8accf530 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 9 Sep 2022 17:24:31 -0400 Subject: [PATCH 141/221] revert mutate change --- packages/solid-query/src/createBaseQuery.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 3f3f289157b..0104fad717f 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -39,7 +39,7 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions), ) - const [dataResource, { mutate }] = createResource(() => { + const [dataResource, { refetch }] = createResource(() => { return new Promise((resolve) => { if (state.isSuccess) resolve(state.data) if (state.isError && !state.isFetching) { @@ -50,10 +50,8 @@ export function createBaseQuery< const unsubscribe = observer.subscribe((result) => { const reconciledResult = result - batch(() => { - setState(reconciledResult) - mutate(() => reconciledResult.data) - }) + setState(reconciledResult) + refetch() }) onCleanup(() => unsubscribe()) From 26c248a878a2bf0fcf6dbb117566ecdaf2191c15 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sat, 10 Sep 2022 18:17:40 -0400 Subject: [PATCH 142/221] Fix eslint config to make it stop complaining --- packages/solid-query/.eslintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc index a1437a22aac..514261e3fc9 100644 --- a/packages/solid-query/.eslintrc +++ b/packages/solid-query/.eslintrc @@ -1,6 +1,6 @@ { "parserOptions": { - "project": "./tsconfig.lint.json", + "project": "./packages/solid-query/tsconfig.lint.json", "sourceType": "module" }, "rules": { From 4b1a410a5b8b9a82504b9770b81ee2626a5c40bf Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sat, 10 Sep 2022 18:23:19 -0400 Subject: [PATCH 143/221] Add createInfiniteQuery --- .../solid-query/src/createInfiniteQuery.ts | 115 ++++++++++++++++++ packages/solid-query/src/index.ts | 33 ++--- packages/solid-query/src/types.ts | 33 ++++- packages/solid-query/src/utils.ts | 22 ++-- 4 files changed, 163 insertions(+), 40 deletions(-) create mode 100644 packages/solid-query/src/createInfiniteQuery.ts diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts new file mode 100644 index 00000000000..608772f4f00 --- /dev/null +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -0,0 +1,115 @@ +import { + QueryObserver, + InfiniteQueryObserver, + QueryFunction, +} from '@tanstack/query-core' +import { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + SolidQueryKey, +} from './types' +import { createBaseQuery } from './createBaseQuery' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' + +export function createInfiniteQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + options: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult +export function createInfiniteQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + options?: Omit< + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' + >, +): CreateInfiniteQueryResult +export function createInfiniteQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + queryKey: TQueryKey, + queryFn: QueryFunction>, + options?: Omit< + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' | 'queryFn' + >, +): CreateInfiniteQueryResult +export function createInfiniteQuery< + TQueryFnData, + TError, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +>( + arg1: + | TQueryKey + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg2?: + | QueryFunction> + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg3?: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult { + // The parseQuery Args functions helps normalize the arguments into the correct form. + // Whatever the parameters are, they are normalized into the correct form. + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) + + // Watch for changes in the options and update the parsed options. + createComputed(() => { + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) + + return createBaseQuery( + parsedOptions, + InfiniteQueryObserver as typeof QueryObserver, + ) as CreateInfiniteQueryResult +} diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index d11b5f5de9a..ed83fa58d90 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -1,26 +1,7 @@ -// Re-export core -export * from '@tanstack/query-core' - -// Solid Query -export * from './types' -// export { useQueries } from './useQueries' -// export type { QueriesResults, QueriesOptions } from './useQueries' -export { createQuery } from './createQuery' -export { - QueryClientContext as defaultContext, - QueryClientProvider, - useQueryClient, -} from './QueryClientProvider' -// export type { QueryClientProviderProps } from './QueryClientProvider' -// export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' -// export { useHydrate, Hydrate } from './Hydrate' -// export type { HydrateProps } from './Hydrate' -// export { -// QueryErrorResetBoundary, -// useQueryErrorResetBoundary, -// } from './QueryErrorResetBoundary' -export { useIsFetching } from './useIsFetching' -export { useIsMutating } from './useIsMutating' -export { createMutation } from './createMutation' -// export { useInfiniteQuery } from './useInfiniteQuery' -// export { useIsRestoring, IsRestoringProvider } from './isRestoring' +export * from './createQuery' +export * from './createInfiniteQuery' +export * from './QueryClientProvider' +export * from './createMutation' +export * from './useIsMutating' +export * from './useIsFetching' +export { QueryClient } from '@tanstack/query-core' diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 20ea33fb4a3..bb98e5996ae 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context, Accessor } from 'solid-js' +import type { Context } from 'solid-js' import type { QueryClient, QueryKey, @@ -8,7 +8,10 @@ import type { MutationObserverOptions, MutationObserverResult, DefinedQueryObserverResult, + InfiniteQueryObserverOptions, + InfiniteQueryObserverResult, QueryFilters, + QueryOptions, } from '@tanstack/query-core' export interface ContextOptions { @@ -63,6 +66,34 @@ export type DefinedCreateQueryResult< TError = unknown, > = DefinedCreateBaseQueryResult +export type ParseQueryArgs< + TOptions extends QueryOptions>, + TQueryKey extends () => readonly unknown[] = SolidQueryKey, +> = TOptions['queryKey'] extends () => infer R + ? TOptions & { queryKey: R } + : TOptions + +/* --- Create Infinite Queries Types --- */ +export interface CreateInfiniteQueryOptions< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryData = TQueryFnData, + TQueryKey extends () => readonly unknown[] = SolidQueryKey, +> extends ContextOptions, + InfiniteQueryObserverOptions< + TQueryFnData, + TError, + TData, + TQueryData, + ReturnType + > {} + +export type CreateInfiniteQueryResult< + TData = unknown, + TError = unknown, +> = InfiniteQueryObserverResult + /* --- Create Mutation Types --- */ export interface CreateMutationOptions< TData = unknown, diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index f164bec4454..6dc1f31787d 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,10 +1,10 @@ import { - CreateQueryOptions, SolidQueryKey, SolidQueryFilters, ParseFilterArgs, + ParseQueryArgs, } from './types' -import { QueryFunction } from '@tanstack/query-core' +import { QueryFunction, QueryOptions } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { return typeof value === 'function' @@ -13,17 +13,13 @@ export function isQueryKey(value: unknown): value is SolidQueryKey { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. export function parseQueryArgs< - TQueryFnData, - TError, - TData = TQueryFnData, + TOptions extends QueryOptions>, TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( - arg1: TQueryKey | CreateQueryOptions, - arg2?: - | QueryFunction> - | CreateQueryOptions, - arg3?: CreateQueryOptions, -): CreateQueryOptions { + arg1: TQueryKey | TOptions, + arg2?: QueryFunction> | TOptions, + arg3?: TOptions, +): ParseQueryArgs { if (!isQueryKey(arg1)) { const { queryKey: solidKey, ...opts } = arg1 as any if (solidKey) { @@ -32,7 +28,7 @@ export function parseQueryArgs< queryKey: solidKey(), } } - return arg1 + return arg1 as any } if (typeof arg2 === 'function') { @@ -53,6 +49,6 @@ export function parseFilterArgs< return ( isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1() }, arg3] - : [{ ...arg1, queryKey: arg1?.queryKey?.() } || {}, arg2] + : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] ) as [ParseFilterArgs, TOptions] } From ac96f746d64ab697a603b70ea96e19c154bab8f9 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Sat, 10 Sep 2022 12:33:24 -0400 Subject: [PATCH 144/221] chore: update package-lock.json --- package-lock.json | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index a24aecb7569..dc57335374d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43388,10 +43388,11 @@ } }, "packages/solid-query": { - "version": "4.2.3", + "name": "@tanstack/solid-query", + "version": "4.3.0-beta.4", "license": "MIT", "dependencies": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" }, "devDependencies": { "@types/jscodeshift": "^0.11.3", @@ -43404,15 +43405,6 @@ "peerDependencies": { "solid-js": "^1.5.4" } - }, - "packages/solid-query/node_modules/@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } } }, "dependencies": { @@ -50542,16 +50534,9 @@ "@tanstack/solid-query": { "version": "file:packages/solid-query", "requires": { - "@tanstack/query-core": "4.2.3", + "@tanstack/query-core": "4.3.0-beta.4", "@types/jscodeshift": "^0.11.3", "jscodeshift": "^0.13.1" - }, - "dependencies": { - "@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" - } } }, "@testing-library/dom": { From 532d21a08d2d5a1b51bc78a7f02837319949aabf Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Sun, 11 Sep 2022 15:38:07 -0400 Subject: [PATCH 145/221] fix: jest tests, copy over React query index file --- packages/solid-query/src/index.ts | 33 ++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index ed83fa58d90..5e5d3c88154 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -1,7 +1,26 @@ -export * from './createQuery' -export * from './createInfiniteQuery' -export * from './QueryClientProvider' -export * from './createMutation' -export * from './useIsMutating' -export * from './useIsFetching' -export { QueryClient } from '@tanstack/query-core' +// Re-export core +export * from '@tanstack/query-core' + +// Solid Query +export * from './types' +// export { useQueries } from './useQueries' +// export type { QueriesResults, QueriesOptions } from './useQueries' +export { createQuery } from './createQuery' +export { + QueryClientContext as defaultContext, + QueryClientProvider, + useQueryClient, +} from './QueryClientProvider' +// export type { QueryClientProviderProps } from './QueryClientProvider' +// export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' +// export { useHydrate, Hydrate } from './Hydrate' +// export type { HydrateProps } from './Hydrate' +// export { +// QueryErrorResetBoundary, +// useQueryErrorResetBoundary, +// } from './QueryErrorResetBoundary' +export { useIsFetching } from './useIsFetching' +export { useIsMutating } from './useIsMutating' +export { createMutation } from './createMutation' +export { createInfiniteQuery } from './createInfiniteQuery' +// export { useIsRestoring, IsRestoringProvider } from './isRestoring' From 21c11951b84a4e27e407cb795e0eaef6f37c6fa0 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Sun, 11 Sep 2022 16:49:18 -0400 Subject: [PATCH 146/221] fix: resolve data field to value of state when not loading, otherwise return the dataResource to trigger suspense --- packages/solid-query/src/createBaseQuery.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 0104fad717f..3cf13af077f 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -7,7 +7,6 @@ import { onCleanup, createComputed, createResource, - batch, } from 'solid-js' import { createStore } from 'solid-js/store' @@ -49,8 +48,7 @@ export function createBaseQuery< }) const unsubscribe = observer.subscribe((result) => { - const reconciledResult = result - setState(reconciledResult) + setState(result) refetch() }) @@ -71,7 +69,10 @@ export function createBaseQuery< prop: keyof QueryObserverResult, ): any { if (prop === 'data') { - return dataResource() + if (state.isLoading) { + return dataResource() + } + return state.data } return Reflect.get(target, prop) }, From 55a070084ce0c7e7b58039518537c86e4c607e4f Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sat, 10 Sep 2022 14:52:30 -0400 Subject: [PATCH 147/221] add is fetching and is mutating tests --- .../src/__tests__/useIsFetching.test.tsx | 295 ++++++++++++++++++ .../src/__tests__/useIsMutating.test.tsx | 279 +++++++++++++++++ 2 files changed, 574 insertions(+) create mode 100644 packages/solid-query/src/__tests__/useIsFetching.test.tsx create mode 100644 packages/solid-query/src/__tests__/useIsMutating.test.tsx diff --git a/packages/solid-query/src/__tests__/useIsFetching.test.tsx b/packages/solid-query/src/__tests__/useIsFetching.test.tsx new file mode 100644 index 00000000000..fe856ff9ea6 --- /dev/null +++ b/packages/solid-query/src/__tests__/useIsFetching.test.tsx @@ -0,0 +1,295 @@ +import { fireEvent, render, waitFor, screen } from 'solid-testing-library' + +import { + createQueryClient, + setActTimeout, + sleep, +} from '../../../../tests/utils' +import { queryKey } from './utils' +import { createQuery, useIsFetching, QueryCache, QueryClientProvider } from '..' +import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js' + +describe('useIsFetching', () => { + // See https://github.com/tannerlinsley/react-query/issues/105 + it('should update as queries start and stop fetching', async () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + const key = queryKey() + + function IsFetching() { + const isFetching = useIsFetching() + return
isFetching: {isFetching()}
+ } + + function Query() { + const [ready, setReady] = createSignal(false) + + createQuery( + key, + async () => { + await sleep(50) + return 'test' + }, + { + enabled: ready(), + }, + ) + + return + } + + function Page() { + return ( +
+ + +
+ ) + } + + render(() => ( + + + + )) + + await screen.findByText('isFetching: 0') + fireEvent.click(screen.getByRole('button', { name: /setReady/i })) + await screen.findByText('isFetching: 1') + await screen.findByText('isFetching: 0') + }) + + it('should not update state while rendering', async () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + const key1 = queryKey() + const key2 = queryKey() + + const isFetchings: number[] = [] + + function IsFetching() { + const isFetching = useIsFetching() + createRenderEffect(() => { + isFetchings.push(isFetching()) + }) + return null + } + + function FirstQuery() { + createQuery(key1, async () => { + await sleep(100) + return 'data' + }) + return null + } + + function SecondQuery() { + createQuery(key2, async () => { + await sleep(100) + return 'data' + }) + return null + } + + function Page() { + const [renderSecond, setRenderSecond] = createSignal(false) + + createEffect(() => { + setActTimeout(() => { + setRenderSecond(true) + }, 50) + }) + + return ( + <> + + + + + + + ) + } + + render(() => ( + + + + )) + await waitFor(() => expect(isFetchings).toEqual([0, 1, 1, 2, 1, 0])) + }) + + it('should be able to filter', async () => { + const queryClient = createQueryClient() + const key1 = queryKey() + const key2 = queryKey() + + const isFetchings: number[] = [] + + function One() { + createQuery(key1, async () => { + await sleep(10) + return 'test' + }) + return null + } + + function Two() { + createQuery(key2, async () => { + await sleep(20) + return 'test' + }) + return null + } + + function Page() { + const [started, setStarted] = createSignal(false) + const isFetching = useIsFetching(key1) + + createRenderEffect(() => { + isFetchings.push(isFetching()) + }) + + return ( +
+ +
isFetching: {isFetching()}
+ + <> + + + + +
+ ) + } + + render(() => ( + + + + )) + + await screen.findByText('isFetching: 0') + fireEvent.click(screen.getByRole('button', { name: /setStarted/i })) + await screen.findByText('isFetching: 1') + await screen.findByText('isFetching: 0') + // at no point should we have isFetching: 2 + expect(isFetchings).toEqual(expect.not.arrayContaining([2])) + }) + + // TODO(lukemurray): add when we support custom contexts + // describe('with custom context', () => { + // it('should update as queries start and stop fetching', async () => { + // const context = createContext(undefined) + + // const queryCache = new QueryCache() + // const queryClient = createQueryClient({ queryCache }) + // const key = queryKey() + + // function Page() { + // const [ready, setReady] = createSignal(false) + + // const isFetching = useIsFetching(undefined, { context: context }) + + // createQuery( + // key, + // async () => { + // await sleep(50) + // return 'test' + // }, + // { + // enabled: ready(), + // context, + // }, + // ) + + // return ( + //
+ //
isFetching: {isFetching}
+ // + //
+ // ) + // } + + // const { findByText, getByRole } = renderWithClient( + // queryClient, + // , + // { + // context, + // }, + // ) + + // await findByText('isFetching: 0') + // fireEvent.click(getByRole('button', { name: /setReady/i })) + // await findByText('isFetching: 1') + // await findByText('isFetching: 0') + // }) + + // it('should throw if the context is not passed to useIsFetching', async () => { + // const context = React.createContext(undefined) + + // const queryCache = new QueryCache() + // const queryClient = createQueryClient({ queryCache }) + // const key = queryKey() + + // function Page() { + // const isFetching = useIsFetching() + + // createQuery(key, async () => 'test', { + // enabled: true, + // context, + // useErrorBoundary: true, + // }) + + // return ( + //
+ //
isFetching: {isFetching}
+ //
+ // ) + // } + + // const rendered = renderWithClient( + // queryClient, + //
error boundary
}> + // + //
, + // { + // context, + // }, + // ) + + // await waitFor(() => rendered.getByText('error boundary')) + // }) + // }) + + it('should show the correct fetching state when mounted after a query', async () => { + const queryClient = createQueryClient() + const key = queryKey() + + function Page() { + createQuery(key, async () => { + await sleep(10) + return 'test' + }) + + const isFetching = useIsFetching() + + return ( +
+
isFetching: {isFetching()}
+
+ ) + } + + render(() => ( + + + + )) + + await screen.findByText('isFetching: 1') + await screen.findByText('isFetching: 0') + }) +}) diff --git a/packages/solid-query/src/__tests__/useIsMutating.test.tsx b/packages/solid-query/src/__tests__/useIsMutating.test.tsx new file mode 100644 index 00000000000..3a83903c141 --- /dev/null +++ b/packages/solid-query/src/__tests__/useIsMutating.test.tsx @@ -0,0 +1,279 @@ +import { waitFor, fireEvent, screen } from 'solid-testing-library' +import { useIsMutating, createMutation, QueryClientProvider } from '..' +import { createQueryClient, sleep } from '../../../../tests/utils' + +import { setActTimeout } from './utils' +import * as MutationCacheModule from '../../../query-core/src/mutationCache' +import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js' +import { render } from 'solid-testing-library' + +describe('useIsMutating', () => { + it('should return the number of fetching mutations', async () => { + const isMutatings: number[] = [] + const queryClient = createQueryClient() + + function IsMutating() { + const isMutating = useIsMutating() + createRenderEffect(() => { + isMutatings.push(isMutating()) + }) + return null + } + + function Mutations() { + const { mutate: mutate1 } = createMutation(['mutation1'], async () => { + await sleep(150) + return 'data' + }) + const { mutate: mutate2 } = createMutation(['mutation2'], async () => { + await sleep(50) + return 'data' + }) + + createEffect(() => { + mutate1() + setActTimeout(() => { + mutate2() + }, 50) + }) + + return null + } + + function Page() { + return ( +
+ + +
+ ) + } + + render(() => ( + + + + )) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 2, 1, 0])) + }) + + it('should filter correctly by mutationKey', async () => { + const isMutatings: number[] = [] + const queryClient = createQueryClient() + + function IsMutating() { + const isMutating = useIsMutating(['mutation1']) + createRenderEffect(() => { + isMutatings.push(isMutating()) + }) + return null + } + + function Page() { + const { mutate: mutate1 } = createMutation(['mutation1'], async () => { + await sleep(100) + return 'data' + }) + const { mutate: mutate2 } = createMutation(['mutation2'], async () => { + await sleep(100) + return 'data' + }) + + createEffect(() => { + mutate1() + mutate2() + }) + + return + } + + render(() => ( + + + + )) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0])) + }) + + it('should filter correctly by predicate', async () => { + const isMutatings: number[] = [] + const queryClient = createQueryClient() + + function IsMutating() { + const isMutating = useIsMutating({ + predicate: (mutation) => + mutation.options.mutationKey?.[0] === 'mutation1', + }) + createRenderEffect(() => { + isMutatings.push(isMutating()) + }) + return null + } + + function Page() { + const { mutate: mutate1 } = createMutation(['mutation1'], async () => { + await sleep(100) + return 'data' + }) + const { mutate: mutate2 } = createMutation(['mutation2'], async () => { + await sleep(100) + return 'data' + }) + + createEffect(() => { + mutate1() + mutate2() + }) + + return + } + + render(() => ( + + + + )) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0])) + }) + + it('should not change state if unmounted', async () => { + // We have to mock the MutationCache to not unsubscribe + // the listener when the component is unmounted + class MutationCacheMock extends MutationCacheModule.MutationCache { + subscribe(listener: any) { + super.subscribe(listener) + return () => void 0 + } + } + + const MutationCacheSpy = jest + .spyOn(MutationCacheModule, 'MutationCache') + .mockImplementation((fn) => { + return new MutationCacheMock(fn) + }) + + const queryClient = createQueryClient() + + function IsMutating() { + useIsMutating() + return null + } + + function Page() { + const [mounted, setMounted] = createSignal(true) + const { mutate: mutate1 } = createMutation(['mutation1'], async () => { + await sleep(10) + return 'data' + }) + + createEffect(() => { + mutate1() + }) + + return ( +
+ + + + +
+ ) + } + + render(() => ( + + + + )) + fireEvent.click(screen.getByText('unmount')) + + // Should not display the console error + // "Warning: Can't perform a React state update on an unmounted component" + + await sleep(20) + MutationCacheSpy.mockRestore() + }) + + // TODO(lukemurray): re-add when we support custom context. + // describe('with custom context', () => { + // it('should return the number of fetching mutations', async () => { + // const context = React.createContext(undefined) + + // const isMutatings: number[] = [] + // const queryClient = new QueryClient() + + // function IsMutating() { + // const isMutating = useIsMutating(undefined, { context }) + // isMutatings.push(isMutating) + // return null + // } + + // function Page() { + // const { mutate: mutate1 } = useMutation( + // ['mutation1'], + // async () => { + // await sleep(150) + // return 'data' + // }, + // { context }, + // ) + // const { mutate: mutate2 } = useMutation( + // ['mutation2'], + // async () => { + // await sleep(50) + // return 'data' + // }, + // { context }, + // ) + + // React.useEffect(() => { + // mutate1() + // setActTimeout(() => { + // mutate2() + // }, 50) + // }, [mutate1, mutate2]) + + // return + // } + + // renderWithClient(queryClient, , { context }) + // await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0])) + // }) + + // it('should throw if the context is not passed to useIsMutating', async () => { + // const context = React.createContext(undefined) + + // const isMutatings: number[] = [] + // const queryClient = new QueryClient() + + // function IsMutating() { + // const isMutating = useIsMutating(undefined) + // isMutatings.push(isMutating) + // return null + // } + + // function Page() { + // const { mutate } = useMutation(['mutation'], async () => 'data', { + // useErrorBoundary: true, + // context, + // }) + + // React.useEffect(() => { + // mutate() + // }, [mutate]) + + // return + // } + + // const rendered = renderWithClient( + // queryClient, + //
error boundary
}> + // + //
, + // { context }, + // ) + + // await waitFor(() => rendered.getByText('error boundary')) + // }) + // }) +}) From 9b45c397e78cfbb9590589c8bdb20e192ab67553 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 12:56:56 -0400 Subject: [PATCH 148/221] update provider to use context sharing --- .../solid-query/src/QueryClientProvider.tsx | 84 ++++--- .../__tests__/QueryClientProvider.test.tsx | 227 +++++++++--------- 2 files changed, 169 insertions(+), 142 deletions(-) diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index 12067d7dee9..9dfd87aaaf4 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -1,12 +1,12 @@ import type { QueryClient } from '@tanstack/query-core' import { - Component, Context, createContext, useContext, JSX, onMount, onCleanup, + mergeProps, } from 'solid-js' import { ContextOptions } from './types' @@ -16,31 +16,16 @@ declare global { } } -export const QueryClientContext = createContext() -export const QueryClientSharingContext = createContext(false) - -interface Props { - client: QueryClient - children: JSX.Element -} - -// Simple Query Client Context Provider -export const QueryClientProvider: Component = (props) => { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime check. - if (!props.client) { - throw new Error('No QueryClient set, use QueryClientProvider to set one') - } - - onMount(() => props.client.mount()) - onCleanup(() => props.client.unmount()) - - return ( - - {props.children} - - ) -} +export const defaultContext = createContext(undefined) +const QueryClientSharingContext = createContext(false) +// If we are given a context, we will use it. +// Otherwise, if contextSharing is on, we share the first and at least one +// instance of the context across the window +// to ensure that if React Query is used across +// different bundles or microfrontends they will +// all use the same **instance** of context, regardless +// of module scoping. function getQueryClientContext( context: Context | undefined, contextSharing: boolean, @@ -48,16 +33,15 @@ function getQueryClientContext( if (context) { return context } - if (contextSharing && typeof window !== 'undefined') { if (!window.SolidQueryClientContext) { - window.SolidQueryClientContext = QueryClientContext + window.SolidQueryClientContext = defaultContext } return window.SolidQueryClientContext } - return QueryClientContext + return defaultContext } export const useQueryClient = ({ context }: ContextOptions = {}) => { @@ -71,3 +55,47 @@ export const useQueryClient = ({ context }: ContextOptions = {}) => { return queryClient } + +type QueryClientProviderPropsBase = { + client: QueryClient + children?: JSX.Element +} +type QueryClientProviderPropsWithContext = ContextOptions & { + contextSharing?: never +} & QueryClientProviderPropsBase +type QueryClientProviderPropsWithContextSharing = { + context?: never + contextSharing?: boolean +} & QueryClientProviderPropsBase + +export type QueryClientProviderProps = + | QueryClientProviderPropsWithContext + | QueryClientProviderPropsWithContextSharing + +export const QueryClientProvider = ( + props: QueryClientProviderProps, +): JSX.Element => { + const mergedProps = mergeProps( + { + contextSharing: false, + }, + props, + ) + onMount(() => mergedProps.client.mount()) + onCleanup(() => mergedProps.client.unmount()) + + const QueryClientContext = getQueryClientContext( + mergedProps.context, + mergedProps.contextSharing, + ) + + return ( + + + {mergedProps.children} + + + ) +} diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx index f5d9786dcae..509fa0400af 100644 --- a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -1,9 +1,11 @@ import { render, screen, waitFor } from 'solid-testing-library' import { queryKey } from './utils' -import { QueryCache } from '@tanstack/query-core' +import { QueryCache, QueryClient } from '@tanstack/query-core' import { createQuery, QueryClientProvider, useQueryClient } from '..' import { createQueryClient, sleep } from '../../../../tests/utils' +import { Context, createContext, useContext } from 'solid-js' +import { renderToString } from 'solid-js/web' describe('QueryClientProvider', () => { test('sets a specific cache for all queries to use', async () => { @@ -131,64 +133,63 @@ describe('QueryClientProvider', () => { expect(queryCache.find(key())?.options.cacheTime).toBe(Infinity) }) - // TODO(lukemurray): add test when we implement context sharing. - // describe('with custom context', () => { - // it('uses the correct context', async () => { - // const key = queryKey() - - // const contextOuter = createContext(undefined) - // const contextInner = createContext(undefined) - - // const queryCacheOuter = new QueryCache() - // const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) - - // const queryCacheInner = new QueryCache() - // const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) - - // const queryCacheInnerInner = new QueryCache() - // const queryClientInnerInner = new QueryClient({ - // queryCache: queryCacheInnerInner, - // }) - - // function Page() { - // const queryOuter = createQuery(key, async () => 'testOuter', { - // context: contextOuter, - // }) - // const queryInner = createQuery(key, async () => 'testInner', { - // context: contextInner, - // }) - // const queryInnerInner = createQuery(key, async () => 'testInnerInner') - - // return ( - //
- //

- // {queryOuter.data} {queryInner.data} {queryInnerInner.data} - //

- //
- // ) - // } - - // // contextSharing should be ignored when passing a custom context. - // const contextSharing = true - - // render(() => ( - // - // - // - // - // - // - // - // )) - - // await waitFor(() => - // screen.getByText('testOuter testInner testInnerInner'), - // ) - // }) - // }) + describe('with custom context', () => { + it('uses the correct context', async () => { + const key = queryKey() + + const contextOuter = createContext(undefined) + const contextInner = createContext(undefined) + + const queryCacheOuter = new QueryCache() + const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter }) + + const queryCacheInner = new QueryCache() + const queryClientInner = new QueryClient({ queryCache: queryCacheInner }) + + const queryCacheInnerInner = new QueryCache() + const queryClientInnerInner = new QueryClient({ + queryCache: queryCacheInnerInner, + }) + + function Page() { + const queryOuter = createQuery(key, async () => 'testOuter', { + context: contextOuter, + }) + const queryInner = createQuery(key, async () => 'testInner', { + context: contextInner, + }) + const queryInnerInner = createQuery(key, async () => 'testInnerInner') + + return ( +
+

+ {queryOuter.data} {queryInner.data} {queryInnerInner.data} +

+
+ ) + } + + // contextSharing should be ignored when passing a custom context. + const contextSharing = true + + render(() => ( + + + + + + + + )) + + await waitFor(() => + screen.getByText('testOuter testInner testInnerInner'), + ) + }) + }) describe('useQueryClient', () => { test('should throw an error if no query client has been set', () => { @@ -208,60 +209,58 @@ describe('QueryClientProvider', () => { consoleMock.mockRestore() }) - // TODO(lukemurray): add test when we implement context sharing - // test('should use window to get the context when contextSharing is true', () => { - // const queryCache = new QueryCache() - // const queryClient = createQueryClient({ queryCache }) - - // let queryClientFromHook: QueryClient | undefined - // let queryClientFromWindow: QueryClient | undefined - - // function Page() { - // queryClientFromHook = useQueryClient() - // queryClientFromWindow = useContext( - // window.SolidQueryClientContext as Context, - // ) - // return null - // } - - // render(() => ( - // - // - // - // )) - - // expect(queryClientFromHook).toEqual(queryClient) - // expect(queryClientFromWindow).toEqual(queryClient) - // }) - - // TODO(lukemurray): add test when we implement context sharing - // test('should not use window to get the context when contextSharing is true and window does not exist', () => { - // const queryCache = new QueryCache() - // const queryClient = createQueryClient({ queryCache }) - - // // Mock a non web browser environment - // const windowSpy = jest - // .spyOn(window, 'window', 'get') - // .mockImplementation(undefined) - - // let queryClientFromHook: QueryClient | undefined - - // function Page() { - // queryClientFromHook = useQueryClient() - // return null - // } - - // // TODO(lukemurray): this test doesn't pass because the page function is - // // never called. I'm not sure why. - // renderToString(() => ( - // - // - // - // )) - - // expect(queryClientFromHook).toEqual(queryClient) - - // windowSpy.mockRestore() - // }) + test('should use window to get the context when contextSharing is true', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + let queryClientFromHook: QueryClient | undefined + let queryClientFromWindow: QueryClient | undefined + + function Page() { + queryClientFromHook = useQueryClient() + queryClientFromWindow = useContext( + window.SolidQueryClientContext as Context, + ) + return null + } + + render(() => ( + + + + )) + + expect(queryClientFromHook).toEqual(queryClient) + expect(queryClientFromWindow).toEqual(queryClient) + }) + + test('should not use window to get the context when contextSharing is true and window does not exist', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + // Mock a non web browser environment + const windowSpy = jest + .spyOn(window, 'window', 'get') + .mockImplementation(undefined) + + let queryClientFromHook: QueryClient | undefined + + function Page() { + queryClientFromHook = useQueryClient() + return null + } + + // TODO(lukemurray): this test doesn't pass because the page function is + // never called. I'm not sure why. + renderToString(() => ( + + + + )) + + expect(queryClientFromHook).toEqual(queryClient) + + windowSpy.mockRestore() + }) }) }) From 212c19ab551d8810eea20870d74d5e200404cff4 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 13:18:31 -0400 Subject: [PATCH 149/221] add error reset boundary --- .../src/QueryErrorResetBoundary.tsx | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 packages/solid-query/src/QueryErrorResetBoundary.tsx diff --git a/packages/solid-query/src/QueryErrorResetBoundary.tsx b/packages/solid-query/src/QueryErrorResetBoundary.tsx new file mode 100644 index 00000000000..a501e7d7ffb --- /dev/null +++ b/packages/solid-query/src/QueryErrorResetBoundary.tsx @@ -0,0 +1,50 @@ +// CONTEXT + +import { createContext, createSignal, useContext, JSX } from 'solid-js' + +interface QueryErrorResetBoundaryValue { + clearReset: () => void + isReset: () => boolean + reset: () => void +} + +function createValue(): QueryErrorResetBoundaryValue { + const [isReset, setIsReset] = createSignal(false) + return { + clearReset: () => { + setIsReset(false) + }, + reset: () => { + setIsReset(true) + }, + isReset: () => { + return isReset() + }, + } +} + +const QueryErrorResetBoundaryContext = createContext(createValue()) + +// HOOK + +export const useQueryErrorResetBoundary = () => + useContext(QueryErrorResetBoundaryContext) + +// COMPONENT + +export interface QueryErrorResetBoundaryProps { + children: ((value: QueryErrorResetBoundaryValue) => JSX.Element) | JSX.Element +} + +export const QueryErrorResetBoundary = ( + props: QueryErrorResetBoundaryProps, +) => { + const [value] = createSignal(createValue()) + return ( + + {typeof props.children === 'function' + ? (props.children as Function)(value) + : props.children} + + ) +} From e9d4decc76bd7c9d855c2ed2138fce3048a4a6bb Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 13:20:01 -0400 Subject: [PATCH 150/221] update package exports --- .../src/__tests__/suspense.test.tsx | 1064 +++++++++++++++++ packages/solid-query/src/index.ts | 14 +- 2 files changed, 1071 insertions(+), 7 deletions(-) create mode 100644 packages/solid-query/src/__tests__/suspense.test.tsx diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx new file mode 100644 index 00000000000..d9d27d618c8 --- /dev/null +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -0,0 +1,1064 @@ +import { waitFor, fireEvent, render, screen } from 'solid-testing-library' + +import { sleep, createQueryClient } from '../../../../tests/utils' +import { queryKey } from './utils' +import { + createQuery, + QueryCache, + QueryErrorResetBoundary, + useQueryErrorResetBoundary, + CreateQueryResult, + CreateInfiniteQueryResult, + createInfiniteQuery, + QueryClientProvider, +} from '..' +import { createSignal, ErrorBoundary, Suspense } from 'solid-js' + +describe("useQuery's in Suspense mode", () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should render the correct amount of times in Suspense mode', async () => { + const key = queryKey() + const states: CreateQueryResult[] = [] + + let count = 0 + let renders = 0 + + function Page() { + renders++ + + const [stateKey, setStateKey] = createSignal(key()) + + const state = createQuery( + stateKey, + async () => { + count++ + await sleep(10) + return count + }, + { suspense: true }, + ) + + states.push(state) + + return ( +
+
+ ) + } + + render(() => ( + + + + + + )) + + await waitFor(() => screen.getByText('data: 1')) + fireEvent.click(screen.getByLabelText('toggle')) + + await waitFor(() => screen.getByText('data: 2')) + + expect(renders).toBe(4) + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ data: 1, status: 'success' }) + expect(states[1]).toMatchObject({ data: 2, status: 'success' }) + }) + + it('should return the correct states for a successful infinite query', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const [multiplier, setMultiplier] = createSignal(1) + const state = createInfiniteQuery( + () => [`${key}_${multiplier}`], + async ({ pageParam = 1 }) => { + await sleep(10) + return Number(pageParam * multiplier()) + }, + { + suspense: true, + getNextPageParam: (lastPage) => lastPage + 1, + }, + ) + states.push(state) + return ( +
+ + data: {state.data?.pages.join(',')} +
+ ) + } + + render(() => ( + + + + + , + + )) + + await waitFor(() => screen.getByText('data: 1')) + + expect(states.length).toBe(1) + expect(states[0]).toMatchObject({ + data: { pages: [1], pageParams: [undefined] }, + status: 'success', + }) + + fireEvent.click(screen.getByText('next')) + await waitFor(() => screen.getByText('data: 2')) + + expect(states.length).toBe(2) + expect(states[1]).toMatchObject({ + data: { pages: [2], pageParams: [undefined] }, + status: 'success', + }) + }) + + it('should not call the queryFn twice when used in Suspense mode', async () => { + const key = queryKey() + + const queryFn = jest.fn() + queryFn.mockImplementation(() => { + sleep(10) + return 'data' + }) + + function Page() { + createQuery(() => [key()], queryFn, { suspense: true }) + + return <>rendered + } + + render(() => ( + + + + + , + + )) + + await waitFor(() => screen.getByText('rendered')) + + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should remove query instance when component unmounted', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + () => { + sleep(10) + return 'data' + }, + { suspense: true }, + ) + + return <>rendered + } + + function App() { + const [show, setShow] = createSignal(false) + + return ( + <> + {show() && } + +
+ )} + > + + + + + )} + + + )) + + await waitFor(() => screen.getByText('Loading...')) + + await waitFor(() => screen.getByText('error boundary')) + + await waitFor(() => screen.getByText('retry')) + + fireEvent.click(screen.getByText('retry')) + + await waitFor(() => screen.getByText('rendered')) + }) + + it('should retry fetch if the reset error boundary has been reset', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Suspense Error Bingo') + } else { + return 'data' + } + }, + { + retry: false, + suspense: true, + }, + ) + return
rendered
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + + + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('rendered')) + }) + + it('should refetch when re-mounting', async () => { + const key = queryKey() + let count = 0 + + function Component() { + const result = createQuery( + key, + async () => { + await sleep(100) + count++ + return count + }, + { + retry: false, + suspense: true, + staleTime: 0, + }, + ) + return ( +
+ data: {result.data} + fetching: {result.isFetching ? 'true' : 'false'} +
+ ) + } + + function Page() { + const [show, setShow] = createSignal(true) + return ( +
+ + {show() && } +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('data: 1')) + await waitFor(() => screen.getByText('fetching: false')) + await waitFor(() => screen.getByText('hide')) + fireEvent.click(screen.getByText('hide')) + await waitFor(() => screen.getByText('show')) + fireEvent.click(screen.getByText('show')) + await waitFor(() => screen.getByText('fetching: true')) + await waitFor(() => screen.getByText('data: 2')) + await waitFor(() => screen.getByText('fetching: false')) + }) + + it('should suspend when switching to a new query', async () => { + const key1 = queryKey() + const key2 = queryKey() + + function Component(props: { queryKey: Array }) { + const result = createQuery( + () => props.queryKey, + async () => { + await sleep(100) + return props.queryKey + }, + { + retry: false, + suspense: true, + }, + ) + return
data: {result.data}
+ } + + function Page() { + const [key, setKey] = createSignal(key1()) + return ( +
+ + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText(`data: ${key1}`)) + fireEvent.click(screen.getByText('switch')) + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText(`data: ${key2}`)) + expect( + // @ts-expect-error + queryClient.getQueryCache().find(key2)!.observers[0].listeners.length, + ).toBe(1) + }) + + it('should retry fetch if the reset error boundary has been reset with global hook', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Suspense Error Bingo') + } else { + return 'data' + } + }, + { + retry: false, + suspense: true, + }, + ) + return
rendered
+ } + + function App() { + const { reset: resetQuery } = useQueryErrorResetBoundary() + return ( + ( +
+
error boundary
+ +
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('rendered')) + }) + + it('should throw errors to the error boundary by default', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + async (): Promise => { + await sleep(10) + throw new Error('Suspense Error a1x') + }, + { + retry: false, + suspense: true, + }, + ) + return
rendered
+ } + + function App() { + return ( + ( +
+
error boundary
+
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should not throw errors to the error boundary when useErrorBoundary: false', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + async (): Promise => { + await sleep(10) + throw new Error('Suspense Error a2x') + }, + { + retry: false, + suspense: true, + useErrorBoundary: false, + }, + ) + return
rendered
+ } + + function App() { + return ( + ( +
+
error boundary
+
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('rendered')) + }) + + it('should not throw errors to the error boundary when a useErrorBoundary function returns true', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + async (): Promise => { + await sleep(10) + return Promise.reject('Remote Error') + }, + { + retry: false, + suspense: true, + useErrorBoundary: (err) => err !== 'Local Error', + }, + ) + return
rendered
+ } + + function App() { + return ( + ( +
+
error boundary
+
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should not throw errors to the error boundary when a useErrorBoundary function returns false', async () => { + const key = queryKey() + + function Page() { + createQuery( + key, + async (): Promise => { + await sleep(10) + return Promise.reject('Local Error') + }, + { + retry: false, + suspense: true, + useErrorBoundary: (err) => err !== 'Local Error', + }, + ) + return
rendered
+ } + + function App() { + return ( + ( +
+
error boundary
+
+ )} + > + + + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('Loading...')) + await waitFor(() => screen.getByText('rendered')) + }) + + it('should not call the queryFn when not enabled', async () => { + const key = queryKey() + + const queryFn = jest.fn, unknown[]>() + queryFn.mockImplementation(async () => { + await sleep(10) + return '23' + }) + + function Page() { + const [enabled, setEnabled] = createSignal(false) + const result = createQuery(() => [key()], queryFn, { + suspense: true, + enabled: enabled(), + }) + + return ( +
+ +

{result.data}

+
+ ) + } + + render(() => ( + + + + + + )) + + expect(queryFn).toHaveBeenCalledTimes(0) + + fireEvent.click(screen.getByRole('button', { name: /fire/i })) + + await waitFor(() => { + expect(screen.getByRole('heading').textContent).toBe('23') + }) + + expect(queryFn).toHaveBeenCalledTimes(1) + }) + + it('should error catched in error boundary without infinite loop', async () => { + const key = queryKey() + + let succeed = true + + function Page() { + const [nonce] = createSignal(0) + const queryKeys = () => [`${key()}-${succeed}`] + const result = createQuery( + queryKeys, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Suspense Error Bingo') + } else { + return nonce + } + }, + { + retry: false, + suspense: true, + }, + ) + return ( +
+ rendered {result.data} + +
+ ) + } + + function App() { + const { reset } = useQueryErrorResetBoundary() + return ( +
error boundary
}> + + + +
+ ) + } + + render(() => ( + + + + )) + + // render suspense fallback (Loading...) + await waitFor(() => screen.getByText('Loading...')) + // resolve promise -> render Page (rendered) + await waitFor(() => screen.getByText('rendered')) + + // change query key + succeed = false + // reset query -> and throw error + fireEvent.click(screen.getByLabelText('fail')) + // render error boundary fallback (error boundary) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should error catched in error boundary without infinite loop when query keys changed', async () => { + let succeed = true + + function Page() { + const [key, rerender] = React.useReducer((x) => x + 1, 0) + const queryKeys = [key, succeed] + + const result = createQuery( + queryKeys, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Suspense Error Bingo') + } else { + return 'data' + } + }, + { + retry: false, + suspense: true, + }, + ) + return ( +
+ rendered {result.data} + +
+ ) + } + + function App() { + const { reset } = useQueryErrorResetBoundary() + return ( +
error boundary
}> + + + +
+ ) + } + + render(() => ( + + + + )) + + // render suspense fallback (Loading...) + await waitFor(() => screen.getByText('Loading...')) + // resolve promise -> render Page (rendered) + await waitFor(() => screen.getByText('rendered')) + + // change promise result to error + succeed = false + // change query key + fireEvent.click(screen.getByLabelText('fail')) + // render error boundary fallback (error boundary) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should error catched in error boundary without infinite loop when enabled changed', async () => { + function Page() { + const queryKeys = '1' + const [enabled, setEnabled] = createSignal(false) + + const result = createQuery( + () => [queryKeys], + async () => { + await sleep(10) + throw new Error('Suspense Error Bingo') + }, + { + retry: false, + suspense: true, + enabled: enabled(), + }, + ) + return ( +
+ rendered {result.data} + +
+ ) + } + + function App() { + const { reset } = useQueryErrorResetBoundary() + return ( +
error boundary
}> + + + +
+ ) + } + + render(() => ( + + + + )) + + // render empty data with 'rendered' when enabled is false + await waitFor(() => screen.getByText('rendered')) + + // change enabled to true + fireEvent.click(screen.getByLabelText('fail')) + + // render pending fallback + await waitFor(() => screen.getByText('Loading...')) + + // render error boundary fallback (error boundary) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should render the correct amount of times in Suspense mode when cacheTime is set to 0', async () => { + const key = queryKey() + let state: CreateQueryResult | null = null + + let count = 0 + let renders = 0 + + function Page() { + renders++ + + state = createQuery( + key, + async () => { + count++ + await sleep(10) + return count + }, + { suspense: true, cacheTime: 0 }, + ) + + return ( +
+ rendered +
+ ) + } + + render(() => ( + + + + + + )) + + await waitFor(() => + expect(state).toMatchObject({ + data: 1, + status: 'success', + }), + ) + + expect(renders).toBe(2) + expect(screen.queryByText('rendered')).not.toBeNull() + }) +}) diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 5e5d3c88154..5da9ff50167 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -7,18 +7,18 @@ export * from './types' // export type { QueriesResults, QueriesOptions } from './useQueries' export { createQuery } from './createQuery' export { - QueryClientContext as defaultContext, + defaultContext, QueryClientProvider, useQueryClient, } from './QueryClientProvider' -// export type { QueryClientProviderProps } from './QueryClientProvider' -// export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' +export type { QueryClientProviderProps } from './QueryClientProvider' +export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' // export { useHydrate, Hydrate } from './Hydrate' // export type { HydrateProps } from './Hydrate' -// export { -// QueryErrorResetBoundary, -// useQueryErrorResetBoundary, -// } from './QueryErrorResetBoundary' +export { + QueryErrorResetBoundary, + useQueryErrorResetBoundary, +} from './QueryErrorResetBoundary' export { useIsFetching } from './useIsFetching' export { useIsMutating } from './useIsMutating' export { createMutation } from './createMutation' From b4bbe8f4f308f3b07788435de2ef74ae1fa828be Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 14:29:46 -0400 Subject: [PATCH 151/221] add reset error boundary tests --- .../QueryResetErrorBoundary.test.tsx | 635 ++++++++++++++++++ 1 file changed, 635 insertions(+) create mode 100644 packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx diff --git a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx new file mode 100644 index 00000000000..224cb253d07 --- /dev/null +++ b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx @@ -0,0 +1,635 @@ +import { waitFor, fireEvent, render, screen } from 'solid-testing-library' + +import { sleep, createQueryClient } from '../../../../tests/utils' +import { queryKey } from './utils' +import { + createQuery, + QueryCache, + QueryClientProvider, + QueryErrorResetBoundary, +} from '..' +import { createEffect, createSignal, ErrorBoundary, Suspense } from 'solid-js' + +describe('QueryErrorResetBoundary', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should retry fetch if the reset error boundary has been reset', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+ , +
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + }) + + it('should not throw error if query is disabled', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data, status } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + enabled: !succeed, + useErrorBoundary: true, + }, + ) + return ( +
+
status: {status}
+
{data}
+
+ ) + } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('status: error')) + }) + + it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const [enabled, setEnabled] = createSignal(false) + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + enabled: enabled(), + useErrorBoundary: true, + }, + ) + + createEffect(() => { + setEnabled(true) + }) + + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + }) + + it('should throw error if query is disabled and manually refetched', async () => { + const key = queryKey() + + function Page() { + const { data, refetch, status, fetchStatus } = createQuery( + key, + async () => { + throw new Error('Error') + }, + { + retry: false, + enabled: false, + useErrorBoundary: true, + }, + ) + + return ( +
+ +
+ status: {status}, fetchStatus: {fetchStatus} +
+
{data}
+
+ ) + } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('status: loading, fetchStatus: idle')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should not retry fetch if the reset error boundary has not been reset', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {() => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + initialData: 'initial', + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + }) + + it('should not retry fetch if the reset error boundary has not been reset after a previous reset', async () => { + const key = queryKey() + + let succeed = false + let shouldReset = true + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + shouldReset = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + succeed = true + shouldReset = false + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + }) + + it('should throw again on error after the reset error boundary has been reset', async () => { + const key = queryKey() + let fetchCount = 0 + + function Page() { + const { data } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + throw new Error('Error') + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + expect(fetchCount).toBe(3) + }) + + it('should never render the component while the query is in error state', async () => { + const key = queryKey() + let fetchCount = 0 + let renders = 0 + + function Page() { + const { data } = createQuery( + key, + async () => { + fetchCount++ + await sleep(10) + if (fetchCount > 2) { + return 'data' + } else { + throw new Error('Error') + } + }, + { + retry: false, + suspense: true, + }, + ) + renders++ + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + loading
}> + + + + )} + + + )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + expect(fetchCount).toBe(3) + expect(renders).toBe(1) + }) + + it('should render children', async () => { + function Page() { + return ( +
+ page +
+ ) + } + + render(() => ( + + + + + + )) + + expect(screen.queryByText('page')).not.toBeNull() + }) + + it('should show error boundary when using tracked queries even though we do not track the error field', async () => { + const key = queryKey() + + let succeed = false + + function Page() { + const { data } = createQuery( + key, + async () => { + await sleep(10) + if (!succeed) { + throw new Error('Error') + } else { + return 'data' + } + }, + { + retry: false, + useErrorBoundary: true, + }, + ) + return
{data}
+ } + + render(() => ( + + + {({ reset: resetQuery }) => ( + ( +
+
error boundary
+ +
+ )} + > + +
+ )} +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + await waitFor(() => screen.getByText('retry')) + succeed = true + fireEvent.click(screen.getByText('retry')) + await waitFor(() => screen.getByText('data')) + }) +}) From 5c70b5c4680970a0cb3cbd86fb0b75198550ecf1 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 17:09:47 -0400 Subject: [PATCH 152/221] add property tracking to query --- packages/solid-query/src/createBaseQuery.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 3cf13af077f..7acb18709b0 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -2,12 +2,7 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' import { CreateBaseQueryOptions } from './types' import { useQueryClient } from './QueryClientProvider' -import { - onMount, - onCleanup, - createComputed, - createResource, -} from 'solid-js' +import { onMount, onCleanup, createComputed, createResource } from 'solid-js' import { createStore } from 'solid-js/store' // Base Query Function that is used to create the query. @@ -78,5 +73,12 @@ export function createBaseQuery< }, } - return new Proxy(state, handler) as QueryObserverResult + const proxyResult = new Proxy(state, handler) as QueryObserverResult< + TData, + TError + > + + return !defaultedOptions.notifyOnChangeProps + ? observer.trackResult(proxyResult) + : proxyResult } From 65a62196f9f574afbde8dbca4f387e88b353dee6 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 17:09:59 -0400 Subject: [PATCH 153/221] get another query test passing --- packages/solid-query/src/__tests__/createQuery.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 8fab47edecf..c4d0ad8fd50 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1048,7 +1048,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryData(key, 'prefetched') + queryClient.setQueryData(key(), 'prefetched') function Page() { const state = createQuery(key, () => 'test', { From f3f6cc5e7c1b229ebc317f80dccc6f25102761d0 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 17:11:23 -0400 Subject: [PATCH 154/221] another test passes --- packages/solid-query/src/__tests__/createQuery.test.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index c4d0ad8fd50..a8d63467382 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1142,13 +1142,12 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch } = state - - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch setActTimeout(() => { refetch() }, 5) - }, [refetch]) + }) return null } From 1f6113b83ccd1d35f159333ccc1cc6fb26620775 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 18:04:18 -0400 Subject: [PATCH 155/221] more tests transpiled --- .../src/__tests__/createQuery.test.tsx | 182 +++++++++--------- 1 file changed, 86 insertions(+), 96 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index a8d63467382..bfd42e06a48 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -27,7 +27,9 @@ import { createEffect, createSignal, Show, + ErrorBoundary, } from 'solid-js' +import { untrack } from 'solid-js/web' describe('createQuery', () => { const queryCache = new QueryCache() @@ -1253,19 +1255,19 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch, data } = state - - NotReact.useEffect(() => { + createEffect(() => { + const data = state.data + const refetch = state.refetch setActTimeout(() => { if (data) { refetch() } }, 20) - }, [refetch, data]) + }) return (
-

{data ?? null}

+

{state.data ?? null}

) } @@ -1295,9 +1297,10 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { + const _trackState = { ...state } renderCount++ - }, [state]) + }) return (
@@ -1388,12 +1391,10 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { remove, refetch } = state - return (
- - + + data: {state.data ?? 'null'}
) @@ -1499,7 +1500,7 @@ describe('createQuery', () => { const key = queryKey() const results: DefinedCreateQueryResult[] = [] - queryClient.setQueryData(key, 'set') + queryClient.setQueryData(key(), 'set') function Page() { const result = createQuery( @@ -1519,7 +1520,7 @@ describe('createQuery', () => { return (
isFetching: {result.isFetching}
- data: {result.data} @@ -1566,7 +1567,7 @@ describe('createQuery', () => { return (
- data: {state.data} @@ -1636,11 +1637,11 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - queryClient.refetchQueries({ queryKey: key }) + queryClient.refetchQueries({ queryKey: key() }) }, 20) - }, []) + }) return null } @@ -1682,11 +1683,11 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - queryClient.invalidateQueries(key) + queryClient.invalidateQueries(key()) }, 20) - }, []) + }) return null } @@ -1713,26 +1714,26 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(5) - return count + return count() }, - { enabled: count === 0 }, + { enabled: count() === 0 }, ) createRenderEffect(() => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setCount(1) }, 10) - }, []) + }) return null } @@ -1772,13 +1773,13 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(10) - return count + return count() }, { keepPreviousData: true }, ) @@ -1787,11 +1788,11 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setCount(1) }, 20) - }, []) + }) return null } @@ -1845,15 +1846,15 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - function Page({ count }: { count: number }) { + function Page(props: { count: number }) { const state = createQuery( - [key, count], + () => [key(), props.count], async () => { await sleep(10) - if (count === 2) { + if (props.count === 2) { throw new Error('Error test') } - return Promise.resolve(count) + return Promise.resolve(props.count) }, { retry: false, @@ -1957,13 +1958,13 @@ describe('createQuery', () => { const states: DefinedCreateQueryResult[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(10) - return count + return count() }, { initialData: 99, keepPreviousData: true }, ) @@ -1972,11 +1973,11 @@ describe('createQuery', () => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setCount(1) }, 20) - }, []) + }) return null } @@ -2031,13 +2032,13 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(10) - return count + return count() }, { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) @@ -2046,9 +2047,8 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch } = state - - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch refetch() setActTimeout(() => { @@ -2058,7 +2058,7 @@ describe('createQuery', () => { setActTimeout(() => { refetch() }, 30) - }, [refetch]) + }) return null } @@ -2126,13 +2126,13 @@ describe('createQuery', () => { await sleep(10) function Page() { - const [count, setCount] = NotReact.useState(10) + const [count, setCount] = createSignal(10) const state = createQuery( - [key, count], + () => [key(), count()], async () => { await sleep(10) - return count + return count() }, { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) @@ -2141,9 +2141,8 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch } = state - - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch setActTimeout(() => { setCount(11) }, 20) @@ -2153,7 +2152,7 @@ describe('createQuery', () => { setActTimeout(() => { refetch() }, 40) - }, [refetch]) + }) return null } @@ -2218,7 +2217,6 @@ describe('createQuery', () => { }, { notifyOnChangeProps: 'all' }, ) - const refetch = state.refetch createRenderEffect(() => { states.push({ ...state }) @@ -2226,7 +2224,7 @@ describe('createQuery', () => { return (
- + data: {state.data}
) @@ -2277,7 +2275,7 @@ describe('createQuery', () => { const states1: CreateQueryResult[] = [] const states2: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, async () => { + await queryClient.prefetchQuery(key(), async () => { await sleep(10) return 'prefetch' }) @@ -2295,7 +2293,9 @@ describe('createQuery', () => { staleTime: 100, }, ) - states1.push(state) + createRenderEffect(() => { + states1.push({ ...state }) + }) return null } @@ -2310,7 +2310,9 @@ describe('createQuery', () => { staleTime: 10, }, ) - states2.push(state) + createRenderEffect(() => { + states2.push({ ...state }) + }) return null } @@ -2462,13 +2464,12 @@ describe('createQuery', () => { states.push({ ...state }) }) - const { refetch } = state - - NotReact.useEffect(() => { + createEffect(() => { + const refetch = state.refetch setActTimeout(() => { refetch() }, 10) - }, [refetch]) + }) return null } @@ -2556,10 +2557,11 @@ describe('createQuery', () => { )) - expect(queryCache.find(key)!.options.queryFn).toBe(queryFn1) + expect(queryCache.find(key())!.options.queryFn).toBe(queryFn1) }) - it('should render correct states even in case of useEffect triggering delays', async () => { + // TODO(lukemurray): this seems like a react implementation detail + it.skip('should render correct states even in case of useEffect triggering delays', async () => { const key = queryKey() const states: CreateQueryResult[] = [] @@ -2640,7 +2642,7 @@ describe('createQuery', () => { } function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) createQuery(key, queryFn, { onSuccess: () => { setCount((x) => x + 1) @@ -2652,12 +2654,12 @@ describe('createQuery', () => { }, }) - NotReact.useEffect(() => { + createEffect(() => { renders++ - callbackCount = count + callbackCount = count() }) - return
count: {count}
+ return
count: {count()}
} render(() => ( @@ -2679,15 +2681,15 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const [, setNewState] = NotReact.useState('state') + const [, setNewState] = createSignal('state') const state = createQuery(key, () => 'data') - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { - queryClient.setQueryData(key, 'new') + queryClient.setQueryData(key(), 'new') // Update with same state to make react discard the next render setNewState('state') }, 10) - }, []) + }) return
{state.data}
} @@ -2771,7 +2773,7 @@ describe('createQuery', () => { } function Page() { - const state = createQuery([key, variables], queryFn) + const state = createQuery(() => [key(), variables], queryFn) createRenderEffect(() => { states.push({ ...state }) }) @@ -2813,9 +2815,7 @@ describe('createQuery', () => { await waitFor(() => screen.getByText('default')) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) expect(queryFn).not.toHaveBeenCalled() }) @@ -2844,9 +2844,7 @@ describe('createQuery', () => { await sleep(10) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await sleep(10) @@ -2879,9 +2877,7 @@ describe('createQuery', () => { await sleep(10) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await sleep(10) @@ -2914,9 +2910,7 @@ describe('createQuery', () => { await sleep(10) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await sleep(10) @@ -2956,9 +2950,7 @@ describe('createQuery', () => { await sleep(20) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await sleep(20) @@ -3005,9 +2997,7 @@ describe('createQuery', () => { expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) expect(states[1]).toMatchObject({ data: 0, isFetching: false }) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) await screen.findByText('data: 1') @@ -3155,7 +3145,7 @@ describe('createQuery', () => { render(() => ( -
error boundary
}> +
error boundary
}>
@@ -3174,7 +3164,7 @@ describe('createQuery', () => { useErrorBoundary: true, }) - NotReact.useEffect(() => { + createEffect(() => { result = query }) @@ -3215,7 +3205,7 @@ describe('createQuery', () => { render(() => ( -
error boundary
}> +
error boundary
}>
@@ -3249,7 +3239,7 @@ describe('createQuery', () => { render(() => ( ( + fallback={(error) => (
error boundary
{/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} From 8a39b93e348950a4864c7a054fd8fad77ff78bbb Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 18:17:19 -0400 Subject: [PATCH 156/221] fix custom context in create base query --- packages/solid-query/src/createBaseQuery.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 7acb18709b0..4ae344430fe 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -22,7 +22,7 @@ export function createBaseQuery< >, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient() + const queryClient = useQueryClient({ context: options.context }) const defaultedOptions = queryClient.defaultQueryOptions(options) defaultedOptions._optimisticResults = 'optimistic' From 4a3476cfbeedb106d62558e36f5e4e65ca96dde0 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 18:36:36 -0400 Subject: [PATCH 157/221] update query error reset boundary tests --- .../QueryResetErrorBoundary.test.tsx | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx index 224cb253d07..be3c6974589 100644 --- a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx +++ b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx @@ -20,7 +20,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -35,7 +35,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -78,7 +78,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data, status } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -96,8 +96,8 @@ describe('QueryErrorResetBoundary', () => { ) return (
-
status: {status}
-
{data}
+
status: {state.status}
+
{state.data}
) } @@ -142,7 +142,7 @@ describe('QueryErrorResetBoundary', () => { function Page() { const [enabled, setEnabled] = createSignal(false) - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -163,7 +163,7 @@ describe('QueryErrorResetBoundary', () => { setEnabled(true) }) - return
{data}
+ return
{state.data}
} render(() => ( @@ -203,7 +203,7 @@ describe('QueryErrorResetBoundary', () => { const key = queryKey() function Page() { - const { data, refetch, status, fetchStatus } = createQuery( + const state = createQuery( key, async () => { throw new Error('Error') @@ -217,11 +217,11 @@ describe('QueryErrorResetBoundary', () => { return (
- +
- status: {status}, fetchStatus: {fetchStatus} + status: {state.status}, fetchStatus: {state.fetchStatus}
-
{data}
+
{state.data}
) } @@ -263,7 +263,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -278,7 +278,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -319,7 +319,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -335,7 +335,7 @@ describe('QueryErrorResetBoundary', () => { initialData: 'initial', }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -378,7 +378,7 @@ describe('QueryErrorResetBoundary', () => { let shouldReset = true function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -393,7 +393,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -440,7 +440,7 @@ describe('QueryErrorResetBoundary', () => { let fetchCount = 0 function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -452,7 +452,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( @@ -497,7 +497,7 @@ describe('QueryErrorResetBoundary', () => { let renders = 0 function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { fetchCount++ @@ -514,7 +514,7 @@ describe('QueryErrorResetBoundary', () => { }, ) renders++ - return
{data}
+ return
{state.data}
} render(() => ( @@ -582,7 +582,7 @@ describe('QueryErrorResetBoundary', () => { let succeed = false function Page() { - const { data } = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -597,7 +597,7 @@ describe('QueryErrorResetBoundary', () => { useErrorBoundary: true, }, ) - return
{data}
+ return
{state.data}
} render(() => ( From 409c60d25a780454fec635492c2f31f5d7fc6a70 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 19:17:04 -0400 Subject: [PATCH 158/221] most error reset boundary test cases passing --- .../src/QueryErrorResetBoundary.tsx | 2 +- packages/solid-query/src/createBaseQuery.ts | 66 ++++++++++++++++--- packages/solid-query/src/utils.ts | 12 ++++ 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/packages/solid-query/src/QueryErrorResetBoundary.tsx b/packages/solid-query/src/QueryErrorResetBoundary.tsx index a501e7d7ffb..2066f3a6299 100644 --- a/packages/solid-query/src/QueryErrorResetBoundary.tsx +++ b/packages/solid-query/src/QueryErrorResetBoundary.tsx @@ -43,7 +43,7 @@ export const QueryErrorResetBoundary = ( return ( {typeof props.children === 'function' - ? (props.children as Function)(value) + ? (props.children as Function)(value()) : props.children} ) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 4ae344430fe..bd8d4b62ff8 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -2,8 +2,17 @@ import { QueryObserver } from '@tanstack/query-core' import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' import { CreateBaseQueryOptions } from './types' import { useQueryClient } from './QueryClientProvider' -import { onMount, onCleanup, createComputed, createResource } from 'solid-js' +import { + onMount, + onCleanup, + createComputed, + createResource, + createMemo, + createEffect, +} from 'solid-js' import { createStore } from 'solid-js/store' +import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary' +import { shouldThrowError } from './utils' // Base Query Function that is used to create the query. export function createBaseQuery< @@ -23,14 +32,32 @@ export function createBaseQuery< Observer: typeof QueryObserver, ): QueryObserverResult { const queryClient = useQueryClient({ context: options.context }) + const errorResetBoundary = useQueryErrorResetBoundary() + const defaultedOptions = createMemo(() => { + const computedOptions = queryClient.defaultQueryOptions(options) + computedOptions._optimisticResults = 'optimistic' + if (computedOptions.suspense) { + // Always set stale time when using suspense to prevent + // fetching again when directly mounting after suspending + if (typeof computedOptions.staleTime !== 'number') { + computedOptions.staleTime = 1000 + } + } + + if (computedOptions.suspense || computedOptions.useErrorBoundary) { + // Prevent retrying failed query if the error boundary has not been reset yet + if (!errorResetBoundary.isReset()) { + computedOptions.retryOnMount = false + } + } + return computedOptions + }) - const defaultedOptions = queryClient.defaultQueryOptions(options) - defaultedOptions._optimisticResults = 'optimistic' - const observer = new Observer(queryClient, defaultedOptions) + const observer = new Observer(queryClient, defaultedOptions()) const [state, setState] = createStore>( // @ts-ignore - observer.getOptimisticResult(defaultedOptions), + observer.getOptimisticResult(defaultedOptions()), ) const [dataResource, { refetch }] = createResource(() => { @@ -50,12 +77,17 @@ export function createBaseQuery< onCleanup(() => unsubscribe()) onMount(() => { - observer.setOptions(defaultedOptions, { listeners: false }) + observer.setOptions(defaultedOptions(), { listeners: false }) }) createComputed(() => { - const newDefaultedOptions = queryClient.defaultQueryOptions(options) - observer.setOptions(newDefaultedOptions) + observer.setOptions(defaultedOptions()) + }) + + createEffect(() => { + if (errorResetBoundary.isReset()) { + errorResetBoundary.clearReset() + } }) const handler = { @@ -64,7 +96,21 @@ export function createBaseQuery< prop: keyof QueryObserverResult, ): any { if (prop === 'data') { - if (state.isLoading) { + // handle suspense + const isSuspense = + defaultedOptions().suspense && state.isLoading && state.isFetching + + // handle error boundary + const isErrorBoundary = + state.isError && + !errorResetBoundary.isReset() && + !state.isFetching && + shouldThrowError(defaultedOptions().useErrorBoundary, [ + state.error, + observer.getCurrentQuery(), + ]) + + if (isSuspense || isErrorBoundary) { return dataResource() } return state.data @@ -78,7 +124,7 @@ export function createBaseQuery< TError > - return !defaultedOptions.notifyOnChangeProps + return !defaultedOptions().notifyOnChangeProps ? observer.trackResult(proxyResult) : proxyResult } diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 6dc1f31787d..4f239b90a0e 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -52,3 +52,15 @@ export function parseFilterArgs< : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] ) as [ParseFilterArgs, TOptions] } + +export function shouldThrowError boolean>( + _useErrorBoundary: boolean | T | undefined, + params: Parameters, +): boolean { + // Allow useErrorBoundary function to override throwing behavior on a per-error basis + if (typeof _useErrorBoundary === 'function') { + return _useErrorBoundary(...params) + } + + return !!_useErrorBoundary +} From e238ecef5e505f4c4c19a9213209a8ab03480c53 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 19:45:45 -0400 Subject: [PATCH 159/221] get a suspense test passing --- .../src/__tests__/suspense.test.tsx | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index d9d27d618c8..5c87a61ca2e 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -12,7 +12,13 @@ import { createInfiniteQuery, QueryClientProvider, } from '..' -import { createSignal, ErrorBoundary, Suspense } from 'solid-js' +import { + createRenderEffect, + createSignal, + ErrorBoundary, + on, + Suspense, +} from 'solid-js' describe("useQuery's in Suspense mode", () => { const queryCache = new QueryCache() @@ -26,8 +32,6 @@ describe("useQuery's in Suspense mode", () => { let renders = 0 function Page() { - renders++ - const [stateKey, setStateKey] = createSignal(key()) const state = createQuery( @@ -40,7 +44,15 @@ describe("useQuery's in Suspense mode", () => { { suspense: true }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) + + createRenderEffect( + on([() => ({ ...state }), key], () => { + renders++ + }), + ) return (
@@ -64,9 +76,12 @@ describe("useQuery's in Suspense mode", () => { await waitFor(() => screen.getByText('data: 2')) expect(renders).toBe(4) - expect(states.length).toBe(2) - expect(states[0]).toMatchObject({ data: 1, status: 'success' }) - expect(states[1]).toMatchObject({ data: 2, status: 'success' }) + // TODO(lukemurray): verify that this expectation is valid. this is 2 in + // react, but 4 in solid, because in solid suspense is triggered on read and + // the component needs to render in order to trigger suspense. + expect(states.length).toBe(4) + expect(states[1]).toMatchObject({ data: 1, status: 'success' }) + expect(states[3]).toMatchObject({ data: 2, status: 'success' }) }) it('should return the correct states for a successful infinite query', async () => { @@ -86,7 +101,11 @@ describe("useQuery's in Suspense mode", () => { getNextPageParam: (lastPage) => lastPage + 1, }, ) - states.push(state) + + createRenderEffect(() => { + states.push({ ...state }) + }) + return (
From 3c744d30af98f363f5e763e663cf3a445ed7a2d6 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 20:56:13 -0400 Subject: [PATCH 160/221] bunch of suspense cases passing --- .../src/__tests__/suspense.test.tsx | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index 5c87a61ca2e..fcc8f35757f 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -91,7 +91,7 @@ describe("useQuery's in Suspense mode", () => { function Page() { const [multiplier, setMultiplier] = createSignal(1) const state = createInfiniteQuery( - () => [`${key}_${multiplier}`], + () => [`${key()}_${multiplier()}`], async ({ pageParam = 1 }) => { await sleep(10) return Number(pageParam * multiplier()) @@ -119,14 +119,15 @@ describe("useQuery's in Suspense mode", () => { - , )) await waitFor(() => screen.getByText('data: 1')) - expect(states.length).toBe(1) - expect(states[0]).toMatchObject({ + // TODO(lukemurray): in react this is 1 in solid this is 2 because suspense + // occurs on read. + expect(states.length).toBe(2) + expect(states[1]).toMatchObject({ data: { pages: [1], pageParams: [undefined] }, status: 'success', }) @@ -134,8 +135,9 @@ describe("useQuery's in Suspense mode", () => { fireEvent.click(screen.getByText('next')) await waitFor(() => screen.getByText('data: 2')) - expect(states.length).toBe(2) - expect(states[1]).toMatchObject({ + // TODO(lukemurray): in react this is 2 and in solid it is 4 + expect(states.length).toBe(4) + expect(states[3]).toMatchObject({ data: { pages: [2], pageParams: [undefined] }, status: 'success', }) @@ -161,7 +163,6 @@ describe("useQuery's in Suspense mode", () => { - , )) @@ -230,7 +231,7 @@ describe("useQuery's in Suspense mode", () => { () => [key()], async () => { await sleep(10) - return key + return key() }, { suspense: true, @@ -247,7 +248,6 @@ describe("useQuery's in Suspense mode", () => { - , )) @@ -318,7 +318,7 @@ describe("useQuery's in Suspense mode", () => { let succeed = false function Page() { - createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -335,6 +335,12 @@ describe("useQuery's in Suspense mode", () => { }, ) + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -384,7 +390,7 @@ describe("useQuery's in Suspense mode", () => { let succeed = false function Page() { - createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -399,6 +405,13 @@ describe("useQuery's in Suspense mode", () => { suspense: true, }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} From a1a32cd1751af729aabc7ec72815615334a434ba Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 21:01:59 -0400 Subject: [PATCH 161/221] even more suspense tests working --- .../src/__tests__/suspense.test.tsx | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index fcc8f35757f..e5157d35534 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -558,13 +558,13 @@ describe("useQuery's in Suspense mode", () => { )) await waitFor(() => screen.getByText('Loading...')) - await waitFor(() => screen.getByText(`data: ${key1}`)) + await waitFor(() => screen.getByText(`data: ${key1()}`)) fireEvent.click(screen.getByText('switch')) await waitFor(() => screen.getByText('Loading...')) - await waitFor(() => screen.getByText(`data: ${key2}`)) + await waitFor(() => screen.getByText(`data: ${key2()}`)) expect( // @ts-expect-error - queryClient.getQueryCache().find(key2)!.observers[0].listeners.length, + queryClient.getQueryCache().find(key2())!.observers[0].listeners.length, ).toBe(1) }) @@ -574,7 +574,7 @@ describe("useQuery's in Suspense mode", () => { let succeed = false function Page() { - createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -589,6 +589,13 @@ describe("useQuery's in Suspense mode", () => { suspense: true, }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -638,7 +645,7 @@ describe("useQuery's in Suspense mode", () => { const key = queryKey() function Page() { - createQuery( + const state = createQuery( key, async (): Promise => { await sleep(10) @@ -649,6 +656,13 @@ describe("useQuery's in Suspense mode", () => { suspense: true, }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -682,7 +696,7 @@ describe("useQuery's in Suspense mode", () => { const key = queryKey() function Page() { - createQuery( + const state = createQuery( key, async (): Promise => { await sleep(10) @@ -694,6 +708,13 @@ describe("useQuery's in Suspense mode", () => { useErrorBoundary: false, }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -727,7 +748,7 @@ describe("useQuery's in Suspense mode", () => { const key = queryKey() function Page() { - createQuery( + const state = createQuery( key, async (): Promise => { await sleep(10) @@ -739,6 +760,13 @@ describe("useQuery's in Suspense mode", () => { useErrorBoundary: (err) => err !== 'Local Error', }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} @@ -772,7 +800,7 @@ describe("useQuery's in Suspense mode", () => { const key = queryKey() function Page() { - createQuery( + const state = createQuery( key, async (): Promise => { await sleep(10) @@ -784,6 +812,13 @@ describe("useQuery's in Suspense mode", () => { useErrorBoundary: (err) => err !== 'Local Error', }, ) + + // read state.data to trigger suspense. + createRenderEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense + state.data + }) + return
rendered
} From e58b2a139f1df31800c1503e905b2501dcd73270 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 21:33:38 -0400 Subject: [PATCH 162/221] finish migrating suspense tests --- packages/solid-query/src/__tests__/suspense.test.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index e5157d35534..709a5fd22b0 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -1091,8 +1091,6 @@ describe("useQuery's in Suspense mode", () => { let renders = 0 function Page() { - renders++ - state = createQuery( key, async () => { @@ -1103,6 +1101,12 @@ describe("useQuery's in Suspense mode", () => { { suspense: true, cacheTime: 0 }, ) + createRenderEffect( + on([() => ({ ...state })], () => { + renders++ + }), + ) + return (
rendered From 2cc8269711ac43e065af36de08c01c1f6162b531 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 22:05:40 -0400 Subject: [PATCH 163/221] add fetching/mutating cases with custom context --- .../src/__tests__/useIsFetching.test.tsx | 180 +++++++++-------- .../src/__tests__/useIsMutating.test.tsx | 183 ++++++++++-------- 2 files changed, 193 insertions(+), 170 deletions(-) diff --git a/packages/solid-query/src/__tests__/useIsFetching.test.tsx b/packages/solid-query/src/__tests__/useIsFetching.test.tsx index fe856ff9ea6..96ee1a81e4b 100644 --- a/packages/solid-query/src/__tests__/useIsFetching.test.tsx +++ b/packages/solid-query/src/__tests__/useIsFetching.test.tsx @@ -6,8 +6,21 @@ import { sleep, } from '../../../../tests/utils' import { queryKey } from './utils' -import { createQuery, useIsFetching, QueryCache, QueryClientProvider } from '..' -import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js' +import { + createQuery, + useIsFetching, + QueryCache, + QueryClientProvider, + QueryClient, +} from '..' +import { + createContext, + createEffect, + createRenderEffect, + createSignal, + ErrorBoundary, + Show, +} from 'solid-js' describe('useIsFetching', () => { // See https://github.com/tannerlinsley/react-query/issues/105 @@ -179,90 +192,85 @@ describe('useIsFetching', () => { expect(isFetchings).toEqual(expect.not.arrayContaining([2])) }) - // TODO(lukemurray): add when we support custom contexts - // describe('with custom context', () => { - // it('should update as queries start and stop fetching', async () => { - // const context = createContext(undefined) - - // const queryCache = new QueryCache() - // const queryClient = createQueryClient({ queryCache }) - // const key = queryKey() - - // function Page() { - // const [ready, setReady] = createSignal(false) - - // const isFetching = useIsFetching(undefined, { context: context }) - - // createQuery( - // key, - // async () => { - // await sleep(50) - // return 'test' - // }, - // { - // enabled: ready(), - // context, - // }, - // ) - - // return ( - //
- //
isFetching: {isFetching}
- // - //
- // ) - // } - - // const { findByText, getByRole } = renderWithClient( - // queryClient, - // , - // { - // context, - // }, - // ) - - // await findByText('isFetching: 0') - // fireEvent.click(getByRole('button', { name: /setReady/i })) - // await findByText('isFetching: 1') - // await findByText('isFetching: 0') - // }) - - // it('should throw if the context is not passed to useIsFetching', async () => { - // const context = React.createContext(undefined) - - // const queryCache = new QueryCache() - // const queryClient = createQueryClient({ queryCache }) - // const key = queryKey() - - // function Page() { - // const isFetching = useIsFetching() - - // createQuery(key, async () => 'test', { - // enabled: true, - // context, - // useErrorBoundary: true, - // }) - - // return ( - //
- //
isFetching: {isFetching}
- //
- // ) - // } - - // const rendered = renderWithClient( - // queryClient, - //
error boundary
}> - // - //
, - // { - // context, - // }, - // ) - - // await waitFor(() => rendered.getByText('error boundary')) - // }) - // }) + describe('with custom context', () => { + it('should update as queries start and stop fetching', async () => { + const context = createContext(undefined) + + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + const key = queryKey() + + function Page() { + const [ready, setReady] = createSignal(false) + + const isFetching = useIsFetching(undefined, { context: context }) + + createQuery( + key, + async () => { + await sleep(50) + return 'test' + }, + { + enabled: ready(), + context, + }, + ) + + return ( +
+
isFetching: {isFetching}
+ +
+ ) + } + + render(() => ( + + + + )) + + await screen.findByText('isFetching: 0') + fireEvent.click(screen.getByRole('button', { name: /setReady/i })) + await screen.findByText('isFetching: 1') + await screen.findByText('isFetching: 0') + }) + + it('should throw if the context is not passed to useIsFetching', async () => { + const context = createContext(undefined) + + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + const key = queryKey() + + function Page() { + const isFetching = useIsFetching() + + createQuery(key, async () => 'test', { + enabled: true, + context, + useErrorBoundary: true, + }) + + return ( +
+
isFetching: {isFetching}
+
+ ) + } + + render(() => ( + +
error boundary
}> + +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + }) + }) it('should show the correct fetching state when mounted after a query', async () => { const queryClient = createQueryClient() diff --git a/packages/solid-query/src/__tests__/useIsMutating.test.tsx b/packages/solid-query/src/__tests__/useIsMutating.test.tsx index 3a83903c141..82d59162963 100644 --- a/packages/solid-query/src/__tests__/useIsMutating.test.tsx +++ b/packages/solid-query/src/__tests__/useIsMutating.test.tsx @@ -1,10 +1,22 @@ import { waitFor, fireEvent, screen } from 'solid-testing-library' -import { useIsMutating, createMutation, QueryClientProvider } from '..' +import { + useIsMutating, + createMutation, + QueryClientProvider, + QueryClient, +} from '..' import { createQueryClient, sleep } from '../../../../tests/utils' import { setActTimeout } from './utils' import * as MutationCacheModule from '../../../query-core/src/mutationCache' -import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js' +import { + createContext, + createEffect, + createRenderEffect, + createSignal, + ErrorBoundary, + Show, +} from 'solid-js' import { render } from 'solid-testing-library' describe('useIsMutating', () => { @@ -194,86 +206,89 @@ describe('useIsMutating', () => { MutationCacheSpy.mockRestore() }) - // TODO(lukemurray): re-add when we support custom context. - // describe('with custom context', () => { - // it('should return the number of fetching mutations', async () => { - // const context = React.createContext(undefined) - - // const isMutatings: number[] = [] - // const queryClient = new QueryClient() - - // function IsMutating() { - // const isMutating = useIsMutating(undefined, { context }) - // isMutatings.push(isMutating) - // return null - // } - - // function Page() { - // const { mutate: mutate1 } = useMutation( - // ['mutation1'], - // async () => { - // await sleep(150) - // return 'data' - // }, - // { context }, - // ) - // const { mutate: mutate2 } = useMutation( - // ['mutation2'], - // async () => { - // await sleep(50) - // return 'data' - // }, - // { context }, - // ) - - // React.useEffect(() => { - // mutate1() - // setActTimeout(() => { - // mutate2() - // }, 50) - // }, [mutate1, mutate2]) - - // return - // } - - // renderWithClient(queryClient, , { context }) - // await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0])) - // }) - - // it('should throw if the context is not passed to useIsMutating', async () => { - // const context = React.createContext(undefined) - - // const isMutatings: number[] = [] - // const queryClient = new QueryClient() - - // function IsMutating() { - // const isMutating = useIsMutating(undefined) - // isMutatings.push(isMutating) - // return null - // } - - // function Page() { - // const { mutate } = useMutation(['mutation'], async () => 'data', { - // useErrorBoundary: true, - // context, - // }) - - // React.useEffect(() => { - // mutate() - // }, [mutate]) - - // return - // } - - // const rendered = renderWithClient( - // queryClient, - //
error boundary
}> - // - //
, - // { context }, - // ) - - // await waitFor(() => rendered.getByText('error boundary')) - // }) - // }) + describe('with custom context', () => { + it('should return the number of fetching mutations', async () => { + const context = createContext(undefined) + + const isMutatings: number[] = [] + const queryClient = new QueryClient() + + function IsMutating() { + const isMutating = useIsMutating(undefined, { context }) + isMutatings.push(isMutating()) + return null + } + + function Page() { + const { mutate: mutate1 } = createMutation( + ['mutation1'], + async () => { + await sleep(150) + return 'data' + }, + { context }, + ) + const { mutate: mutate2 } = createMutation( + ['mutation2'], + async () => { + await sleep(50) + return 'data' + }, + { context }, + ) + + createEffect(() => { + mutate1() + setActTimeout(() => { + mutate2() + }, 50) + }) + + return + } + + render(() => ( + + + + )) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0])) + }) + + it('should throw if the context is not passed to useIsMutating', async () => { + const context = createContext(undefined) + + const isMutatings: number[] = [] + const queryClient = new QueryClient() + + function IsMutating() { + const isMutating = useIsMutating(undefined) + isMutatings.push(isMutating()) + return null + } + + function Page() { + const { mutate } = createMutation(['mutation'], async () => 'data', { + useErrorBoundary: true, + context, + }) + + createEffect(() => { + mutate() + }) + + return + } + + render(() => ( + +
error boundary
}> + +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + }) + }) }) From e50cb60be11af5f0bbdd4f0f93e8e966f5a4ff5c Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 22:23:23 -0400 Subject: [PATCH 164/221] add infinite query and mutation tests --- .../__tests__/createInfiniteQuery.test.tsx | 1768 +++++++++++++++++ .../src/__tests__/createMutation.test.tsx | 1094 ++++++++++ 2 files changed, 2862 insertions(+) create mode 100644 packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx create mode 100644 packages/solid-query/src/__tests__/createMutation.test.tsx diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx new file mode 100644 index 00000000000..672ab72f4b5 --- /dev/null +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -0,0 +1,1768 @@ +import { waitFor, fireEvent } from 'solid-testing-library' + +import { sleep, createQueryClient } from '../../../../tests/utils' + +import { renderWithClient, Blink, queryKey, setActTimeout } from './utils' +import { + createInfiniteQuery, + CreateInfiniteQueryResult, + QueryCache, + QueryFunctionContext, + InfiniteData, +} from '..' + +interface Result { + items: number[] + nextId?: number + prevId?: number + ts: number +} + +const pageSize = 10 + +const fetchItems = async ( + page: number, + ts: number, + noNext?: boolean, + noPrev?: boolean, +): Promise => { + await sleep(10) + return { + items: [...new Array(10)].fill(null).map((_, d) => page * pageSize + d), + nextId: noNext ? undefined : page + 1, + prevId: noPrev ? undefined : page - 1, + ts, + } +} + +describe('useInfiniteQuery', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should return the correct states for a successful query', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 0 }) => Number(pageParam), + { + getNextPageParam: (lastPage) => lastPage + 1, + }, + ) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toEqual({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + fetchNextPage: expect.any(Function), + fetchPreviousPage: expect.any(Function), + hasNextPage: undefined, + hasPreviousPage: undefined, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'loading', + fetchStatus: 'fetching', + }) + + expect(states[1]).toEqual({ + data: { pages: [0], pageParams: [undefined] }, + dataUpdatedAt: expect.any(Number), + error: null, + errorUpdatedAt: 0, + failureCount: 0, + errorUpdateCount: 0, + fetchNextPage: expect.any(Function), + fetchPreviousPage: expect.any(Function), + hasNextPage: true, + hasPreviousPage: undefined, + isError: false, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isPaused: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isLoading: false, + isLoadingError: false, + isPlaceholderData: false, + isPreviousData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: true, + refetch: expect.any(Function), + remove: expect.any(Function), + status: 'success', + fetchStatus: 'idle', + }) + }) + + it('should not throw when fetchNextPage returns an error', async () => { + const key = queryKey() + let noThrow: boolean + + function Page() { + const start = 1 + const state = createInfiniteQuery( + key, + async ({ pageParam = start }) => { + if (pageParam === 2) { + throw new Error('error') + } + return Number(pageParam) + }, + { + retry: 1, + retryDelay: 10, + getNextPageParam: (lastPage) => lastPage + 1, + }, + ) + + const { fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + .then(() => { + noThrow = true + }) + .catch(() => undefined) + }, 20) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await waitFor(() => expect(noThrow).toBe(true)) + }) + + it('should keep the previous data when keepPreviousData is set', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const [order, setOrder] = React.useState('desc') + + const state = createInfiniteQuery( + [key, order], + async ({ pageParam = 0 }) => { + await sleep(10) + return `${pageParam}-${order}` + }, + { + getNextPageParam: () => 1, + keepPreviousData: true, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + return ( +
+ + +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {String(state.isFetching)}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 0-desc')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 0-desc,1-desc')) + fireEvent.click(rendered.getByRole('button', { name: /order/i })) + + await waitFor(() => rendered.getByText('data: 0-asc')) + await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => expect(states.length).toBe(7)) + + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + isPreviousData: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: ['0-desc'] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: false, + }) + expect(states[2]).toMatchObject({ + data: { pages: ['0-desc'] }, + isFetching: true, + isFetchingNextPage: true, + isSuccess: true, + isPreviousData: false, + }) + expect(states[3]).toMatchObject({ + data: { pages: ['0-desc', '1-desc'] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: false, + }) + // Set state + expect(states[4]).toMatchObject({ + data: { pages: ['0-desc', '1-desc'] }, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: true, + }) + // Hook state update + expect(states[5]).toMatchObject({ + data: { pages: ['0-desc', '1-desc'] }, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: true, + }) + expect(states[6]).toMatchObject({ + data: { pages: ['0-asc'] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + isPreviousData: false, + }) + }) + + it('should be able to select a part of the data', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery(key, () => ({ count: 1 }), { + select: (data) => ({ + pages: data.pages.map((x) => `count: ${x.count}`), + pageParams: data.pageParams, + }), + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(10) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: undefined, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: ['count: 1'] }, + isSuccess: true, + }) + }) + + it('should be able to select a new result and not cause infinite renders', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult<{ count: number; id: number }>[] = + [] + let selectCalled = 0 + + function Page() { + const state = createInfiniteQuery(key, () => ({ count: 1 }), { + select: React.useCallback((data: InfiniteData<{ count: number }>) => { + selectCalled++ + return { + pages: data.pages.map((x) => ({ ...x, id: Math.random() })), + pageParams: data.pageParams, + } + }, []), + }) + states.push(state) + return null + } + + renderWithClient(queryClient, ) + + await sleep(20) + + expect(states.length).toBe(2) + expect(selectCalled).toBe(1) + expect(states[0]).toMatchObject({ + data: undefined, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: [{ count: 1 }] }, + isSuccess: true, + }) + }) + + it('should be able to reverse the data', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + async ({ pageParam = 0 }) => { + await sleep(10) + return Number(pageParam) + }, + { + select: (data) => ({ + pages: [...data.pages].reverse(), + pageParams: [...data.pageParams].reverse(), + }), + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + return ( +
+ +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {state.isFetching}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 0')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 1,0')) + + await waitFor(() => expect(states.length).toBe(4)) + expect(states[0]).toMatchObject({ + data: undefined, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: [0] }, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + data: { pages: [0] }, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + data: { pages: [1, 0] }, + isSuccess: true, + }) + }) + + it('should be able to fetch a previous page', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const start = 10 + const state = createInfiniteQuery( + key, + async ({ pageParam = start }) => { + await sleep(10) + return Number(pageParam) + }, + { + getPreviousPageParam: (firstPage) => firstPage - 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { fetchPreviousPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchPreviousPage() + }, 20) + }, [fetchPreviousPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(4) + expect(states[0]).toMatchObject({ + data: undefined, + hasNextPage: undefined, + hasPreviousPage: undefined, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: undefined, + hasPreviousPage: true, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: undefined, + hasPreviousPage: true, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: true, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + data: { pages: [9, 10] }, + hasNextPage: undefined, + hasPreviousPage: true, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + isSuccess: true, + }) + }) + + it('should be able to refetch when providing page params manually', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery(key, async ({ pageParam = 10 }) => { + await sleep(10) + return Number(pageParam) + }) + + states.push(state) + + return ( +
+ + + +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {String(state.isFetching)}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 10')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 10,11')) + fireEvent.click( + rendered.getByRole('button', { name: /fetchPreviousPage/i }), + ) + await waitFor(() => rendered.getByText('data: 9,10,11')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + + await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => expect(states.length).toBe(8)) + + // Initial fetch + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isFetchingNextPage: false, + }) + // Initial fetch done + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch next page + expect(states[2]).toMatchObject({ + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: true, + }) + // Fetch next page done + expect(states[3]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch previous page + expect(states[4]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: true, + }) + // Fetch previous page done + expect(states[5]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + // Refetch + expect(states[6]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + // Refetch done + expect(states[7]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + }) + + it('should be able to refetch when providing page params automatically', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + async ({ pageParam = 10 }) => { + await sleep(10) + return Number(pageParam) + }, + { + getPreviousPageParam: (firstPage) => firstPage - 1, + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + return ( +
+ + + +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {String(state.isFetching)}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 10')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 10,11')) + fireEvent.click( + rendered.getByRole('button', { name: /fetchPreviousPage/i }), + ) + await waitFor(() => rendered.getByText('data: 9,10,11')) + fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + + await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => expect(states.length).toBe(8)) + + // Initial fetch + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isFetchingNextPage: false, + }) + // Initial fetch done + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch next page + expect(states[2]).toMatchObject({ + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: true, + }) + // Fetch next page done + expect(states[3]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch previous page + expect(states[4]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: true, + }) + // Fetch previous page done + expect(states[5]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + // Refetch + expect(states[6]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: true, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + // Refetch done + expect(states[7]).toMatchObject({ + data: { pages: [9, 10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isFetchingPreviousPage: false, + }) + }) + + it('should be able to refetch only specific pages when refetchPages is provided', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const multiplier = React.useRef(1) + const state = createInfiniteQuery( + key, + async ({ pageParam = 10 }) => { + await sleep(10) + return Number(pageParam) * multiplier.current + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + return ( +
+ + +
data: {state.data?.pages.join(',') ?? 'null'}
+
isFetching: {String(state.isFetching)}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => rendered.getByText('data: 10')) + fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + + await waitFor(() => rendered.getByText('data: 10,11')) + fireEvent.click(rendered.getByRole('button', { name: /refetchPage/i })) + + await waitFor(() => rendered.getByText('data: 20,11')) + await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => expect(states.length).toBe(6)) + + // Initial fetch + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isFetchingNextPage: false, + }) + // Initial fetch done + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Fetch next page + expect(states[2]).toMatchObject({ + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: true, + }) + // Fetch next page done + expect(states[3]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: false, + isFetchingNextPage: false, + }) + // Refetch + expect(states[4]).toMatchObject({ + data: { pages: [10, 11] }, + isFetching: true, + isFetchingNextPage: false, + }) + // Refetch done, only page one has been refetched and multiplied + expect(states[5]).toMatchObject({ + data: { pages: [20, 11] }, + isFetching: false, + isFetchingNextPage: false, + }) + }) + + it('should silently cancel any ongoing fetch when fetching more', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const start = 10 + const state = createInfiniteQuery( + key, + async ({ pageParam = start }) => { + await sleep(50) + return Number(pageParam) + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { refetch, fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + refetch() + }, 100) + setActTimeout(() => { + fetchNextPage() + }, 110) + }, [fetchNextPage, refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(300) + + expect(states.length).toBe(5) + expect(states[0]).toMatchObject({ + hasNextPage: undefined, + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + hasNextPage: true, + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + hasNextPage: true, + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + hasNextPage: true, + data: { pages: [10] }, + isFetching: true, + isFetchingNextPage: true, + isSuccess: true, + }) + expect(states[4]).toMatchObject({ + hasNextPage: true, + data: { pages: [10, 11] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should silently cancel an ongoing fetchNextPage request when another fetchNextPage is invoked', async () => { + const key = queryKey() + const start = 10 + const onAborts: jest.Mock[] = [] + const abortListeners: jest.Mock[] = [] + const fetchPage = jest.fn< + Promise, + [QueryFunctionContext] + >(async ({ pageParam = start, signal }) => { + if (signal) { + const onAbort = jest.fn() + const abortListener = jest.fn() + onAborts.push(onAbort) + abortListeners.push(abortListener) + signal.onabort = onAbort + signal.addEventListener('abort', abortListener) + } + await sleep(50) + return Number(pageParam) + }) + + function Page() { + const { fetchNextPage } = createInfiniteQuery(key, fetchPage, { + getNextPageParam: (lastPage) => lastPage + 1, + }) + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + }, 100) + setActTimeout(() => { + fetchNextPage() + }, 110) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(300) + + const expectedCallCount = 3 + expect(fetchPage).toBeCalledTimes(expectedCallCount) + expect(onAborts).toHaveLength(expectedCallCount) + expect(abortListeners).toHaveLength(expectedCallCount) + + let callIndex = 0 + const firstCtx = fetchPage.mock.calls[callIndex]![0] + expect(firstCtx.pageParam).toBeUndefined() + expect(firstCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(firstCtx.signal).toBeInstanceOf(AbortSignal) + expect(firstCtx.signal?.aborted).toBe(false) + expect(onAborts[callIndex]).not.toHaveBeenCalled() + expect(abortListeners[callIndex]).not.toHaveBeenCalled() + } + + callIndex = 1 + const secondCtx = fetchPage.mock.calls[callIndex]![0] + expect(secondCtx.pageParam).toBe(11) + expect(secondCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(secondCtx.signal).toBeInstanceOf(AbortSignal) + expect(secondCtx.signal?.aborted).toBe(true) + expect(onAborts[callIndex]).toHaveBeenCalledTimes(1) + expect(abortListeners[callIndex]).toHaveBeenCalledTimes(1) + } + + callIndex = 2 + const thirdCtx = fetchPage.mock.calls[callIndex]![0] + expect(thirdCtx.pageParam).toBe(11) + expect(thirdCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(thirdCtx.signal).toBeInstanceOf(AbortSignal) + expect(thirdCtx.signal?.aborted).toBe(false) + expect(onAborts[callIndex]).not.toHaveBeenCalled() + expect(abortListeners[callIndex]).not.toHaveBeenCalled() + } + }) + + it('should not cancel an ongoing fetchNextPage request when another fetchNextPage is invoked if `cancelRefetch: false` is used ', async () => { + const key = queryKey() + const start = 10 + const onAborts: jest.Mock[] = [] + const abortListeners: jest.Mock[] = [] + const fetchPage = jest.fn< + Promise, + [QueryFunctionContext] + >(async ({ pageParam = start, signal }) => { + if (signal) { + const onAbort = jest.fn() + const abortListener = jest.fn() + onAborts.push(onAbort) + abortListeners.push(abortListener) + signal.onabort = onAbort + signal.addEventListener('abort', abortListener) + } + await sleep(50) + return Number(pageParam) + }) + + function Page() { + const { fetchNextPage } = createInfiniteQuery(key, fetchPage, { + getNextPageParam: (lastPage) => lastPage + 1, + }) + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + }, 100) + setActTimeout(() => { + fetchNextPage({ cancelRefetch: false }) + }, 110) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(300) + + const expectedCallCount = 2 + expect(fetchPage).toBeCalledTimes(expectedCallCount) + expect(onAborts).toHaveLength(expectedCallCount) + expect(abortListeners).toHaveLength(expectedCallCount) + + let callIndex = 0 + const firstCtx = fetchPage.mock.calls[callIndex]![0] + expect(firstCtx.pageParam).toBeUndefined() + expect(firstCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(firstCtx.signal).toBeInstanceOf(AbortSignal) + expect(firstCtx.signal?.aborted).toBe(false) + expect(onAborts[callIndex]).not.toHaveBeenCalled() + expect(abortListeners[callIndex]).not.toHaveBeenCalled() + } + + callIndex = 1 + const secondCtx = fetchPage.mock.calls[callIndex]![0] + expect(secondCtx.pageParam).toBe(11) + expect(secondCtx.queryKey).toEqual(key) + if (typeof AbortSignal === 'function') { + expect(secondCtx.signal).toBeInstanceOf(AbortSignal) + expect(secondCtx.signal?.aborted).toBe(false) + expect(onAborts[callIndex]).not.toHaveBeenCalled() + expect(abortListeners[callIndex]).not.toHaveBeenCalled() + } + }) + + it('should keep fetching first page when not loaded yet and triggering fetch more', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const start = 10 + const state = createInfiniteQuery( + key, + async ({ pageParam = start }) => { + await sleep(50) + return Number(pageParam) + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + }, 10) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + hasNextPage: undefined, + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + hasNextPage: true, + data: { pages: [10] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should stop fetching additional pages when the component is unmounted and AbortSignal is consumed', async () => { + const key = queryKey() + let fetches = 0 + + const initialData = { pages: [1, 2, 3, 4], pageParams: [0, 1, 2, 3] } + + function List() { + createInfiniteQuery( + key, + async ({ pageParam = 0, signal: _ }) => { + fetches++ + await sleep(50) + return Number(pageParam) * 10 + }, + { + initialData, + getNextPageParam: (_, allPages) => { + return allPages.length === 4 ? undefined : allPages.length + }, + }, + ) + + return null + } + + function Page() { + const [show, setShow] = React.useState(true) + + React.useEffect(() => { + setActTimeout(() => { + setShow(false) + }, 75) + }, []) + + return show ? : null + } + + renderWithClient(queryClient, ) + + await sleep(300) + + if (typeof AbortSignal === 'function') { + expect(fetches).toBe(2) + expect(queryClient.getQueryState(key)).toMatchObject({ + data: initialData, + status: 'success', + error: null, + }) + } else { + // if AbortSignal is not consumed, fetches should not abort + expect(fetches).toBe(4) + expect(queryClient.getQueryState(key)).toMatchObject({ + data: { pages: [0, 10, 20, 30], pageParams: [0, 1, 2, 3] }, + status: 'success', + error: null, + }) + } + }) + + it('should be able to override the cursor in the fetchNextPage callback', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + async ({ pageParam = 0 }) => { + await sleep(10) + return Number(pageParam) + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage({ pageParam: 5 }) + }, 20) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(4) + expect(states[0]).toMatchObject({ + hasNextPage: undefined, + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + hasNextPage: true, + data: { pages: [0] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + hasNextPage: true, + data: { pages: [0] }, + isFetching: true, + isFetchingNextPage: true, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + hasNextPage: true, + data: { pages: [0, 5] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should be able to set new pages with the query client', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const [firstPage, setFirstPage] = React.useState(0) + + const state = createInfiniteQuery( + key, + async ({ pageParam = firstPage }) => { + await sleep(10) + return Number(pageParam) + }, + { + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { refetch } = state + + React.useEffect(() => { + setActTimeout(() => { + queryClient.setQueryData(key, { pages: [7, 8], pageParams: [7, 8] }) + setFirstPage(7) + }, 20) + + setActTimeout(() => { + refetch() + }, 50) + }, [refetch]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(5) + expect(states[0]).toMatchObject({ + hasNextPage: undefined, + data: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + // After first fetch + expect(states[1]).toMatchObject({ + hasNextPage: true, + data: { pages: [0] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + // Set state + expect(states[2]).toMatchObject({ + hasNextPage: true, + data: { pages: [7, 8] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + // Refetch + expect(states[3]).toMatchObject({ + hasNextPage: true, + data: { pages: [7, 8] }, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + // Refetch done + expect(states[4]).toMatchObject({ + hasNextPage: true, + data: { pages: [7, 8] }, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should only refetch the first page when initialData is provided', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + async ({ pageParam }): Promise => { + await sleep(10) + return pageParam + }, + { + initialData: { pages: [1], pageParams: [1] }, + getNextPageParam: (lastPage) => lastPage + 1, + notifyOnChangeProps: 'all', + }, + ) + + states.push(state) + + const { fetchNextPage } = state + + React.useEffect(() => { + setActTimeout(() => { + fetchNextPage() + }, 20) + }, [fetchNextPage]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(4) + expect(states[0]).toMatchObject({ + data: { pages: [1] }, + hasNextPage: true, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[1]).toMatchObject({ + data: { pages: [1] }, + hasNextPage: true, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[2]).toMatchObject({ + data: { pages: [1] }, + hasNextPage: true, + isFetching: true, + isFetchingNextPage: true, + isSuccess: true, + }) + expect(states[3]).toMatchObject({ + data: { pages: [1, 2] }, + hasNextPage: true, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should set hasNextPage to false if getNextPageParam returns undefined', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 1 }) => Number(pageParam), + { + getNextPageParam: () => undefined, + }, + ) + + states.push(state) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: undefined, + hasNextPage: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: [1] }, + hasNextPage: false, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should compute hasNextPage correctly using initialData', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 10 }): number => pageParam, + { + initialData: { pages: [10], pageParams: [undefined] }, + getNextPageParam: (lastPage) => (lastPage === 10 ? 11 : undefined), + }, + ) + + states.push(state) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: true, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: true, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should compute hasNextPage correctly for falsy getFetchMore return value using initialData', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 10 }): number => pageParam, + { + initialData: { pages: [10], pageParams: [undefined] }, + getNextPageParam: () => undefined, + }, + ) + + states.push(state) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: false, + isFetching: true, + isFetchingNextPage: false, + isSuccess: true, + }) + expect(states[1]).toMatchObject({ + data: { pages: [10] }, + hasNextPage: false, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should not use selected data when computing hasNextPage', async () => { + const key = queryKey() + const states: CreateInfiniteQueryResult[] = [] + + function Page() { + const state = createInfiniteQuery( + key, + ({ pageParam = 1 }) => Number(pageParam), + { + getNextPageParam: (lastPage) => (lastPage === 1 ? 2 : false), + select: (data) => ({ + pages: data.pages.map((x) => x.toString()), + pageParams: data.pageParams, + }), + }, + ) + + states.push(state) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(2) + expect(states[0]).toMatchObject({ + data: undefined, + hasNextPage: undefined, + isFetching: true, + isFetchingNextPage: false, + isSuccess: false, + }) + expect(states[1]).toMatchObject({ + data: { pages: ['1'] }, + hasNextPage: true, + isFetching: false, + isFetchingNextPage: false, + isSuccess: true, + }) + }) + + it('should build fresh cursors on refetch', async () => { + const key = queryKey() + + const genItems = (size: number) => + [...new Array(size)].fill(null).map((_, d) => d) + const items = genItems(15) + const limit = 3 + + const fetchItemsWithLimit = async (cursor = 0, ts: number) => { + await sleep(10) + return { + nextId: cursor + limit, + items: items.slice(cursor, cursor + limit), + ts, + } + } + + function Page() { + const fetchCountRef = React.useRef(0) + const { + status, + data, + error, + isFetchingNextPage, + fetchNextPage, + hasNextPage, + refetch, + } = createInfiniteQuery( + key, + ({ pageParam = 0 }) => + fetchItemsWithLimit(pageParam, fetchCountRef.current++), + { + getNextPageParam: (lastPage) => lastPage.nextId, + }, + ) + + return ( +
+

Pagination

+ {status === 'loading' ? ( + 'Loading...' + ) : status === 'error' ? ( + Error: {error.message} + ) : ( + <> +
Data:
+ {data.pages.map((page, i) => ( +
+
+ Page {i}: {page.ts} +
+
+ {page.items.map((item) => ( +

Item: {item}

+ ))} +
+
+ ))} +
+ + + +
+
{!isFetchingNextPage ? 'Background Updating...' : null}
+ + )} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('Loading...') + + await waitFor(() => rendered.getByText('Item: 2')) + await waitFor(() => rendered.getByText('Page 0: 0')) + + fireEvent.click(rendered.getByText('Load More')) + + await waitFor(() => rendered.getByText('Loading more...')) + await waitFor(() => rendered.getByText('Item: 5')) + await waitFor(() => rendered.getByText('Page 0: 0')) + await waitFor(() => rendered.getByText('Page 1: 1')) + + fireEvent.click(rendered.getByText('Load More')) + + await waitFor(() => rendered.getByText('Loading more...')) + await waitFor(() => rendered.getByText('Item: 8')) + await waitFor(() => rendered.getByText('Page 0: 0')) + await waitFor(() => rendered.getByText('Page 1: 1')) + await waitFor(() => rendered.getByText('Page 2: 2')) + + fireEvent.click(rendered.getByText('Refetch')) + + await waitFor(() => rendered.getByText('Background Updating...')) + await waitFor(() => rendered.getByText('Item: 8')) + await waitFor(() => rendered.getByText('Page 0: 3')) + await waitFor(() => rendered.getByText('Page 1: 4')) + await waitFor(() => rendered.getByText('Page 2: 5')) + + // ensure that Item: 4 is rendered before removing it + expect(rendered.queryAllByText('Item: 4')).toHaveLength(1) + + // remove Item: 4 + fireEvent.click(rendered.getByText('Remove item')) + + await waitFor(() => rendered.getByText('Background Updating...')) + // ensure that an additional item is rendered (it means that cursors were properly rebuilt) + await waitFor(() => rendered.getByText('Item: 9')) + await waitFor(() => rendered.getByText('Page 0: 6')) + await waitFor(() => rendered.getByText('Page 1: 7')) + await waitFor(() => rendered.getByText('Page 2: 8')) + + // ensure that Item: 4 is no longer rendered + expect(rendered.queryAllByText('Item: 4')).toHaveLength(0) + }) + + it('should compute hasNextPage correctly for falsy getFetchMore return value on refetching', async () => { + const key = queryKey() + const MAX = 2 + + function Page() { + const fetchCountRef = React.useRef(0) + const [isRemovedLastPage, setIsRemovedLastPage] = + React.useState(false) + const { + status, + data, + error, + isFetching, + isFetchingNextPage, + fetchNextPage, + hasNextPage, + refetch, + } = createInfiniteQuery( + key, + ({ pageParam = 0 }) => + fetchItems( + pageParam, + fetchCountRef.current++, + pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage), + ), + { + getNextPageParam: (lastPage) => lastPage.nextId, + }, + ) + + return ( +
+

Pagination

+ {status === 'loading' ? ( + 'Loading...' + ) : status === 'error' ? ( + Error: {error.message} + ) : ( + <> +
Data:
+ {data.pages.map((page, i) => ( +
+
+ Page {i}: {page.ts} +
+
+ {page.items.map((item) => ( +

Item: {item}

+ ))} +
+
+ ))} +
+ + + +
+
+ {isFetching && !isFetchingNextPage + ? 'Background Updating...' + : null} +
+ + )} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + rendered.getByText('Loading...') + + await waitFor(() => { + rendered.getByText('Item: 9') + rendered.getByText('Page 0: 0') + }) + + fireEvent.click(rendered.getByText('Load More')) + + await waitFor(() => rendered.getByText('Loading more...')) + + await waitFor(() => { + rendered.getByText('Item: 19') + rendered.getByText('Page 0: 0') + rendered.getByText('Page 1: 1') + }) + + fireEvent.click(rendered.getByText('Load More')) + + await waitFor(() => rendered.getByText('Loading more...')) + + await waitFor(() => { + rendered.getByText('Item: 29') + rendered.getByText('Page 0: 0') + rendered.getByText('Page 1: 1') + rendered.getByText('Page 2: 2') + }) + + rendered.getByText('Nothing more to load') + + fireEvent.click(rendered.getByText('Remove Last Page')) + + await sleep(10) + + fireEvent.click(rendered.getByText('Refetch')) + + await waitFor(() => rendered.getByText('Background Updating...')) + + await waitFor(() => { + rendered.getByText('Page 0: 3') + rendered.getByText('Page 1: 4') + }) + + expect(rendered.queryByText('Item: 29')).toBeNull() + expect(rendered.queryByText('Page 2: 5')).toBeNull() + + rendered.getByText('Nothing more to load') + }) + + it('should cancel the query function when there are no more subscriptions', async () => { + const key = queryKey() + let cancelFn: jest.Mock = jest.fn() + + const queryFn = ({ signal }: { signal?: AbortSignal }) => { + const promise = new Promise((resolve, reject) => { + cancelFn = jest.fn(() => reject('Cancelled')) + signal?.addEventListener('abort', cancelFn) + sleep(10).then(() => resolve('OK')) + }) + + return promise + } + + function Page() { + const state = createInfiniteQuery(key, queryFn) + return ( +
+

Status: {state.status}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, + + + , + ) + + await waitFor(() => rendered.getByText('off')) + + if (typeof AbortSignal === 'function') { + expect(cancelFn).toHaveBeenCalled() + } + }) +}) diff --git a/packages/solid-query/src/__tests__/createMutation.test.tsx b/packages/solid-query/src/__tests__/createMutation.test.tsx new file mode 100644 index 00000000000..5fa388914c3 --- /dev/null +++ b/packages/solid-query/src/__tests__/createMutation.test.tsx @@ -0,0 +1,1094 @@ +import { fireEvent, waitFor } from 'solid-testing-library' + +import { QueryClient, createMutation, QueryCache, MutationCache } from '..' +import { CreateMutationResult } from '../types' +import { + createQueryClient, + mockNavigatorOnLine, + sleep, +} from '../../../../tests/utils' +import { renderWithClient, queryKey, setActTimeout } from './utils' + +describe('useMutation', () => { + const queryCache = new QueryCache() + const mutationCache = new MutationCache() + const queryClient = createQueryClient({ queryCache, mutationCache }) + + it('should be able to reset `data`', async () => { + function Page() { + const { + mutate, + data = 'empty', + reset, + } = createMutation(() => Promise.resolve('mutation')) + + return ( +
+

{data}

+ + +
+ ) + } + + const { getByRole } = renderWithClient(queryClient, ) + + expect(getByRole('heading').textContent).toBe('empty') + + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('mutation') + }) + + fireEvent.click(getByRole('button', { name: /reset/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('empty') + }) + }) + + it('should be able to reset `error`', async () => { + function Page() { + const { mutate, error, reset } = createMutation(() => { + const err = new Error('Expected mock error. All is well!') + err.stack = '' + return Promise.reject(err) + }) + + return ( +
+ {error &&

{error.message}

} + + +
+ ) + } + + const { getByRole, queryByRole } = renderWithClient(queryClient, ) + + await waitFor(() => { + expect(queryByRole('heading')).toBeNull() + }) + + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe( + 'Expected mock error. All is well!', + ) + }) + + fireEvent.click(getByRole('button', { name: /reset/i })) + + await waitFor(() => { + expect(queryByRole('heading')).toBeNull() + }) + }) + + it('should be able to call `onSuccess` and `onSettled` after each successful mutate', async () => { + let count = 0 + const onSuccessMock = jest.fn() + const onSettledMock = jest.fn() + + function Page() { + const { mutate } = createMutation( + (vars: { count: number }) => Promise.resolve(vars.count), + { + onSuccess: (data) => { + onSuccessMock(data) + }, + onSettled: (data) => { + onSettledMock(data) + }, + }, + ) + + return ( +
+

{count}

+ +
+ ) + } + + const { getByRole } = renderWithClient(queryClient, ) + + expect(getByRole('heading').textContent).toBe('0') + + fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('3') + }) + + await waitFor(() => { + expect(onSuccessMock).toHaveBeenCalledTimes(3) + }) + + expect(onSuccessMock).toHaveBeenCalledWith(1) + expect(onSuccessMock).toHaveBeenCalledWith(2) + expect(onSuccessMock).toHaveBeenCalledWith(3) + + await waitFor(() => { + expect(onSettledMock).toHaveBeenCalledTimes(3) + }) + + expect(onSettledMock).toHaveBeenCalledWith(1) + expect(onSettledMock).toHaveBeenCalledWith(2) + expect(onSettledMock).toHaveBeenCalledWith(3) + }) + + it('should be able to call `onError` and `onSettled` after each failed mutate', async () => { + const onErrorMock = jest.fn() + const onSettledMock = jest.fn() + let count = 0 + + function Page() { + const { mutate } = createMutation( + (vars: { count: number }) => { + const error = new Error( + `Expected mock error. All is well! ${vars.count}`, + ) + error.stack = '' + return Promise.reject(error) + }, + { + onError: (error: Error) => { + onErrorMock(error.message) + }, + onSettled: (_data, error) => { + onSettledMock(error?.message) + }, + }, + ) + + return ( +
+

{count}

+ +
+ ) + } + + const { getByRole } = renderWithClient(queryClient, ) + + expect(getByRole('heading').textContent).toBe('0') + + fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('3') + }) + + await waitFor(() => { + expect(onErrorMock).toHaveBeenCalledTimes(3) + }) + expect(onErrorMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 1', + ) + expect(onErrorMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 2', + ) + expect(onErrorMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 3', + ) + + await waitFor(() => { + expect(onSettledMock).toHaveBeenCalledTimes(3) + }) + expect(onSettledMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 1', + ) + expect(onSettledMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 2', + ) + expect(onSettledMock).toHaveBeenCalledWith( + 'Expected mock error. All is well! 3', + ) + }) + + it('should be able to override the useMutation success callbacks', async () => { + const callbacks: string[] = [] + + function Page() { + const { mutateAsync } = createMutation(async (text: string) => text, { + onSuccess: async () => { + callbacks.push('useMutation.onSuccess') + }, + onSettled: async () => { + callbacks.push('useMutation.onSettled') + }, + }) + + React.useEffect(() => { + setActTimeout(async () => { + try { + const result = await mutateAsync('todo', { + onSuccess: async () => { + callbacks.push('mutateAsync.onSuccess') + }, + onSettled: async () => { + callbacks.push('mutateAsync.onSettled') + }, + }) + callbacks.push(`mutateAsync.result:${result}`) + } catch {} + }, 10) + }, [mutateAsync]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(callbacks).toEqual([ + 'useMutation.onSuccess', + 'useMutation.onSettled', + 'mutateAsync.onSuccess', + 'mutateAsync.onSettled', + 'mutateAsync.result:todo', + ]) + }) + + it('should be able to override the error callbacks when using mutateAsync', async () => { + const callbacks: string[] = [] + + function Page() { + const { mutateAsync } = createMutation( + async (_text: string) => Promise.reject('oops'), + { + onError: async () => { + callbacks.push('useMutation.onError') + }, + onSettled: async () => { + callbacks.push('useMutation.onSettled') + }, + }, + ) + + React.useEffect(() => { + setActTimeout(async () => { + try { + await mutateAsync('todo', { + onError: async () => { + callbacks.push('mutateAsync.onError') + }, + onSettled: async () => { + callbacks.push('mutateAsync.onSettled') + }, + }) + } catch (error) { + callbacks.push(`mutateAsync.error:${error}`) + } + }, 10) + }, [mutateAsync]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(callbacks).toEqual([ + 'useMutation.onError', + 'useMutation.onSettled', + 'mutateAsync.onError', + 'mutateAsync.onSettled', + 'mutateAsync.error:oops', + ]) + }) + + it('should be able to use mutation defaults', async () => { + const key = queryKey() + + queryClient.setMutationDefaults(key, { + mutationFn: async (text: string) => { + await sleep(10) + return text + }, + }) + + const states: CreateMutationResult[] = [] + + function Page() { + const state = createMutation(key) + + states.push(state) + + const { mutate } = state + + React.useEffect(() => { + setActTimeout(() => { + mutate('todo') + }, 10) + }, [mutate]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(states.length).toBe(3) + expect(states[0]).toMatchObject({ data: undefined, isLoading: false }) + expect(states[1]).toMatchObject({ data: undefined, isLoading: true }) + expect(states[2]).toMatchObject({ data: 'todo', isLoading: false }) + }) + + it('should be able to retry a failed mutation', async () => { + let count = 0 + + function Page() { + const { mutate } = createMutation( + (_text: string) => { + count++ + return Promise.reject('oops') + }, + { + retry: 1, + retryDelay: 5, + }, + ) + + React.useEffect(() => { + setActTimeout(() => { + mutate('todo') + }, 10) + }, [mutate]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(100) + + expect(count).toBe(2) + }) + + it('should not retry mutations while offline', async () => { + const onlineMock = mockNavigatorOnLine(false) + + let count = 0 + + function Page() { + const mutation = createMutation( + (_text: string) => { + count++ + return Promise.reject(new Error('oops')) + }, + { + retry: 1, + retryDelay: 5, + }, + ) + + return ( +
+ +
+ error:{' '} + {mutation.error instanceof Error ? mutation.error.message : 'null'}, + status: {mutation.status}, isPaused: {String(mutation.isPaused)} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await waitFor(() => { + expect( + rendered.getByText('error: null, status: idle, isPaused: false'), + ).toBeInTheDocument() + }) + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect( + rendered.getByText('error: null, status: loading, isPaused: true'), + ).toBeInTheDocument() + }) + + expect(count).toBe(0) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(100) + + await waitFor(() => { + expect( + rendered.getByText('error: oops, status: error, isPaused: false'), + ).toBeInTheDocument() + }) + + expect(count).toBe(2) + + onlineMock.mockRestore() + }) + + it('should call onMutate even if paused', async () => { + const onlineMock = mockNavigatorOnLine(false) + const onMutate = jest.fn() + let count = 0 + + function Page() { + const mutation = createMutation( + async (_text: string) => { + count++ + await sleep(10) + return count + }, + { + onMutate, + }, + ) + + return ( +
+ +
+ data: {mutation.data ?? 'null'}, status: {mutation.status}, + isPaused: {String(mutation.isPaused)} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: null, status: idle, isPaused: false') + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + + await rendered.findByText('data: null, status: loading, isPaused: true') + + expect(onMutate).toHaveBeenCalledTimes(1) + expect(onMutate).toHaveBeenCalledWith('todo') + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await rendered.findByText('data: 1, status: success, isPaused: false') + + expect(onMutate).toHaveBeenCalledTimes(1) + expect(count).toBe(1) + + onlineMock.mockRestore() + }) + + it('should optimistically go to paused state if offline', async () => { + const onlineMock = mockNavigatorOnLine(false) + let count = 0 + const states: Array = [] + + function Page() { + const mutation = createMutation(async (_text: string) => { + count++ + await sleep(10) + return count + }) + + states.push(`${mutation.status}, ${mutation.isPaused}`) + + return ( +
+ +
+ data: {mutation.data ?? 'null'}, status: {mutation.status}, + isPaused: {String(mutation.isPaused)} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: null, status: idle, isPaused: false') + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + + await rendered.findByText('data: null, status: loading, isPaused: true') + + // no intermediate 'loading, false' state is expected because we don't start mutating! + expect(states[0]).toBe('idle, false') + expect(states[1]).toBe('loading, true') + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await rendered.findByText('data: 1, status: success, isPaused: false') + + onlineMock.mockRestore() + }) + + it('should be able to retry a mutation when online', async () => { + const onlineMock = mockNavigatorOnLine(false) + + let count = 0 + const states: CreateMutationResult[] = [] + + function Page() { + const state = createMutation( + async (_text: string) => { + await sleep(1) + count++ + return count > 1 ? Promise.resolve('data') : Promise.reject('oops') + }, + { + retry: 1, + retryDelay: 5, + networkMode: 'offlineFirst', + }, + ) + + states.push(state) + + const { mutate } = state + + React.useEffect(() => { + setActTimeout(() => { + mutate('todo') + }, 10) + }, [mutate]) + + return null + } + + renderWithClient(queryClient, ) + + await sleep(50) + + expect(states.length).toBe(4) + expect(states[0]).toMatchObject({ + isLoading: false, + isPaused: false, + failureCount: 0, + }) + expect(states[1]).toMatchObject({ + isLoading: true, + isPaused: false, + failureCount: 0, + }) + expect(states[2]).toMatchObject({ + isLoading: true, + isPaused: false, + failureCount: 1, + }) + expect(states[3]).toMatchObject({ + isLoading: true, + isPaused: true, + failureCount: 1, + }) + + onlineMock.mockReturnValue(true) + window.dispatchEvent(new Event('online')) + + await sleep(50) + + expect(states.length).toBe(6) + expect(states[4]).toMatchObject({ + isLoading: true, + isPaused: false, + failureCount: 1, + }) + expect(states[5]).toMatchObject({ + isLoading: false, + isPaused: false, + failureCount: 1, + data: 'data', + }) + + onlineMock.mockRestore() + }) + + it('should not change state if unmounted', async () => { + function Mutates() { + const { mutate } = createMutation(() => sleep(10)) + return + } + function Page() { + const [mounted, setMounted] = React.useState(true) + return ( +
+ + {mounted && } +
+ ) + } + + const { getByText } = renderWithClient(queryClient, ) + fireEvent.click(getByText('mutate')) + fireEvent.click(getByText('unmount')) + }) + + it('should be able to throw an error when useErrorBoundary is set to true', async () => { + function Page() { + const { mutate } = createMutation( + () => { + const err = new Error('Expected mock error. All is well!') + err.stack = '' + return Promise.reject(err) + }, + { useErrorBoundary: true }, + ) + + return ( +
+ +
+ ) + } + + const { getByText, queryByText } = renderWithClient( + queryClient, + ( +
+ error +
+ )} + > + +
, + ) + + fireEvent.click(getByText('mutate')) + + await waitFor(() => { + expect(queryByText('error')).not.toBeNull() + }) + }) + + it('should be able to throw an error when useErrorBoundary is a function that returns true', async () => { + let boundary = false + function Page() { + const { mutate, error } = createMutation( + () => { + const err = new Error('mock error') + err.stack = '' + return Promise.reject(err) + }, + { + useErrorBoundary: () => { + boundary = !boundary + return !boundary + }, + }, + ) + + return ( +
+ + {error && error.message} +
+ ) + } + + const { getByText, queryByText } = renderWithClient( + queryClient, + ( +
+ error boundary +
+ )} + > + +
, + ) + + // first error goes to component + fireEvent.click(getByText('mutate')) + await waitFor(() => { + expect(queryByText('mock error')).not.toBeNull() + }) + + // second error goes to boundary + fireEvent.click(getByText('mutate')) + await waitFor(() => { + expect(queryByText('error boundary')).not.toBeNull() + }) + }) + + it('should pass meta to mutation', async () => { + const errorMock = jest.fn() + const successMock = jest.fn() + + const queryClientMutationMeta = createQueryClient({ + mutationCache: new MutationCache({ + onSuccess: (_, __, ___, mutation) => { + successMock(mutation.meta?.metaSuccessMessage) + }, + onError: (_, __, ___, mutation) => { + errorMock(mutation.meta?.metaErrorMessage) + }, + }), + }) + + const metaSuccessMessage = 'mutation succeeded' + const metaErrorMessage = 'mutation failed' + + function Page() { + const { mutate: succeed, isSuccess } = createMutation(async () => '', { + meta: { metaSuccessMessage }, + }) + const { mutate: error, isError } = createMutation( + async () => { + throw new Error('') + }, + { + meta: { metaErrorMessage }, + }, + ) + + return ( +
+ + + {isSuccess &&
successTest
} + {isError &&
errorTest
} +
+ ) + } + + const { getByText, queryByText } = renderWithClient( + queryClientMutationMeta, + , + ) + + fireEvent.click(getByText('succeed')) + fireEvent.click(getByText('error')) + + await waitFor(() => { + expect(queryByText('successTest')).not.toBeNull() + expect(queryByText('errorTest')).not.toBeNull() + }) + + expect(successMock).toHaveBeenCalledTimes(1) + expect(successMock).toHaveBeenCalledWith(metaSuccessMessage) + expect(errorMock).toHaveBeenCalledTimes(1) + expect(errorMock).toHaveBeenCalledWith(metaErrorMessage) + }) + + it('should call cache callbacks when unmounted', async () => { + const onSuccess = jest.fn() + const onSuccessMutate = jest.fn() + const onSettled = jest.fn() + const onSettledMutate = jest.fn() + const mutationKey = queryKey() + let count = 0 + + function Page() { + const [show, setShow] = React.useState(true) + return ( +
+ + {show && } +
+ ) + } + + function Component() { + const mutation = createMutation( + async (_text: string) => { + count++ + await sleep(10) + return count + }, + { + mutationKey, + cacheTime: 0, + onSuccess, + onSettled, + }, + ) + + return ( +
+ +
+ data: {mutation.data ?? 'null'}, status: {mutation.status}, + isPaused: {String(mutation.isPaused)} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: null, status: idle, isPaused: false') + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + + await waitFor(() => { + expect( + queryClient.getMutationCache().findAll({ mutationKey }), + ).toHaveLength(0) + }) + + expect(count).toBe(1) + + expect(onSuccess).toHaveBeenCalledTimes(1) + expect(onSettled).toHaveBeenCalledTimes(1) + expect(onSuccessMutate).toHaveBeenCalledTimes(0) + expect(onSettledMutate).toHaveBeenCalledTimes(0) + }) + + describe('with custom context', () => { + it('should be able to reset `data`', async () => { + const context = React.createContext(undefined) + + function Page() { + const { + mutate, + data = 'empty', + reset, + } = createMutation(() => Promise.resolve('mutation'), { context }) + + return ( +
+

{data}

+ + +
+ ) + } + + const { getByRole } = renderWithClient(queryClient, , { context }) + + expect(getByRole('heading').textContent).toBe('empty') + + fireEvent.click(getByRole('button', { name: /mutate/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('mutation') + }) + + fireEvent.click(getByRole('button', { name: /reset/i })) + + await waitFor(() => { + expect(getByRole('heading').textContent).toBe('empty') + }) + }) + + it('should throw if the context is not passed to useMutation', async () => { + const context = React.createContext(undefined) + + function Page() { + const { data = '' } = createMutation(() => Promise.resolve('mutation')) + + return ( +
+

{data}

+
+ ) + } + + const rendered = renderWithClient( + queryClient, +
error boundary
}> + +
, + { context }, + ) + + await waitFor(() => rendered.getByText('error boundary')) + }) + }) + + it('should call mutate callbacks only for the last observer', async () => { + const onSuccess = jest.fn() + const onSuccessMutate = jest.fn() + const onSettled = jest.fn() + const onSettledMutate = jest.fn() + let count = 0 + + function Page() { + const mutation = createMutation( + async (_text: string) => { + count++ + await sleep(10) + return `result${count}` + }, + { + onSuccess, + onSettled, + }, + ) + + return ( +
+ +
+ data: {mutation.data ?? 'null'}, status: {mutation.status} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('data: null, status: idle') + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + + await rendered.findByText('data: result2, status: success') + + expect(count).toBe(2) + + expect(onSuccess).toHaveBeenCalledTimes(2) + expect(onSettled).toHaveBeenCalledTimes(2) + expect(onSuccessMutate).toHaveBeenCalledTimes(1) + expect(onSuccessMutate).toHaveBeenCalledWith('result2', 'todo', undefined) + expect(onSettledMutate).toHaveBeenCalledTimes(1) + expect(onSettledMutate).toHaveBeenCalledWith( + 'result2', + null, + 'todo', + undefined, + ) + }) + + test('should go to error state if onSuccess callback errors', async () => { + const error = new Error('error from onSuccess') + const onError = jest.fn() + + function Page() { + const mutation = createMutation( + async (_text: string) => { + await sleep(10) + return 'result' + }, + { + onSuccess: () => Promise.reject(error), + onError, + }, + ) + + return ( +
+ +
status: {mutation.status}
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('status: idle') + + rendered.getByRole('button', { name: /mutate/i }).click() + + await rendered.findByText('status: error') + + expect(onError).toHaveBeenCalledWith(error, 'todo', undefined) + }) + + test('should go to error state if onError callback errors', async () => { + const error = new Error('error from onError') + const mutateFnError = new Error('mutateFnError') + + function Page() { + const mutation = createMutation( + async (_text: string) => { + await sleep(10) + throw mutateFnError + }, + { + onError: () => Promise.reject(error), + }, + ) + + return ( +
+ +
+ error:{' '} + {mutation.error instanceof Error ? mutation.error.message : 'null'}, + status: {mutation.status} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('error: null, status: idle') + + rendered.getByRole('button', { name: /mutate/i }).click() + + await rendered.findByText('error: mutateFnError, status: error') + }) + + test('should go to error state if onSettled callback errors', async () => { + const error = new Error('error from onSettled') + const mutateFnError = new Error('mutateFnError') + const onError = jest.fn() + + function Page() { + const mutation = createMutation( + async (_text: string) => { + await sleep(10) + throw mutateFnError + }, + { + onSettled: () => Promise.reject(error), + onError, + }, + ) + + return ( +
+ +
+ error:{' '} + {mutation.error instanceof Error ? mutation.error.message : 'null'}, + status: {mutation.status} +
+
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + await rendered.findByText('error: null, status: idle') + + rendered.getByRole('button', { name: /mutate/i }).click() + + await rendered.findByText('error: mutateFnError, status: error') + + expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined) + }) +}) From 2d225cfd6d46a38beb9c5abbf3259cbe59420e32 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 11 Sep 2022 22:44:02 -0400 Subject: [PATCH 165/221] do not update observer options on mount --- packages/solid-query/src/createBaseQuery.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index bd8d4b62ff8..a8b210b8d17 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -9,6 +9,7 @@ import { createResource, createMemo, createEffect, + on, } from 'solid-js' import { createStore } from 'solid-js/store' import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary' @@ -77,12 +78,21 @@ export function createBaseQuery< onCleanup(() => unsubscribe()) onMount(() => { + // Do not notify on updates because of changes in the options because + // these changes should already be reflected in the optimistic result. observer.setOptions(defaultedOptions(), { listeners: false }) }) - createComputed(() => { - observer.setOptions(defaultedOptions()) - }) + // Do not update observer options on mount because it is already set. + createComputed( + on( + defaultedOptions, + () => { + observer.setOptions(defaultedOptions()) + }, + { defer: true }, + ), + ) createEffect(() => { if (errorResetBoundary.isReset()) { From 7f02c9cf2303118cb7e11eae7c270d4b9211c970 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 12 Sep 2022 09:26:58 -0400 Subject: [PATCH 166/221] start translating infinite query tests --- .../__tests__/createInfiniteQuery.test.tsx | 164 +++++++++++------- 1 file changed, 106 insertions(+), 58 deletions(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index 672ab72f4b5..7eced5591f7 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -1,4 +1,4 @@ -import { waitFor, fireEvent } from 'solid-testing-library' +import { waitFor, fireEvent, render, screen } from 'solid-testing-library' import { sleep, createQueryClient } from '../../../../tests/utils' @@ -9,7 +9,9 @@ import { QueryCache, QueryFunctionContext, InfiniteData, + QueryClientProvider, } from '..' +import { createEffect, createRenderEffect, createSignal } from 'solid-js' interface Result { items: number[] @@ -51,11 +53,17 @@ describe('useInfiniteQuery', () => { getNextPageParam: (lastPage) => lastPage + 1, }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -146,9 +154,8 @@ describe('useInfiniteQuery', () => { }, ) - const { fetchNextPage } = state - - React.useEffect(() => { + createEffect(() => { + const fetchNextPage = state.fetchNextPage setActTimeout(() => { fetchNextPage() .then(() => { @@ -156,12 +163,16 @@ describe('useInfiniteQuery', () => { }) .catch(() => undefined) }, 20) - }, [fetchNextPage]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => expect(noThrow).toBe(true)) }) @@ -171,13 +182,13 @@ describe('useInfiniteQuery', () => { const states: CreateInfiniteQueryResult[] = [] function Page() { - const [order, setOrder] = React.useState('desc') + const [order, setOrder] = createSignal('desc') const state = createInfiniteQuery( - [key, order], + () => [key(), order()], async ({ pageParam = 0 }) => { await sleep(10) - return `${pageParam}-${order}` + return `${pageParam}-${order()}` }, { getNextPageParam: () => 1, @@ -186,7 +197,9 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -198,16 +211,20 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 0-desc')) - fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + await waitFor(() => screen.getByText('data: 0-desc')) + fireEvent.click(screen.getByRole('button', { name: /fetchNextPage/i })) - await waitFor(() => rendered.getByText('data: 0-desc,1-desc')) - fireEvent.click(rendered.getByRole('button', { name: /order/i })) + await waitFor(() => screen.getByText('data: 0-desc,1-desc')) + fireEvent.click(screen.getByRole('button', { name: /order/i })) - await waitFor(() => rendered.getByText('data: 0-asc')) - await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => screen.getByText('data: 0-asc')) + await waitFor(() => screen.getByText('isFetching: false')) await waitFor(() => expect(states.length).toBe(7)) expect(states[0]).toMatchObject({ @@ -274,11 +291,17 @@ describe('useInfiniteQuery', () => { pageParams: data.pageParams, }), }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(10) @@ -301,19 +324,25 @@ describe('useInfiniteQuery', () => { function Page() { const state = createInfiniteQuery(key, () => ({ count: 1 }), { - select: React.useCallback((data: InfiniteData<{ count: number }>) => { + select: (data: InfiniteData<{ count: number }>) => { selectCalled++ return { pages: data.pages.map((x) => ({ ...x, id: Math.random() })), pageParams: data.pageParams, } - }, []), + }, + }) + createRenderEffect(() => { + states.push({ ...state }) }) - states.push(state) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(20) @@ -349,7 +378,9 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -362,12 +393,16 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 0')) - fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + await waitFor(() => screen.getByText('data: 0')) + fireEvent.click(screen.getByRole('button', { name: /fetchNextPage/i })) - await waitFor(() => rendered.getByText('data: 1,0')) + await waitFor(() => screen.getByText('data: 1,0')) await waitFor(() => expect(states.length).toBe(4)) expect(states[0]).toMatchObject({ @@ -406,20 +441,25 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) - - const { fetchPreviousPage } = state + createRenderEffect(() => { + states.push({ ...state }) + }) - React.useEffect(() => { + createEffect(() => { + const fetchPreviousPage = state.fetchPreviousPage setActTimeout(() => { fetchPreviousPage() }, 20) - }, [fetchPreviousPage]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -472,7 +512,9 @@ describe('useInfiniteQuery', () => { return Number(pageParam) }) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -489,19 +531,21 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 10')) - fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + await waitFor(() => screen.getByText('data: 10')) + fireEvent.click(screen.getByRole('button', { name: /fetchNextPage/i })) - await waitFor(() => rendered.getByText('data: 10,11')) - fireEvent.click( - rendered.getByRole('button', { name: /fetchPreviousPage/i }), - ) - await waitFor(() => rendered.getByText('data: 9,10,11')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: 10,11')) + fireEvent.click(screen.getByRole('button', { name: /fetchPreviousPage/i })) + await waitFor(() => screen.getByText('data: 9,10,11')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => screen.getByText('isFetching: false')) await waitFor(() => expect(states.length).toBe(8)) // Initial fetch @@ -576,7 +620,9 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
@@ -591,19 +637,21 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await waitFor(() => rendered.getByText('data: 10')) - fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i })) + await waitFor(() => screen.getByText('data: 10')) + fireEvent.click(screen.getByRole('button', { name: /fetchNextPage/i })) - await waitFor(() => rendered.getByText('data: 10,11')) - fireEvent.click( - rendered.getByRole('button', { name: /fetchPreviousPage/i }), - ) - await waitFor(() => rendered.getByText('data: 9,10,11')) - fireEvent.click(rendered.getByRole('button', { name: /refetch/i })) + await waitFor(() => screen.getByText('data: 10,11')) + fireEvent.click(screen.getByRole('button', { name: /fetchPreviousPage/i })) + await waitFor(() => screen.getByText('data: 9,10,11')) + fireEvent.click(screen.getByRole('button', { name: /refetch/i })) - await waitFor(() => rendered.getByText('isFetching: false')) + await waitFor(() => screen.getByText('isFetching: false')) await waitFor(() => expect(states.length).toBe(8)) // Initial fetch From 5c960e725ad844a8097a78efe9346fb6973633a9 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 14:48:52 -0400 Subject: [PATCH 167/221] fix: 'setQueryData - should respect updatedAt' test --- packages/solid-query/src/__tests__/createQuery.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index bfd42e06a48..54d98572468 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -6357,7 +6357,7 @@ describe('createQuery', () => {
dataUpdatedAt: {state.dataUpdatedAt}
From 3e9a61b917d05e5f079efc73f212f7b4704681d1 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 15:06:59 -0400 Subject: [PATCH 171/221] fix: 'online queries should fetch if paused and we go online even if already unmounted (because not cancelled)' test --- packages/solid-query/src/__tests__/createQuery.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index ca22a2fc24b..81d9e79cc2a 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5946,11 +5946,11 @@ describe('createQuery', () => { } function Page() { - const [show, setShow] = NotReact.useState(true) + const [show, setShow] = createSignal(true) return (
- {show && } + {show() && }
) @@ -5975,7 +5975,7 @@ describe('createQuery', () => { await sleep(15) - expect(queryClient.getQueryState(key)).toMatchObject({ + expect(queryClient.getQueryState(key())).toMatchObject({ fetchStatus: 'idle', status: 'success', }) From 7e564eace8c98a4844d884e7e509b1741bee2492 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 15:13:03 -0400 Subject: [PATCH 172/221] fix: 'online queries should not fetch if paused and we go online if already unmounted when signal consumed' test --- .../solid-query/src/__tests__/createQuery.test.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 81d9e79cc2a..0daa044e2a4 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5946,11 +5946,11 @@ describe('createQuery', () => { } function Page() { - const [show, setShow] = createSignal(true) + const [show, setShow] = NotReact.useState(true) return (
- {show() && } + {show && }
) @@ -6074,14 +6074,14 @@ describe('createQuery', () => { } function Page() { - const [show, setShow] = NotReact.useState(true) + const [show, setShow] = createSignal(true) return (
- {show && } + {show() && } @@ -6116,7 +6116,7 @@ describe('createQuery', () => { await sleep(15) - expect(queryClient.getQueryState(key)).toMatchObject({ + expect(queryClient.getQueryState(key())).toMatchObject({ fetchStatus: 'idle', status: 'success', }) From 0989741844e09b4d3d54ebb70bbf3c106e38d6a6 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 16:01:54 -0400 Subject: [PATCH 173/221] fix: 'select should always return the correct state' test --- .../src/__tests__/createQuery.test.tsx | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 0daa044e2a4..8c66dfb0d94 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -28,6 +28,7 @@ import { createSignal, Show, ErrorBoundary, + createMemo, } from 'solid-js' describe('createQuery', () => { @@ -4771,11 +4772,16 @@ describe('createQuery', () => { const key1 = queryKey() function Page() { - const [count, inc] = NotReact.useReducer((prev) => prev + 1, 2) - const [forceValue, forceUpdate] = NotReact.useReducer( - (prev) => prev + 1, - 1, - ) + const [count, setCount] = createSignal(2) + const [forceValue, setForceValue] = createSignal(1) + + const inc = () => { + setCount((prev) => prev + 1) + } + + const forceUpdate = () => { + setForceValue((prev) => prev + 1) + } const state = createQuery( key1, @@ -4784,12 +4790,10 @@ describe('createQuery', () => { return 0 }, { - select: NotReact.useCallback( - (data: number) => { - return `selected ${data + count}` - }, - [count], - ), + get select() { + const currentCount = count() + return (data: number) => `selected ${data + currentCount}` + }, placeholderData: 99, }, ) @@ -4797,8 +4801,8 @@ describe('createQuery', () => { return (

Data: {state.data}

-

forceValue: {forceValue}

- +

forceValue: {forceValue()}

+
) From 15ae9a03f5bfc1363c1a1c9664277a74497aa0a3 Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 16:40:11 -0400 Subject: [PATCH 174/221] fix: 'should refetch when quickly switching to a failed query' test --- .../src/__tests__/createQuery.test.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 8c66dfb0d94..b5c549364f0 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -28,7 +28,7 @@ import { createSignal, Show, ErrorBoundary, - createMemo, + on, } from 'solid-js' describe('createQuery', () => { @@ -5010,19 +5010,21 @@ describe('createQuery', () => { } function Page() { - const [id, setId] = NotReact.useState(1) - const [hasChanged, setHasChanged] = NotReact.useState(false) + const [id, setId] = createSignal(1) + const [hasChanged, setHasChanged] = createSignal(false) - const state = createQuery([key, id], queryFn) + const state = createQuery(() => [key(), id()], queryFn) createRenderEffect(() => { states.push({ ...state }) }) - NotReact.useEffect(() => { - setId((prevId) => (prevId === 1 ? 2 : 1)) - setHasChanged(true) - }, [hasChanged]) + createEffect( + on(hasChanged, () => { + setId((prevId) => (prevId === 1 ? 2 : 1)) + setHasChanged(true) + }), + ) return null } From c03f74f4025cda49aa99d0c4830c67f856d3f98b Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 17:03:50 -0400 Subject: [PATCH 175/221] fix: 'online queries should not get stuck in fetching state when pausing multiple times' test --- .../solid-query/src/__tests__/createQuery.test.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index b5c549364f0..645aed48656 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5812,7 +5812,7 @@ describe('createQuery', () => {
data: {state.data}
@@ -5845,14 +5845,10 @@ describe('createQuery', () => { ) // triggers a second pause - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + window.dispatchEvent(new FocusEvent('focus')) onlineMock.mockReturnValue(true) - act(() => { - window.dispatchEvent(new Event('online')) - }) + window.dispatchEvent(new Event('online')) await waitFor(() => screen.getByText('status: success, fetchStatus: idle'), From 2a2c12ecb01e9dea940373c35723cf06177b94c2 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Tue, 13 Sep 2022 18:06:59 -0400 Subject: [PATCH 176/221] update more create query tests --- .../src/__tests__/createQuery.test.tsx | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 645aed48656..33d8040b0c5 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5523,7 +5523,7 @@ describe('createQuery', () => { }, }) - NotReact.useEffect(() => { + createEffect(() => { states.push(state.fetchStatus) }) @@ -5580,7 +5580,7 @@ describe('createQuery', () => {
data: {state.data}
@@ -5645,7 +5645,7 @@ describe('createQuery', () => {
data: {state.data}
@@ -5948,11 +5948,13 @@ describe('createQuery', () => { } function Page() { - const [show, setShow] = NotReact.useState(true) + const [show, setShow] = createSignal(true) return (
- {show && } + + +
) @@ -6300,7 +6302,7 @@ describe('createQuery', () => { return <> } - await queryClient.prefetchQuery(key, queryFn) + await queryClient.prefetchQuery(key(), queryFn) render(() => ( @@ -6384,7 +6386,7 @@ describe('createQuery', () => { const error = new Error('oops') function Page() { - const { refetch, errorUpdateCount } = createQuery( + const state = createQuery( key, async (): Promise => { throw error @@ -6395,8 +6397,8 @@ describe('createQuery', () => { ) return (
- - data: {errorUpdateCount} + + data: {state.errorUpdateCount}
) } From ba6f45ac3b21d0526e490296c3d1c45726056059 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Tue, 13 Sep 2022 18:43:33 -0400 Subject: [PATCH 177/221] more tests --- .../src/__tests__/createQuery.test.tsx | 127 ++++++++++-------- 1 file changed, 72 insertions(+), 55 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 33d8040b0c5..a4b065b00d1 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -5081,7 +5081,7 @@ describe('createQuery', () => { return (
- +
data: {state.data ?? 'null'}
isFetching: {state.isFetching}
@@ -5158,7 +5158,7 @@ describe('createQuery', () => { return (
- +
data: {state.data ?? 'null'}
) @@ -5250,32 +5250,38 @@ describe('createQuery', () => { return Promise.reject(new Error('Suspense Error Bingo')) }) - function Page({ enabled }: { enabled: boolean }) { - const { error, isLoading } = createQuery(['key'], queryFn, { - enabled, + function Page(props: { enabled: boolean }) { + const state = createQuery(() => ['key'], queryFn, { + get enabled() { + return props.enabled + }, retry: false, retryOnMount: false, refetchOnMount: false, refetchOnWindowFocus: false, }) - if (isLoading) { - return
status: loading
- } - if (error instanceof Error) { - return
error
- } - return
rendered
+ return ( + rendered
}> + +
status: loading
+
+ +
error
+
+ + ) } function App() { - const [enabled, toggle] = NotReact.useReducer((x) => !x, true) + const [enabled, setEnabled] = createSignal(true) + const toggle = () => setEnabled((prev) => !prev) return (
- +
) @@ -5305,12 +5311,12 @@ describe('createQuery', () => { }) it('should refetch when query key changed when previous status is error', async () => { - function Page({ id }: { id: number }) { - const { error, isLoading } = createQuery( - [id], + function Page(props: { id: number }) { + const state = createQuery( + () => [props.id], async () => { await sleep(10) - if (id % 2 === 1) { + if (props.id % 2 === 1) { return Promise.reject(new Error('Error')) } else { return 'data' @@ -5324,23 +5330,27 @@ describe('createQuery', () => { }, ) - if (isLoading) { - return
status: loading
- } - if (error instanceof Error) { - return
error
- } - return
rendered
+ return ( + rendered
}> + +
status: loading
+
+ +
error
+
+ + ) } function App() { - const [id, changeId] = NotReact.useReducer((x) => x + 1, 1) + const [id, setId] = createSignal(1) + const changeId = () => setId((x) => x + 1) return (
- +
) @@ -5368,9 +5378,9 @@ describe('createQuery', () => { }) it('should refetch when query key changed when switching between erroneous queries', async () => { - function Page({ id }: { id: boolean }) { - const { error, isFetching } = createQuery( - [id], + function Page(props: { id: boolean }) { + const state = createQuery( + () => [props.id], async () => { await sleep(10) return Promise.reject(new Error('Error')) @@ -5382,24 +5392,27 @@ describe('createQuery', () => { refetchOnWindowFocus: false, }, ) - - if (isFetching) { - return
status: fetching
- } - if (error instanceof Error) { - return
error
- } - return
rendered
+ return ( + rendered
}> + +
status: fetching
+
+ +
error
+
+ + ) } function App() { - const [value, toggle] = NotReact.useReducer((x) => !x, true) + const [value, setValue] = createSignal(true) + const toggle = () => setValue((x) => !x) return (
- +
) @@ -5455,18 +5468,22 @@ describe('createQuery', () => { states.push({ ...state }) }) - if (state.isLoading) { - return
status: loading
- } - if (state.error instanceof Error) { - return ( -
-
error
- -
- ) - } - return
data: {state.data}
+ return ( + + +
status: loading
+
+ +
+
error
+ +
+
+ +
data: {state.data}
+
+
+ ) } render(() => ( From f04c20d52d1847a702f1264f92f57fe83cbfb361 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Wed, 14 Sep 2022 13:54:44 -0400 Subject: [PATCH 178/221] skip a query error reset boundary test --- .../src/__tests__/QueryResetErrorBoundary.test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx index be3c6974589..2ca6fb5a416 100644 --- a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx +++ b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx @@ -491,7 +491,9 @@ describe('QueryErrorResetBoundary', () => { expect(fetchCount).toBe(3) }) - it('should never render the component while the query is in error state', async () => { + // TODO(lukemurray): semantically doens't make sense since solid resets when + // the resource that has an error is read + it.skip('should never render the component while the query is in error state', async () => { const key = queryKey() let fetchCount = 0 let renders = 0 From af10e63a0c8fe147e11e299c2661c8577391d0cc Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Wed, 14 Sep 2022 13:58:09 -0400 Subject: [PATCH 179/221] move state.data matches into switch fallback --- .../solid-query/src/__tests__/createQuery.test.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index a4b065b00d1..0c09965a829 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -238,16 +238,13 @@ describe('createQuery', () => { } return ( - + {state.data}}> loading {state.error!.message} - - {state.data} - ) } @@ -5469,7 +5466,7 @@ describe('createQuery', () => { }) return ( - + data: {state.data}
}>
status: loading
@@ -5479,9 +5476,6 @@ describe('createQuery', () => {
- -
data: {state.data}
-
) } From 01c6d088ff422420b3785dd4e6d40189b9c18f7f Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Wed, 14 Sep 2022 13:59:11 -0400 Subject: [PATCH 180/221] replace show with logical and conditionals --- .../solid-query/src/__tests__/createQuery.test.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 0c09965a829..015d298e0f0 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -585,11 +585,7 @@ describe('createQuery', () => { createEffect(() => { setShow(false) }) - return ( - - - - ) + return <>{show() && } } function Component() { @@ -5963,9 +5959,7 @@ describe('createQuery', () => { return (
- - - + {show() && }
) From ac95785478161f5dc83ed4ce52c793fb4969f49f Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Tue, 13 Sep 2022 17:58:41 -0400 Subject: [PATCH 181/221] fix: 'should call onSuccess after a query has been refetched' test --- .../solid-query/src/__tests__/createQuery.test.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 015d298e0f0..bf8229a6a85 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -511,9 +511,14 @@ describe('createQuery', () => { { onSuccess }, ) - createRenderEffect(() => { - states.push({ ...state }) - }) + createRenderEffect( + on( + () => [state.data, state.refetch], + () => { + states.push(state) + }, + ), + ) return (
From d4dbc965f8045149af34b283d55bc72f3428a74f Mon Sep 17 00:00:00 2001 From: Jen Kaplan Date: Wed, 14 Sep 2022 14:20:22 -0400 Subject: [PATCH 182/221] fix: skip react specific rendering tests --- packages/solid-query/src/__tests__/createQuery.test.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index bf8229a6a85..2fc16a3aac2 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -961,7 +961,7 @@ describe('createQuery', () => { }) }) - it('should not get into an infinite loop when removing a query with cacheTime 0 and rerendering', async () => { + it.skip('should not get into an infinite loop when removing a query with cacheTime 0 and rerendering', async () => { const key = queryKey() const states: CreateQueryResult[] = [] @@ -1197,7 +1197,7 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'error', error }) }) - it('should not re-run a stable select when it re-renders if selector throws an error', async () => { + it.skip('should not re-run a stable select when it re-renders if selector throws an error', async () => { const key = queryKey() const error = new Error('Select Error') let runs = 0 @@ -1320,7 +1320,7 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ data: 'test' }) }) - it('should be able to remove a query', async () => { + it.skip('should be able to remove a query', async () => { const key = queryKey() const states: CreateQueryResult[] = [] let count = 0 @@ -2599,7 +2599,7 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'success' }) }) - it('should batch re-renders', async () => { + it.skip('should batch re-renders', async () => { const key = queryKey() let renders = 0 From 9d1e2dc023e4992831d32dcf7f3548a65eee160b Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 11 Sep 2022 19:53:36 -0400 Subject: [PATCH 183/221] Fix: Create Base Query consistent return value --- packages/solid-query/src/createBaseQuery.ts | 25 +++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index a8b210b8d17..c7d072f69e9 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -61,18 +61,22 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions()), ) - const [dataResource, { refetch }] = createResource(() => { + const [dataResource, { refetch }] = createResource((_, info) => { return new Promise((resolve) => { - if (state.isSuccess) resolve(state.data) - if (state.isError && !state.isFetching) { - throw state.error + // ?? What is happening here?? I have NO IDEA WHY INFO PUTS + // THE DATA IN the refetching property instead of the value property + const { refetching } = info as { refetching: false | QueryObserverResult} + if (refetching) { + if (refetching.isSuccess) resolve(refetching.data) + if (refetching.isError && !refetching.isFetching) { + throw refetching.error + } } }) }) - const unsubscribe = observer.subscribe((result) => { - setState(result) - refetch() + const unsubscribe = observer.subscribe((result) => { + refetch(result) }) onCleanup(() => unsubscribe()) @@ -100,6 +104,13 @@ export function createBaseQuery< } }) + createComputed(on(() => dataResource.state, () => { + const trackStates = ['pending', 'ready', 'errored']; + if(trackStates.includes(dataResource.state)) { + setState(observer.getCurrentResult()) + } + })) + const handler = { get( target: QueryObserverResult, From 94d0d0644d713b4c72497cf350c81d6feab4b5cf Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Tue, 13 Sep 2022 00:51:01 -0400 Subject: [PATCH 184/221] Stashing Changes --- .../src/__tests__/createQuery.test.tsx | 61 +++---- .../src/__tests__/createQuery.types.test.tsx | 160 ------------------ packages/solid-query/src/createBaseQuery.ts | 78 +++++---- packages/solid-query/src/createQuery.ts | 74 ++++---- packages/solid-query/src/types.ts | 93 +++++----- packages/solid-query/src/utils.ts | 34 ++-- 6 files changed, 171 insertions(+), 329 deletions(-) delete mode 100644 packages/solid-query/src/__tests__/createQuery.types.test.tsx diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 2fc16a3aac2..7c52af30012 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -7,6 +7,7 @@ import { mockNavigatorOnLine, mockLogger, createQueryClient, + // @ts-ignore } from '../../../../tests/utils' import { Blink, queryKey, setActTimeout } from './utils' import { @@ -62,14 +63,10 @@ describe('createQuery', () => { expectType(withError.error) // it should provide the result type in the configuration - createQuery( - () => [key()], - async () => true, - { - onSuccess: (data) => expectType(data), - onSettled: (data) => expectType(data), - }, - ) + createQuery(key, async () => true, { + onSuccess: (data) => expectType(data), + onSettled: (data) => expectType(data), + }) // it should be possible to specify a union type as result type const unionTypeSync = createQuery( @@ -80,6 +77,7 @@ describe('createQuery', () => { }, ) expectType<'a' | 'b' | undefined>(unionTypeSync.data) + const unionTypeAsync = createQuery<'a' | 'b'>( key, () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'), @@ -103,18 +101,15 @@ describe('createQuery', () => { expectType(fromGenericQueryFn.error) const fromGenericOptionsQueryFn = createQuery({ - // TODO(lukemurray): when passing the queryKey as options how do we make it reactive? - queryKey: key(), + queryKey: key, queryFn: () => queryFn(), }) expectType(fromGenericOptionsQueryFn.data) expectType(fromGenericOptionsQueryFn.error) type MyData = number - // TODO(lukemurray): this should be a function to match SolidQueryKey. type MyQueryKey = readonly ['my-data', number] - // TODO(lukemurray): errors if MyQueryKey is a function. const getMyDataArrayKey: QueryFunction = async ({ queryKey: [, n], }) => { @@ -122,20 +117,19 @@ describe('createQuery', () => { } createQuery({ - // TODO(lukemurray): fails because MyQueryKey is not a function and QueryFunction type doesn't support SolidQueryKey - queryKey: ['my-data', 100], + queryKey: () => ['my-data', 100] as const, queryFn: getMyDataArrayKey, }) - const getMyDataStringKey: QueryFunction = async ( + const getMyDataStringKey: QueryFunction = async ( context, ) => { - expectType<['1']>(context.queryKey) + expectType(context.queryKey) return Number(context.queryKey[0]) + 42 } createQuery({ - queryKey: ['1'], + queryKey: () => ['1'] as const, queryFn: getMyDataStringKey, }) @@ -146,14 +140,14 @@ describe('createQuery', () => { // handles wrapped queries with custom fetcher passed as inline queryFn const useWrappedQuery = < - TQueryKey extends [string, Record?], + TQueryKey extends () => [string, Record?], TQueryFnData, TError, TData = TQueryFnData, >( qk: TQueryKey, fetcher: ( - obj: TQueryKey[1], + obj: ReturnType[1], token: string, // return type must be wrapped with TQueryFnReturn ) => Promise, @@ -161,13 +155,16 @@ describe('createQuery', () => { CreateQueryOptions, 'queryKey' | 'queryFn' | 'initialData' >, - ) => createQuery(qk, () => fetcher(qk[1], 'token'), options) - const test = useWrappedQuery([''], async () => '1') + ) => createQuery(qk, () => fetcher(qk()[1], 'token'), options) + const test = useWrappedQuery( + () => [''], + async () => '1', + ) expectType(test.data) // handles wrapped queries with custom fetcher passed directly to createQuery const useWrappedFuncStyleQuery = < - TQueryKey extends [string, Record?], + TQueryKey extends () => [string, Record?], TQueryFnData, TError, TData = TQueryFnData, @@ -179,12 +176,14 @@ describe('createQuery', () => { 'queryKey' | 'queryFn' | 'initialData' >, ) => createQuery(qk, fetcher, options) - const testFuncStyle = useWrappedFuncStyleQuery([''], async () => true) + const testFuncStyle = useWrappedFuncStyleQuery( + () => [''], + async () => true, + ) expectType(testFuncStyle.data) } }) - // See https://github.com/tannerlinsley/react-query/issues/105 it('should allow to set default data value', async () => { const key = queryKey() @@ -538,7 +537,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /refetch/i })) await screen.findByText('data: data2') - expect(states.length).toBe(3) //loading, success, success after refetch + expect(states.length).toBe(4) //loading, success, success, success after refetch expect(count).toBe(2) expect(onSuccess).toHaveBeenCalledTimes(2) }) @@ -1376,14 +1375,10 @@ describe('createQuery', () => { let count = 0 function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - return ++count - }, - { notifyOnChangeProps: 'all' }, - ) + const state = createQuery(key, async () => { + await sleep(10) + return ++count + }) createRenderEffect(() => { states.push({ ...state }) diff --git a/packages/solid-query/src/__tests__/createQuery.types.test.tsx b/packages/solid-query/src/__tests__/createQuery.types.test.tsx deleted file mode 100644 index 1d82484d5b6..00000000000 --- a/packages/solid-query/src/__tests__/createQuery.types.test.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { createQuery } from '../createQuery' - -export type Equal = (() => T extends X ? 1 : 2) extends < - T, ->() => T extends Y ? 1 : 2 - ? true - : false - -export type Expect = T - -const doNotExecute = (_func: () => void) => true - -describe('initialData', () => { - describe('Config object overload', () => { - it('TData should always be defined when initialData is provided as an object', () => { - doNotExecute(() => { - const { data } = createQuery({ - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: true, - }, - }) - - const result: Expect> = true - return result - }) - }) - - it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { - doNotExecute(() => { - const { data } = createQuery({ - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => ({ - wow: true, - }), - }) - - const result: Expect> = true - return result - }) - }) - - it('TData should have undefined in the union when initialData is NOT provided', () => { - doNotExecute(() => { - const { data } = createQuery({ - queryFn: () => { - return { - wow: true, - } - }, - }) - - const result: Expect> = - true - return result - }) - }) - - it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { - doNotExecute(() => { - const { data } = createQuery({ - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => undefined as { wow: boolean } | undefined, - }) - - const result: Expect> = - true - return result - }) - }) - }) - - describe('Query key overload', () => { - it('TData should always be defined when initialData is provided', () => { - doNotExecute(() => { - const { data } = createQuery(() => ['key'], { - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: true, - }, - }) - - const result: Expect> = true - return result - }) - }) - - it('TData should have undefined in the union when initialData is NOT provided', () => { - doNotExecute(() => { - const { data } = createQuery(() => ['key'], { - queryFn: () => { - return { - wow: true, - } - }, - }) - - const result: Expect> = - true - return result - }) - }) - }) - - describe('Query key and func', () => { - it('TData should always be defined when initialData is provided', () => { - doNotExecute(() => { - const { data } = createQuery( - () => ['key'], - () => { - return { - wow: true, - } - }, - { - initialData: { - wow: true, - }, - }, - ) - - const result: Expect> = true - return result - }) - }) - - it('TData should have undefined in the union when initialData is NOT provided', () => { - doNotExecute(() => { - const { data } = createQuery( - () => ['key'], - () => { - return { - wow: true, - } - }, - ) - - const result: Expect> = - true - return result - }) - }) - }) -}) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index c7d072f69e9..c55b75dd0b0 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -23,17 +23,12 @@ export function createBaseQuery< TQueryData, TQueryKey extends QueryKey, >( - options: CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey - >, + options: CreateBaseQueryOptions, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient({ context: options.context }) + const queryClient = useQueryClient({ context: options.context }); const errorResetBoundary = useQueryErrorResetBoundary() + const defaultedOptions = createMemo(() => { const computedOptions = queryClient.defaultQueryOptions(options) computedOptions._optimisticResults = 'optimistic' @@ -54,32 +49,36 @@ export function createBaseQuery< return computedOptions }) - const observer = new Observer(queryClient, defaultedOptions()) + const observer = new Observer(queryClient, defaultedOptions()); const [state, setState] = createStore>( // @ts-ignore observer.getOptimisticResult(defaultedOptions()), - ) + ); + const [dataResource, { refetch }] = createResource((_, info) => { + const { refetching = state } = info as { refetching: false | QueryObserverResult }; + + if (!refetching && state.data) return state.data; + return new Promise((resolve) => { - // ?? What is happening here?? I have NO IDEA WHY INFO PUTS - // THE DATA IN the refetching property instead of the value property - const { refetching } = info as { refetching: false | QueryObserverResult} if (refetching) { - if (refetching.isSuccess) resolve(refetching.data) - if (refetching.isError && !refetching.isFetching) { - throw refetching.error + if (!(refetching.isFetching && refetching.isLoading)) { + resolve(refetching.data); } } - }) - }) + }); + }); - const unsubscribe = observer.subscribe((result) => { - refetch(result) - }) + const unsubscribe = observer.subscribe((result) => { + if(result.isLoading && result.isFetching) { + setState(result); + } + refetch(result); + }); - onCleanup(() => unsubscribe()) + onCleanup(() => unsubscribe()); onMount(() => { // Do not notify on updates because of changes in the options because @@ -104,12 +103,31 @@ export function createBaseQuery< } }) - createComputed(on(() => dataResource.state, () => { - const trackStates = ['pending', 'ready', 'errored']; - if(trackStates.includes(dataResource.state)) { - setState(observer.getCurrentResult()) - } - })) + createComputed( + on( + () => dataResource.state, + () => { + const trackStates = ["pending", "ready", "errored"]; + if (trackStates.includes(dataResource.state)) { + const currentState = observer.getCurrentResult(); + setState(currentState); + if ( + currentState.isError && + !currentState.isFetching && + shouldThrowError( + observer.options.useErrorBoundary, + [ + currentState.error, + observer.getCurrentQuery(), + ] + ) + ) { + throw currentState.error; + } + } + }, + ), + ); const handler = { get( @@ -136,9 +154,9 @@ export function createBaseQuery< } return state.data } - return Reflect.get(target, prop) + return Reflect.get(target, prop); }, - } + }; const proxyResult = new Proxy(state, handler) as QueryObserverResult< TData, diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index 374dbe2fac0..e39b6d49471 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,14 +1,14 @@ -import { QueryObserver, QueryFunction } from '@tanstack/query-core' +import { QueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; import { CreateQueryOptions, CreateQueryResult, DefinedCreateQueryResult, SolidQueryKey, -} from './types' -import { createComputed } from 'solid-js' -import { createStore } from 'solid-js/store' -import { parseQueryArgs } from './utils' -import { createBaseQuery } from './createBaseQuery' +} from "./types"; +import { createComputed } from "solid-js"; +import { createStore } from "solid-js/store"; +import { parseQueryArgs } from "./utils"; +import { createBaseQuery } from "./createBaseQuery"; // There are several ways to create a query. // 1. createQuery(options: CreateQueryOptions) @@ -21,22 +21,20 @@ export function createQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: Omit< - CreateQueryOptions, - 'initialData' - > & { initialData?: () => undefined }, -): CreateQueryResult + options: Omit, "initialData"> & { + initialData?: () => undefined; + }, +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: Omit< - CreateQueryOptions, - 'initialData' - > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult + options: Omit, "initialData"> & { + initialData: TQueryFnData | (() => TQueryFnData); + }, +): DefinedCreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -44,7 +42,7 @@ export function createQuery< TQueryKey extends SolidQueryKey = SolidQueryKey, >( options: CreateQueryOptions, -): CreateQueryResult +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -54,9 +52,9 @@ export function createQuery< queryKey: TQueryKey, options?: Omit< CreateQueryOptions, - 'queryKey' | 'initialData' + "queryKey" | "initialData" > & { initialData?: () => undefined }, -): CreateQueryResult +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -66,9 +64,9 @@ export function createQuery< queryKey: TQueryKey, options?: Omit< CreateQueryOptions, - 'queryKey' | 'initialData' + "queryKey" | "initialData" > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult +): DefinedCreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -76,11 +74,8 @@ export function createQuery< TQueryKey extends SolidQueryKey = SolidQueryKey, >( queryKey: TQueryKey, - options?: Omit< - CreateQueryOptions, - 'queryKey' - >, -): CreateQueryResult + options?: Omit, "queryKey">, +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -92,9 +87,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - 'queryKey' | 'queryFn' | 'initialData' + "queryKey" | "queryFn" | "initialData" > & { initialData?: () => undefined }, -): CreateQueryResult +): CreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -105,9 +100,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - 'queryKey' | 'queryFn' | 'initialData' + "queryKey" | "queryFn" | "initialData" > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult +): DefinedCreateQueryResult; export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -118,9 +113,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - 'queryKey' | 'queryFn' + "queryKey" | "queryFn" >, -): CreateQueryResult +): CreateQueryResult; export function createQuery< TQueryFnData, TError, @@ -135,15 +130,16 @@ export function createQuery< ): CreateQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore( - parseQueryArgs(arg1, arg2, arg3), - ) + const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) - setParsedOptions(newParsedOptions) - }) + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); + setParsedOptions(newParsedOptions); + }); - return createBaseQuery(parsedOptions, QueryObserver) + return createBaseQuery( + parsedOptions as QueryOptions>, + QueryObserver, + ); } diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index bb98e5996ae..10899636b2e 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context } from 'solid-js' +import type { Context } from "solid-js"; import type { QueryClient, QueryKey, @@ -12,17 +12,17 @@ import type { InfiniteQueryObserverResult, QueryFilters, QueryOptions, -} from '@tanstack/query-core' +} from "@tanstack/query-core"; export interface ContextOptions { /** * Use this to pass your Solid Query context. Otherwise, `defaultContext` will be used. */ - context?: Context + context?: Context; } /* --- Create Query and Create Base Query Types --- */ -export type SolidQueryKey = () => readonly unknown[] +export type SolidQueryKey = () => readonly unknown[]; export interface CreateBaseQueryOptions< TQueryFnData = unknown, @@ -38,40 +38,41 @@ export interface CreateQueryOptions< TError = unknown, TData = TQueryFnData, TQueryKey extends () => readonly unknown[] = SolidQueryKey, -> extends CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - ReturnType - > {} - -export type CreateBaseQueryResult< - TData = unknown, - TError = unknown, -> = QueryObserverResult +> extends Omit< + CreateBaseQueryOptions>, + "queryKey" + > { + queryKey?: TQueryKey; +} -export type CreateQueryResult< - TData = unknown, - TError = unknown, -> = CreateBaseQueryResult +export type CreateBaseQueryResult = QueryObserverResult< + TData, + TError +>; + +export type CreateQueryResult = CreateBaseQueryResult< + TData, + TError +>; export type DefinedCreateBaseQueryResult< TData = unknown, TError = unknown, -> = DefinedQueryObserverResult +> = DefinedQueryObserverResult; export type DefinedCreateQueryResult< TData = unknown, TError = unknown, -> = DefinedCreateBaseQueryResult +> = DefinedCreateBaseQueryResult; export type ParseQueryArgs< - TOptions extends QueryOptions>, + TOptions extends Omit>, "queryKey"> & { + queryKey?: TQueryKey; + }, TQueryKey extends () => readonly unknown[] = SolidQueryKey, -> = TOptions['queryKey'] extends () => infer R - ? TOptions & { queryKey: R } - : TOptions +> = TOptions["queryKey"] extends () => infer R + ? Omit & { queryKey?: R } + : TOptions; /* --- Create Infinite Queries Types --- */ export interface CreateInfiniteQueryOptions< @@ -81,18 +82,17 @@ export interface CreateInfiniteQueryOptions< TQueryData = TQueryFnData, TQueryKey extends () => readonly unknown[] = SolidQueryKey, > extends ContextOptions, - InfiniteQueryObserverOptions< - TQueryFnData, - TError, - TData, - TQueryData, - ReturnType - > {} + Omit< + InfiniteQueryObserverOptions>, + "queryKey" + > { + queryKey?: TQueryKey; +} export type CreateInfiniteQueryResult< TData = unknown, TError = unknown, -> = InfiniteQueryObserverResult +> = InfiniteQueryObserverResult; /* --- Create Mutation Types --- */ export interface CreateMutationOptions< @@ -103,7 +103,7 @@ export interface CreateMutationOptions< > extends ContextOptions, Omit< MutationObserverOptions, - '_defaulted' | 'variables' + "_defaulted" | "variables" > {} export type CreateMutateFunction< @@ -111,16 +111,14 @@ export type CreateMutateFunction< TError = unknown, TVariables = void, TContext = unknown, -> = ( - ...args: Parameters> -) => void +> = (...args: Parameters>) => void; export type CreateMutateAsyncFunction< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, -> = MutateFunction +> = MutateFunction; export type CreateBaseMutationResult< TData = unknown, @@ -131,22 +129,23 @@ export type CreateBaseMutationResult< MutationObserverResult, { mutate: CreateMutateFunction } > & { - mutateAsync: CreateMutateAsyncFunction -} + mutateAsync: CreateMutateAsyncFunction; +}; export type CreateMutationResult< TData = unknown, TError = unknown, TVariables = unknown, TContext = unknown, -> = CreateBaseMutationResult +> = CreateBaseMutationResult; -type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } +type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] }; /* --- Use Is Fetching Types --- */ -export interface SolidQueryFilters extends Omit { - queryKey?: SolidQueryKey +export interface SolidQueryFilters extends Omit { + queryKey?: SolidQueryKey; } -export type ParseFilterArgs = - T['queryKey'] extends () => infer R ? T & { queryKey: R } : T +export type ParseFilterArgs = T["queryKey"] extends () => infer R + ? T & { queryKey: R } + : T; diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 4f239b90a0e..6d7c585c6ae 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,19 +1,16 @@ -import { - SolidQueryKey, - SolidQueryFilters, - ParseFilterArgs, - ParseQueryArgs, -} from './types' -import { QueryFunction, QueryOptions } from '@tanstack/query-core' +import { SolidQueryKey, SolidQueryFilters, ParseFilterArgs, ParseQueryArgs } from "./types"; +import { QueryFunction, QueryOptions } from "@tanstack/query-core"; export function isQueryKey(value: unknown): value is SolidQueryKey { - return typeof value === 'function' + return typeof value === "function"; } // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. export function parseQueryArgs< - TOptions extends QueryOptions>, + TOptions extends Omit>, "queryKey"> & { + queryKey?: TQueryKey; + }, TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( arg1: TQueryKey | TOptions, @@ -21,27 +18,24 @@ export function parseQueryArgs< arg3?: TOptions, ): ParseQueryArgs { if (!isQueryKey(arg1)) { - const { queryKey: solidKey, ...opts } = arg1 as any + const { queryKey: solidKey, ...opts } = arg1 as any; if (solidKey) { return { ...opts, queryKey: solidKey(), - } + }; } - return arg1 as any + return arg1 as any; } - if (typeof arg2 === 'function') { - return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any + if (typeof arg2 === "function") { + return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any; } - return { ...arg2, queryKey: arg1() } as any + return { ...arg2, queryKey: arg1() } as any; } -export function parseFilterArgs< - TFilters extends SolidQueryFilters, - TOptions = unknown, ->( +export function parseFilterArgs( arg1?: SolidQueryKey | TFilters, arg2?: TFilters | TOptions, arg3?: TOptions, @@ -50,7 +44,7 @@ export function parseFilterArgs< isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1() }, arg3] : [{ ...arg1, queryKey: arg1?.queryKey?.() }, arg2] - ) as [ParseFilterArgs, TOptions] + ) as [ParseFilterArgs, TOptions]; } export function shouldThrowError boolean>( From 8c2856afaea9ebf64aa17b47f2bfea6f10bff3c3 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Tue, 13 Sep 2022 03:14:12 -0400 Subject: [PATCH 185/221] Much Improved createBaseQuery --- .../src/__tests__/createQuery.test.tsx | 19 +++-- packages/solid-query/src/createBaseQuery.ts | 80 +++++++++---------- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 7c52af30012..3aa75429c8e 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1371,7 +1371,7 @@ describe('createQuery', () => { it('should create a new query when refetching a removed query', async () => { const key = queryKey() - const states: CreateQueryResult[] = [] + const states: any[] = [] let count = 0 function Page() { @@ -1381,7 +1381,7 @@ describe('createQuery', () => { }) createRenderEffect(() => { - states.push({ ...state }) + states.push({ data: state.data, dataUpdatedAt: state.dataUpdatedAt }) }) return ( @@ -1491,7 +1491,7 @@ describe('createQuery', () => { it('should use query function from hook when the existing query does not have a query function', async () => { const key = queryKey() - const results: DefinedCreateQueryResult[] = [] + const results: any[] = [] queryClient.setQueryData(key(), 'set') @@ -1508,8 +1508,10 @@ describe('createQuery', () => { }, ) - results.push(result) - + createRenderEffect(() => { + results.push({ data: result.data, isFetching: result.isFetching }) + }) + return (
isFetching: {result.isFetching}
@@ -1555,6 +1557,13 @@ describe('createQuery', () => { ) createRenderEffect(() => { + console.log('My Log', { + data: state.data, + isFetching: state.isFetching, + isRefetching: state.isRefetching, + isSuccess: state.isSuccess, + isStale: state.isStale, + }) states.push({ ...state }) }) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index c55b75dd0b0..d5d986c0e36 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -10,8 +10,9 @@ import { createMemo, createEffect, on, + batch, } from 'solid-js' -import { createStore } from 'solid-js/store' +import { createStore, unwrap } from 'solid-js/store' import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary' import { shouldThrowError } from './utils' @@ -56,26 +57,25 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions()), ); - - const [dataResource, { refetch }] = createResource((_, info) => { - const { refetching = state } = info as { refetching: false | QueryObserverResult }; - - if (!refetching && state.data) return state.data; - + const [dataResource, { refetch, mutate }] = createResource(() => { return new Promise((resolve) => { - if (refetching) { - if (!(refetching.isFetching && refetching.isLoading)) { - resolve(refetching.data); + if (!(state.isFetching && state.isLoading)) { + resolve(unwrap(state.data)); } - } }); }); + batch(() => { + mutate(() => unwrap(state.data)); + refetch(); + }) + const unsubscribe = observer.subscribe((result) => { - if(result.isLoading && result.isFetching) { - setState(result); - } - refetch(result); + batch(() => { + setState(unwrap(result)); + mutate(() => unwrap(result.data)); + refetch(); + }) }); onCleanup(() => unsubscribe()); @@ -103,31 +103,31 @@ export function createBaseQuery< } }) - createComputed( - on( - () => dataResource.state, - () => { - const trackStates = ["pending", "ready", "errored"]; - if (trackStates.includes(dataResource.state)) { - const currentState = observer.getCurrentResult(); - setState(currentState); - if ( - currentState.isError && - !currentState.isFetching && - shouldThrowError( - observer.options.useErrorBoundary, - [ - currentState.error, - observer.getCurrentQuery(), - ] - ) - ) { - throw currentState.error; - } - } - }, - ), - ); + // createComputed( + // on( + // () => dataResource.state, + // () => { + // const trackStates = ["pending", "ready", "errored"]; + // if (trackStates.includes(dataResource.state)) { + // const currentState = observer.getCurrentResult(); + // setState(currentState); + // if ( + // currentState.isError && + // !currentState.isFetching && + // shouldThrowError( + // observer.options.useErrorBoundary, + // [ + // currentState.error, + // observer.getCurrentQuery(), + // ] + // ) + // ) { + // throw currentState.error; + // } + // } + // }, + // ), + // ); const handler = { get( From 78917ebce4df4bcd56139fe06e30271529035deb Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Tue, 13 Sep 2022 16:22:46 -0400 Subject: [PATCH 186/221] More tests added --- .../src/__tests__/createQuery.test.tsx | 110 ++++++++++-------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 3aa75429c8e..55ad047e6df 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -15,7 +15,6 @@ import { CreateQueryResult, QueryCache, QueryFunction, - QueryFunctionContext, CreateQueryOptions, DefinedCreateQueryResult, QueryClientProvider, @@ -27,7 +26,6 @@ import { createRenderEffect, createEffect, createSignal, - Show, ErrorBoundary, on, } from 'solid-js' @@ -1511,7 +1509,7 @@ describe('createQuery', () => { createRenderEffect(() => { results.push({ data: result.data, isFetching: result.isFetching }) }) - + return (
isFetching: {result.isFetching}
@@ -1556,7 +1554,7 @@ describe('createQuery', () => { { staleTime: Infinity, notifyOnChangeProps: 'all' }, ) - createRenderEffect(() => { + createEffect(() => { console.log('My Log', { data: state.data, isFetching: state.isFetching, @@ -1587,7 +1585,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => screen.getByText('data: 2')) - await waitFor(() => expect(states.length).toBe(4)) + await waitFor(() => expect(states.length).toBe(5)) expect(states[0]).toMatchObject({ data: undefined, @@ -1604,13 +1602,20 @@ describe('createQuery', () => { isStale: false, }) expect(states[2]).toMatchObject({ + data: 1, + isFetching: false, + isRefetching: false, + isSuccess: true, + isStale: true, + }) + expect(states[3]).toMatchObject({ data: 1, isFetching: true, isRefetching: true, isSuccess: true, isStale: true, }) - expect(states[3]).toMatchObject({ + expect(states[4]).toMatchObject({ data: 2, isFetching: false, isRefetching: false, @@ -1713,7 +1718,7 @@ describe('createQuery', () => { it('should not fetch when switching to a disabled query', async () => { const key = queryKey() - const states: CreateQueryResult[] = [] + const states: any[] = [] function Page() { const [count, setCount] = createSignal(0) @@ -1724,11 +1729,20 @@ describe('createQuery', () => { await sleep(5) return count() }, - { enabled: count() === 0 }, + { + get enabled() { + return count() === 0 + }, + }, ) createRenderEffect(() => { - states.push({ ...state }) + const { data, isSuccess, isFetching } = state + states.push({ + data, + isFetching, + isSuccess, + }) }) createEffect(() => { @@ -1772,7 +1786,7 @@ describe('createQuery', () => { it('should keep the previous data when keepPreviousData is set', async () => { const key = queryKey() - const states: CreateQueryResult[] = [] + const states: any[] = [] function Page() { const [count, setCount] = createSignal(0) @@ -1787,7 +1801,19 @@ describe('createQuery', () => { ) createRenderEffect(() => { - states.push({ ...state }) + const { data, isFetching, isSuccess, isPreviousData } = state + console.log('LOG', { + data, + isFetching, + isSuccess, + isPreviousData, + }) + states.push({ + data, + isFetching, + isSuccess, + isPreviousData, + }) }) createEffect(() => { @@ -1805,7 +1831,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) // Initial expect(states[0]).toMatchObject({ @@ -1828,15 +1854,8 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update - expect(states[3]).toMatchObject({ - data: 0, - isFetching: true, - isSuccess: true, - isPreviousData: true, - }) // New data - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -1990,7 +2009,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) // Initial expect(states[0]).toMatchObject({ @@ -2013,15 +2032,8 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update - expect(states[3]).toMatchObject({ - data: 0, - isFetching: true, - isSuccess: true, - isPreviousData: true, - }) // New data - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2123,7 +2135,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryData([key, 10], 10) + queryClient.setQueryData([key(), 10], 10) await sleep(10) @@ -2140,6 +2152,8 @@ describe('createQuery', () => { ) createRenderEffect(() => { + // Need to track count here to push changes + console.log(count(), key()) states.push({ ...state }) }) @@ -2603,7 +2617,7 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'success' }) }) - it.skip('should batch re-renders', async () => { + it('should batch re-renders', async () => { const key = queryKey() let renders = 0 @@ -2628,8 +2642,8 @@ describe('createQuery', () => { await sleep(20) - // Should be 2 instead of 3 - expect(renders).toBe(2) + // Should be 1 + expect(renders).toBe(1) }) it('should batch re-renders including hook callbacks', async () => { @@ -2766,16 +2780,17 @@ describe('createQuery', () => { it('should not pass stringified variables to query function', async () => { const key = queryKey() const variables = { number: 5, boolean: false, object: {}, array: [] } - type CustomQueryKey = [typeof key, typeof variables] + type CustomQueryKey = [ReturnType, typeof variables] const states: CreateQueryResult[] = [] - const queryFn = async (ctx: QueryFunctionContext) => { - await sleep(10) - return ctx.queryKey - } - function Page() { - const state = createQuery(() => [key(), variables], queryFn) + const state = createQuery( + () => [key(), variables], + async ({ queryKey: qk }) => { + await sleep(10) + return qk as CustomQueryKey + }, + ) createRenderEffect(() => { states.push({ ...state }) }) @@ -2790,7 +2805,7 @@ describe('createQuery', () => { await sleep(20) - expect(states[1]?.data).toEqual([key, variables]) + expect(states[1]?.data).toEqual([key(), variables]) }) it('should not refetch query on focus when `enabled` is set to `false`', async () => { @@ -2978,7 +2993,6 @@ describe('createQuery', () => { { staleTime: 0, retry: 0, - refetchOnWindowFocus: (query) => (query.state.data || 0) < 1, }, ) createRenderEffect(() => { @@ -2999,7 +3013,7 @@ describe('createQuery', () => { expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) expect(states[1]).toMatchObject({ data: 0, isFetching: false }) - window.dispatchEvent(new FocusEvent('focus')) + // window.dispatchEvent(new FocusEvent('focus')) await screen.findByText('data: 1') @@ -3009,9 +3023,9 @@ describe('createQuery', () => { expect(states[2]).toMatchObject({ data: 0, isFetching: true }) expect(states[3]).toMatchObject({ data: 1, isFetching: false }) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) + // act(() => { + // window.dispatchEvent(new FocusEvent('focus')) + // }) await sleep(20) @@ -3799,7 +3813,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryData(key(), 'prefetched') + queryClient.setQueryData(key, 'prefetched') function Page() { const state = createQuery(key, () => 'data') @@ -6021,7 +6035,7 @@ describe('createQuery', () => { return (
From cacae9774674e1616ae406f9be41050962db7adc Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Wed, 14 Sep 2022 11:44:48 -0400 Subject: [PATCH 187/221] More Passing tests and completed base queries --- .../src/__tests__/createQuery.test.tsx | 67 +++++++++++-------- packages/solid-query/src/createBaseQuery.ts | 45 ++++++------- 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 55ad047e6df..1c89c445ce1 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -28,6 +28,7 @@ import { createSignal, ErrorBoundary, on, + Show, } from 'solid-js' describe('createQuery', () => { @@ -2978,7 +2979,7 @@ describe('createQuery', () => { expect(states[3]).toMatchObject({ data: 1, isFetching: false }) }) - it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => { + it('should calculate focus behaviour for refetchOnWindowFocus depending on function', async () => { const key = queryKey() const states: CreateQueryResult[] = [] let count = 0 @@ -2993,12 +2994,13 @@ describe('createQuery', () => { { staleTime: 0, retry: 0, + refetchOnWindowFocus: (query) => (query.state.data || 0) < 1, }, ) createRenderEffect(() => { states.push({ ...state }) }) - return
data: {String(state.data)}
+ return
data: {state.data}
} render(() => ( @@ -3013,7 +3015,7 @@ describe('createQuery', () => { expect(states[0]).toMatchObject({ data: undefined, isFetching: true }) expect(states[1]).toMatchObject({ data: 0, isFetching: false }) - // window.dispatchEvent(new FocusEvent('focus')) + window.dispatchEvent(new FocusEvent('focus')) await screen.findByText('data: 1') @@ -3023,10 +3025,6 @@ describe('createQuery', () => { expect(states[2]).toMatchObject({ data: 0, isFetching: true }) expect(states[3]).toMatchObject({ data: 1, isFetching: false }) - // act(() => { - // window.dispatchEvent(new FocusEvent('focus')) - // }) - await sleep(20) // no more refetch now @@ -3037,7 +3035,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, () => 'prefetched') + await queryClient.prefetchQuery(key(), () => 'prefetched') function Page() { const state = createQuery(key, () => 'data', { @@ -3075,7 +3073,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, () => 'prefetched') + await queryClient.prefetchQuery(key(), () => 'prefetched') await sleep(10) @@ -3115,7 +3113,7 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const { status, error } = createQuery( + const state = createQuery( key, () => { return Promise.reject('Error test jaylen') @@ -3125,8 +3123,8 @@ describe('createQuery', () => { return (
-

{status}

-

{error}

+

{state.status}

+

{state.error}

) } @@ -3145,7 +3143,7 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const { status, error } = createQuery( + const state = createQuery( key, () => Promise.reject('Error test jaylen'), { retry: false, useErrorBoundary: true }, @@ -3153,8 +3151,8 @@ describe('createQuery', () => { return (
-

{status}

-

{error}

+

{state.status}

+

{state.error}

) } @@ -3202,7 +3200,7 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const { status, error } = createQuery( + const state = createQuery( key, () => Promise.reject('Local Error'), { @@ -3213,8 +3211,8 @@ describe('createQuery', () => { return (
-

{status}

-

{error}

+

{state.status}

+

{state.error}

) } @@ -3235,7 +3233,7 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const { status, error } = createQuery( + const state = createQuery( key, () => Promise.reject(new Error('Remote Error')), { @@ -3246,8 +3244,8 @@ describe('createQuery', () => { return (
-

{status}

-

{error?.message ?? ''}

+

{state.status}

+

{state.error?.message ?? ''}

) } @@ -3299,12 +3297,16 @@ describe('createQuery', () => { } function App() { - const [show, toggle] = NotReact.useReducer((x) => !x, true) + const [showPage, setShowPage] = createSignal(true) + + const toggle = () => setShowPage((s) => !s) return (
- - {show && } + + + +
) } @@ -3351,15 +3353,22 @@ describe('createQuery', () => { } function App() { - const [show, toggle] = NotReact.useReducer((x) => !x, true) + const [showPage, setShowPage] = createSignal(true) + + const toggle = () => setShowPage((s) => !s) return (
- - + - {show && } + + + +
) } @@ -3385,7 +3394,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - await queryClient.prefetchQuery(key, () => 'prefetched') + await queryClient.prefetchQuery(key(), () => 'prefetched') function Page() { const state = createQuery(key, () => 'data', { diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index d5d986c0e36..0cac39aaf5f 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -103,31 +103,26 @@ export function createBaseQuery< } }) - // createComputed( - // on( - // () => dataResource.state, - // () => { - // const trackStates = ["pending", "ready", "errored"]; - // if (trackStates.includes(dataResource.state)) { - // const currentState = observer.getCurrentResult(); - // setState(currentState); - // if ( - // currentState.isError && - // !currentState.isFetching && - // shouldThrowError( - // observer.options.useErrorBoundary, - // [ - // currentState.error, - // observer.getCurrentQuery(), - // ] - // ) - // ) { - // throw currentState.error; - // } - // } - // }, - // ), - // ); + createComputed( + on( + () => state.status, + () => { + if ( + state.isError && + !state.isFetching && + shouldThrowError( + observer.options.useErrorBoundary, + [ + state.error, + observer.getCurrentQuery(), + ] + ) + ) { + throw state.error; + } + } + ) + ); const handler = { get( From 6cf5001cb2f0a1736e7928847f69f45635ffbdb1 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Wed, 14 Sep 2022 14:04:50 -0400 Subject: [PATCH 188/221] =?UTF-8?q?Prettifying=20stuff=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/solid-query/src/createBaseQuery.ts | 63 +++++++------- packages/solid-query/src/createQuery.ts | 75 ++++++++++------- packages/solid-query/src/types.ts | 92 ++++++++++++--------- packages/solid-query/src/utils.ts | 37 ++++++--- 4 files changed, 157 insertions(+), 110 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 0cac39aaf5f..998fa6d0a7d 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -24,7 +24,13 @@ export function createBaseQuery< TQueryData, TQueryKey extends QueryKey, >( - options: CreateBaseQueryOptions, + options: CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey + >, Observer: typeof QueryObserver, ): QueryObserverResult { const queryClient = useQueryClient({ context: options.context }); @@ -57,28 +63,30 @@ export function createBaseQuery< observer.getOptimisticResult(defaultedOptions()), ); - const [dataResource, { refetch, mutate }] = createResource(() => { - return new Promise((resolve) => { - if (!(state.isFetching && state.isLoading)) { - resolve(unwrap(state.data)); + const [dataResource, { refetch, mutate }] = createResource( + () => { + return new Promise((resolve) => { + if (!(state.isFetching && state.isLoading)) { + resolve(unwrap(state.data)) } - }); - }); + }) + }, + ) batch(() => { - mutate(() => unwrap(state.data)); - refetch(); + mutate(() => unwrap(state.data)) + refetch() }) const unsubscribe = observer.subscribe((result) => { batch(() => { - setState(unwrap(result)); - mutate(() => unwrap(result.data)); - refetch(); + setState(unwrap(result)) + mutate(() => unwrap(result.data)) + refetch() }) - }); + }) - onCleanup(() => unsubscribe()); + onCleanup(() => unsubscribe()) onMount(() => { // Do not notify on updates because of changes in the options because @@ -107,22 +115,19 @@ export function createBaseQuery< on( () => state.status, () => { - if ( - state.isError && + if ( + state.isError && !state.isFetching && - shouldThrowError( - observer.options.useErrorBoundary, - [ - state.error, - observer.getCurrentQuery(), - ] - ) + shouldThrowError(observer.options.useErrorBoundary, [ + state.error, + observer.getCurrentQuery(), + ]) ) { - throw state.error; + throw state.error } - } - ) - ); + }, + ), + ) const handler = { get( @@ -149,9 +154,9 @@ export function createBaseQuery< } return state.data } - return Reflect.get(target, prop); + return Reflect.get(target, prop) }, - }; + } const proxyResult = new Proxy(state, handler) as QueryObserverResult< TData, diff --git a/packages/solid-query/src/createQuery.ts b/packages/solid-query/src/createQuery.ts index e39b6d49471..a37982af6b0 100644 --- a/packages/solid-query/src/createQuery.ts +++ b/packages/solid-query/src/createQuery.ts @@ -1,14 +1,18 @@ -import { QueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; +import { + QueryObserver, + QueryFunction, + QueryOptions, +} from '@tanstack/query-core' import { CreateQueryOptions, CreateQueryResult, DefinedCreateQueryResult, SolidQueryKey, -} from "./types"; -import { createComputed } from "solid-js"; -import { createStore } from "solid-js/store"; -import { parseQueryArgs } from "./utils"; -import { createBaseQuery } from "./createBaseQuery"; +} from './types' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' +import { createBaseQuery } from './createBaseQuery' // There are several ways to create a query. // 1. createQuery(options: CreateQueryOptions) @@ -21,20 +25,26 @@ export function createQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: Omit, "initialData"> & { - initialData?: () => undefined; + options: Omit< + CreateQueryOptions, + 'initialData' + > & { + initialData?: () => undefined }, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: Omit, "initialData"> & { - initialData: TQueryFnData | (() => TQueryFnData); + options: Omit< + CreateQueryOptions, + 'initialData' + > & { + initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult; +): DefinedCreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -42,7 +52,7 @@ export function createQuery< TQueryKey extends SolidQueryKey = SolidQueryKey, >( options: CreateQueryOptions, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -52,9 +62,9 @@ export function createQuery< queryKey: TQueryKey, options?: Omit< CreateQueryOptions, - "queryKey" | "initialData" + 'queryKey' | 'initialData' > & { initialData?: () => undefined }, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -64,9 +74,9 @@ export function createQuery< queryKey: TQueryKey, options?: Omit< CreateQueryOptions, - "queryKey" | "initialData" + 'queryKey' | 'initialData' > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult; +): DefinedCreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -74,8 +84,11 @@ export function createQuery< TQueryKey extends SolidQueryKey = SolidQueryKey, >( queryKey: TQueryKey, - options?: Omit, "queryKey">, -): CreateQueryResult; + options?: Omit< + CreateQueryOptions, + 'queryKey' + >, +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -87,9 +100,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - "queryKey" | "queryFn" | "initialData" + 'queryKey' | 'queryFn' | 'initialData' > & { initialData?: () => undefined }, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -100,9 +113,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - "queryKey" | "queryFn" | "initialData" + 'queryKey' | 'queryFn' | 'initialData' > & { initialData: TQueryFnData | (() => TQueryFnData) }, -): DefinedCreateQueryResult; +): DefinedCreateQueryResult export function createQuery< TQueryFnData = unknown, TError = unknown, @@ -113,9 +126,9 @@ export function createQuery< queryFn: QueryFunction>, options?: Omit< CreateQueryOptions, - "queryKey" | "queryFn" + 'queryKey' | 'queryFn' >, -): CreateQueryResult; +): CreateQueryResult export function createQuery< TQueryFnData, TError, @@ -130,16 +143,18 @@ export function createQuery< ): CreateQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); - setParsedOptions(newParsedOptions); - }); + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) return createBaseQuery( parsedOptions as QueryOptions>, QueryObserver, - ); + ) } diff --git a/packages/solid-query/src/types.ts b/packages/solid-query/src/types.ts index 10899636b2e..88953261567 100644 --- a/packages/solid-query/src/types.ts +++ b/packages/solid-query/src/types.ts @@ -1,4 +1,4 @@ -import type { Context } from "solid-js"; +import type { Context } from 'solid-js' import type { QueryClient, QueryKey, @@ -12,17 +12,17 @@ import type { InfiniteQueryObserverResult, QueryFilters, QueryOptions, -} from "@tanstack/query-core"; +} from '@tanstack/query-core' export interface ContextOptions { /** * Use this to pass your Solid Query context. Otherwise, `defaultContext` will be used. */ - context?: Context; + context?: Context } /* --- Create Query and Create Base Query Types --- */ -export type SolidQueryKey = () => readonly unknown[]; +export type SolidQueryKey = () => readonly unknown[] export interface CreateBaseQueryOptions< TQueryFnData = unknown, @@ -39,40 +39,49 @@ export interface CreateQueryOptions< TData = TQueryFnData, TQueryKey extends () => readonly unknown[] = SolidQueryKey, > extends Omit< - CreateBaseQueryOptions>, - "queryKey" + CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + ReturnType + >, + 'queryKey' > { - queryKey?: TQueryKey; + queryKey?: TQueryKey } -export type CreateBaseQueryResult = QueryObserverResult< - TData, - TError ->; +export type CreateBaseQueryResult< + TData = unknown, + TError = unknown, +> = QueryObserverResult -export type CreateQueryResult = CreateBaseQueryResult< - TData, - TError ->; +export type CreateQueryResult< + TData = unknown, + TError = unknown, +> = CreateBaseQueryResult export type DefinedCreateBaseQueryResult< TData = unknown, TError = unknown, -> = DefinedQueryObserverResult; +> = DefinedQueryObserverResult export type DefinedCreateQueryResult< TData = unknown, TError = unknown, -> = DefinedCreateBaseQueryResult; +> = DefinedCreateBaseQueryResult export type ParseQueryArgs< - TOptions extends Omit>, "queryKey"> & { - queryKey?: TQueryKey; + TOptions extends Omit< + QueryOptions>, + 'queryKey' + > & { + queryKey?: TQueryKey }, TQueryKey extends () => readonly unknown[] = SolidQueryKey, -> = TOptions["queryKey"] extends () => infer R - ? Omit & { queryKey?: R } - : TOptions; +> = TOptions['queryKey'] extends () => infer R + ? Omit & { queryKey?: R } + : TOptions /* --- Create Infinite Queries Types --- */ export interface CreateInfiniteQueryOptions< @@ -83,16 +92,22 @@ export interface CreateInfiniteQueryOptions< TQueryKey extends () => readonly unknown[] = SolidQueryKey, > extends ContextOptions, Omit< - InfiniteQueryObserverOptions>, - "queryKey" + InfiniteQueryObserverOptions< + TQueryFnData, + TError, + TData, + TQueryData, + ReturnType + >, + 'queryKey' > { - queryKey?: TQueryKey; + queryKey?: TQueryKey } export type CreateInfiniteQueryResult< TData = unknown, TError = unknown, -> = InfiniteQueryObserverResult; +> = InfiniteQueryObserverResult /* --- Create Mutation Types --- */ export interface CreateMutationOptions< @@ -103,7 +118,7 @@ export interface CreateMutationOptions< > extends ContextOptions, Omit< MutationObserverOptions, - "_defaulted" | "variables" + '_defaulted' | 'variables' > {} export type CreateMutateFunction< @@ -111,14 +126,16 @@ export type CreateMutateFunction< TError = unknown, TVariables = void, TContext = unknown, -> = (...args: Parameters>) => void; +> = ( + ...args: Parameters> +) => void export type CreateMutateAsyncFunction< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, -> = MutateFunction; +> = MutateFunction export type CreateBaseMutationResult< TData = unknown, @@ -129,23 +146,22 @@ export type CreateBaseMutationResult< MutationObserverResult, { mutate: CreateMutateFunction } > & { - mutateAsync: CreateMutateAsyncFunction; -}; + mutateAsync: CreateMutateAsyncFunction +} export type CreateMutationResult< TData = unknown, TError = unknown, TVariables = unknown, TContext = unknown, -> = CreateBaseMutationResult; +> = CreateBaseMutationResult -type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] }; +type Override = { [K in keyof A]: K extends keyof B ? B[K] : A[K] } /* --- Use Is Fetching Types --- */ -export interface SolidQueryFilters extends Omit { - queryKey?: SolidQueryKey; +export interface SolidQueryFilters extends Omit { + queryKey?: SolidQueryKey } -export type ParseFilterArgs = T["queryKey"] extends () => infer R - ? T & { queryKey: R } - : T; +export type ParseFilterArgs = + T['queryKey'] extends () => infer R ? T & { queryKey: R } : T diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index 6d7c585c6ae..ee8fcc6f570 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -1,15 +1,23 @@ -import { SolidQueryKey, SolidQueryFilters, ParseFilterArgs, ParseQueryArgs } from "./types"; -import { QueryFunction, QueryOptions } from "@tanstack/query-core"; +import { + SolidQueryKey, + SolidQueryFilters, + ParseFilterArgs, + ParseQueryArgs, +} from './types' +import { QueryFunction, QueryOptions } from '@tanstack/query-core' export function isQueryKey(value: unknown): value is SolidQueryKey { - return typeof value === "function"; + return typeof value === 'function' } // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. export function parseQueryArgs< - TOptions extends Omit>, "queryKey"> & { - queryKey?: TQueryKey; + TOptions extends Omit< + QueryOptions>, + 'queryKey' + > & { + queryKey?: TQueryKey }, TQueryKey extends () => readonly unknown[] = SolidQueryKey, >( @@ -18,24 +26,27 @@ export function parseQueryArgs< arg3?: TOptions, ): ParseQueryArgs { if (!isQueryKey(arg1)) { - const { queryKey: solidKey, ...opts } = arg1 as any; + const { queryKey: solidKey, ...opts } = arg1 as any if (solidKey) { return { ...opts, queryKey: solidKey(), - }; + } } - return arg1 as any; + return arg1 as any } - if (typeof arg2 === "function") { - return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any; + if (typeof arg2 === 'function') { + return { ...arg3, queryKey: arg1(), queryFn: arg2 } as any } - return { ...arg2, queryKey: arg1() } as any; + return { ...arg2, queryKey: arg1() } as any } -export function parseFilterArgs( +export function parseFilterArgs< + TFilters extends SolidQueryFilters, + TOptions = unknown, +>( arg1?: SolidQueryKey | TFilters, arg2?: TFilters | TOptions, arg3?: TOptions, @@ -44,7 +55,7 @@ export function parseFilterArgs, TOptions]; + ) as [ParseFilterArgs, TOptions] } export function shouldThrowError boolean>( From 9f7669f646470e937f8d68ff76b7bab89141bb96 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Thu, 15 Sep 2022 02:10:47 -0400 Subject: [PATCH 189/221] More passing tests --- .../src/__tests__/createQuery.test.tsx | 215 ++++++++++-------- 1 file changed, 126 insertions(+), 89 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 1c89c445ce1..636e37d9eba 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -29,6 +29,7 @@ import { ErrorBoundary, on, Show, + createMemo, } from 'solid-js' describe('createQuery', () => { @@ -1195,27 +1196,32 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'error', error }) }) - it.skip('should not re-run a stable select when it re-renders if selector throws an error', async () => { + it('should not re-run a stable select when it re-renders if selector throws an error', async () => { const key = queryKey() const error = new Error('Select Error') let runs = 0 function Page() { - const [, rerender] = NotReact.useReducer(() => ({}), {}) const state = createQuery( key, () => (runs === 0 ? 'test' : 'test2'), { - select: NotReact.useCallback(() => { + select: () => { runs++ throw error - }, []), + }, }, ) return (
error: {state.error?.message}
- +
) @@ -1370,7 +1376,7 @@ describe('createQuery', () => { it('should create a new query when refetching a removed query', async () => { const key = queryKey() - const states: any[] = [] + const states: Partial>[] = [] let count = 0 function Page() { @@ -1490,7 +1496,7 @@ describe('createQuery', () => { it('should use query function from hook when the existing query does not have a query function', async () => { const key = queryKey() - const results: any[] = [] + const results: Partial>[] = [] queryClient.setQueryData(key(), 'set') @@ -1719,7 +1725,7 @@ describe('createQuery', () => { it('should not fetch when switching to a disabled query', async () => { const key = queryKey() - const states: any[] = [] + const states: Partial>[] = [] function Page() { const [count, setCount] = createSignal(0) @@ -1787,7 +1793,7 @@ describe('createQuery', () => { it('should keep the previous data when keepPreviousData is set', async () => { const key = queryKey() - const states: any[] = [] + const states: Partial>[] = [] function Page() { const [count, setCount] = createSignal(0) @@ -2458,7 +2464,9 @@ describe('createQuery', () => { // 7. Observer options updated // 8. Observer result updated -> stale // 9. Observer options updated - expect(fn).toHaveBeenCalledTimes(9) + // Number 9 wont run in Solid JS + // Number 9 runs in react because the component re-renders after 8 + expect(fn).toHaveBeenCalledTimes(8) }) it('should not re-render when it should only re-render on data changes and the data did not change', async () => { @@ -3597,16 +3605,20 @@ describe('createQuery', () => { const states: DefinedCreateQueryResult<{ count: number }>[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) - const state = createQuery([key, count], () => ({ count: 10 }), { - staleTime: Infinity, - initialData: () => ({ count }), - }) + const [count, setCount] = createSignal(0) + const state = createQuery( + () => ['data', count()], + () => ({ count: 10 }), + { + staleTime: Infinity, + initialData: () => ({ count: count() }), + }, + ) createRenderEffect(() => { states.push({ ...state }) }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setCount(1) }, 10) @@ -3639,15 +3651,15 @@ describe('createQuery', () => { }) function Page() { - const { status, failureCount } = createQuery(key, queryFn, { + const state = createQuery(key, queryFn, { retry: 1, retryDelay: 1, }) return (
-

{status}

-

Failed {failureCount} times

+

{state.status}

+

Failed {state.failureCount} times

) } @@ -3681,20 +3693,16 @@ describe('createQuery', () => { }) function Page() { - const { status, failureCount, error } = createQuery< - unknown, - string, - [string] - >(key, queryFn, { + const state = createQuery(key, queryFn, { retryDelay: 1, retry: (_failureCount, err) => err !== 'NoRetry', }) return (
-

{status}

-

Failed {failureCount} times

-

{error}

+

{state.status}

+

Failed {state.failureCount} times

+

{state.error}

) } @@ -3725,15 +3733,15 @@ describe('createQuery', () => { }) function Page() { - const { status, failureCount } = createQuery(key, queryFn, { + const state = createQuery(key, queryFn, { retry: 1, retryDelay: (_, error: DelayError) => error.delay, }) return (
-

{status}

-

Failed {failureCount} times

+

{state.status}

+

Failed {state.failureCount} times

) } @@ -3799,11 +3807,8 @@ describe('createQuery', () => { await sleep(10) await waitFor(() => screen.getByText('failureCount 1')) - act(() => { - // reset visibilityState to original value - visibilityMock.mockRestore() - window.dispatchEvent(new FocusEvent('focus')) - }) + visibilityMock.mockRestore() + window.dispatchEvent(new FocusEvent('focus')) // Wait for the final result await waitFor(() => screen.getByText('failureCount 4')) @@ -3822,7 +3827,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - queryClient.setQueryData(key, 'prefetched') + queryClient.setQueryData(key(), 'prefetched') function Page() { const state = createQuery(key, () => 'data') @@ -3929,7 +3934,7 @@ describe('createQuery', () => { const prefetchQueryFn = jest.fn() prefetchQueryFn.mockImplementation(() => 'not yet...') - await queryClient.prefetchQuery(key, prefetchQueryFn, { + await queryClient.prefetchQuery(key(), prefetchQueryFn, { staleTime: 10, }) @@ -3967,7 +3972,7 @@ describe('createQuery', () => { return 'not yet...' }) - await queryClient.prefetchQuery(key, prefetchQueryFn, { + await queryClient.prefetchQuery(key(), prefetchQueryFn, { staleTime: 1000, }) @@ -4035,8 +4040,8 @@ describe('createQuery', () => { let count = 0 function Page() { - const [enabled, setEnabled] = NotReact.useState(false) - const [isPrefetched, setPrefetched] = NotReact.useState(false) + const [enabled, setEnabled] = createSignal(false) + const [isPrefetched, setPrefetched] = createSignal(false) const query = createQuery( key, @@ -4046,23 +4051,25 @@ describe('createQuery', () => { return count }, { - enabled, + get enabled() { + return enabled() + }, }, ) - NotReact.useEffect(() => { + createEffect(() => { async function prefetch() { - await queryClient.prefetchQuery(key, () => + await queryClient.prefetchQuery(key(), () => Promise.resolve('prefetched data'), ) - act(() => setPrefetched(true)) + setPrefetched(true) } prefetch() - }, []) + }) return (
- {isPrefetched &&
isPrefetched
} + {isPrefetched() &&
isPrefetched
}
data: {query.data}
@@ -4086,10 +4093,12 @@ describe('createQuery', () => { const key = queryKey() function Page() { - const [shouldFetch, setShouldFetch] = NotReact.useState(false) + const [shouldFetch, setShouldFetch] = createSignal(false) const query = createQuery(key, () => 'data', { - enabled: shouldFetch, + get enabled() { + return shouldFetch() + }, }) return ( @@ -4129,7 +4138,11 @@ describe('createQuery', () => { const result = createQuery(key, () => 'serverData', { initialData: 'data', }) - results.push(result) + + createRenderEffect(() => { + results.push({ ...result }) + }) + return null } @@ -4152,7 +4165,11 @@ describe('createQuery', () => { function Page() { const result = createQuery(key, () => 1, { initialData: 0 }) - results.push(result) + + createRenderEffect(() => { + results.push({ ...result }) + }) + return null } @@ -4175,20 +4192,26 @@ describe('createQuery', () => { const results: DefinedCreateQueryResult[] = [] function Page() { - const [shouldFetch, setShouldFetch] = NotReact.useState(true) + const [shouldFetch, setShouldFetch] = createSignal(true) const result = createQuery(key, () => 'fetched data', { - enabled: shouldFetch, - initialData: shouldFetch ? 'initial' : 'initial falsy', + get enabled() { + return shouldFetch() + }, + get initialData() { + return shouldFetch() ? 'initial' : 'initial falsy' + }, }) - results.push(result) + createRenderEffect(() => { + results.push({ ...result }) + }) - NotReact.useEffect(() => { + createEffect(() => { setActTimeout(() => { setShouldFetch(false) }, 5) - }, []) + }) return null } @@ -4200,10 +4223,10 @@ describe('createQuery', () => { )) await sleep(50) - expect(results.length).toBe(3) + expect(results.length).toBe(2) expect(results[0]).toMatchObject({ data: 'initial', isStale: true }) expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true }) - expect(results[2]).toMatchObject({ data: 'fetched data', isStale: true }) + // Wont render 3rd time, because data is still the same }) it('it should support enabled:false in query object syntax', async () => { @@ -4268,7 +4291,7 @@ describe('createQuery', () => { return
{query.data}
} - render(() => ( + const result = render(() => ( @@ -4276,9 +4299,9 @@ describe('createQuery', () => { await waitFor(() => screen.getByText('fetched data')) - screen.unmount() + result.unmount() - const query = queryCache.find(key) + const query = queryCache.find(key()) // @ts-expect-error expect(query!.cacheTimeout).toBe(undefined) }) @@ -4300,10 +4323,10 @@ describe('createQuery', () => { ) }) - NotReact.useMemo(() => { + createMemo(() => { memoFn() return result.data - }, [result.data]) + }) return (
@@ -4334,18 +4357,20 @@ describe('createQuery', () => { let count = 0 function Page() { - const [int, setInt] = NotReact.useState(200) - const { data } = createQuery(key, () => count++, { - refetchInterval: int, + const [int, setInt] = createSignal(200) + const query = createQuery(key, () => count++, { + get refetchInterval() { + return int() + }, }) - NotReact.useEffect(() => { - if (data === 2) { + createEffect(() => { + if (query.data === 2) { setInt(0) } - }, [data]) + }) - return
count: {data}
+ return
count: {query.data}
} render(() => ( @@ -4377,7 +4402,9 @@ describe('createQuery', () => { }, ) - states.push(queryInfo) + createRenderEffect(() => { + states.push({ ...queryInfo }) + }) return (
@@ -4442,7 +4469,9 @@ describe('createQuery', () => { refetchInterval: 0, }) - states.push(queryInfo) + createRenderEffect(() => { + states.push({ ...queryInfo }) + }) return
count: {queryInfo.data}
} @@ -4475,7 +4504,10 @@ describe('createQuery', () => { it('should accept an empty string as query key', async () => { function Page() { - const result = createQuery([''], (ctx) => ctx.queryKey) + const result = createQuery( + () => [''], + (ctx) => ctx.queryKey, + ) return <>{JSON.stringify(result.data)} } @@ -4490,7 +4522,10 @@ describe('createQuery', () => { it('should accept an object as query key', async () => { function Page() { - const result = createQuery([{ a: 'a' }], (ctx) => ctx.queryKey) + const result = createQuery( + () => [{ a: 'a' }], + (ctx) => ctx.queryKey, + ) return <>{JSON.stringify(result.data)} } @@ -4514,8 +4549,12 @@ describe('createQuery', () => { } function Page() { - const [enabled, setEnabled] = NotReact.useState(false) - const result = createQuery(key, queryFn, { enabled }) + const [enabled, setEnabled] = createSignal(false) + const result = createQuery(key, queryFn, { + get enabled() { + return enabled() + }, + }) return ( <> @@ -4585,18 +4624,22 @@ describe('createQuery', () => { const states: { state: CreateQueryResult; count: number }[] = [] function Page() { - const [count, setCount] = NotReact.useState(0) + const [count, setCount] = createSignal(0) const state = createQuery(key1, () => 'data', { placeholderData: 'placeholder', - enabled: count === 0, + get enabled() { + return count() === 0 + }, }) - states.push({ state, count }) + createRenderEffect(() => { + states.push({ state: { ...state }, count: count() }) + }) - NotReact.useEffect(() => { + createEffect(() => { setCount(1) - }, []) + }) return (
@@ -4719,8 +4762,6 @@ describe('createQuery', () => { )) await waitFor(() => screen.getByText('Data: 2')) - screen.rerender() - expect(states).toMatchObject([ { isSuccess: true, @@ -4732,17 +4773,13 @@ describe('createQuery', () => { isPlaceholderData: false, data: '2', }, - { - isSuccess: true, - isPlaceholderData: false, - data: '2', - }, ]) expect(placeholderFunctionRunCount).toEqual(1) }) - it('select should only run when dependencies change if memoized', async () => { + // React Specific implementation. Not really needed since solid functions are stable + it.skip('select should only run when dependencies change if memoized', async () => { const key1 = queryKey() let selectRun = 0 From de5a0ba1ca12f5fbdb9e70f5e2c71d07c4d3b905 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 10:10:46 -0400 Subject: [PATCH 190/221] fixing merge --- .../src/__tests__/createQuery.test.tsx | 158 +++++++++-------- .../src/__tests__/createQuery.types.test.tsx | 160 ++++++++++++++++++ 2 files changed, 238 insertions(+), 80 deletions(-) create mode 100644 packages/solid-query/src/__tests__/createQuery.types.test.tsx diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 636e37d9eba..3e8b504e967 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -7,7 +7,6 @@ import { mockNavigatorOnLine, mockLogger, createQueryClient, - // @ts-ignore } from '../../../../tests/utils' import { Blink, queryKey, setActTimeout } from './utils' import { @@ -15,6 +14,7 @@ import { CreateQueryResult, QueryCache, QueryFunction, + QueryFunctionContext, CreateQueryOptions, DefinedCreateQueryResult, QueryClientProvider, @@ -63,10 +63,14 @@ describe('createQuery', () => { expectType(withError.error) // it should provide the result type in the configuration - createQuery(key, async () => true, { - onSuccess: (data) => expectType(data), - onSettled: (data) => expectType(data), - }) + createQuery( + () => [key()], + async () => true, + { + onSuccess: (data) => expectType(data), + onSettled: (data) => expectType(data), + }, + ) // it should be possible to specify a union type as result type const unionTypeSync = createQuery( @@ -77,7 +81,6 @@ describe('createQuery', () => { }, ) expectType<'a' | 'b' | undefined>(unionTypeSync.data) - const unionTypeAsync = createQuery<'a' | 'b'>( key, () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'), @@ -184,6 +187,7 @@ describe('createQuery', () => { } }) + // See https://github.com/tannerlinsley/react-query/issues/105 it('should allow to set default data value', async () => { const key = queryKey() @@ -537,7 +541,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /refetch/i })) await screen.findByText('data: data2') - expect(states.length).toBe(4) //loading, success, success, success after refetch + expect(states.length).toBe(3) //loading, success, success after refetch expect(count).toBe(2) expect(onSuccess).toHaveBeenCalledTimes(2) }) @@ -1196,12 +1200,13 @@ describe('createQuery', () => { expect(states[1]).toMatchObject({ status: 'error', error }) }) - it('should not re-run a stable select when it re-renders if selector throws an error', async () => { + it.skip('should not re-run a stable select when it re-renders if selector throws an error', async () => { const key = queryKey() const error = new Error('Select Error') let runs = 0 function Page() { + const [, rerender] = NotReact.useReducer(() => ({}), {}) const state = createQuery( key, () => (runs === 0 ? 'test' : 'test2'), @@ -1215,13 +1220,7 @@ describe('createQuery', () => { return (
error: {state.error?.message}
- +
) @@ -1380,10 +1379,14 @@ describe('createQuery', () => { let count = 0 function Page() { - const state = createQuery(key, async () => { - await sleep(10) - return ++count - }) + const state = createQuery( + key, + async () => { + await sleep(10) + return ++count + }, + { notifyOnChangeProps: 'all' }, + ) createRenderEffect(() => { states.push({ data: state.data, dataUpdatedAt: state.dataUpdatedAt }) @@ -1561,14 +1564,7 @@ describe('createQuery', () => { { staleTime: Infinity, notifyOnChangeProps: 'all' }, ) - createEffect(() => { - console.log('My Log', { - data: state.data, - isFetching: state.isFetching, - isRefetching: state.isRefetching, - isSuccess: state.isSuccess, - isStale: state.isStale, - }) + createRenderEffect(() => { states.push({ ...state }) }) @@ -1592,7 +1588,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => screen.getByText('data: 2')) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) expect(states[0]).toMatchObject({ data: undefined, @@ -1609,20 +1605,13 @@ describe('createQuery', () => { isStale: false, }) expect(states[2]).toMatchObject({ - data: 1, - isFetching: false, - isRefetching: false, - isSuccess: true, - isStale: true, - }) - expect(states[3]).toMatchObject({ data: 1, isFetching: true, isRefetching: true, isSuccess: true, isStale: true, }) - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 2, isFetching: false, isRefetching: false, @@ -1809,12 +1798,6 @@ describe('createQuery', () => { createRenderEffect(() => { const { data, isFetching, isSuccess, isPreviousData } = state - console.log('LOG', { - data, - isFetching, - isSuccess, - isPreviousData, - }) states.push({ data, isFetching, @@ -1838,7 +1821,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(4)) + await waitFor(() => expect(states.length).toBe(5)) // Initial expect(states[0]).toMatchObject({ @@ -1861,8 +1844,15 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // New data + // Hook state update expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2016,7 +2006,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(4)) + await waitFor(() => expect(states.length).toBe(5)) // Initial expect(states[0]).toMatchObject({ @@ -2039,8 +2029,15 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // New data + // Hook state update expect(states[3]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPreviousData: true, + }) + // New data + expect(states[4]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2159,8 +2156,8 @@ describe('createQuery', () => { ) createRenderEffect(() => { - // Need to track count here to push changes - console.log(count(), key()) + const _trackCount = count() + const _trackKey = key() states.push({ ...state }) }) @@ -2792,12 +2789,14 @@ describe('createQuery', () => { type CustomQueryKey = [ReturnType, typeof variables] const states: CreateQueryResult[] = [] + // TODO(lukemurray): extract the query function to a variable queryFn + function Page() { const state = createQuery( - () => [key(), variables], - async ({ queryKey: qk }) => { + () => [key(), variables] as const, + async (ctx) => { await sleep(10) - return qk as CustomQueryKey + return ctx.queryKey }, ) createRenderEffect(() => { @@ -2987,7 +2986,7 @@ describe('createQuery', () => { expect(states[3]).toMatchObject({ data: 1, isFetching: false }) }) - it('should calculate focus behaviour for refetchOnWindowFocus depending on function', async () => { + it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => { const key = queryKey() const states: CreateQueryResult[] = [] let count = 0 @@ -3033,6 +3032,10 @@ describe('createQuery', () => { expect(states[2]).toMatchObject({ data: 0, isFetching: true }) expect(states[3]).toMatchObject({ data: 1, isFetching: false }) + act(() => { + window.dispatchEvent(new FocusEvent('focus')) + }) + await sleep(20) // no more refetch now @@ -3305,16 +3308,14 @@ describe('createQuery', () => { } function App() { - const [showPage, setShowPage] = createSignal(true) + const [show, setShow] = createSignal(true) - const toggle = () => setShowPage((s) => !s) + const toggle = () => setShow((s) => !s) return (
- - - - + + {show() && }
) } @@ -3361,22 +3362,19 @@ describe('createQuery', () => { } function App() { - const [showPage, setShowPage] = createSignal(true) + const [show, setShow] = createSignal(true) - const toggle = () => setShowPage((s) => !s) + const toggle = () => setShow((s) => !s) return (
- + - - - - + {show() && }
) } @@ -3607,7 +3605,7 @@ describe('createQuery', () => { function Page() { const [count, setCount] = createSignal(0) const state = createQuery( - () => ['data', count()], + () => [key(), count()], () => ({ count: 10 }), { staleTime: Infinity, @@ -4223,10 +4221,10 @@ describe('createQuery', () => { )) await sleep(50) - expect(results.length).toBe(2) + expect(results.length).toBe(3) expect(results[0]).toMatchObject({ data: 'initial', isStale: true }) expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true }) - // Wont render 3rd time, because data is still the same + expect(results[2]).toMatchObject({ data: 'fetched data', isStale: true }) }) it('it should support enabled:false in query object syntax', async () => { @@ -4358,19 +4356,19 @@ describe('createQuery', () => { function Page() { const [int, setInt] = createSignal(200) - const query = createQuery(key, () => count++, { + const state = createQuery(key, () => count++, { get refetchInterval() { return int() }, }) createEffect(() => { - if (query.data === 2) { + if (state.data === 2) { setInt(0) } }) - return
count: {query.data}
+ return
count: {state.data}
} render(() => ( @@ -4391,7 +4389,7 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const queryInfo = createQuery( + const state = createQuery( key, async () => { await sleep(10) @@ -4403,15 +4401,15 @@ describe('createQuery', () => { ) createRenderEffect(() => { - states.push({ ...queryInfo }) + states.push({ ...state }) }) return (
-

count: {queryInfo.data}

-

status: {queryInfo.status}

-

data: {queryInfo.data}

-

refetch: {queryInfo.isRefetching}

+

count: {state.data}

+

status: {state.status}

+

data: {state.data}

+

refetch: {state.isRefetching}

) } @@ -4465,15 +4463,15 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { - const queryInfo = createQuery(key, () => 1, { + const state = createQuery(key, () => 1, { refetchInterval: 0, }) createRenderEffect(() => { - states.push({ ...queryInfo }) + states.push({ ...state }) }) - return
count: {queryInfo.data}
+ return
count: {state.data}
} render(() => ( diff --git a/packages/solid-query/src/__tests__/createQuery.types.test.tsx b/packages/solid-query/src/__tests__/createQuery.types.test.tsx new file mode 100644 index 00000000000..1d82484d5b6 --- /dev/null +++ b/packages/solid-query/src/__tests__/createQuery.types.test.tsx @@ -0,0 +1,160 @@ +import { createQuery } from '../createQuery' + +export type Equal = (() => T extends X ? 1 : 2) extends < + T, +>() => T extends Y ? 1 : 2 + ? true + : false + +export type Expect = T + +const doNotExecute = (_func: () => void) => true + +describe('initialData', () => { + describe('Config object overload', () => { + it('TData should always be defined when initialData is provided as an object', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => ({ + wow: true, + }), + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + }) + + const result: Expect> = + true + return result + }) + }) + + it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { + doNotExecute(() => { + const { data } = createQuery({ + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + }) + + const result: Expect> = + true + return result + }) + }) + }) + + describe('Query key overload', () => { + it('TData should always be defined when initialData is provided', () => { + doNotExecute(() => { + const { data } = createQuery(() => ['key'], { + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery(() => ['key'], { + queryFn: () => { + return { + wow: true, + } + }, + }) + + const result: Expect> = + true + return result + }) + }) + }) + + describe('Query key and func', () => { + it('TData should always be defined when initialData is provided', () => { + doNotExecute(() => { + const { data } = createQuery( + () => ['key'], + () => { + return { + wow: true, + } + }, + { + initialData: { + wow: true, + }, + }, + ) + + const result: Expect> = true + return result + }) + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + doNotExecute(() => { + const { data } = createQuery( + () => ['key'], + () => { + return { + wow: true, + } + }, + ) + + const result: Expect> = + true + return result + }) + }) + }) +}) From e294c6c2d76f7bbf6d7d47fd3302a7fcf3f1f958 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 10:12:30 -0400 Subject: [PATCH 191/221] prettier --- packages/solid-query/src/createBaseQuery.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 998fa6d0a7d..36f9a77af05 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -33,7 +33,7 @@ export function createBaseQuery< >, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient({ context: options.context }); + const queryClient = useQueryClient({ context: options.context }) const errorResetBoundary = useQueryErrorResetBoundary() const defaultedOptions = createMemo(() => { @@ -56,12 +56,12 @@ export function createBaseQuery< return computedOptions }) - const observer = new Observer(queryClient, defaultedOptions()); + const observer = new Observer(queryClient, defaultedOptions()) const [state, setState] = createStore>( // @ts-ignore observer.getOptimisticResult(defaultedOptions()), - ); + ) const [dataResource, { refetch, mutate }] = createResource( () => { From bfb422ffafcdf175987e8718d3f2137e7928fd74 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 10:32:24 -0400 Subject: [PATCH 192/221] more merge fixes --- .../src/__tests__/createQuery.test.tsx | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 3e8b504e967..76fcef1dec3 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -14,7 +14,6 @@ import { CreateQueryResult, QueryCache, QueryFunction, - QueryFunctionContext, CreateQueryOptions, DefinedCreateQueryResult, QueryClientProvider, @@ -28,7 +27,6 @@ import { createSignal, ErrorBoundary, on, - Show, createMemo, } from 'solid-js' @@ -1206,6 +1204,7 @@ describe('createQuery', () => { let runs = 0 function Page() { + //@ts-expect-error -- we skip this test, and no such thing as rerender in solid const [, rerender] = NotReact.useReducer(() => ({}), {}) const state = createQuery( key, @@ -1298,10 +1297,14 @@ describe('createQuery', () => { states.push({ ...state }) }) - createEffect(() => { - const _trackState = { ...state } - renderCount++ - }) + createEffect( + on( + () => ({ ...state }), + () => { + renderCount++ + }, + ), + ) return (
@@ -1329,6 +1332,7 @@ describe('createQuery', () => { let count = 0 function Page() { + //@ts-expect-error -- we skip this test, and no such thing as rerender in solid const [, rerender] = NotReact.useState({}) const state = createQuery(key, () => ++count, { notifyOnChangeProps: 'all', @@ -1860,7 +1864,8 @@ describe('createQuery', () => { }) }) - it('should transition to error state when keepPreviousData is set', async () => { + // this test relies on rerenders which don't exist in solid + it.skip('should transition to error state when keepPreviousData is set', async () => { const key = queryKey() const states: CreateQueryResult[] = [] @@ -1899,8 +1904,10 @@ describe('createQuery', () => { )) await waitFor(() => screen.getByText('data: 0')) + // @ts-expect-error we skip this test and rerenders don't exist in solid act(() => screen.rerender()) await waitFor(() => screen.getByText('data: 1')) + // @ts-expect-error we skip this test and rerenders don't exist in solid act(() => screen.rerender()) await waitFor(() => screen.getByText('error: Error test')) @@ -2155,11 +2162,11 @@ describe('createQuery', () => { { enabled: false, keepPreviousData: true, notifyOnChangeProps: 'all' }, ) - createRenderEffect(() => { - const _trackCount = count() - const _trackKey = key() - states.push({ ...state }) - }) + createRenderEffect( + on([() => ({ ...state }), count], () => { + states.push({ ...state }) + }), + ) createEffect(() => { const refetch = state.refetch @@ -2587,6 +2594,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] + // @ts-expect-error - we skip this test const originalUseEffect = NotReact.useEffect // Try to simulate useEffect timing delay @@ -2612,7 +2620,7 @@ describe('createQuery', () => { )) - queryClient.setQueryData(key, 'data') + queryClient.setQueryData(key(), 'data') await sleep(50) // @ts-ignore @@ -2648,8 +2656,7 @@ describe('createQuery', () => { await sleep(20) - // Should be 1 - expect(renders).toBe(1) + expect(renders).toBe(2) }) it('should batch re-renders including hook callbacks', async () => { @@ -3007,7 +3014,7 @@ describe('createQuery', () => { createRenderEffect(() => { states.push({ ...state }) }) - return
data: {state.data}
+ return
data: {String(state.data)}
} render(() => ( From 4c95bcc713a6855834ac30f232074145bab6951b Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 11:42:37 -0400 Subject: [PATCH 193/221] add comment about reactive notifyOnChange props --- packages/solid-query/src/createBaseQuery.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 36f9a77af05..b612afbeea7 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -163,6 +163,7 @@ export function createBaseQuery< TError > + // TODO(lukemurray): is it possible to make this reactive based on defaulted options? return !defaultedOptions().notifyOnChangeProps ? observer.trackResult(proxyResult) : proxyResult From 02598ff5667a46b988c15bf2aebda60fdc67ea52 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 11:42:52 -0400 Subject: [PATCH 194/221] ignore some errors in tests --- .../solid-query/src/__tests__/QueryClientProvider.test.tsx | 4 ++-- packages/solid-query/src/__tests__/createQuery.test.tsx | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx index 509fa0400af..6b4055779da 100644 --- a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -250,8 +250,8 @@ describe('QueryClientProvider', () => { return null } - // TODO(lukemurray): this test doesn't pass because the page function is - // never called. I'm not sure why. + // TODO(lukemurray): fails because renderToString never calls Page + // probably an SSR-testing issue we need to fix. renderToString(() => ( diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 76fcef1dec3..f34f1ba65dd 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -967,6 +967,7 @@ describe('createQuery', () => { const states: CreateQueryResult[] = [] function Page() { + //@ts-expect-error -- skip this test const [, rerender] = NotReact.useState({}) const state = createQuery( @@ -987,6 +988,7 @@ describe('createQuery', () => { const { remove } = state + //@ts-expect-error skip this test NotReact.useEffect(() => { setActTimeout(() => { remove() @@ -4790,6 +4792,7 @@ describe('createQuery', () => { let selectRun = 0 function Page() { + //@ts-expect-error skip this test const [count, inc] = NotReact.useReducer((prev) => prev + 1, 2) const state = createQuery( @@ -4799,6 +4802,7 @@ describe('createQuery', () => { return 0 }, { + //@ts-expect-error skip this test select: NotReact.useCallback( (data: number) => { selectRun++ From 1f364e83f12a183deb6d399fa70ee98eeb7c0b8f Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Fri, 16 Sep 2022 14:49:02 -0400 Subject: [PATCH 195/221] replace instances of test with it --- .../src/__tests__/QueryClientProvider.test.tsx | 12 ++++++------ .../src/__tests__/createMutation.test.tsx | 6 +++--- .../solid-query/src/__tests__/createQuery.test.tsx | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx index 6b4055779da..28cef444692 100644 --- a/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/solid-query/src/__tests__/QueryClientProvider.test.tsx @@ -8,7 +8,7 @@ import { Context, createContext, useContext } from 'solid-js' import { renderToString } from 'solid-js/web' describe('QueryClientProvider', () => { - test('sets a specific cache for all queries to use', async () => { + it('sets a specific cache for all queries to use', async () => { const key = queryKey() const queryCache = new QueryCache() @@ -40,7 +40,7 @@ describe('QueryClientProvider', () => { expect(queryCache.find(key())).toBeDefined() }) - test('allows multiple caches to be partitioned', async () => { + it('allows multiple caches to be partitioned', async () => { const key1 = queryKey() const key2 = queryKey() @@ -95,7 +95,7 @@ describe('QueryClientProvider', () => { expect(queryCache2.find(key2())).toBeDefined() }) - test("uses defaultOptions for queries when they don't provide their own config", async () => { + it("uses defaultOptions for queries when they don't provide their own config", async () => { const key = queryKey() const queryCache = new QueryCache() @@ -192,7 +192,7 @@ describe('QueryClientProvider', () => { }) describe('useQueryClient', () => { - test('should throw an error if no query client has been set', () => { + it('should throw an error if no query client has been set', () => { const consoleMock = jest .spyOn(console, 'error') .mockImplementation(() => undefined) @@ -209,7 +209,7 @@ describe('QueryClientProvider', () => { consoleMock.mockRestore() }) - test('should use window to get the context when contextSharing is true', () => { + it('should use window to get the context when contextSharing is true', () => { const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) @@ -234,7 +234,7 @@ describe('QueryClientProvider', () => { expect(queryClientFromWindow).toEqual(queryClient) }) - test('should not use window to get the context when contextSharing is true and window does not exist', () => { + it('should not use window to get the context when contextSharing is true and window does not exist', () => { const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) diff --git a/packages/solid-query/src/__tests__/createMutation.test.tsx b/packages/solid-query/src/__tests__/createMutation.test.tsx index 5fa388914c3..c8807dd70bf 100644 --- a/packages/solid-query/src/__tests__/createMutation.test.tsx +++ b/packages/solid-query/src/__tests__/createMutation.test.tsx @@ -981,7 +981,7 @@ describe('useMutation', () => { ) }) - test('should go to error state if onSuccess callback errors', async () => { + it('should go to error state if onSuccess callback errors', async () => { const error = new Error('error from onSuccess') const onError = jest.fn() @@ -1016,7 +1016,7 @@ describe('useMutation', () => { expect(onError).toHaveBeenCalledWith(error, 'todo', undefined) }) - test('should go to error state if onError callback errors', async () => { + it('should go to error state if onError callback errors', async () => { const error = new Error('error from onError') const mutateFnError = new Error('mutateFnError') @@ -1052,7 +1052,7 @@ describe('useMutation', () => { await rendered.findByText('error: mutateFnError, status: error') }) - test('should go to error state if onSettled callback errors', async () => { + it('should go to error state if onSettled callback errors', async () => { const error = new Error('error from onSettled') const mutateFnError = new Error('mutateFnError') const onError = jest.fn() diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index f34f1ba65dd..27be5191a2b 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -4262,7 +4262,7 @@ describe('createQuery', () => { }) // See https://github.com/tannerlinsley/react-query/issues/360 - test('should init to status:loading, fetchStatus:idle when enabled is false', async () => { + it('should init to status:loading, fetchStatus:idle when enabled is false', async () => { const key = queryKey() function Page() { @@ -4288,7 +4288,7 @@ describe('createQuery', () => { await waitFor(() => screen.getByText('status: loading, idle')) }) - test('should not schedule garbage collection, if cacheTimeout is set to `Infinity`', async () => { + it('should not schedule garbage collection, if cacheTimeout is set to `Infinity`', async () => { const key = queryKey() function Page() { From c37da6e526f0659e3d333e6446a1edfe7e55d7af Mon Sep 17 00:00:00 2001 From: Luke Murray <34020210+lukesmurray@users.noreply.github.com> Date: Fri, 16 Sep 2022 14:53:05 -0400 Subject: [PATCH 196/221] replace react in comment with solid Co-authored-by: Jen Kaplan --- packages/solid-query/src/QueryClientProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index 9dfd87aaaf4..21987bccab0 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -22,7 +22,7 @@ const QueryClientSharingContext = createContext(false) // If we are given a context, we will use it. // Otherwise, if contextSharing is on, we share the first and at least one // instance of the context across the window -// to ensure that if React Query is used across +// to ensure that if Solid Query is used across // different bundles or microfrontends they will // all use the same **instance** of context, regardless // of module scoping. From 31cbee1830cfdb13d28260a14f24915dc77de281 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 16 Sep 2022 21:21:02 -0400 Subject: [PATCH 197/221] Completed tests and reviewed PR --- .../src/QueryErrorResetBoundary.tsx | 50 -- .../QueryResetErrorBoundary.test.tsx | 637 ------------------ .../src/__tests__/createQuery.test.tsx | 128 ++-- .../src/__tests__/suspense.test.tsx | 138 +--- .../src/__tests__/useIsFetching.test.tsx | 11 +- .../src/__tests__/useIsMutating.test.tsx | 15 +- packages/solid-query/src/createBaseQuery.ts | 162 ++--- packages/solid-query/src/index.ts | 11 +- 8 files changed, 157 insertions(+), 995 deletions(-) delete mode 100644 packages/solid-query/src/QueryErrorResetBoundary.tsx delete mode 100644 packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx diff --git a/packages/solid-query/src/QueryErrorResetBoundary.tsx b/packages/solid-query/src/QueryErrorResetBoundary.tsx deleted file mode 100644 index 2066f3a6299..00000000000 --- a/packages/solid-query/src/QueryErrorResetBoundary.tsx +++ /dev/null @@ -1,50 +0,0 @@ -// CONTEXT - -import { createContext, createSignal, useContext, JSX } from 'solid-js' - -interface QueryErrorResetBoundaryValue { - clearReset: () => void - isReset: () => boolean - reset: () => void -} - -function createValue(): QueryErrorResetBoundaryValue { - const [isReset, setIsReset] = createSignal(false) - return { - clearReset: () => { - setIsReset(false) - }, - reset: () => { - setIsReset(true) - }, - isReset: () => { - return isReset() - }, - } -} - -const QueryErrorResetBoundaryContext = createContext(createValue()) - -// HOOK - -export const useQueryErrorResetBoundary = () => - useContext(QueryErrorResetBoundaryContext) - -// COMPONENT - -export interface QueryErrorResetBoundaryProps { - children: ((value: QueryErrorResetBoundaryValue) => JSX.Element) | JSX.Element -} - -export const QueryErrorResetBoundary = ( - props: QueryErrorResetBoundaryProps, -) => { - const [value] = createSignal(createValue()) - return ( - - {typeof props.children === 'function' - ? (props.children as Function)(value()) - : props.children} - - ) -} diff --git a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx b/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx deleted file mode 100644 index 2ca6fb5a416..00000000000 --- a/packages/solid-query/src/__tests__/QueryResetErrorBoundary.test.tsx +++ /dev/null @@ -1,637 +0,0 @@ -import { waitFor, fireEvent, render, screen } from 'solid-testing-library' - -import { sleep, createQueryClient } from '../../../../tests/utils' -import { queryKey } from './utils' -import { - createQuery, - QueryCache, - QueryClientProvider, - QueryErrorResetBoundary, -} from '..' -import { createEffect, createSignal, ErrorBoundary, Suspense } from 'solid-js' - -describe('QueryErrorResetBoundary', () => { - const queryCache = new QueryCache() - const queryClient = createQueryClient({ queryCache }) - - it('should retry fetch if the reset error boundary has been reset', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
- , -
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - }) - - it('should not throw error if query is disabled', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - enabled: !succeed, - useErrorBoundary: true, - }, - ) - return ( -
-
status: {state.status}
-
{state.data}
-
- ) - } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('status: error')) - }) - - it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const [enabled, setEnabled] = createSignal(false) - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - enabled: enabled(), - useErrorBoundary: true, - }, - ) - - createEffect(() => { - setEnabled(true) - }) - - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - }) - - it('should throw error if query is disabled and manually refetched', async () => { - const key = queryKey() - - function Page() { - const state = createQuery( - key, - async () => { - throw new Error('Error') - }, - { - retry: false, - enabled: false, - useErrorBoundary: true, - }, - ) - - return ( -
- -
- status: {state.status}, fetchStatus: {state.fetchStatus} -
-
{state.data}
-
- ) - } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('status: loading, fetchStatus: idle')) - fireEvent.click(screen.getByRole('button', { name: /refetch/i })) - await waitFor(() => screen.getByText('error boundary')) - }) - - it('should not retry fetch if the reset error boundary has not been reset', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {() => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - }) - - it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - initialData: 'initial', - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - }) - - it('should not retry fetch if the reset error boundary has not been reset after a previous reset', async () => { - const key = queryKey() - - let succeed = false - let shouldReset = true - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - shouldReset = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - succeed = true - shouldReset = false - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - }) - - it('should throw again on error after the reset error boundary has been reset', async () => { - const key = queryKey() - let fetchCount = 0 - - function Page() { - const state = createQuery( - key, - async () => { - fetchCount++ - await sleep(10) - throw new Error('Error') - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - expect(fetchCount).toBe(3) - }) - - // TODO(lukemurray): semantically doens't make sense since solid resets when - // the resource that has an error is read - it.skip('should never render the component while the query is in error state', async () => { - const key = queryKey() - let fetchCount = 0 - let renders = 0 - - function Page() { - const state = createQuery( - key, - async () => { - fetchCount++ - await sleep(10) - if (fetchCount > 2) { - return 'data' - } else { - throw new Error('Error') - } - }, - { - retry: false, - suspense: true, - }, - ) - renders++ - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - loading
}> - - - - )} - - - )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - expect(fetchCount).toBe(3) - expect(renders).toBe(1) - }) - - it('should render children', async () => { - function Page() { - return ( -
- page -
- ) - } - - render(() => ( - - - - - - )) - - expect(screen.queryByText('page')).not.toBeNull() - }) - - it('should show error boundary when using tracked queries even though we do not track the error field', async () => { - const key = queryKey() - - let succeed = false - - function Page() { - const state = createQuery( - key, - async () => { - await sleep(10) - if (!succeed) { - throw new Error('Error') - } else { - return 'data' - } - }, - { - retry: false, - useErrorBoundary: true, - }, - ) - return
{state.data}
- } - - render(() => ( - - - {({ reset: resetQuery }) => ( - ( -
-
error boundary
- -
- )} - > - -
- )} -
-
- )) - - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('data')) - }) -}) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 27be5191a2b..099b3e153b9 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1570,7 +1570,14 @@ describe('createQuery', () => { { staleTime: Infinity, notifyOnChangeProps: 'all' }, ) - createRenderEffect(() => { + createEffect(() => { + console.log('My Log', { + data: state.data, + isFetching: state.isFetching, + isRefetching: state.isRefetching, + isSuccess: state.isSuccess, + isStale: state.isStale, + }) states.push({ ...state }) }) @@ -1594,7 +1601,7 @@ describe('createQuery', () => { fireEvent.click(screen.getByRole('button', { name: /invalidate/i })) await waitFor(() => screen.getByText('data: 2')) - await waitFor(() => expect(states.length).toBe(4)) + await waitFor(() => expect(states.length).toBe(5)) expect(states[0]).toMatchObject({ data: undefined, @@ -1611,13 +1618,20 @@ describe('createQuery', () => { isStale: false, }) expect(states[2]).toMatchObject({ + data: 1, + isFetching: false, + isRefetching: false, + isSuccess: true, + isStale: true, + }) + expect(states[3]).toMatchObject({ data: 1, isFetching: true, isRefetching: true, isSuccess: true, isStale: true, }) - expect(states[3]).toMatchObject({ + expect(states[4]).toMatchObject({ data: 2, isFetching: false, isRefetching: false, @@ -1804,6 +1818,12 @@ describe('createQuery', () => { createRenderEffect(() => { const { data, isFetching, isSuccess, isPreviousData } = state + console.log('LOG', { + data, + isFetching, + isSuccess, + isPreviousData, + }) states.push({ data, isFetching, @@ -1827,7 +1847,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) // Initial expect(states[0]).toMatchObject({ @@ -1850,15 +1870,8 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update - expect(states[3]).toMatchObject({ - data: 0, - isFetching: true, - isSuccess: true, - isPreviousData: true, - }) // New data - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2015,7 +2028,7 @@ describe('createQuery', () => { )) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(4)) // Initial expect(states[0]).toMatchObject({ @@ -2038,15 +2051,8 @@ describe('createQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update - expect(states[3]).toMatchObject({ - data: 0, - isFetching: true, - isSuccess: true, - isPreviousData: true, - }) // New data - expect(states[4]).toMatchObject({ + expect(states[3]).toMatchObject({ data: 1, isFetching: false, isSuccess: true, @@ -2658,7 +2664,9 @@ describe('createQuery', () => { await sleep(20) - expect(renders).toBe(2) + // Since components are rendered once + // There wiil only be one pass + expect(renders).toBe(1) }) it('should batch re-renders including hook callbacks', async () => { @@ -2995,7 +3003,7 @@ describe('createQuery', () => { expect(states[3]).toMatchObject({ data: 1, isFetching: false }) }) - it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => { + it('should calculate focus behaviour for refetchOnWindowFocus depending on function', async () => { const key = queryKey() const states: CreateQueryResult[] = [] let count = 0 @@ -3016,7 +3024,7 @@ describe('createQuery', () => { createRenderEffect(() => { states.push({ ...state }) }) - return
data: {String(state.data)}
+ return
data: {state.data}
} render(() => ( @@ -3041,10 +3049,6 @@ describe('createQuery', () => { expect(states[2]).toMatchObject({ data: 0, isFetching: true }) expect(states[3]).toMatchObject({ data: 1, isFetching: false }) - act(() => { - window.dispatchEvent(new FocusEvent('focus')) - }) - await sleep(20) // no more refetch now @@ -4230,10 +4234,10 @@ describe('createQuery', () => { )) await sleep(50) - expect(results.length).toBe(3) + expect(results.length).toBe(2) expect(results[0]).toMatchObject({ data: 'initial', isStale: true }) expect(results[1]).toMatchObject({ data: 'fetched data', isStale: true }) - expect(results[2]).toMatchObject({ data: 'fetched data', isStale: true }) + // Wont render 3rd time, because data is still the same }) it('it should support enabled:false in query object syntax', async () => { @@ -4904,10 +4908,7 @@ describe('createQuery', () => { const states: Array> = [] function Page() { - const [forceValue, forceUpdate] = NotReact.useReducer( - (prev) => prev + 1, - 1, - ) + const [forceValue, setForceValue] = createSignal(1) const state = createQuery( key1, @@ -4920,11 +4921,15 @@ describe('createQuery', () => { }, ) - NotReact.useEffect(() => { + createEffect(() => { if (state.data) { states.push(state.data) } - }, [state.data]) + }) + + const forceUpdate = () => { + setForceValue((prev) => prev + 1) + } return (
@@ -4994,7 +4999,7 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - const queryFn: QueryFunction = async ( + const queryFn: QueryFunction, number]> = async ( ctx, ) => { const [, limit] = ctx.queryKey @@ -5004,7 +5009,7 @@ describe('createQuery', () => { } function Page(props: { limit: number }) { - const state = createQuery([key, props.limit], queryFn) + const state = createQuery(() => ([key(), props.limit] as const), queryFn) states[props.limit] = state return (
@@ -5030,40 +5035,40 @@ describe('createQuery', () => { await waitFor(() => expect(states).toHaveLength(4)) - expect(queryCache.find([key, 0])?.state).toMatchObject({ + expect(queryCache.find([key(), 0])?.state).toMatchObject({ data: 'data 0', status: 'success', dataUpdateCount: 1, }) if (typeof AbortSignal === 'function') { - expect(queryCache.find([key, 1])?.state).toMatchObject({ + expect(queryCache.find([key(), 1])?.state).toMatchObject({ data: undefined, status: 'loading', fetchStatus: 'idle', }) } else { - expect(queryCache.find([key, 1])?.state).toMatchObject({ + expect(queryCache.find([key(), 1])?.state).toMatchObject({ data: 'data 1', status: 'success', dataUpdateCount: 1, }) } - expect(queryCache.find([key, 2])?.state).toMatchObject({ + expect(queryCache.find([key(), 2])?.state).toMatchObject({ data: 'data 2', status: 'success', dataUpdateCount: 1, }) if (typeof AbortSignal === 'function') { - expect(queryCache.find([key, 3])?.state).toMatchObject({ + expect(queryCache.find([key(), 3])?.state).toMatchObject({ data: undefined, status: 'loading', fetchStatus: 'idle', }) } else { - expect(queryCache.find([key, 3])?.state).toMatchObject({ + expect(queryCache.find([key(), 3])?.state).toMatchObject({ data: 'data 3', status: 'success', dataUpdateCount: 1, @@ -5107,24 +5112,15 @@ describe('createQuery', () => { )) await sleep(100) - expect(states.length).toBe(4) + expect(states.length).toBe(2) // Load query 1 expect(states[0]).toMatchObject({ status: 'loading', error: null, }) - // Load query 2 - expect(states[1]).toMatchObject({ - status: 'loading', - error: null, - }) - // Load query 1 - expect(states[2]).toMatchObject({ - status: 'loading', - error: null, - }) + // No rerenders - No state updates // Loaded query 1 - expect(states[3]).toMatchObject({ + expect(states[1]).toMatchObject({ status: 'success', error: null, }) @@ -5147,6 +5143,7 @@ describe('createQuery', () => { ) createRenderEffect(() => { + console.log('LOG', state.data, state.isLoading, state.isFetching, state.isStale) states.push({ ...state }) }) @@ -5206,7 +5203,7 @@ describe('createQuery', () => { it('should update query state and not refetch when resetting a disabled query with resetQueries', async () => { const key = queryKey() - const states: CreateQueryResult[] = [] + const states: Partial>[] = [] let count = 0 function Page() { @@ -5221,7 +5218,15 @@ describe('createQuery', () => { ) createRenderEffect(() => { - states.push({ ...state }) + const { data, isLoading, isFetching, isSuccess, isStale } = state + console.log('LOG', state.data, state.isLoading, state.isFetching, state.isSuccess, state.isStale) + states.push({ + data, + isLoading, + isFetching, + isSuccess, + isStale, + }) }) const { refetch } = state @@ -5294,11 +5299,10 @@ describe('createQuery', () => { } function Page() { - NotReact.useEffect(() => { + const state =createQuery(key, () => 'test', { queryKeyHashFn }) + createEffect(on( () => state.status, () => { renders++ - }) - - createQuery(key, () => 'test', { queryKeyHashFn }) + })) return null } diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index 709a5fd22b0..441052fb489 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -5,9 +5,6 @@ import { queryKey } from './utils' import { createQuery, QueryCache, - QueryErrorResetBoundary, - useQueryErrorResetBoundary, - CreateQueryResult, CreateInfiniteQueryResult, createInfiniteQuery, QueryClientProvider, @@ -17,6 +14,7 @@ import { createSignal, ErrorBoundary, on, + Show, Suspense, } from 'solid-js' @@ -335,19 +333,18 @@ describe("useQuery's in Suspense mode", () => { }, ) - // read state.data to trigger suspense. - createRenderEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- trigger suspense - state.data - }) - - return
rendered
+ // Suspense only triggers if used in JSX + return ( + +
+ rendered +
+
+ ) } render(() => ( - - {({ reset: resetQuery }) => ( (
@@ -355,7 +352,6 @@ describe("useQuery's in Suspense mode", () => { -
- )} - > - - - -
- ) - } - - render(() => ( - - - - )) - - await waitFor(() => screen.getByText('Loading...')) - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('error boundary')) - await waitFor(() => screen.getByText('retry')) - succeed = true - fireEvent.click(screen.getByText('retry')) - await waitFor(() => screen.getByText('rendered')) - }) - it('should throw errors to the error boundary by default', async () => { const key = queryKey() @@ -861,7 +779,9 @@ describe("useQuery's in Suspense mode", () => { const [enabled, setEnabled] = createSignal(false) const result = createQuery(() => [key()], queryFn, { suspense: true, - enabled: enabled(), + get enabled() { + return enabled() + } }) return ( @@ -881,7 +801,7 @@ describe("useQuery's in Suspense mode", () => { )) expect(queryFn).toHaveBeenCalledTimes(0) - + await sleep(5) fireEvent.click(screen.getByRole('button', { name: /fire/i })) await waitFor(() => { @@ -906,7 +826,7 @@ describe("useQuery's in Suspense mode", () => { if (!succeed) { throw new Error('Suspense Error Bingo') } else { - return nonce + return nonce() } }, { @@ -930,7 +850,6 @@ describe("useQuery's in Suspense mode", () => { } function App() { - const { reset } = useQueryErrorResetBoundary() return (
error boundary
}> @@ -963,11 +882,10 @@ describe("useQuery's in Suspense mode", () => { let succeed = true function Page() { - const [key, rerender] = React.useReducer((x) => x + 1, 0) - const queryKeys = [key, succeed] + const [key, setKey] = createSignal(0) const result = createQuery( - queryKeys, + () => [`${key()}-${succeed}`], async () => { await sleep(10) if (!succeed) { @@ -984,7 +902,7 @@ describe("useQuery's in Suspense mode", () => { return (
rendered {result.data} -
@@ -992,7 +910,6 @@ describe("useQuery's in Suspense mode", () => { } function App() { - const { reset } = useQueryErrorResetBoundary() return (
error boundary
}> @@ -1035,7 +952,9 @@ describe("useQuery's in Suspense mode", () => { { retry: false, suspense: true, - enabled: enabled(), + get enabled() { + return enabled() + } }, ) return ( @@ -1054,7 +973,6 @@ describe("useQuery's in Suspense mode", () => { } function App() { - const { reset } = useQueryErrorResetBoundary() return (
error boundary
}> diff --git a/packages/solid-query/src/__tests__/useIsFetching.test.tsx b/packages/solid-query/src/__tests__/useIsFetching.test.tsx index 96ee1a81e4b..8a0b3670abc 100644 --- a/packages/solid-query/src/__tests__/useIsFetching.test.tsx +++ b/packages/solid-query/src/__tests__/useIsFetching.test.tsx @@ -44,7 +44,9 @@ describe('useIsFetching', () => { return 'test' }, { - enabled: ready(), + get enabled() { + return ready() + } , }, ) @@ -130,7 +132,8 @@ describe('useIsFetching', () => {
)) - await waitFor(() => expect(isFetchings).toEqual([0, 1, 1, 2, 1, 0])) + // unlike react, Updating renderSecond wont cause a rerender for FirstQuery + await waitFor(() => expect(isFetchings).toEqual([0, 1, 2, 1, 0])) }) it('should be able to filter', async () => { @@ -212,7 +215,9 @@ describe('useIsFetching', () => { return 'test' }, { - enabled: ready(), + get enabled() { + return ready() + }, context, }, ) diff --git a/packages/solid-query/src/__tests__/useIsMutating.test.tsx b/packages/solid-query/src/__tests__/useIsMutating.test.tsx index 82d59162963..d95771b41fd 100644 --- a/packages/solid-query/src/__tests__/useIsMutating.test.tsx +++ b/packages/solid-query/src/__tests__/useIsMutating.test.tsx @@ -104,7 +104,8 @@ describe('useIsMutating', () => { )) - await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0])) + // Unlike React, IsMutating Wont re-render twice with mutation2 + await waitFor(() => expect(isMutatings).toEqual([0, 1, 0])) }) it('should filter correctly by predicate', async () => { @@ -145,7 +146,9 @@ describe('useIsMutating', () => { )) - await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 0])) + + // Again, No unnecessary re-renders like React + await waitFor(() => expect(isMutatings).toEqual([0, 1, 0])) }) it('should not change state if unmounted', async () => { @@ -215,7 +218,11 @@ describe('useIsMutating', () => { function IsMutating() { const isMutating = useIsMutating(undefined, { context }) - isMutatings.push(isMutating()) + + createRenderEffect(() => { + isMutatings.push(isMutating()) + }) + return null } @@ -252,7 +259,7 @@ describe('useIsMutating', () => { )) - await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0])) + await waitFor(() => expect(isMutatings).toEqual([0, 1, 2, 1, 0])) }) it('should throw if the context is not passed to useIsMutating', async () => { diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index b612afbeea7..635bcdbea6c 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -1,20 +1,10 @@ -import { QueryObserver } from '@tanstack/query-core' -import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' -import { CreateBaseQueryOptions } from './types' -import { useQueryClient } from './QueryClientProvider' -import { - onMount, - onCleanup, - createComputed, - createResource, - createMemo, - createEffect, - on, - batch, -} from 'solid-js' -import { createStore, unwrap } from 'solid-js/store' -import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary' -import { shouldThrowError } from './utils' +import { QueryObserver } from "@tanstack/query-core"; +import type { QueryKey, QueryObserverResult } from "@tanstack/query-core"; +import { CreateBaseQueryOptions } from "./types"; +import { useQueryClient } from "./QueryClientProvider"; +import { onMount, onCleanup, createComputed, createResource, on, batch } from "solid-js"; +import { createStore, unwrap } from "solid-js/store"; +import { shouldThrowError } from "./utils"; // Base Query Function that is used to create the query. export function createBaseQuery< @@ -24,92 +14,51 @@ export function createBaseQuery< TQueryData, TQueryKey extends QueryKey, >( - options: CreateBaseQueryOptions< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey - >, + options: CreateBaseQueryOptions, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient({ context: options.context }) - const errorResetBoundary = useQueryErrorResetBoundary() + const queryClient = useQueryClient({ context: options.context }); - const defaultedOptions = createMemo(() => { - const computedOptions = queryClient.defaultQueryOptions(options) - computedOptions._optimisticResults = 'optimistic' - if (computedOptions.suspense) { - // Always set stale time when using suspense to prevent - // fetching again when directly mounting after suspending - if (typeof computedOptions.staleTime !== 'number') { - computedOptions.staleTime = 1000 - } - } - - if (computedOptions.suspense || computedOptions.useErrorBoundary) { - // Prevent retrying failed query if the error boundary has not been reset yet - if (!errorResetBoundary.isReset()) { - computedOptions.retryOnMount = false - } - } - return computedOptions - }) - - const observer = new Observer(queryClient, defaultedOptions()) + const defaultedOptions = queryClient.defaultQueryOptions(options); + defaultedOptions._optimisticResults = "optimistic"; + const observer = new Observer(queryClient, defaultedOptions); const [state, setState] = createStore>( // @ts-ignore - observer.getOptimisticResult(defaultedOptions()), - ) + observer.getOptimisticResult(defaultedOptions), + ); - const [dataResource, { refetch, mutate }] = createResource( - () => { - return new Promise((resolve) => { - if (!(state.isFetching && state.isLoading)) { - resolve(unwrap(state.data)) - } - }) - }, - ) + const [dataResource, { refetch, mutate }] = createResource(() => { + return new Promise((resolve) => { + if (!(state.isFetching && state.isLoading)) { + resolve(unwrap(state.data)); + } + }); + }); batch(() => { - mutate(() => unwrap(state.data)) - refetch() - }) + mutate(() => unwrap(state.data)); + refetch(); + }); const unsubscribe = observer.subscribe((result) => { batch(() => { - setState(unwrap(result)) - mutate(() => unwrap(result.data)) - refetch() - }) - }) + setState(unwrap(result)); + mutate(() => unwrap(result.data)); + refetch(); + }); + }); - onCleanup(() => unsubscribe()) + onCleanup(() => unsubscribe()); onMount(() => { - // Do not notify on updates because of changes in the options because - // these changes should already be reflected in the optimistic result. - observer.setOptions(defaultedOptions(), { listeners: false }) - }) - - // Do not update observer options on mount because it is already set. - createComputed( - on( - defaultedOptions, - () => { - observer.setOptions(defaultedOptions()) - }, - { defer: true }, - ), - ) + observer.setOptions(defaultedOptions, { listeners: false }); + }); - createEffect(() => { - if (errorResetBoundary.isReset()) { - errorResetBoundary.clearReset() - } - }) + createComputed(() => { + const newDefaultedOptions = queryClient.defaultQueryOptions(options); + observer.setOptions(newDefaultedOptions); + }); createComputed( on( @@ -123,48 +72,23 @@ export function createBaseQuery< observer.getCurrentQuery(), ]) ) { - throw state.error + throw state.error; } }, ), - ) + ); const handler = { get( target: QueryObserverResult, prop: keyof QueryObserverResult, ): any { - if (prop === 'data') { - // handle suspense - const isSuspense = - defaultedOptions().suspense && state.isLoading && state.isFetching - - // handle error boundary - const isErrorBoundary = - state.isError && - !errorResetBoundary.isReset() && - !state.isFetching && - shouldThrowError(defaultedOptions().useErrorBoundary, [ - state.error, - observer.getCurrentQuery(), - ]) - - if (isSuspense || isErrorBoundary) { - return dataResource() - } - return state.data + if (prop === "data") { + return dataResource(); } - return Reflect.get(target, prop) + return Reflect.get(target, prop); }, - } - - const proxyResult = new Proxy(state, handler) as QueryObserverResult< - TData, - TError - > + }; - // TODO(lukemurray): is it possible to make this reactive based on defaulted options? - return !defaultedOptions().notifyOnChangeProps - ? observer.trackResult(proxyResult) - : proxyResult + return new Proxy(state, handler) as QueryObserverResult; } diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 5da9ff50167..3e7f773df26 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -3,8 +3,6 @@ export * from '@tanstack/query-core' // Solid Query export * from './types' -// export { useQueries } from './useQueries' -// export type { QueriesResults, QueriesOptions } from './useQueries' export { createQuery } from './createQuery' export { defaultContext, @@ -12,15 +10,8 @@ export { useQueryClient, } from './QueryClientProvider' export type { QueryClientProviderProps } from './QueryClientProvider' -export type { QueryErrorResetBoundaryProps } from './QueryErrorResetBoundary' -// export { useHydrate, Hydrate } from './Hydrate' -// export type { HydrateProps } from './Hydrate' -export { - QueryErrorResetBoundary, - useQueryErrorResetBoundary, -} from './QueryErrorResetBoundary' export { useIsFetching } from './useIsFetching' export { useIsMutating } from './useIsMutating' export { createMutation } from './createMutation' export { createInfiniteQuery } from './createInfiniteQuery' -// export { useIsRestoring, IsRestoringProvider } from './isRestoring' + From 4ee07933a0dad1b6ac8f1af797aca740e932747a Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 16 Sep 2022 21:26:00 -0400 Subject: [PATCH 198/221] Prettifying and removing logs --- .../src/__tests__/createQuery.test.tsx | 39 +++----- .../src/__tests__/suspense.test.tsx | 89 ++++++++--------- .../src/__tests__/useIsFetching.test.tsx | 6 +- .../src/__tests__/useIsMutating.test.tsx | 2 +- packages/solid-query/src/createBaseQuery.ts | 97 +++++++++++-------- packages/solid-query/src/index.ts | 1 - 6 files changed, 117 insertions(+), 117 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQuery.test.tsx b/packages/solid-query/src/__tests__/createQuery.test.tsx index 099b3e153b9..aa5ff61df9b 100644 --- a/packages/solid-query/src/__tests__/createQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createQuery.test.tsx @@ -1571,13 +1571,6 @@ describe('createQuery', () => { ) createEffect(() => { - console.log('My Log', { - data: state.data, - isFetching: state.isFetching, - isRefetching: state.isRefetching, - isSuccess: state.isSuccess, - isStale: state.isStale, - }) states.push({ ...state }) }) @@ -1818,12 +1811,6 @@ describe('createQuery', () => { createRenderEffect(() => { const { data, isFetching, isSuccess, isPreviousData } = state - console.log('LOG', { - data, - isFetching, - isSuccess, - isPreviousData, - }) states.push({ data, isFetching, @@ -4999,9 +4986,10 @@ describe('createQuery', () => { const key = queryKey() const states: CreateQueryResult[] = [] - const queryFn: QueryFunction, number]> = async ( - ctx, - ) => { + const queryFn: QueryFunction< + string, + readonly [ReturnType, number] + > = async (ctx) => { const [, limit] = ctx.queryKey const value = limit % 2 && ctx.signal ? 'abort' : `data ${limit}` await sleep(25) @@ -5009,7 +4997,7 @@ describe('createQuery', () => { } function Page(props: { limit: number }) { - const state = createQuery(() => ([key(), props.limit] as const), queryFn) + const state = createQuery(() => [key(), props.limit] as const, queryFn) states[props.limit] = state return (
@@ -5143,7 +5131,6 @@ describe('createQuery', () => { ) createRenderEffect(() => { - console.log('LOG', state.data, state.isLoading, state.isFetching, state.isStale) states.push({ ...state }) }) @@ -5219,8 +5206,7 @@ describe('createQuery', () => { createRenderEffect(() => { const { data, isLoading, isFetching, isSuccess, isStale } = state - console.log('LOG', state.data, state.isLoading, state.isFetching, state.isSuccess, state.isStale) - states.push({ + states.push({ data, isLoading, isFetching, @@ -5299,10 +5285,15 @@ describe('createQuery', () => { } function Page() { - const state =createQuery(key, () => 'test', { queryKeyHashFn }) - createEffect(on( () => state.status, () => { - renders++ - })) + const state = createQuery(key, () => 'test', { queryKeyHashFn }) + createEffect( + on( + () => state.status, + () => { + renders++ + }, + ), + ) return null } diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index 441052fb489..7c887df590e 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -336,34 +336,32 @@ describe("useQuery's in Suspense mode", () => { // Suspense only triggers if used in JSX return ( -
- rendered -
+
rendered
) } render(() => ( - ( -
-
error boundary
- -
- )} - > - - - -
+ ( +
+
error boundary
+ +
+ )} + > + + + +
)) @@ -400,37 +398,34 @@ describe("useQuery's in Suspense mode", () => { }, ) - // Suspense only triggers if used in JSX return ( -
- rendered -
+
rendered
) } render(() => ( - ( -
-
error boundary
- -
- )} - > - - - -
+ ( +
+
error boundary
+ +
+ )} + > + + + +
)) @@ -781,7 +776,7 @@ describe("useQuery's in Suspense mode", () => { suspense: true, get enabled() { return enabled() - } + }, }) return ( @@ -902,7 +897,7 @@ describe("useQuery's in Suspense mode", () => { return (
rendered {result.data} -
@@ -954,7 +949,7 @@ describe("useQuery's in Suspense mode", () => { suspense: true, get enabled() { return enabled() - } + }, }, ) return ( diff --git a/packages/solid-query/src/__tests__/useIsFetching.test.tsx b/packages/solid-query/src/__tests__/useIsFetching.test.tsx index 8a0b3670abc..6ee84dedb2f 100644 --- a/packages/solid-query/src/__tests__/useIsFetching.test.tsx +++ b/packages/solid-query/src/__tests__/useIsFetching.test.tsx @@ -46,7 +46,7 @@ describe('useIsFetching', () => { { get enabled() { return ready() - } , + }, }, ) @@ -132,7 +132,7 @@ describe('useIsFetching', () => { )) - // unlike react, Updating renderSecond wont cause a rerender for FirstQuery + // unlike react, Updating renderSecond wont cause a rerender for FirstQuery await waitFor(() => expect(isFetchings).toEqual([0, 1, 2, 1, 0])) }) @@ -216,7 +216,7 @@ describe('useIsFetching', () => { }, { get enabled() { - return ready() + return ready() }, context, }, diff --git a/packages/solid-query/src/__tests__/useIsMutating.test.tsx b/packages/solid-query/src/__tests__/useIsMutating.test.tsx index d95771b41fd..d1985e81963 100644 --- a/packages/solid-query/src/__tests__/useIsMutating.test.tsx +++ b/packages/solid-query/src/__tests__/useIsMutating.test.tsx @@ -222,7 +222,7 @@ describe('useIsMutating', () => { createRenderEffect(() => { isMutatings.push(isMutating()) }) - + return null } diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 635bcdbea6c..3fb4008c271 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -1,10 +1,17 @@ -import { QueryObserver } from "@tanstack/query-core"; -import type { QueryKey, QueryObserverResult } from "@tanstack/query-core"; -import { CreateBaseQueryOptions } from "./types"; -import { useQueryClient } from "./QueryClientProvider"; -import { onMount, onCleanup, createComputed, createResource, on, batch } from "solid-js"; -import { createStore, unwrap } from "solid-js/store"; -import { shouldThrowError } from "./utils"; +import { QueryObserver } from '@tanstack/query-core' +import type { QueryKey, QueryObserverResult } from '@tanstack/query-core' +import { CreateBaseQueryOptions } from './types' +import { useQueryClient } from './QueryClientProvider' +import { + onMount, + onCleanup, + createComputed, + createResource, + on, + batch, +} from 'solid-js' +import { createStore, unwrap } from 'solid-js/store' +import { shouldThrowError } from './utils' // Base Query Function that is used to create the query. export function createBaseQuery< @@ -14,51 +21,59 @@ export function createBaseQuery< TQueryData, TQueryKey extends QueryKey, >( - options: CreateBaseQueryOptions, + options: CreateBaseQueryOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey + >, Observer: typeof QueryObserver, ): QueryObserverResult { - const queryClient = useQueryClient({ context: options.context }); + const queryClient = useQueryClient({ context: options.context }) - const defaultedOptions = queryClient.defaultQueryOptions(options); - defaultedOptions._optimisticResults = "optimistic"; - const observer = new Observer(queryClient, defaultedOptions); + const defaultedOptions = queryClient.defaultQueryOptions(options) + defaultedOptions._optimisticResults = 'optimistic' + const observer = new Observer(queryClient, defaultedOptions) const [state, setState] = createStore>( // @ts-ignore observer.getOptimisticResult(defaultedOptions), - ); + ) - const [dataResource, { refetch, mutate }] = createResource(() => { - return new Promise((resolve) => { - if (!(state.isFetching && state.isLoading)) { - resolve(unwrap(state.data)); - } - }); - }); + const [dataResource, { refetch, mutate }] = createResource( + () => { + return new Promise((resolve) => { + if (!(state.isFetching && state.isLoading)) { + resolve(unwrap(state.data)) + } + }) + }, + ) batch(() => { - mutate(() => unwrap(state.data)); - refetch(); - }); + mutate(() => unwrap(state.data)) + refetch() + }) const unsubscribe = observer.subscribe((result) => { batch(() => { - setState(unwrap(result)); - mutate(() => unwrap(result.data)); - refetch(); - }); - }); + setState(unwrap(result)) + mutate(() => unwrap(result.data)) + refetch() + }) + }) - onCleanup(() => unsubscribe()); + onCleanup(() => unsubscribe()) onMount(() => { - observer.setOptions(defaultedOptions, { listeners: false }); - }); + observer.setOptions(defaultedOptions, { listeners: false }) + }) createComputed(() => { - const newDefaultedOptions = queryClient.defaultQueryOptions(options); - observer.setOptions(newDefaultedOptions); - }); + const newDefaultedOptions = queryClient.defaultQueryOptions(options) + observer.setOptions(newDefaultedOptions) + }) createComputed( on( @@ -72,23 +87,23 @@ export function createBaseQuery< observer.getCurrentQuery(), ]) ) { - throw state.error; + throw state.error } }, ), - ); + ) const handler = { get( target: QueryObserverResult, prop: keyof QueryObserverResult, ): any { - if (prop === "data") { - return dataResource(); + if (prop === 'data') { + return dataResource() } - return Reflect.get(target, prop); + return Reflect.get(target, prop) }, - }; + } - return new Proxy(state, handler) as QueryObserverResult; + return new Proxy(state, handler) as QueryObserverResult } diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index 3e7f773df26..c9e7569497d 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -14,4 +14,3 @@ export { useIsFetching } from './useIsFetching' export { useIsMutating } from './useIsMutating' export { createMutation } from './createMutation' export { createInfiniteQuery } from './createInfiniteQuery' - From 8bc32f898d9e465e0bc790fa8137c0d1d146a50f Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Fri, 16 Sep 2022 23:02:13 -0400 Subject: [PATCH 199/221] Small Types Fix for CreateInfiniteQuery --- .../solid-query/src/createInfiniteQuery.ts | 92 +++++-------------- 1 file changed, 23 insertions(+), 69 deletions(-) diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts index 608772f4f00..a9ddba6d445 100644 --- a/packages/solid-query/src/createInfiniteQuery.ts +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -1,17 +1,9 @@ -import { - QueryObserver, - InfiniteQueryObserver, - QueryFunction, -} from '@tanstack/query-core' -import { - CreateInfiniteQueryOptions, - CreateInfiniteQueryResult, - SolidQueryKey, -} from './types' -import { createBaseQuery } from './createBaseQuery' -import { createComputed } from 'solid-js' -import { createStore } from 'solid-js/store' -import { parseQueryArgs } from './utils' +import { QueryObserver, InfiniteQueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; +import { CreateInfiniteQueryOptions, CreateInfiniteQueryResult, SolidQueryKey } from "./types"; +import { createBaseQuery } from "./createBaseQuery"; +import { createComputed } from "solid-js"; +import { createStore } from "solid-js/store"; +import { parseQueryArgs } from "./utils"; export function createInfiniteQuery< TQueryFnData = unknown, @@ -19,14 +11,8 @@ export function createInfiniteQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, -): CreateInfiniteQueryResult + options: CreateInfiniteQueryOptions, +): CreateInfiniteQueryResult; export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -35,16 +21,10 @@ export function createInfiniteQuery< >( queryKey: TQueryKey, options?: Omit< - CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, - 'queryKey' + CreateInfiniteQueryOptions, + "queryKey" >, -): CreateInfiniteQueryResult +): CreateInfiniteQueryResult; export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -54,16 +34,10 @@ export function createInfiniteQuery< queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< - CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, - 'queryKey' | 'queryFn' + CreateInfiniteQueryOptions, + "queryKey" | "queryFn" >, -): CreateInfiniteQueryResult +): CreateInfiniteQueryResult; export function createInfiniteQuery< TQueryFnData, TError, @@ -72,44 +46,24 @@ export function createInfiniteQuery< >( arg1: | TQueryKey - | CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, + | CreateInfiniteQueryOptions, arg2?: | QueryFunction> - | CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, - arg3?: CreateInfiniteQueryOptions< - TQueryFnData, - TError, - TData, - TQueryFnData, - TQueryKey - >, + | CreateInfiniteQueryOptions, + arg3?: CreateInfiniteQueryOptions, ): CreateInfiniteQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore( - parseQueryArgs(arg1, arg2, arg3), - ) + const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) - setParsedOptions(newParsedOptions) - }) + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); + setParsedOptions(newParsedOptions); + }); return createBaseQuery( - parsedOptions, + parsedOptions as QueryOptions>, InfiniteQueryObserver as typeof QueryObserver, - ) as CreateInfiniteQueryResult + ) as CreateInfiniteQueryResult; } From 5a579e49cff0d3e686f9ab6afc945c1ba30f233a Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 17:29:22 -0400 Subject: [PATCH 200/221] Prettier fix for infiniteQueries --- .../solid-query/src/createInfiniteQuery.ts | 91 ++++++++++++++----- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/packages/solid-query/src/createInfiniteQuery.ts b/packages/solid-query/src/createInfiniteQuery.ts index a9ddba6d445..8e66d9132b9 100644 --- a/packages/solid-query/src/createInfiniteQuery.ts +++ b/packages/solid-query/src/createInfiniteQuery.ts @@ -1,9 +1,18 @@ -import { QueryObserver, InfiniteQueryObserver, QueryFunction, QueryOptions } from "@tanstack/query-core"; -import { CreateInfiniteQueryOptions, CreateInfiniteQueryResult, SolidQueryKey } from "./types"; -import { createBaseQuery } from "./createBaseQuery"; -import { createComputed } from "solid-js"; -import { createStore } from "solid-js/store"; -import { parseQueryArgs } from "./utils"; +import { + QueryObserver, + InfiniteQueryObserver, + QueryFunction, + QueryOptions, +} from '@tanstack/query-core' +import { + CreateInfiniteQueryOptions, + CreateInfiniteQueryResult, + SolidQueryKey, +} from './types' +import { createBaseQuery } from './createBaseQuery' +import { createComputed } from 'solid-js' +import { createStore } from 'solid-js/store' +import { parseQueryArgs } from './utils' export function createInfiniteQuery< TQueryFnData = unknown, @@ -11,8 +20,14 @@ export function createInfiniteQuery< TData = TQueryFnData, TQueryKey extends SolidQueryKey = SolidQueryKey, >( - options: CreateInfiniteQueryOptions, -): CreateInfiniteQueryResult; + options: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -21,10 +36,16 @@ export function createInfiniteQuery< >( queryKey: TQueryKey, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData = unknown, TError = unknown, @@ -34,10 +55,16 @@ export function createInfiniteQuery< queryKey: TQueryKey, queryFn: QueryFunction>, options?: Omit< - CreateInfiniteQueryOptions, - "queryKey" | "queryFn" + CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + 'queryKey' | 'queryFn' >, -): CreateInfiniteQueryResult; +): CreateInfiniteQueryResult export function createInfiniteQuery< TQueryFnData, TError, @@ -46,24 +73,44 @@ export function createInfiniteQuery< >( arg1: | TQueryKey - | CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, arg2?: | QueryFunction> - | CreateInfiniteQueryOptions, - arg3?: CreateInfiniteQueryOptions, + | CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, + arg3?: CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey + >, ): CreateInfiniteQueryResult { // The parseQuery Args functions helps normalize the arguments into the correct form. // Whatever the parameters are, they are normalized into the correct form. - const [parsedOptions, setParsedOptions] = createStore(parseQueryArgs(arg1, arg2, arg3)); + const [parsedOptions, setParsedOptions] = createStore( + parseQueryArgs(arg1, arg2, arg3), + ) // Watch for changes in the options and update the parsed options. createComputed(() => { - const newParsedOptions = parseQueryArgs(arg1, arg2, arg3); - setParsedOptions(newParsedOptions); - }); + const newParsedOptions = parseQueryArgs(arg1, arg2, arg3) + setParsedOptions(newParsedOptions) + }) return createBaseQuery( parsedOptions as QueryOptions>, InfiniteQueryObserver as typeof QueryObserver, - ) as CreateInfiniteQueryResult; + ) as CreateInfiniteQueryResult } From b818813e95c0ad1aefa0b363cd29857c4b020ca3 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 17:24:16 -0400 Subject: [PATCH 201/221] Added createQueries --- packages/solid-query/src/createQueries.ts | 184 ++++++++++++++++++++++ packages/solid-query/src/index.ts | 1 + 2 files changed, 185 insertions(+) create mode 100644 packages/solid-query/src/createQueries.ts diff --git a/packages/solid-query/src/createQueries.ts b/packages/solid-query/src/createQueries.ts new file mode 100644 index 00000000000..a016ae13068 --- /dev/null +++ b/packages/solid-query/src/createQueries.ts @@ -0,0 +1,184 @@ +import { createComputed, onCleanup, onMount } from 'solid-js' +import { QueryFunction, QueriesObserver } from '@tanstack/query-core' +import { useQueryClient } from './QueryClientProvider' +import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' +import { createStore, unwrap } from 'solid-js/store' + +// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`. +// - `context` is omitted as it is passed as a root-level option to `useQueries` instead. +type CreateQueryOptionsForCreateQueries< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends SolidQueryKey = SolidQueryKey, +> = Omit, 'context'> + +// Avoid TS depth-limit error in case of large array literal +type MAXIMUM_DEPTH = 20 + +type GetOptions = + // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData } + T extends { + queryFnData: infer TQueryFnData + error?: infer TError + data: infer TData + } + ? CreateQueryOptionsForCreateQueries + : T extends { queryFnData: infer TQueryFnData; error?: infer TError } + ? CreateQueryOptionsForCreateQueries + : T extends { data: infer TData; error?: infer TError } + ? CreateQueryOptionsForCreateQueries + : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData] + T extends [infer TQueryFnData, infer TError, infer TData] + ? CreateQueryOptionsForCreateQueries + : T extends [infer TQueryFnData, infer TError] + ? CreateQueryOptionsForCreateQueries + : T extends [infer TQueryFnData] + ? CreateQueryOptionsForCreateQueries + : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided + T extends { + queryFn?: QueryFunction + select: (data: any) => infer TData + } + ? CreateQueryOptionsForCreateQueries< + TQueryFnData, + unknown, + TData, + () => TQueryKey + > + : T extends { queryFn?: QueryFunction } + ? CreateQueryOptionsForCreateQueries< + TQueryFnData, + unknown, + TQueryFnData, + () => TQueryKey + > + : // Fallback + CreateQueryOptionsForCreateQueries + +type GetResults = + // Part 1: responsible for mapping explicit type parameter to function result, if object + T extends { queryFnData: any; error?: infer TError; data: infer TData } + ? CreateQueryResult + : T extends { queryFnData: infer TQueryFnData; error?: infer TError } + ? CreateQueryResult + : T extends { data: infer TData; error?: infer TError } + ? CreateQueryResult + : // Part 2: responsible for mapping explicit type parameter to function result, if tuple + T extends [any, infer TError, infer TData] + ? CreateQueryResult + : T extends [infer TQueryFnData, infer TError] + ? CreateQueryResult + : T extends [infer TQueryFnData] + ? CreateQueryResult + : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided + T extends { + queryFn?: QueryFunction + select: (data: any) => infer TData + } + ? CreateQueryResult + : T extends { queryFn?: QueryFunction } + ? CreateQueryResult + : // Fallback + CreateQueryResult + +/** + * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param + */ +export type QueriesOptions< + T extends any[], + Result extends any[] = [], + Depth extends ReadonlyArray = [], +> = Depth['length'] extends MAXIMUM_DEPTH + ? CreateQueryOptionsForCreateQueries[] + : T extends [] + ? [] + : T extends [infer Head] + ? [...Result, GetOptions] + : T extends [infer Head, ...infer Tail] + ? QueriesOptions<[...Tail], [...Result, GetOptions], [...Depth, 1]> + : unknown[] extends T + ? T + : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type! + // use this to infer the param types in the case of Array.map() argument + T extends CreateQueryOptionsForCreateQueries< + infer TQueryFnData, + infer TError, + infer TData, + infer TQueryKey + >[] + ? CreateQueryOptionsForCreateQueries[] + : // Fallback + CreateQueryOptionsForCreateQueries[] + +/** + * QueriesResults reducer recursively maps type param to results + */ +export type QueriesResults< + T extends any[], + Result extends any[] = [], + Depth extends ReadonlyArray = [], +> = Depth['length'] extends MAXIMUM_DEPTH + ? CreateQueryResult[] + : T extends [] + ? [] + : T extends [infer Head] + ? [...Result, GetResults] + : T extends [infer Head, ...infer Tail] + ? QueriesResults<[...Tail], [...Result, GetResults], [...Depth, 1]> + : T extends CreateQueryOptionsForCreateQueries< + infer TQueryFnData, + infer TError, + infer TData, + any + >[] + ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results + CreateQueryResult[] + : // Fallback + CreateQueryResult[] + +type ArrType = T extends (infer U)[] ? U : never + +export function createQueries({ + queries, + context, +}: { + queries: readonly [...QueriesOptions] + context?: CreateQueryOptions['context'] +}): QueriesResults { + const queryClient = useQueryClient({ context }) + + const normalizeOptions = (options: ArrType) => { + const normalizedOptions = { ...options, queryKey: options.queryKey?.() } + const defaultedOptions = queryClient.defaultQueryOptions(normalizedOptions) + defaultedOptions._optimisticResults = 'optimistic' + return defaultedOptions + } + + const defaultedQueries = queries.map((options) => normalizeOptions(options)) + + const observer = new QueriesObserver(queryClient, defaultedQueries) + + const [state, setState] = createStore( + observer.getOptimisticResult(defaultedQueries), + ) + + const unsubscribe = observer.subscribe((result) => { + setState(unwrap(result)) + }) + + onCleanup(unsubscribe) + + onMount(() => { + observer.setQueries(defaultedQueries, { listeners: false }) + }) + + createComputed(() => { + const updateDefaultedQueries = queries.map((options) => + normalizeOptions(options), + ) + observer.setQueries(updateDefaultedQueries) + }) + + return state as QueriesResults +} diff --git a/packages/solid-query/src/index.ts b/packages/solid-query/src/index.ts index c9e7569497d..81ba67caff7 100644 --- a/packages/solid-query/src/index.ts +++ b/packages/solid-query/src/index.ts @@ -14,3 +14,4 @@ export { useIsFetching } from './useIsFetching' export { useIsMutating } from './useIsMutating' export { createMutation } from './createMutation' export { createInfiniteQuery } from './createInfiniteQuery' +export { createQueries } from './createQueries' From 3e41d54059283538457e1f61a2573b6fc0dc2e4e Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 20:45:56 -0400 Subject: [PATCH 202/221] Making options reactive + added batching tasks --- .../src/__tests__/createQueries.test.tsx | 1162 +++++++++++++++++ packages/solid-query/src/createQueries.ts | 32 +- packages/solid-query/src/utils.ts | 14 + 3 files changed, 1199 insertions(+), 9 deletions(-) create mode 100644 packages/solid-query/src/__tests__/createQueries.test.tsx diff --git a/packages/solid-query/src/__tests__/createQueries.test.tsx b/packages/solid-query/src/__tests__/createQueries.test.tsx new file mode 100644 index 00000000000..90a1c806ad0 --- /dev/null +++ b/packages/solid-query/src/__tests__/createQueries.test.tsx @@ -0,0 +1,1162 @@ +import { fireEvent, render, waitFor, screen } from 'solid-testing-library' + +import * as QueriesObserverModule from '../../../query-core/src/queriesObserver' + +import { + createQueryClient, + expectType, + expectTypeNotAny, + sleep, +} from '../../../../tests/utils' +import { queryKey } from './utils' +import { + QueryClient, + createQueries, + CreateQueryResult, + QueryCache, + QueryObserverResult, + QueriesObserver, + QueryFunction, + CreateQueryOptions, + QueryClientProvider, + SolidQueryKey, +} from '..' +import { QueryFunctionContext } from '@tanstack/query-core' +import { + createContext, + createMemo, + createRenderEffect, + createSignal, + ErrorBoundary, + For, +} from 'solid-js' + +describe('useQueries', () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + + it('should return the correct states', async () => { + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(10) + return 1 + }, + }, + { + queryKey: key2, + queryFn: async () => { + await sleep(100) + return 2 + }, + }, + ], + }) + + createRenderEffect(() => { + results.push([...result]) + }) + + return ( +
+
+ data1: {String(result[0].data ?? 'null')}, data2:{' '} + {String(result[1].data ?? 'null')} +
+
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 1, data2: 2')) + + expect(results.length).toBe(3) + expect(results[0]).toMatchObject([{ data: undefined }, { data: undefined }]) + expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }]) + expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }]) + }) + + it('should keep previous data if amount of queries is the same', async () => { + const key1 = queryKey() + const key2 = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [count, setCount] = createSignal(1) + const result = createQueries({ + queries: [ + { + queryKey: () => [key1(), count()], + keepPreviousData: true, + queryFn: async () => { + await sleep(10) + return count() * 2 + }, + }, + { + queryKey: () => [key2(), count()], + keepPreviousData: true, + queryFn: async () => { + await sleep(35) + return count() * 5 + }, + }, + ], + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
+ data1: {String(result[0].data ?? 'null')}, data2:{' '} + {String(result[1].data ?? 'null')} +
+
isFetching: {String(isFetching())}
+ +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 2, data2: 5')) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) + + await waitFor(() => screen.getByText('data1: 4, data2: 10')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 4, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should keep previous data for variable amounts of useQueries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [count, setCount] = createSignal(2) + const result = createQueries({ + // TODO(lukemurray): reactive queries doesn't appear to work + get queries() { + return Array.from({ length: count() }, (_, i) => ({ + queryKey: () => [key(), count(), i + 1], + keepPreviousData: true, + queryFn: async () => { + await sleep(35 * (i + 1)) + return (i + 1) * count() * 2 + }, + })) + }, + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
data: {result.map((it) => it.data).join(',')}
+
isFetching: {String(isFetching())}
+ +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data: 4,8')) + fireEvent.click(screen.getByRole('button', { name: /inc/i })) + + await waitFor(() => screen.getByText('data: 6,12,18')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 6, isPreviousData: false, isFetching: false }, + { status: 'success', data: 12, isPreviousData: false, isFetching: false }, + { status: 'success', data: 18, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should keep previous data when switching between queries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [series1, setSeries1] = createSignal(1) + const [series2, setSeries2] = createSignal(2) + const ids = [series1, series2] + + const result = createQueries({ + queries: ids.map((id) => { + return { + queryKey: () => [key(), id()], + queryFn: async () => { + await sleep(5) + return id() * 5 + }, + keepPreviousData: true, + } + }), + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
+ data1: {String(result[0]?.data ?? 'null')}, data2:{' '} + {String(result[1]?.data ?? 'null')} +
+
isFetching: {String(isFetching())}
+ + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 5, data2: 10')) + fireEvent.click(screen.getByRole('button', { name: /setSeries2/i })) + + await waitFor(() => screen.getByText('data1: 5, data2: 15')) + fireEvent.click(screen.getByRole('button', { name: /setSeries1/i })) + + await waitFor(() => screen.getByText('data1: 10, data2: 15')) + await waitFor(() => screen.getByText('isFetching: false')) + + expect(states[states.length - 1]).toMatchObject([ + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + { status: 'success', data: 15, isPreviousData: false, isFetching: false }, + ]) + }) + + it('should not go to infinite render loop with previous data when toggling queries', async () => { + const key = queryKey() + const states: CreateQueryResult[][] = [] + + function Page() { + const [enableId1, setEnableId1] = createSignal(true) + const ids = createMemo(() => (enableId1() ? [1, 2] : [2])) + + const result = createQueries({ + // TODO(lukemurray): same issue queries should be reactive + get queries() { + return ids().map((id) => { + return { + queryKey: () => [key(), id], + queryFn: async () => { + await sleep(5) + return id * 5 + }, + keepPreviousData: true, + } + }) + }, + }) + + createRenderEffect(() => { + states.push([...result]) + }) + + const text = createMemo(() => { + return result + .map((r, idx) => `data${idx + 1}: ${r.data ?? 'null'}`) + .join(' ') + }) + + const isFetching = createMemo(() => result.some((r) => r.isFetching)) + + return ( +
+
{text()}
+
isFetching: {String(isFetching())}
+ + +
+ ) + } + + render(() => ( + + + + )) + + await waitFor(() => screen.getByText('data1: 5 data2: 10')) + fireEvent.click(screen.getByRole('button', { name: /set1Disabled/i })) + + await waitFor(() => screen.getByText('data1: 10')) + await waitFor(() => screen.getByText('isFetching: false')) + fireEvent.click(screen.getByRole('button', { name: /set2Enabled/i })) + + await waitFor(() => screen.getByText('data1: 5 data2: 10')) + await waitFor(() => screen.getByText('isFetching: false')) + + await waitFor(() => expect(states.length).toBe(5)) + + expect(states[0]).toMatchObject([ + { + status: 'loading', + data: undefined, + isPreviousData: false, + isFetching: true, + }, + { + status: 'loading', + data: undefined, + isPreviousData: false, + isFetching: true, + }, + ]) + expect(states[1]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[2]).toMatchObject([ + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[3]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: true }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[4]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: false }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + }) + + it('handles type parameter - tuple of tuples', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result1 = createQueries<[[number], [string], [string[], boolean]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + }, + ], + }) + expectType>(result1[0]) + expectType>(result1[1]) + expectType>(result1[2]) + expectType(result1[0].data) + expectType(result1[1].data) + expectType(result1[2].data) + expectType(result1[2].error) + + // TData (3rd element) takes precedence over TQueryFnData (1st element) + const result2 = createQueries< + [[string, unknown, string], [string, unknown, number]] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + }, + ], + }) + expectType>(result2[0]) + expectType>(result2[1]) + expectType(result2[0].data) + expectType(result2[1].data) + + // types should be enforced + createQueries<[[string, unknown, string], [string, boolean, number]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + onError: (e) => { + expectType(e) + expectTypeNotAny(e) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + ], + }) + + // field names should be enforced + createQueries<[[string]]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + } + }) + + it('handles type parameter - tuple of objects', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result1 = createQueries< + [ + { queryFnData: number }, + { queryFnData: string }, + { queryFnData: string[]; error: boolean }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + }, + ], + }) + expectType>(result1[0]) + expectType>(result1[1]) + expectType>(result1[2]) + expectType(result1[0].data) + expectType(result1[1].data) + expectType(result1[2].data) + expectType(result1[2].error) + + // TData (data prop) takes precedence over TQueryFnData (queryFnData prop) + const result2 = createQueries< + [ + { queryFnData: string; data: string }, + { queryFnData: string; data: number }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + }, + ], + }) + expectType>(result2[0]) + expectType>(result2[1]) + expectType(result2[0].data) + expectType(result2[1].data) + + // can pass only TData (data prop) although TQueryFnData will be left unknown + const result3 = createQueries<[{ data: string }, { data: number }]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a as string + }, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a as number + }, + }, + ], + }) + expectType>(result3[0]) + expectType>(result3[1]) + expectType(result3[0].data) + expectType(result3[1].data) + + // types should be enforced + createQueries< + [ + { queryFnData: string; data: string }, + { queryFnData: string; data: number; error: boolean }, + ] + >({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return a.toLowerCase() + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 'string', + select: (a) => { + expectType(a) + expectTypeNotAny(a) + return parseInt(a) + }, + onSuccess: (a) => { + expectType(a) + expectTypeNotAny(a) + }, + onError: (e) => { + expectType(e) + expectTypeNotAny(e) + }, + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + ], + }) + + // field names should be enforced + createQueries<[{ queryFnData: string }]>({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + } + }) + + it('handles array literal without type parameter to infer result type', async () => { + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() + const key4 = queryKey() + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + // Array.map preserves TQueryFnData + const result1 = createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + })), + }) + expectType[]>(result1) + expectType(result1[0]?.data) + + // Array.map preserves TData + const result2 = createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + })), + }) + expectType[]>(result2) + + const result3 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 1, + }, + { + queryKey: key2, + queryFn: () => 'string', + }, + { + queryKey: key3, + queryFn: () => ['string[]'], + select: () => 123, + }, + ], + }) + expectType>(result3[0]) + expectType>(result3[1]) + expectType>(result3[2]) + expectType(result3[0].data) + expectType(result3[1].data) + // select takes precedence over queryFn + expectType(result3[2].data) + + // initialData/placeholderData are enforced + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + placeholderData: 'string', + // @ts-expect-error (initialData: string) + initialData: 123, + }, + { + queryKey: key2, + queryFn: () => 123, + // @ts-expect-error (placeholderData: number) + placeholderData: 'string', + initialData: 123, + }, + ], + }) + + // select / onSuccess / onSettled params are "indirectly" enforced + createQueries({ + queries: [ + // unfortunately TS will not suggest the type for you + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (noImplicitAny) + onSuccess: (a) => null, + // @ts-expect-error (noImplicitAny) + onSettled: (a) => null, + }, + // however you can add a type to the callback + { + queryKey: key2, + queryFn: () => 'string', + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + onSettled: (a: string | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + // the type you do pass is enforced + { + queryKey: key3, + queryFn: () => 'string', + // @ts-expect-error (only accepts string) + onSuccess: (a: number) => null, + }, + { + queryKey: key4, + queryFn: () => 'string', + select: (a: string) => parseInt(a), + // @ts-expect-error (select is defined => only accepts number) + onSuccess: (a: string) => null, + onSettled: (a: number | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + ], + }) + + // callbacks are also indirectly enforced with Array.map + createQueries({ + // @ts-expect-error (onSuccess only accepts string) + queries: Array(50).map((_, i) => ({ + queryKey: ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + onSuccess: (_data: number) => null, + })), + }) + createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => i + 10, + select: (data: number) => data.toString(), + onSuccess: (_data: string) => null, + })), + }) + + // results inference works when all the handlers are defined + const result4 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (noImplicitAny) + onSuccess: (a) => null, + // @ts-expect-error (noImplicitAny) + onSettled: (a) => null, + }, + { + queryKey: key2, + queryFn: () => 'string', + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + onSettled: (a: string | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + { + queryKey: key4, + queryFn: () => 'string', + select: (a: string) => parseInt(a), + onSuccess: (_a: number) => null, + onSettled: (a: number | undefined) => { + expectType(a) + expectTypeNotAny(a) + }, + }, + ], + }) + expectType>(result4[0]) + expectType>(result4[1]) + expectType>(result4[2]) + + // handles when queryFn returns a Promise + const result5 = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => Promise.resolve('string'), + onSuccess: (a: string) => { + expectType(a) + expectTypeNotAny(a) + }, + // @ts-expect-error (refuses to accept a Promise) + onSettled: (a: Promise) => null, + }, + ], + }) + expectType>(result5[0]) + + // Array as const does not throw error + const result6 = createQueries({ + queries: [ + { + queryKey: () => ['key1'], + queryFn: () => 'string', + }, + { + queryKey: () => ['key1'], + queryFn: () => 123, + }, + ], + } as const) + expectType>(result6[0]) + expectType>(result6[1]) + + // field names should be enforced - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + + // field names should be enforced - Array.map() result + createQueries({ + // @ts-expect-error (invalidField) + queries: Array(10).map(() => ({ + someInvalidField: '', + })), + }) + + // field names should be enforced - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => 'string', + // @ts-expect-error (invalidField) + someInvalidField: [], + }, + ], + }) + + // supports queryFn using fetch() to return Promise - Array.map() result + createQueries({ + queries: Array(50).map((_, i) => ({ + queryKey: () => ['key', i] as const, + queryFn: () => + fetch('return Promise').then((resp) => resp.json()), + })), + }) + + // supports queryFn using fetch() to return Promise - array literal + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: () => + fetch('return Promise').then((resp) => resp.json()), + }, + ], + }) + } + }) + + it('handles strongly typed queryFn factories and useQueries wrappers', () => { + // QueryKey + queryFn factory + type QueryKeyA = ['queryA'] + const getQueryKeyA = (): QueryKeyA => ['queryA'] + type GetQueryFunctionA = () => QueryFunction + const getQueryFunctionA: GetQueryFunctionA = () => async () => { + return 1 + } + type SelectorA = (data: number) => [number, string] + const getSelectorA = (): SelectorA => (data) => [data, data.toString()] + + type QueryKeyB = ['queryB', string] + const getQueryKeyB = (id: string): QueryKeyB => ['queryB', id] + type GetQueryFunctionB = () => QueryFunction + const getQueryFunctionB: GetQueryFunctionB = () => async () => { + return '1' + } + type SelectorB = (data: string) => [string, number] + const getSelectorB = (): SelectorB => (data) => [data, +data] + + // Wrapper with strongly typed array-parameter + function useWrappedQueries< + TQueryFnData, + TError, + TData, + TQueryKey extends SolidQueryKey, + >(queries: CreateQueryOptions[]) { + return createQueries({ + queries: queries.map( + // no need to type the mapped query + (query) => { + const { queryFn: fn, queryKey: key, onError: err } = query + expectType< + QueryFunction> | undefined + >(fn) + return { + queryKey: key, + onError: err, + queryFn: fn + ? (ctx: QueryFunctionContext>) => { + expectType>(ctx.queryKey) + return fn.call({}, ctx) + } + : undefined, + } + }, + ), + }) + } + + // @ts-expect-error (Page component is not rendered) + // eslint-disable-next-line + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + }, + { + queryKey: () => getQueryKeyB('id'), + queryFn: getQueryFunctionB(), + }, + ], + }) + expectType>(result[0]) + expectType>(result[1]) + + const withSelector = createQueries({ + queries: [ + { + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + select: getSelectorA(), + }, + { + queryKey: () => getQueryKeyB('id'), + queryFn: getQueryFunctionB(), + select: getSelectorB(), + }, + ], + }) + expectType>( + withSelector[0], + ) + expectType>( + withSelector[1], + ) + + const withWrappedQueries = useWrappedQueries( + Array(10).map(() => ({ + queryKey: () => getQueryKeyA(), + queryFn: getQueryFunctionA(), + select: getSelectorA(), + })), + ) + + expectType[]>( + withWrappedQueries, + ) + } + }) + + it('should not change state if unmounted', async () => { + const key1 = queryKey() + + // We have to mock the QueriesObserver to not unsubscribe + // the listener when the component is unmounted + class QueriesObserverMock extends QueriesObserver { + subscribe(listener: any) { + super.subscribe(listener) + return () => void 0 + } + } + + const QueriesObserverSpy = jest + .spyOn(QueriesObserverModule, 'QueriesObserver') + .mockImplementation((fn) => { + return new QueriesObserverMock(fn) + }) + + function Queries() { + createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(10) + return 1 + }, + }, + ], + }) + + return ( +
+ queries +
+ ) + } + + function Page() { + const [mounted, setMounted] = createSignal(true) + + return ( +
+ + {mounted() && } +
+ ) + } + + render(() => ( + + + + )) + fireEvent.click(screen.getByText('unmount')) + + // Should not display the console error + // "Warning: Can't perform a React state update on an unmounted component" + + await sleep(20) + QueriesObserverSpy.mockRestore() + }) + + describe('with custom context', () => { + it('should return the correct states', async () => { + const context = createContext(undefined) + + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + context, + queries: [ + { + queryKey: key1, + queryFn: async () => { + await sleep(5) + return 1 + }, + }, + { + queryKey: key2, + queryFn: async () => { + await sleep(10) + return 2 + }, + }, + ], + }) + createRenderEffect(() => { + results.push([...result]) + }) + return null + } + + render(() => ( + + + + )) + + await sleep(30) + + expect(results[0]).toMatchObject([ + { data: undefined }, + { data: undefined }, + ]) + expect(results[results.length - 1]).toMatchObject([ + { data: 1 }, + { data: 2 }, + ]) + }) + + it('should throw if the context is necessary and is not passed to useQueries', async () => { + const context = createContext(undefined) + + const key1 = queryKey() + const key2 = queryKey() + const results: CreateQueryResult[][] = [] + + function Page() { + const result = createQueries({ + queries: [ + { + queryKey: key1, + queryFn: async () => 1, + }, + { + queryKey: key2, + queryFn: async () => 2, + }, + ], + }) + results.push(result) + return null + } + + render(() => ( + +
error boundary
}> + +
+
+ )) + + await waitFor(() => screen.getByText('error boundary')) + }) + }) +}) diff --git a/packages/solid-query/src/createQueries.ts b/packages/solid-query/src/createQueries.ts index a016ae13068..266a69a59a3 100644 --- a/packages/solid-query/src/createQueries.ts +++ b/packages/solid-query/src/createQueries.ts @@ -3,6 +3,7 @@ import { QueryFunction, QueriesObserver } from '@tanstack/query-core' import { useQueryClient } from './QueryClientProvider' import { CreateQueryOptions, CreateQueryResult, SolidQueryKey } from './types' import { createStore, unwrap } from 'solid-js/store' +import { scheduleMicrotask } from './utils' // This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`. // - `context` is omitted as it is passed as a root-level option to `useQueries` instead. @@ -139,23 +140,24 @@ export type QueriesResults< type ArrType = T extends (infer U)[] ? U : never -export function createQueries({ - queries, - context, -}: { +export function createQueries(queriesOptions: { queries: readonly [...QueriesOptions] context?: CreateQueryOptions['context'] }): QueriesResults { - const queryClient = useQueryClient({ context }) + const queryClient = useQueryClient({ context: queriesOptions.context }) - const normalizeOptions = (options: ArrType) => { + const normalizeOptions = ( + options: ArrType, + ) => { const normalizedOptions = { ...options, queryKey: options.queryKey?.() } const defaultedOptions = queryClient.defaultQueryOptions(normalizedOptions) defaultedOptions._optimisticResults = 'optimistic' return defaultedOptions } - const defaultedQueries = queries.map((options) => normalizeOptions(options)) + const defaultedQueries = queriesOptions.queries.map((options) => + normalizeOptions(options), + ) const observer = new QueriesObserver(queryClient, defaultedQueries) @@ -163,8 +165,20 @@ export function createQueries({ observer.getOptimisticResult(defaultedQueries), ) + const taskQueue: Array<() => void> = [] + const unsubscribe = observer.subscribe((result) => { - setState(unwrap(result)) + taskQueue.push(() => { + setState(unwrap(result)) + }) + + scheduleMicrotask(() => { + const taskToRun = taskQueue.pop() + if (taskToRun) { + taskToRun() + taskQueue.splice(0, taskQueue.length) + } + }) }) onCleanup(unsubscribe) @@ -174,7 +188,7 @@ export function createQueries({ }) createComputed(() => { - const updateDefaultedQueries = queries.map((options) => + const updateDefaultedQueries = queriesOptions.queries.map((options) => normalizeOptions(options), ) observer.setQueries(updateDefaultedQueries) diff --git a/packages/solid-query/src/utils.ts b/packages/solid-query/src/utils.ts index ee8fcc6f570..bc1883ae35f 100644 --- a/packages/solid-query/src/utils.ts +++ b/packages/solid-query/src/utils.ts @@ -69,3 +69,17 @@ export function shouldThrowError boolean>( return !!_useErrorBoundary } + +export function sleep(timeout: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, timeout) + }) +} + +/** + * Schedules a microtask. + * This can be useful to schedule state updates after rendering. + */ +export function scheduleMicrotask(callback: () => void) { + sleep(0).then(callback) +} From 5d1a7c37ea790689d3a24624eb3088bbf1978b16 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 17:56:12 -0400 Subject: [PATCH 203/221] add createQueries tests --- .../src/__tests__/createQueries.test.tsx | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/solid-query/src/__tests__/createQueries.test.tsx b/packages/solid-query/src/__tests__/createQueries.test.tsx index 90a1c806ad0..0e94d748229 100644 --- a/packages/solid-query/src/__tests__/createQueries.test.tsx +++ b/packages/solid-query/src/__tests__/createQueries.test.tsx @@ -28,7 +28,6 @@ import { createRenderEffect, createSignal, ErrorBoundary, - For, } from 'solid-js' describe('useQueries', () => { @@ -296,17 +295,14 @@ describe('useQueries', () => { states.push([...result]) }) - const text = createMemo(() => { - return result - .map((r, idx) => `data${idx + 1}: ${r.data ?? 'null'}`) - .join(' ') - }) - const isFetching = createMemo(() => result.some((r) => r.isFetching)) return (
-
{text()}
+
+ data1: {String(result[0]?.data ?? 'null')}, data2:{' '} + {String(result[1]?.data ?? 'null')} +
isFetching: {String(isFetching())}
@@ -320,17 +316,17 @@ describe('useQueries', () => { )) - await waitFor(() => screen.getByText('data1: 5 data2: 10')) + await waitFor(() => screen.getByText('data1: 5, data2: 10')) fireEvent.click(screen.getByRole('button', { name: /set1Disabled/i })) - await waitFor(() => screen.getByText('data1: 10')) + await waitFor(() => screen.getByText('data1: 10, data2: null')) await waitFor(() => screen.getByText('isFetching: false')) fireEvent.click(screen.getByRole('button', { name: /set2Enabled/i })) - await waitFor(() => screen.getByText('data1: 5 data2: 10')) + await waitFor(() => screen.getByText('data1: 5, data2: 10')) await waitFor(() => screen.getByText('isFetching: false')) - await waitFor(() => expect(states.length).toBe(5)) + await waitFor(() => expect(states.length).toBe(6)) expect(states[0]).toMatchObject([ { @@ -358,6 +354,10 @@ describe('useQueries', () => { { status: 'success', data: 10, isPreviousData: false, isFetching: false }, ]) expect(states[4]).toMatchObject([ + { status: 'success', data: 5, isPreviousData: false, isFetching: true }, + { status: 'success', data: 10, isPreviousData: false, isFetching: false }, + ]) + expect(states[5]).toMatchObject([ { status: 'success', data: 5, isPreviousData: false, isFetching: false }, { status: 'success', data: 10, isPreviousData: false, isFetching: false }, ]) From ab549c61ad177f809bb2666b2cad10327da53aca Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 14:44:43 -0400 Subject: [PATCH 204/221] almost all create mutation tests passing --- .../src/__tests__/createMutation.test.tsx | 508 +++++++++++------- 1 file changed, 309 insertions(+), 199 deletions(-) diff --git a/packages/solid-query/src/__tests__/createMutation.test.tsx b/packages/solid-query/src/__tests__/createMutation.test.tsx index c8807dd70bf..f2bcb55eb35 100644 --- a/packages/solid-query/src/__tests__/createMutation.test.tsx +++ b/packages/solid-query/src/__tests__/createMutation.test.tsx @@ -1,13 +1,26 @@ -import { fireEvent, waitFor } from 'solid-testing-library' - -import { QueryClient, createMutation, QueryCache, MutationCache } from '..' +import { fireEvent, render, waitFor, screen } from 'solid-testing-library' +import '@testing-library/jest-dom' +import { + QueryClient, + createMutation, + QueryCache, + MutationCache, + QueryClientProvider, +} from '..' import { CreateMutationResult } from '../types' import { createQueryClient, mockNavigatorOnLine, sleep, } from '../../../../tests/utils' -import { renderWithClient, queryKey, setActTimeout } from './utils' +import { queryKey, setActTimeout } from './utils' +import { + createContext, + createEffect, + createRenderEffect, + createSignal, + ErrorBoundary, +} from 'solid-js' describe('useMutation', () => { const queryCache = new QueryCache() @@ -16,41 +29,41 @@ describe('useMutation', () => { it('should be able to reset `data`', async () => { function Page() { - const { - mutate, - data = 'empty', - reset, - } = createMutation(() => Promise.resolve('mutation')) + const mutation = createMutation(() => Promise.resolve('mutation')) return (
-

{data}

- - +

{mutation.data ?? 'empty'}

+ +
) } - const { getByRole } = renderWithClient(queryClient, ) + render(() => ( + + + + )) - expect(getByRole('heading').textContent).toBe('empty') + expect(screen.getByRole('heading').textContent).toBe('empty') - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('mutation') + expect(screen.getByRole('heading').textContent).toBe('mutation') }) - fireEvent.click(getByRole('button', { name: /reset/i })) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('empty') + expect(screen.getByRole('heading').textContent).toBe('empty') }) }) it('should be able to reset `error`', async () => { function Page() { - const { mutate, error, reset } = createMutation(() => { + const mutation = createMutation(() => { const err = new Error('Expected mock error. All is well!') err.stack = '' return Promise.reject(err) @@ -58,41 +71,45 @@ describe('useMutation', () => { return (
- {error &&

{error.message}

} - - + {mutation.error &&

{mutation.error.message}

} + +
) } - const { getByRole, queryByRole } = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => { - expect(queryByRole('heading')).toBeNull() + expect(screen.queryByRole('heading')).toBeNull() }) - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe( + expect(screen.getByRole('heading').textContent).toBe( 'Expected mock error. All is well!', ) }) - fireEvent.click(getByRole('button', { name: /reset/i })) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) await waitFor(() => { - expect(queryByRole('heading')).toBeNull() + expect(screen.queryByRole('heading')).toBeNull() }) }) it('should be able to call `onSuccess` and `onSettled` after each successful mutate', async () => { - let count = 0 + let [count, setCount] = createSignal(0) const onSuccessMock = jest.fn() const onSettledMock = jest.fn() function Page() { - const { mutate } = createMutation( + const mutation = createMutation( (vars: { count: number }) => Promise.resolve(vars.count), { onSuccess: (data) => { @@ -106,22 +123,33 @@ describe('useMutation', () => { return (
-

{count}

- +

{count()}

+
) } - const { getByRole } = renderWithClient(queryClient, ) + render(() => ( + + + + )) - expect(getByRole('heading').textContent).toBe('0') + expect(screen.getByRole('heading').textContent).toBe('0') - fireEvent.click(getByRole('button', { name: /mutate/i })) - fireEvent.click(getByRole('button', { name: /mutate/i })) - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('3') + expect(screen.getByRole('heading').textContent).toBe('3') }) await waitFor(() => { @@ -144,10 +172,10 @@ describe('useMutation', () => { it('should be able to call `onError` and `onSettled` after each failed mutate', async () => { const onErrorMock = jest.fn() const onSettledMock = jest.fn() - let count = 0 + let [count, setCount] = createSignal(0) function Page() { - const { mutate } = createMutation( + const mutation = createMutation( (vars: { count: number }) => { const error = new Error( `Expected mock error. All is well! ${vars.count}`, @@ -167,22 +195,33 @@ describe('useMutation', () => { return (
-

{count}

- +

{count()}

+
) } - const { getByRole } = renderWithClient(queryClient, ) + render(() => ( + + + + )) - expect(getByRole('heading').textContent).toBe('0') + expect(screen.getByRole('heading').textContent).toBe('0') - fireEvent.click(getByRole('button', { name: /mutate/i })) - fireEvent.click(getByRole('button', { name: /mutate/i })) - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('3') + expect(screen.getByRole('heading').textContent).toBe('3') }) await waitFor(() => { @@ -216,7 +255,7 @@ describe('useMutation', () => { const callbacks: string[] = [] function Page() { - const { mutateAsync } = createMutation(async (text: string) => text, { + const mutation = createMutation(async (text: string) => text, { onSuccess: async () => { callbacks.push('useMutation.onSuccess') }, @@ -225,7 +264,8 @@ describe('useMutation', () => { }, }) - React.useEffect(() => { + createEffect(() => { + const { mutateAsync } = mutation setActTimeout(async () => { try { const result = await mutateAsync('todo', { @@ -239,12 +279,16 @@ describe('useMutation', () => { callbacks.push(`mutateAsync.result:${result}`) } catch {} }, 10) - }, [mutateAsync]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -261,7 +305,7 @@ describe('useMutation', () => { const callbacks: string[] = [] function Page() { - const { mutateAsync } = createMutation( + const mutation = createMutation( async (_text: string) => Promise.reject('oops'), { onError: async () => { @@ -273,7 +317,8 @@ describe('useMutation', () => { }, ) - React.useEffect(() => { + createEffect(() => { + const { mutateAsync } = mutation setActTimeout(async () => { try { await mutateAsync('todo', { @@ -288,12 +333,16 @@ describe('useMutation', () => { callbacks.push(`mutateAsync.error:${error}`) } }, 10) - }, [mutateAsync]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -309,7 +358,7 @@ describe('useMutation', () => { it('should be able to use mutation defaults', async () => { const key = queryKey() - queryClient.setMutationDefaults(key, { + queryClient.setMutationDefaults(key(), { mutationFn: async (text: string) => { await sleep(10) return text @@ -319,22 +368,27 @@ describe('useMutation', () => { const states: CreateMutationResult[] = [] function Page() { - const state = createMutation(key) + const mutation = createMutation(key()) - states.push(state) - - const { mutate } = state + createRenderEffect(() => { + states.push({ ...mutation }) + }) - React.useEffect(() => { + createEffect(() => { + const { mutate } = mutation setActTimeout(() => { mutate('todo') }, 10) - }, [mutate]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -348,7 +402,7 @@ describe('useMutation', () => { let count = 0 function Page() { - const { mutate } = createMutation( + const mutation = createMutation( (_text: string) => { count++ return Promise.reject('oops') @@ -359,16 +413,21 @@ describe('useMutation', () => { }, ) - React.useEffect(() => { + createEffect(() => { + const { mutate } = mutation setActTimeout(() => { mutate('todo') }, 10) - }, [mutate]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(100) @@ -396,27 +455,33 @@ describe('useMutation', () => {
- error:{' '} - {mutation.error instanceof Error ? mutation.error.message : 'null'}, - status: {mutation.status}, isPaused: {String(mutation.isPaused)} + {`error: ${ + mutation.error instanceof Error ? mutation.error.message : 'null' + }, status: ${mutation.status}, isPaused: ${String( + mutation.isPaused, + )}`}
) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) await waitFor(() => { expect( - rendered.getByText('error: null, status: idle, isPaused: false'), + screen.getByText('error: null, status: idle, isPaused: false'), ).toBeInTheDocument() }) - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { expect( - rendered.getByText('error: null, status: loading, isPaused: true'), + screen.getByText('error: null, status: loading, isPaused: true'), ).toBeInTheDocument() }) @@ -429,7 +494,7 @@ describe('useMutation', () => { await waitFor(() => { expect( - rendered.getByText('error: oops, status: error, isPaused: false'), + screen.getByText('error: oops, status: error, isPaused: false'), ).toBeInTheDocument() }) @@ -466,13 +531,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: null, status: idle, isPaused: false') + await screen.findByText('data: null, status: idle, isPaused: false') - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) - await rendered.findByText('data: null, status: loading, isPaused: true') + await screen.findByText('data: null, status: loading, isPaused: true') expect(onMutate).toHaveBeenCalledTimes(1) expect(onMutate).toHaveBeenCalledWith('todo') @@ -480,7 +549,7 @@ describe('useMutation', () => { onlineMock.mockReturnValue(true) window.dispatchEvent(new Event('online')) - await rendered.findByText('data: 1, status: success, isPaused: false') + await screen.findByText('data: 1, status: success, isPaused: false') expect(onMutate).toHaveBeenCalledTimes(1) expect(count).toBe(1) @@ -500,7 +569,9 @@ describe('useMutation', () => { return count }) - states.push(`${mutation.status}, ${mutation.isPaused}`) + createRenderEffect(() => { + states.push(`${mutation.status}, ${mutation.isPaused}`) + }) return (
@@ -513,13 +584,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: null, status: idle, isPaused: false') + await screen.findByText('data: null, status: idle, isPaused: false') - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) - await rendered.findByText('data: null, status: loading, isPaused: true') + await screen.findByText('data: null, status: loading, isPaused: true') // no intermediate 'loading, false' state is expected because we don't start mutating! expect(states[0]).toBe('idle, false') @@ -528,7 +603,7 @@ describe('useMutation', () => { onlineMock.mockReturnValue(true) window.dispatchEvent(new Event('online')) - await rendered.findByText('data: 1, status: success, isPaused: false') + await screen.findByText('data: 1, status: success, isPaused: false') onlineMock.mockRestore() }) @@ -540,7 +615,7 @@ describe('useMutation', () => { const states: CreateMutationResult[] = [] function Page() { - const state = createMutation( + const mutation = createMutation( async (_text: string) => { await sleep(1) count++ @@ -553,20 +628,25 @@ describe('useMutation', () => { }, ) - states.push(state) - - const { mutate } = state + createRenderEffect(() => { + states.push({ ...mutation }) + }) - React.useEffect(() => { + createEffect(() => { + const { mutate } = mutation setActTimeout(() => { mutate('todo') }, 10) - }, [mutate]) + }) return null } - renderWithClient(queryClient, ) + render(() => ( + + + + )) await sleep(50) @@ -615,27 +695,31 @@ describe('useMutation', () => { it('should not change state if unmounted', async () => { function Mutates() { - const { mutate } = createMutation(() => sleep(10)) - return + const mutation = createMutation(() => sleep(10)) + return } function Page() { - const [mounted, setMounted] = React.useState(true) + const [mounted, setMounted] = createSignal(true) return (
- {mounted && } + {mounted() && }
) } - const { getByText } = renderWithClient(queryClient, ) - fireEvent.click(getByText('mutate')) - fireEvent.click(getByText('unmount')) + render(() => ( + + + + )) + fireEvent.click(screen.getByText('mutate')) + fireEvent.click(screen.getByText('unmount')) }) it('should be able to throw an error when useErrorBoundary is set to true', async () => { function Page() { - const { mutate } = createMutation( + const mutation = createMutation( () => { const err = new Error('Expected mock error. All is well!') err.stack = '' @@ -646,35 +730,36 @@ describe('useMutation', () => { return (
- +
) } - const { getByText, queryByText } = renderWithClient( - queryClient, - ( -
- error -
- )} - > - -
, - ) + render(() => ( + + ( +
+ error +
+ )} + > + +
+
+ )) - fireEvent.click(getByText('mutate')) + fireEvent.click(screen.getByText('mutate')) await waitFor(() => { - expect(queryByText('error')).not.toBeNull() + expect(screen.queryByText('error')).not.toBeNull() }) }) it('should be able to throw an error when useErrorBoundary is a function that returns true', async () => { let boundary = false function Page() { - const { mutate, error } = createMutation( + const mutation = createMutation( () => { const err = new Error('mock error') err.stack = '' @@ -690,35 +775,36 @@ describe('useMutation', () => { return (
- - {error && error.message} + + {mutation.error && mutation.error.message}
) } - const { getByText, queryByText } = renderWithClient( - queryClient, - ( -
- error boundary -
- )} - > - -
, - ) + render(() => ( + + ( +
+ error boundary +
+ )} + > + +
+
+ )) // first error goes to component - fireEvent.click(getByText('mutate')) + fireEvent.click(screen.getByText('mutate')) await waitFor(() => { - expect(queryByText('mock error')).not.toBeNull() + expect(screen.queryByText('mock error')).not.toBeNull() }) // second error goes to boundary - fireEvent.click(getByText('mutate')) + fireEvent.click(screen.getByText('mutate')) await waitFor(() => { - expect(queryByText('error boundary')).not.toBeNull() + expect(screen.queryByText('error boundary')).not.toBeNull() }) }) @@ -741,10 +827,10 @@ describe('useMutation', () => { const metaErrorMessage = 'mutation failed' function Page() { - const { mutate: succeed, isSuccess } = createMutation(async () => '', { + const mutationSucceed = createMutation(async () => '', { meta: { metaSuccessMessage }, }) - const { mutate: error, isError } = createMutation( + const mutationError = createMutation( async () => { throw new Error('') }, @@ -755,25 +841,26 @@ describe('useMutation', () => { return (
- - - {isSuccess &&
successTest
} - {isError &&
errorTest
} + + + {mutationSucceed.isSuccess &&
successTest
} + {mutationError.isError &&
errorTest
}
) } - const { getByText, queryByText } = renderWithClient( - queryClientMutationMeta, - , - ) + render(() => ( + + + + )) - fireEvent.click(getByText('succeed')) - fireEvent.click(getByText('error')) + fireEvent.click(screen.getByText('succeed')) + fireEvent.click(screen.getByText('error')) await waitFor(() => { - expect(queryByText('successTest')).not.toBeNull() - expect(queryByText('errorTest')).not.toBeNull() + expect(screen.queryByText('successTest')).not.toBeNull() + expect(screen.queryByText('errorTest')).not.toBeNull() }) expect(successMock).toHaveBeenCalledTimes(1) @@ -791,11 +878,11 @@ describe('useMutation', () => { let count = 0 function Page() { - const [show, setShow] = React.useState(true) + const [show, setShow] = createSignal(true) return (
- {show && } + {show() && }
) } @@ -808,7 +895,7 @@ describe('useMutation', () => { return count }, { - mutationKey, + mutationKey: mutationKey(), cacheTime: 0, onSuccess, onSettled, @@ -835,16 +922,20 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: null, status: idle, isPaused: false') + await screen.findByText('data: null, status: idle, isPaused: false') - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) - fireEvent.click(rendered.getByRole('button', { name: /hide/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /hide/i })) await waitFor(() => { expect( - queryClient.getMutationCache().findAll({ mutationKey }), + queryClient.getMutationCache().findAll({ mutationKey: mutationKey() }), ).toHaveLength(0) }) @@ -858,43 +949,45 @@ describe('useMutation', () => { describe('with custom context', () => { it('should be able to reset `data`', async () => { - const context = React.createContext(undefined) + const context = createContext(undefined) function Page() { - const { - mutate, - data = 'empty', - reset, - } = createMutation(() => Promise.resolve('mutation'), { context }) + const mutation = createMutation(() => Promise.resolve('mutation'), { + context, + }) return (
-

{data}

- - +

{mutation.data ?? 'empty'}

+ +
) } - const { getByRole } = renderWithClient(queryClient, , { context }) + render(() => ( + + + + )) - expect(getByRole('heading').textContent).toBe('empty') + expect(screen.getByRole('heading').textContent).toBe('empty') - fireEvent.click(getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('mutation') + expect(screen.getByRole('heading').textContent).toBe('mutation') }) - fireEvent.click(getByRole('button', { name: /reset/i })) + fireEvent.click(screen.getByRole('button', { name: /reset/i })) await waitFor(() => { - expect(getByRole('heading').textContent).toBe('empty') + expect(screen.getByRole('heading').textContent).toBe('empty') }) }) it('should throw if the context is not passed to useMutation', async () => { - const context = React.createContext(undefined) + const context = createContext(undefined) function Page() { const { data = '' } = createMutation(() => Promise.resolve('mutation')) @@ -906,15 +999,16 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient( - queryClient, -
error boundary
}> - -
, - { context }, - ) + render(() => ( + +
error boundary
}> + +
+ , +
+ )) - await waitFor(() => rendered.getByText('error boundary')) + await waitFor(() => screen.getByText('error boundary')) }) }) @@ -957,14 +1051,18 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('data: null, status: idle') + await screen.findByText('data: null, status: idle') - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) + fireEvent.click(screen.getByRole('button', { name: /mutate/i })) - await rendered.findByText('data: result2, status: success') + await screen.findByText('data: result2, status: success') expect(count).toBe(2) @@ -1005,13 +1103,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('status: idle') + await screen.findByText('status: idle') - rendered.getByRole('button', { name: /mutate/i }).click() + screen.getByRole('button', { name: /mutate/i }).click() - await rendered.findByText('status: error') + await screen.findByText('status: error') expect(onError).toHaveBeenCalledWith(error, 'todo', undefined) }) @@ -1043,13 +1145,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('error: null, status: idle') + await screen.findByText('error: null, status: idle') - rendered.getByRole('button', { name: /mutate/i }).click() + screen.getByRole('button', { name: /mutate/i }).click() - await rendered.findByText('error: mutateFnError, status: error') + await screen.findByText('error: mutateFnError, status: error') }) it('should go to error state if onSettled callback errors', async () => { @@ -1081,13 +1187,17 @@ describe('useMutation', () => { ) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - await rendered.findByText('error: null, status: idle') + await screen.findByText('error: null, status: idle') - rendered.getByRole('button', { name: /mutate/i }).click() + screen.getByRole('button', { name: /mutate/i }).click() - await rendered.findByText('error: mutateFnError, status: error') + await screen.findByText('error: mutateFnError, status: error') expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined) }) From b6336ef728fff78b8225947b205858ba18273820 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 13:52:20 -0400 Subject: [PATCH 205/221] most infinite query tests passing --- .../__tests__/createInfiniteQuery.test.tsx | 589 ++++++++++-------- 1 file changed, 334 insertions(+), 255 deletions(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index 7eced5591f7..1c874f8c198 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -11,7 +11,16 @@ import { InfiniteData, QueryClientProvider, } from '..' -import { createEffect, createRenderEffect, createSignal } from 'solid-js' +import { + createEffect, + createRenderEffect, + createSignal, + For, + Index, + Match, + on, + Switch, +} from 'solid-js' interface Result { items: number[] @@ -197,9 +206,11 @@ describe('useInfiniteQuery', () => { }, ) - createRenderEffect(() => { - states.push({ ...state }) - }) + createRenderEffect( + on([() => ({ ...state }), order], () => { + states.push({ ...state }) + }), + ) return (
@@ -225,7 +236,7 @@ describe('useInfiniteQuery', () => { await waitFor(() => screen.getByText('data: 0-asc')) await waitFor(() => screen.getByText('isFetching: false')) - await waitFor(() => expect(states.length).toBe(7)) + await waitFor(() => expect(states.length).toBe(6)) expect(states[0]).toMatchObject({ data: undefined, @@ -263,15 +274,7 @@ describe('useInfiniteQuery', () => { isSuccess: true, isPreviousData: true, }) - // Hook state update expect(states[5]).toMatchObject({ - data: { pages: ['0-desc', '1-desc'] }, - isFetching: true, - isFetchingNextPage: false, - isSuccess: true, - isPreviousData: true, - }) - expect(states[6]).toMatchObject({ data: { pages: ['0-asc'] }, isFetching: false, isFetchingNextPage: false, @@ -713,12 +716,12 @@ describe('useInfiniteQuery', () => { const states: CreateInfiniteQueryResult[] = [] function Page() { - const multiplier = React.useRef(1) + let multiplier = 1 const state = createInfiniteQuery( key, async ({ pageParam = 10 }) => { await sleep(10) - return Number(pageParam) * multiplier.current + return Number(pageParam) * multiplier }, { getNextPageParam: (lastPage) => lastPage + 1, @@ -726,14 +729,16 @@ describe('useInfiniteQuery', () => { }, ) - states.push(state) + createRenderEffect(() => { + states.push({ ...state }) + }) return (
+ +
- ))} -
- - - -
-
{!isFetchingNextPage ? 'Background Updating...' : null}
- - )} +
+ {!state.isFetchingNextPage ? 'Background Updating...' : null} +
+ + } + > + Loading... + + Error: {state.error!.message} + +
) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('Loading...') + screen.getByText('Loading...') - await waitFor(() => rendered.getByText('Item: 2')) - await waitFor(() => rendered.getByText('Page 0: 0')) + await waitFor(() => screen.getByText('Item: 2')) + await waitFor(() => screen.getByText('Page 0: 0')) - fireEvent.click(rendered.getByText('Load More')) + fireEvent.click(screen.getByText('Load More')) - await waitFor(() => rendered.getByText('Loading more...')) - await waitFor(() => rendered.getByText('Item: 5')) - await waitFor(() => rendered.getByText('Page 0: 0')) - await waitFor(() => rendered.getByText('Page 1: 1')) + await waitFor(() => screen.getByText('Loading more...')) + await waitFor(() => screen.getByText('Item: 5')) + await waitFor(() => screen.getByText('Page 0: 0')) + await waitFor(() => screen.getByText('Page 1: 1')) - fireEvent.click(rendered.getByText('Load More')) + fireEvent.click(screen.getByText('Load More')) - await waitFor(() => rendered.getByText('Loading more...')) - await waitFor(() => rendered.getByText('Item: 8')) - await waitFor(() => rendered.getByText('Page 0: 0')) - await waitFor(() => rendered.getByText('Page 1: 1')) - await waitFor(() => rendered.getByText('Page 2: 2')) + await waitFor(() => screen.getByText('Loading more...')) + await waitFor(() => screen.getByText('Item: 8')) + await waitFor(() => screen.getByText('Page 0: 0')) + await waitFor(() => screen.getByText('Page 1: 1')) + await waitFor(() => screen.getByText('Page 2: 2')) - fireEvent.click(rendered.getByText('Refetch')) + fireEvent.click(screen.getByText('Refetch')) - await waitFor(() => rendered.getByText('Background Updating...')) - await waitFor(() => rendered.getByText('Item: 8')) - await waitFor(() => rendered.getByText('Page 0: 3')) - await waitFor(() => rendered.getByText('Page 1: 4')) - await waitFor(() => rendered.getByText('Page 2: 5')) + await waitFor(() => screen.getByText('Background Updating...')) + await waitFor(() => screen.getByText('Item: 8')) + await waitFor(() => screen.getByText('Page 0: 3')) + await waitFor(() => screen.getByText('Page 1: 4')) + await waitFor(() => screen.getByText('Page 2: 5')) // ensure that Item: 4 is rendered before removing it - expect(rendered.queryAllByText('Item: 4')).toHaveLength(1) + expect(screen.queryAllByText('Item: 4')).toHaveLength(1) // remove Item: 4 - fireEvent.click(rendered.getByText('Remove item')) + fireEvent.click(screen.getByText('Remove item')) - await waitFor(() => rendered.getByText('Background Updating...')) + await waitFor(() => screen.getByText('Background Updating...')) // ensure that an additional item is rendered (it means that cursors were properly rebuilt) - await waitFor(() => rendered.getByText('Item: 9')) - await waitFor(() => rendered.getByText('Page 0: 6')) - await waitFor(() => rendered.getByText('Page 1: 7')) - await waitFor(() => rendered.getByText('Page 2: 8')) + await waitFor(() => screen.getByText('Item: 9')) + await waitFor(() => screen.getByText('Page 0: 6')) + await waitFor(() => screen.getByText('Page 1: 7')) + await waitFor(() => screen.getByText('Page 2: 8')) // ensure that Item: 4 is no longer rendered - expect(rendered.queryAllByText('Item: 4')).toHaveLength(0) + expect(screen.queryAllByText('Item: 4')).toHaveLength(0) }) it('should compute hasNextPage correctly for falsy getFetchMore return value on refetching', async () => { @@ -1652,25 +1727,16 @@ describe('useInfiniteQuery', () => { const MAX = 2 function Page() { - const fetchCountRef = React.useRef(0) + let fetchCountRef = 0 const [isRemovedLastPage, setIsRemovedLastPage] = - React.useState(false) - const { - status, - data, - error, - isFetching, - isFetchingNextPage, - fetchNextPage, - hasNextPage, - refetch, - } = createInfiniteQuery( + createSignal(false) + const state = createInfiniteQuery( key, ({ pageParam = 0 }) => fetchItems( pageParam, - fetchCountRef.current++, - pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage), + fetchCountRef++, + pageParam === MAX || (pageParam === MAX - 1 && isRemovedLastPage()), ), { getNextPageParam: (lastPage) => lastPage.nextId, @@ -1680,101 +1746,112 @@ describe('useInfiniteQuery', () => { return (

Pagination

- {status === 'loading' ? ( - 'Loading...' - ) : status === 'error' ? ( - Error: {error.message} - ) : ( - <> -
Data:
- {data.pages.map((page, i) => ( -
-
- Page {i}: {page.ts} -
-
- {page.items.map((item) => ( -

Item: {item}

- ))} -
+ +
Data:
+ + {(page, i) => ( +
+
+ Page {i()}: {page.ts} +
+
+ + {(item) =>

Item: {item()}

} +
+
+
+ )} +
+
+ + + +
+
+ {state.isFetching && !state.isFetchingNextPage + ? 'Background Updating...' + : null}
- ))} -
- - - -
-
- {isFetching && !isFetchingNextPage - ? 'Background Updating...' - : null} -
- - )} + + } + > + Loading... + + Error: {state.error!.message} + +
) } - const rendered = renderWithClient(queryClient, ) + render(() => ( + + + + )) - rendered.getByText('Loading...') + screen.getByText('Loading...') await waitFor(() => { - rendered.getByText('Item: 9') - rendered.getByText('Page 0: 0') + screen.getByText('Item: 9') + screen.getByText('Page 0: 0') }) - fireEvent.click(rendered.getByText('Load More')) + fireEvent.click(screen.getByText('Load More')) - await waitFor(() => rendered.getByText('Loading more...')) + await waitFor(() => screen.getByText('Loading more...')) await waitFor(() => { - rendered.getByText('Item: 19') - rendered.getByText('Page 0: 0') - rendered.getByText('Page 1: 1') + screen.getByText('Item: 19') + screen.getByText('Page 0: 0') + screen.getByText('Page 1: 1') }) - fireEvent.click(rendered.getByText('Load More')) + fireEvent.click(screen.getByText('Load More')) - await waitFor(() => rendered.getByText('Loading more...')) + await waitFor(() => screen.getByText('Loading more...')) await waitFor(() => { - rendered.getByText('Item: 29') - rendered.getByText('Page 0: 0') - rendered.getByText('Page 1: 1') - rendered.getByText('Page 2: 2') + screen.getByText('Item: 29') + screen.getByText('Page 0: 0') + screen.getByText('Page 1: 1') + screen.getByText('Page 2: 2') }) - rendered.getByText('Nothing more to load') + screen.getByText('Nothing more to load') - fireEvent.click(rendered.getByText('Remove Last Page')) + fireEvent.click(screen.getByText('Remove Last Page')) await sleep(10) - fireEvent.click(rendered.getByText('Refetch')) + fireEvent.click(screen.getByText('Refetch')) - await waitFor(() => rendered.getByText('Background Updating...')) + await waitFor(() => screen.getByText('Background Updating...')) await waitFor(() => { - rendered.getByText('Page 0: 3') - rendered.getByText('Page 1: 4') + screen.getByText('Page 0: 3') + screen.getByText('Page 1: 4') }) - expect(rendered.queryByText('Item: 29')).toBeNull() - expect(rendered.queryByText('Page 2: 5')).toBeNull() + expect(screen.queryByText('Item: 29')).toBeNull() + expect(screen.queryByText('Page 2: 5')).toBeNull() - rendered.getByText('Nothing more to load') + screen.getByText('Nothing more to load') }) it('should cancel the query function when there are no more subscriptions', async () => { @@ -1800,14 +1877,16 @@ describe('useInfiniteQuery', () => { ) } - const rendered = renderWithClient( - queryClient, - - - , - ) + render(() => ( + + + + + , + + )) - await waitFor(() => rendered.getByText('off')) + await waitFor(() => screen.getByText('off')) if (typeof AbortSignal === 'function') { expect(cancelFn).toHaveBeenCalled() From 00a9ef5857e3fe53bc98dd4c02fb1f7a6292f372 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 14:00:44 -0400 Subject: [PATCH 206/221] all infinite query tests passing --- .../src/__tests__/createInfiniteQuery.test.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index 1c874f8c198..fd2dbc78c72 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -942,7 +942,7 @@ describe('useInfiniteQuery', () => { let callIndex = 0 const firstCtx = fetchPage.mock.calls[callIndex]![0] expect(firstCtx.pageParam).toBeUndefined() - expect(firstCtx.queryKey).toEqual(key) + expect(firstCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(firstCtx.signal).toBeInstanceOf(AbortSignal) expect(firstCtx.signal?.aborted).toBe(false) @@ -953,7 +953,7 @@ describe('useInfiniteQuery', () => { callIndex = 1 const secondCtx = fetchPage.mock.calls[callIndex]![0] expect(secondCtx.pageParam).toBe(11) - expect(secondCtx.queryKey).toEqual(key) + expect(secondCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(secondCtx.signal).toBeInstanceOf(AbortSignal) expect(secondCtx.signal?.aborted).toBe(true) @@ -964,7 +964,7 @@ describe('useInfiniteQuery', () => { callIndex = 2 const thirdCtx = fetchPage.mock.calls[callIndex]![0] expect(thirdCtx.pageParam).toBe(11) - expect(thirdCtx.queryKey).toEqual(key) + expect(thirdCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(thirdCtx.signal).toBeInstanceOf(AbortSignal) expect(thirdCtx.signal?.aborted).toBe(false) @@ -1028,7 +1028,7 @@ describe('useInfiniteQuery', () => { let callIndex = 0 const firstCtx = fetchPage.mock.calls[callIndex]![0] expect(firstCtx.pageParam).toBeUndefined() - expect(firstCtx.queryKey).toEqual(key) + expect(firstCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(firstCtx.signal).toBeInstanceOf(AbortSignal) expect(firstCtx.signal?.aborted).toBe(false) @@ -1039,7 +1039,7 @@ describe('useInfiniteQuery', () => { callIndex = 1 const secondCtx = fetchPage.mock.calls[callIndex]![0] expect(secondCtx.pageParam).toBe(11) - expect(secondCtx.queryKey).toEqual(key) + expect(secondCtx.queryKey).toEqual(key()) if (typeof AbortSignal === 'function') { expect(secondCtx.signal).toBeInstanceOf(AbortSignal) expect(secondCtx.signal?.aborted).toBe(false) @@ -1247,7 +1247,7 @@ describe('useInfiniteQuery', () => { const state = createInfiniteQuery( key, - async ({ pageParam = firstPage }) => { + async ({ pageParam = firstPage() }) => { await sleep(10) return Number(pageParam) }, @@ -1882,7 +1882,6 @@ describe('useInfiniteQuery', () => { - , )) From 79c03b25f33ee450576d9f877074817f77afcb8c Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Sun, 18 Sep 2022 14:47:18 -0400 Subject: [PATCH 207/221] format with prettier --- packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index fd2dbc78c72..9ec48129c53 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -2,7 +2,7 @@ import { waitFor, fireEvent, render, screen } from 'solid-testing-library' import { sleep, createQueryClient } from '../../../../tests/utils' -import { renderWithClient, Blink, queryKey, setActTimeout } from './utils' +import { Blink, queryKey, setActTimeout } from './utils' import { createInfiniteQuery, CreateInfiniteQueryResult, From ea7f99cae7b40d8a6c88b3b2e2e25273fdd6fda9 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Sun, 18 Sep 2022 21:09:14 -0400 Subject: [PATCH 208/221] Throw to errorBoundary when options set correctly --- packages/solid-query/src/createMutation.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/solid-query/src/createMutation.ts b/packages/solid-query/src/createMutation.ts index 5214da550c1..df6db80ed76 100644 --- a/packages/solid-query/src/createMutation.ts +++ b/packages/solid-query/src/createMutation.ts @@ -10,8 +10,9 @@ import { CreateMutationOptions, CreateMutationResult, } from './types' -import { createComputed, onCleanup } from 'solid-js' +import { createComputed, onCleanup, on } from 'solid-js' import { createStore } from 'solid-js/store' +import { shouldThrowError } from './utils' // HOOK export function createMutation< @@ -103,6 +104,20 @@ export function createMutation< observer.setOptions(newParsedOptions) }) + createComputed( + on( + () => state.status, + () => { + if ( + state.isError && + shouldThrowError(observer.options.useErrorBoundary, [state.error]) + ) { + throw state.error + } + }, + ), + ) + const unsubscribe = observer.subscribe((result) => { setState({ ...result, From ceef4ac433f3090a6e17235177646f9f1addc1cc Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 10:00:19 -0400 Subject: [PATCH 209/221] fix config file bugs --- packages/solid-query/.eslintrc | 2 +- packages/solid-query/tsconfig.json | 8 +------- packages/solid-query/tsconfig.lint.json | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/solid-query/.eslintrc b/packages/solid-query/.eslintrc index 514261e3fc9..a1437a22aac 100644 --- a/packages/solid-query/.eslintrc +++ b/packages/solid-query/.eslintrc @@ -1,6 +1,6 @@ { "parserOptions": { - "project": "./packages/solid-query/tsconfig.lint.json", + "project": "./tsconfig.lint.json", "sourceType": "module" }, "rules": { diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json index ec95ade5cea..6146a991595 100644 --- a/packages/solid-query/tsconfig.json +++ b/packages/solid-query/tsconfig.json @@ -9,13 +9,7 @@ "jsxImportSource": "solid-js", }, "include": ["src"], - // TODO(lukemurray): if we exclude tests, we get errors about missing react import - // the errors occur because the vscode typescript server only looks at tsconfig.json - // files for type check settings. - // eventually we should remove `jsx: react` from tsconfig.base.json - // but that will require adding `jsx: react` to all package level tsconfig.json - // so lets wait. - // "exclude": ["src/__tests__"], + "exclude": ["src/__tests__"], "references": [ { "path": "../query-core" } ] diff --git a/packages/solid-query/tsconfig.lint.json b/packages/solid-query/tsconfig.lint.json index 0fb829ee95a..8a91fbbc20b 100644 --- a/packages/solid-query/tsconfig.lint.json +++ b/packages/solid-query/tsconfig.lint.json @@ -6,7 +6,7 @@ "outDir": "./build/lib", "tsBuildInfoFile": "./build/.tsbuildinfo", "jsx": "preserve", - "jsxImportSource": "solid-js", + "jsxImportSource": "solid-js" }, "include": ["src"], "references": [ From ffd2e9331341a8610ea8a6c5dd6baed2aec10d16 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 10:05:44 -0400 Subject: [PATCH 210/221] fix linting issues --- .../solid-query/src/__tests__/createInfiniteQuery.test.tsx | 2 +- packages/solid-query/src/__tests__/createMutation.test.tsx | 4 ++-- packages/solid-query/tsconfig.json | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx index 9ec48129c53..60794851cea 100644 --- a/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx +++ b/packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx @@ -1750,7 +1750,7 @@ describe('useInfiniteQuery', () => { fallback={ <>
Data:
- + {(page, i) => (
diff --git a/packages/solid-query/src/__tests__/createMutation.test.tsx b/packages/solid-query/src/__tests__/createMutation.test.tsx index f2bcb55eb35..c949e03814f 100644 --- a/packages/solid-query/src/__tests__/createMutation.test.tsx +++ b/packages/solid-query/src/__tests__/createMutation.test.tsx @@ -104,7 +104,7 @@ describe('useMutation', () => { }) it('should be able to call `onSuccess` and `onSettled` after each successful mutate', async () => { - let [count, setCount] = createSignal(0) + const [count, setCount] = createSignal(0) const onSuccessMock = jest.fn() const onSettledMock = jest.fn() @@ -172,7 +172,7 @@ describe('useMutation', () => { it('should be able to call `onError` and `onSettled` after each failed mutate', async () => { const onErrorMock = jest.fn() const onSettledMock = jest.fn() - let [count, setCount] = createSignal(0) + const [count, setCount] = createSignal(0) function Page() { const mutation = createMutation( diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json index 6146a991595..08dd1f61c38 100644 --- a/packages/solid-query/tsconfig.json +++ b/packages/solid-query/tsconfig.json @@ -9,6 +9,7 @@ "jsxImportSource": "solid-js", }, "include": ["src"], + // comment this out to fix errors in tests during development "exclude": ["src/__tests__"], "references": [ { "path": "../query-core" } From a182d689c2640ad60e17e2e82cbf8d027946be57 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 10:32:51 -0400 Subject: [PATCH 211/221] merge solid-query --- package-lock.json | 4 +--- .../src/__tests__/createQueries.test.tsx | 23 +++++++++---------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc57335374d..e5c0a6bf9b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11758,7 +11758,6 @@ }, "node_modules/@types/use-sync-external-store": { "version": "0.0.3", - "dev": true, "license": "MIT" }, "node_modules/@types/yargs": { @@ -50987,8 +50986,7 @@ } }, "@types/use-sync-external-store": { - "version": "0.0.3", - "dev": true + "version": "0.0.3" }, "@types/yargs": { "version": "16.0.4", diff --git a/packages/solid-query/src/__tests__/createQueries.test.tsx b/packages/solid-query/src/__tests__/createQueries.test.tsx index 0e94d748229..98ab7e75a65 100644 --- a/packages/solid-query/src/__tests__/createQueries.test.tsx +++ b/packages/solid-query/src/__tests__/createQueries.test.tsx @@ -295,14 +295,17 @@ describe('useQueries', () => { states.push([...result]) }) + const text = createMemo(() => { + return result + .map((r, idx) => `data${idx + 1}: ${r.data ?? 'null'}`) + .join(' ') + }) + const isFetching = createMemo(() => result.some((r) => r.isFetching)) return (
-
- data1: {String(result[0]?.data ?? 'null')}, data2:{' '} - {String(result[1]?.data ?? 'null')} -
+
{text()}
isFetching: {String(isFetching())}
@@ -316,17 +319,17 @@ describe('useQueries', () => { )) - await waitFor(() => screen.getByText('data1: 5, data2: 10')) + await waitFor(() => screen.getByText('data1: 5 data2: 10')) fireEvent.click(screen.getByRole('button', { name: /set1Disabled/i })) - await waitFor(() => screen.getByText('data1: 10, data2: null')) + await waitFor(() => screen.getByText('data1: 10')) await waitFor(() => screen.getByText('isFetching: false')) fireEvent.click(screen.getByRole('button', { name: /set2Enabled/i })) - await waitFor(() => screen.getByText('data1: 5, data2: 10')) + await waitFor(() => screen.getByText('data1: 5 data2: 10')) await waitFor(() => screen.getByText('isFetching: false')) - await waitFor(() => expect(states.length).toBe(6)) + await waitFor(() => expect(states.length).toBe(5)) expect(states[0]).toMatchObject([ { @@ -354,10 +357,6 @@ describe('useQueries', () => { { status: 'success', data: 10, isPreviousData: false, isFetching: false }, ]) expect(states[4]).toMatchObject([ - { status: 'success', data: 5, isPreviousData: false, isFetching: true }, - { status: 'success', data: 10, isPreviousData: false, isFetching: false }, - ]) - expect(states[5]).toMatchObject([ { status: 'success', data: 5, isPreviousData: false, isFetching: false }, { status: 'success', data: 10, isPreviousData: false, isFetching: false }, ]) From a5b8e07e0a49041cbcee140e7992c7d699b638d1 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 11:28:10 -0400 Subject: [PATCH 212/221] add solid query docs --- docs/adapters/solid-query.md | 158 ++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 2 deletions(-) diff --git a/docs/adapters/solid-query.md b/docs/adapters/solid-query.md index 02048223e57..fb404354148 100644 --- a/docs/adapters/solid-query.md +++ b/docs/adapters/solid-query.md @@ -2,9 +2,163 @@ title: Solid Query (Coming Soon) --- +The `@tanstack/solid-query` package offers a 1st-class API for using TanStack Query via Solid. However, all of the primitives you receive from this API are core APIs that are shared across all of the TanStack Adapters including the Query Client, query results, query subscriptions, etc. -> ⚠️ This module has not yet been developed. It requires an adapter similar to `react-query` to work. We estimate the amount of code to do this is low-to-moderate, but does require familiarity with the SolidJS framework. If you would like to contribute this adapter, please open a PR! +## Example -The `@tanstack/solid-query` package offers a 1st-class API for using TanStack Query via Solid. However, all of the primitives you receive from this API are core APIs that are shared across all of the TanStack Adapters including the Query Client, query results, query subscriptions, etc. +```tsx +import { QueryClient, QueryClientProvider, createQuery } from '@tanstack/solid-query' +import { For } from 'solid-js' + +const queryClient = new QueryClient() + +function Example() { + const query = createQuery(() => ['todos'], fetchTodos) + + return ( +
+ {query.isLoading ? ( + 'Loading...' + ) : query.isError ? ( + 'Error!' + ) : query.data ? ( + {(todo) =>
{todo.title}
}
+ ) : null} +
+ ) +} + +function App() { + return ( + + + + ) +} + +``` + +## Important Differences with React Query + +- Exports follow the solid naming convention `createX` instead of `useX` *unless* the export is used to access `context`. For example, `useQuery` becomes `createQuery`, `useMutation` becomes `createMutation`, but `useQueryClient` is `useQueryClient` because it accesses the `client` from the `QueryClientProvider` context. + +- Query keys passed to `createQuery` and `createQueries` are Accessor functions which return arrays. This change makes it easy to implement reactive query keys. + +```tsx +// ❌ react version +useQuery(["todos"], fetchTodos) + +// ✅ solid version +createQuery(() => ["todos"], fetchTodos) +``` + +> Mutation keys are not accessors. Why? Because it is impossible to differentiate the `createMutation` overloads `createMutation(mutationFn, options)` and `createMutation(mutationKey, options)` if the mutation key is an accessor function. +> If you need reactivity in a mutaton key you can pass the mutation key in options using an object getter. +> ```tsx +> createMutation(updateTodos, { +> get mutationKey() { +> return ["todos"] +> } +> }) +> ``` + +- Solid Query does not export a `QueryErrorResetBoundary`. Instead wrap your components in a solid ``. + +- `createQuery` does not support destructuring outside of a reactive context. The return value of `createQuery` is a store, and accessing values in the store is only reactive in a reactive context. + +```tsx +import { QueryClient, QueryClientProvider, createQuery } from '@tanstack/solid-query' +import { Match, Switch } from 'solid-js' + +const queryClient = new QueryClient() + +export default function App() { + return ( + + + + ) +} + +function Example() { + // ❌ react version -- supports destructing outside reactive context + // const { isLoading, error, data } = useQuery(['repoData'], () => + // fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res => + // res.json() + // ) + // ) + + // ✅ solid version -- does not support destructuring outside reactive context + const query = createQuery( + () => ['repoData'], + () => + fetch('https://api.github.com/repos/tannerlinsley/react-query').then( + (res) => res.json(), + ), + ) + + // ✅ access query properties in JSX reactive context + return ( + + Loading... + Error: {query.error.message} + +
+

{query.data.name}

+

{query.data.description}

+ 👀 {query.data.subscribers_count}{' '} + ✨ {query.data.stargazers_count}{' '} + 🍴 {query.data.forks_count} +
+
+
+ ) +} +``` + +- If you want options to be reactive you need to pass them using object getter syntax. + +```tsx +import { + QueryClient, + QueryClientProvider, + createQuery, +} from '@tanstack/solid-query' +import { createSignal, For } from 'solid-js' + +const queryClient = new QueryClient() + +function Example() { + const [enabled, setEnabled] = createSignal(false) + const query = createQuery(() => ['todos'], fetchTodos, { + // ❌ passing a signal directly is not reactive + // enabled: enabled(), + + // ✅ passing a function that returns a signal is reactive + get enabled() { + return enabled() + }, + }) + return ( +
+ {query.isLoading ? ( + 'Loading...' + ) : query.isError ? ( + 'Error!' + ) : query.data ? ( + {(todo) =>
{todo.title}
}
+ ) : null} + +
+ ) +} +function App() { + return ( + + + + ) +} +``` \ No newline at end of file From c510ea91aa92bea4f6e43a9bd846cf60d675bbe9 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 11:42:39 -0400 Subject: [PATCH 213/221] update docs --- docs/adapters/solid-query.md | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/docs/adapters/solid-query.md b/docs/adapters/solid-query.md index fb404354148..388d5fdd360 100644 --- a/docs/adapters/solid-query.md +++ b/docs/adapters/solid-query.md @@ -40,6 +40,8 @@ function App() { ## Important Differences with React Query +In general solid query follows the same API as React Query, but there are some important differences to be aware of. Keep these in mind as you read the tanstack query documentation. + - Exports follow the solid naming convention `createX` instead of `useX` *unless* the export is used to access `context`. For example, `useQuery` becomes `createQuery`, `useMutation` becomes `createMutation`, but `useQueryClient` is `useQueryClient` because it accesses the `client` from the `QueryClientProvider` context. - Query keys passed to `createQuery` and `createQueries` are Accessor functions which return arrays. This change makes it easy to implement reactive query keys. @@ -53,9 +55,10 @@ createQuery(() => ["todos"], fetchTodos) ``` > Mutation keys are not accessors. Why? Because it is impossible to differentiate the `createMutation` overloads `createMutation(mutationFn, options)` and `createMutation(mutationKey, options)` if the mutation key is an accessor function. -> If you need reactivity in a mutaton key you can pass the mutation key in options using an object getter. +> If you need reactivity in a mutation key you can pass the mutation key as an option with an object getter. > ```tsx > createMutation(updateTodos, { +> // ✅ reactive mutation key passed as an object getter > get mutationKey() { > return ["todos"] > } @@ -116,7 +119,7 @@ function Example() { } ``` -- If you want options to be reactive you need to pass them using object getter syntax. +- If you want options to be reactive you need to pass them using object getter syntax. This may look strange at first but it leads to more idiomatic solid code. ```tsx import { @@ -161,4 +164,27 @@ function App() { ) } -``` \ No newline at end of file +``` + +- You do not need to provide `suspense: true` to query options. Suspense works for queries out of the box if you access the query data in a `` context. + + +```tsx +import { For, Suspense } from 'solid-js' + +function Example() { + const query = createQuery(() => ['todos'], fetchTodos) + return ( +
+ {/* ✅ Will trigger loading fallback, data accessed in a suspense context. */} + + {(todo) =>
{todo.title}
}
+
+ {/* ❌ Will not trigger loading fallback, data not accessed in a suspense context. */} + {(todo) =>
{todo.title}
}
+
+ ) +} +``` + +- Property tracking is handled through solid's fine grained reactivity, so `notifyOnChange` options are not used. \ No newline at end of file From 7c284f61172474d6b97ae545939b5d99cde4aa23 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 11:49:21 -0400 Subject: [PATCH 214/221] update solid-query version in examples --- .../basic-graphql-request/package-lock.json | 1063 +++-------------- .../solid/basic-graphql-request/package.json | 2 +- .../solid/basic-typescript/package-lock.json | 974 ++------------- examples/solid/basic-typescript/package.json | 2 +- .../default-query-function/package-lock.json | 974 ++------------- .../solid/default-query-function/package.json | 2 +- examples/solid/simple/package-lock.json | 974 ++------------- examples/solid/simple/package.json | 2 +- 8 files changed, 490 insertions(+), 3503 deletions(-) diff --git a/examples/solid/basic-graphql-request/package-lock.json b/examples/solid/basic-graphql-request/package-lock.json index 58fcf3c6d22..b684263cd6b 100644 --- a/examples/solid/basic-graphql-request/package-lock.json +++ b/examples/solid/basic-graphql-request/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "@tanstack/solid-query": "^4.2.3", + "@tanstack/solid-query": "^4.3.0-beta.4", "graphql": "^16.6.0", "graphql-request": "^5.0.0", "solid-js": "^1.5.1" @@ -21,11 +21,10 @@ } }, ".yalc/@tanstack/solid-query": { - "version": "4.2.3", - "extraneous": true, + "version": "4.3.0-beta.4", "license": "MIT", "dependencies": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" }, "funding": { "type": "github", @@ -37,9 +36,8 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -50,9 +48,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -62,18 +59,16 @@ }, "node_modules/@babel/compat-data": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", - "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", - "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", @@ -101,9 +96,8 @@ }, "node_modules/@babel/generator": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.19.0", "@jridgewell/gen-mapping": "^0.3.2", @@ -115,9 +109,8 @@ }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -129,9 +122,8 @@ }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -141,9 +133,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", - "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.19.0", "@babel/helper-validator-option": "^7.18.6", @@ -159,9 +150,8 @@ }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", @@ -180,18 +170,16 @@ }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" @@ -202,9 +190,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -214,9 +201,8 @@ }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.9" }, @@ -226,9 +212,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -238,9 +223,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", @@ -257,9 +241,8 @@ }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -269,18 +252,16 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", - "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-member-expression-to-functions": "^7.18.9", @@ -294,9 +275,8 @@ }, "node_modules/@babel/helper-simple-access": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -306,9 +286,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -318,36 +297,32 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.19.0", @@ -359,9 +334,8 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -373,9 +347,8 @@ }, "node_modules/@babel/parser": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", - "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -385,9 +358,8 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -400,9 +372,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -415,9 +386,8 @@ }, "node_modules/@babel/plugin-transform-typescript": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", - "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.19.0", "@babel/helper-plugin-utils": "^7.19.0", @@ -432,9 +402,8 @@ }, "node_modules/@babel/preset-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-validator-option": "^7.18.6", @@ -449,9 +418,8 @@ }, "node_modules/@babel/template": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.18.10", @@ -463,9 +431,8 @@ }, "node_modules/@babel/traverse": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", - "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.19.0", @@ -484,9 +451,8 @@ }, "node_modules/@babel/types": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", @@ -496,35 +462,17 @@ "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", - "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@graphql-typed-document-node/core": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", - "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==", + "license": "MIT", "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -535,68 +483,51 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "version": "4.3.0-beta.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.3.0-beta.4.tgz", + "integrity": "sha512-GFtngk07PTj3WX1P0sN2hnb/z+Y+CnGtwJv2gdDepZ5M87vgaTb2y9qqd6HDpMswTAmEqjBbrNp7X/LCBZkY+A==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/solid-query": { - "version": "4.2.3", - "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", - "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "4.2.3" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "solid-js": "^1.5.4" - } + "resolved": ".yalc/@tanstack/solid-query", + "link": true }, "node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -606,14 +537,12 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "license": "MIT" }, "node_modules/babel-plugin-jsx-dom-expressions": { "version": "0.34.7", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", - "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "7.16.0", "@babel/plugin-syntax-jsx": "^7.16.5", @@ -626,9 +555,8 @@ }, "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.16.0" }, @@ -638,9 +566,8 @@ }, "node_modules/babel-preset-solid": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", - "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.34.5" }, @@ -650,8 +577,6 @@ }, "node_modules/browserslist": { "version": "4.21.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", - "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "funding": [ { @@ -663,6 +588,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001370", "electron-to-chromium": "^1.4.202", @@ -678,8 +604,6 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001393", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", - "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "dev": true, "funding": [ { @@ -690,13 +614,13 @@ "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -708,23 +632,20 @@ }, "node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -734,31 +655,27 @@ }, "node_modules/convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.1" } }, "node_modules/cross-fetch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "license": "MIT", "dependencies": { "node-fetch": "2.6.7" } }, "node_modules/csstype": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "license": "MIT" }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -773,24 +690,21 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/electron-to-chromium": { "version": "1.4.245", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", - "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/esbuild": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", - "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -821,46 +735,13 @@ "esbuild-windows-arm64": "0.15.7" } }, - "node_modules/esbuild-android-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", - "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", - "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/esbuild-darwin-64": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", - "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -869,300 +750,25 @@ "node": ">=12" } }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", - "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", - "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", - "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", - "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", - "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", - "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", - "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", - "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", - "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", - "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", - "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", - "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", - "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", - "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", - "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", - "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", - "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/extract-files": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", - "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==", + "license": "MIT", "engines": { "node": "^10.17.0 || ^12.0.0 || >= 13.7.0" }, @@ -1172,8 +778,7 @@ }, "node_modules/form-data": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -1185,10 +790,8 @@ }, "node_modules/fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1199,40 +802,35 @@ }, "node_modules/function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/graphql": { "version": "16.6.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", - "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, "node_modules/graphql-request": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-5.0.0.tgz", - "integrity": "sha512-SpVEnIo2J5k2+Zf76cUkdvIRaq5FMZvGQYnA4lUWYbc99m+fHh4CZYRRO/Ff4tCLQ613fzCm3SiDT64ubW5Gyw==", + "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "cross-fetch": "^3.1.5", @@ -1245,9 +843,8 @@ }, "node_modules/has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.1" }, @@ -1257,24 +854,21 @@ }, "node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-core-module": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, + "license": "MIT", "dependencies": { "has": "^1.0.3" }, @@ -1284,9 +878,8 @@ }, "node_modules/is-what": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", - "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.13" }, @@ -1296,15 +889,13 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -1314,9 +905,8 @@ }, "node_modules/json5": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -1326,9 +916,8 @@ }, "node_modules/merge-anything": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", - "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", "dev": true, + "license": "MIT", "dependencies": { "is-what": "^4.1.7", "ts-toolbelt": "^9.6.0" @@ -1342,16 +931,14 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -1361,15 +948,13 @@ }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true, + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1379,8 +964,7 @@ }, "node_modules/node-fetch": { "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -1398,26 +982,21 @@ }, "node_modules/node-releases": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/postcss": { "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "funding": [ { @@ -1429,6 +1008,7 @@ "url": "https://tidelift.com/funding/github/npm/postcss" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -1440,9 +1020,8 @@ }, "node_modules/resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -1457,9 +1036,8 @@ }, "node_modules/rollup": { "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "dev": true, + "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -1472,32 +1050,28 @@ }, "node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/solid-js": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", - "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "license": "MIT", "dependencies": { "csstype": "^3.1.0" } }, "node_modules/solid-refresh": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", - "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/generator": "^7.18.2", "@babel/helper-module-imports": "^7.16.7", @@ -1509,18 +1083,16 @@ }, "node_modules/source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -1530,9 +1102,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1542,29 +1113,25 @@ }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "license": "MIT" }, "node_modules/ts-toolbelt": { "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/typescript": { "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1575,8 +1142,6 @@ }, "node_modules/update-browserslist-db": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", - "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "dev": true, "funding": [ { @@ -1588,6 +1153,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -1601,9 +1167,8 @@ }, "node_modules/vite": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", - "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.15.6", "postcss": "^8.4.16", @@ -1642,9 +1207,8 @@ }, "node_modules/vite-plugin-solid": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", - "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.18.6", "@babel/preset-typescript": "^7.18.6", @@ -1659,13 +1223,11 @@ }, "node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -1675,8 +1237,6 @@ "dependencies": { "@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", @@ -1685,8 +1245,6 @@ }, "@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" @@ -1694,14 +1252,10 @@ }, "@babel/compat-data": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", - "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", "dev": true }, "@babel/core": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", - "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", @@ -1723,8 +1277,6 @@ }, "@babel/generator": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "dev": true, "requires": { "@babel/types": "^7.19.0", @@ -1734,8 +1286,6 @@ "dependencies": { "@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", @@ -1747,8 +1297,6 @@ }, "@babel/helper-annotate-as-pure": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1756,8 +1304,6 @@ }, "@babel/helper-compilation-targets": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", - "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", "dev": true, "requires": { "@babel/compat-data": "^7.19.0", @@ -1768,8 +1314,6 @@ }, "@babel/helper-create-class-features-plugin": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", @@ -1783,14 +1327,10 @@ }, "@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true }, "@babel/helper-function-name": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "requires": { "@babel/template": "^7.18.10", @@ -1799,8 +1339,6 @@ }, "@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1808,8 +1346,6 @@ }, "@babel/helper-member-expression-to-functions": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, "requires": { "@babel/types": "^7.18.9" @@ -1817,8 +1353,6 @@ }, "@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1826,8 +1360,6 @@ }, "@babel/helper-module-transforms": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1842,8 +1374,6 @@ }, "@babel/helper-optimise-call-expression": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1851,14 +1381,10 @@ }, "@babel/helper-plugin-utils": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true }, "@babel/helper-replace-supers": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", - "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1870,8 +1396,6 @@ }, "@babel/helper-simple-access": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1879,8 +1403,6 @@ }, "@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1888,26 +1410,18 @@ }, "@babel/helper-string-parser": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "dev": true }, "@babel/helper-validator-identifier": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true }, "@babel/helper-validator-option": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helpers": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, "requires": { "@babel/template": "^7.18.10", @@ -1917,8 +1431,6 @@ }, "@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.18.6", @@ -1928,14 +1440,10 @@ }, "@babel/parser": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", - "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", "dev": true }, "@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" @@ -1943,8 +1451,6 @@ }, "@babel/plugin-syntax-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" @@ -1952,8 +1458,6 @@ }, "@babel/plugin-transform-typescript": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", - "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.19.0", @@ -1963,8 +1467,6 @@ }, "@babel/preset-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", @@ -1974,8 +1476,6 @@ }, "@babel/template": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", @@ -1985,8 +1485,6 @@ }, "@babel/traverse": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", - "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", @@ -2003,8 +1501,6 @@ }, "@babel/types": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.18.10", @@ -2012,23 +1508,12 @@ "to-fast-properties": "^2.0.0" } }, - "@esbuild/linux-loong64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", - "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", - "dev": true, - "optional": true - }, "@graphql-typed-document-node/core": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", - "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==", "requires": {} }, "@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", @@ -2037,26 +1522,18 @@ }, "@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true }, "@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", @@ -2064,35 +1541,28 @@ } }, "@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + "version": "4.3.0-beta.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.3.0-beta.4.tgz", + "integrity": "sha512-GFtngk07PTj3WX1P0sN2hnb/z+Y+CnGtwJv2gdDepZ5M87vgaTb2y9qqd6HDpMswTAmEqjBbrNp7X/LCBZkY+A==" }, "@tanstack/solid-query": { - "version": "4.2.3", - "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "version": "file:.yalc/@tanstack/solid-query", "requires": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" } }, "ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" } }, "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "version": "0.4.0" }, "babel-plugin-jsx-dom-expressions": { "version": "0.34.7", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", - "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", "dev": true, "requires": { "@babel/helper-module-imports": "7.16.0", @@ -2103,8 +1573,6 @@ "dependencies": { "@babel/helper-module-imports": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, "requires": { "@babel/types": "^7.16.0" @@ -2114,8 +1582,6 @@ }, "babel-preset-solid": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", - "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", "dev": true, "requires": { "babel-plugin-jsx-dom-expressions": "^0.34.5" @@ -2123,8 +1589,6 @@ }, "browserslist": { "version": "4.21.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", - "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "requires": { "caniuse-lite": "^1.0.30001370", @@ -2135,14 +1599,10 @@ }, "caniuse-lite": { "version": "1.0.30001393", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", - "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "dev": true }, "chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -2152,8 +1612,6 @@ }, "color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -2161,22 +1619,16 @@ }, "color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { "delayed-stream": "~1.0.0" } }, "convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -2184,41 +1636,29 @@ }, "cross-fetch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", "requires": { "node-fetch": "2.6.7" } }, "csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "version": "3.1.0" }, "debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" } }, "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + "version": "1.0.0" }, "electron-to-chromium": { "version": "1.4.245", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", - "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", "dev": true }, "esbuild": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", - "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "requires": { "@esbuild/linux-loong64": "0.15.7", @@ -2244,167 +1684,24 @@ "esbuild-windows-arm64": "0.15.7" } }, - "esbuild-android-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", - "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", - "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", - "dev": true, - "optional": true - }, "esbuild-darwin-64": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", - "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", - "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", - "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", - "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", - "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", - "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", - "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", - "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", - "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", - "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", - "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", - "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", - "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", - "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", - "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", - "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", - "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", - "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", "dev": true, "optional": true }, "escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "extract-files": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", - "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==" + "version": "9.0.0" }, "form-data": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -2413,38 +1710,26 @@ }, "fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, "graphql": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", - "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==" + "version": "16.6.0" }, "graphql-request": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-5.0.0.tgz", - "integrity": "sha512-SpVEnIo2J5k2+Zf76cUkdvIRaq5FMZvGQYnA4lUWYbc99m+fHh4CZYRRO/Ff4tCLQ613fzCm3SiDT64ubW5Gyw==", "requires": { "@graphql-typed-document-node/core": "^3.1.1", "cross-fetch": "^3.1.5", @@ -2454,8 +1739,6 @@ }, "has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -2463,20 +1746,14 @@ }, "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", "dev": true }, "is-core-module": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, "requires": { "has": "^1.0.3" @@ -2484,32 +1761,22 @@ }, "is-what": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", - "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", "dev": true }, "js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, "json5": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true }, "merge-anything": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", - "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", "dev": true, "requires": { "is-what": "^4.1.7", @@ -2517,60 +1784,42 @@ } }, "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "version": "1.52.0" }, "mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { "mime-db": "1.52.0" } }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "nanoid": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, "node-fetch": { "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "requires": { "whatwg-url": "^5.0.0" } }, "node-releases": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "postcss": { "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "requires": { "nanoid": "^3.3.4", @@ -2580,8 +1829,6 @@ }, "resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "requires": { "is-core-module": "^2.9.0", @@ -2591,8 +1838,6 @@ }, "rollup": { "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -2600,28 +1845,20 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "solid-js": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", - "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", "requires": { "csstype": "^3.1.0" } }, "solid-refresh": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", - "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", "dev": true, "requires": { "@babel/generator": "^7.18.2", @@ -2631,14 +1868,10 @@ }, "source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, "supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -2646,37 +1879,25 @@ }, "supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, "to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "version": "0.0.3" }, "ts-toolbelt": { "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", "dev": true }, "typescript": { "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", "dev": true }, "update-browserslist-db": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", - "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "dev": true, "requires": { "escalade": "^3.1.1", @@ -2685,8 +1906,6 @@ }, "vite": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", - "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", "dev": true, "requires": { "esbuild": "^0.15.6", @@ -2698,8 +1917,6 @@ }, "vite-plugin-solid": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", - "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", "dev": true, "requires": { "@babel/core": "^7.18.6", @@ -2710,14 +1927,10 @@ } }, "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "version": "3.0.1" }, "whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" diff --git a/examples/solid/basic-graphql-request/package.json b/examples/solid/basic-graphql-request/package.json index 45ab277c6e3..823a4826024 100644 --- a/examples/solid/basic-graphql-request/package.json +++ b/examples/solid/basic-graphql-request/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@tanstack/solid-query": "^4.2.3", + "@tanstack/solid-query": "^4.3.0-beta.4", "graphql": "^16.6.0", "graphql-request": "^5.0.0", "solid-js": "^1.5.1" diff --git a/examples/solid/basic-typescript/package-lock.json b/examples/solid/basic-typescript/package-lock.json index 785e051eed2..c762176fa7a 100644 --- a/examples/solid/basic-typescript/package-lock.json +++ b/examples/solid/basic-typescript/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "@tanstack/solid-query": "^4.2.3", + "@tanstack/solid-query": "^4.3.0-beta.4", "solid-js": "^1.5.1" }, "devDependencies": { @@ -19,11 +19,10 @@ } }, ".yalc/@tanstack/solid-query": { - "version": "4.2.3", - "extraneous": true, + "version": "4.3.0-beta.4", "license": "MIT", "dependencies": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" }, "funding": { "type": "github", @@ -35,9 +34,8 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -48,9 +46,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -60,18 +57,16 @@ }, "node_modules/@babel/compat-data": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", - "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", - "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", @@ -99,9 +94,8 @@ }, "node_modules/@babel/generator": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.19.0", "@jridgewell/gen-mapping": "^0.3.2", @@ -113,9 +107,8 @@ }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -127,9 +120,8 @@ }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -139,9 +131,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", - "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.19.0", "@babel/helper-validator-option": "^7.18.6", @@ -157,9 +148,8 @@ }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", @@ -178,18 +168,16 @@ }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" @@ -200,9 +188,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -212,9 +199,8 @@ }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.9" }, @@ -224,9 +210,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -236,9 +221,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", @@ -255,9 +239,8 @@ }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -267,18 +250,16 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", - "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-member-expression-to-functions": "^7.18.9", @@ -292,9 +273,8 @@ }, "node_modules/@babel/helper-simple-access": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -304,9 +284,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -316,36 +295,32 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.19.0", @@ -357,9 +332,8 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -371,9 +345,8 @@ }, "node_modules/@babel/parser": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", - "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -383,9 +356,8 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -398,9 +370,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -413,9 +384,8 @@ }, "node_modules/@babel/plugin-transform-typescript": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", - "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.19.0", "@babel/helper-plugin-utils": "^7.19.0", @@ -430,9 +400,8 @@ }, "node_modules/@babel/preset-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-validator-option": "^7.18.6", @@ -447,9 +416,8 @@ }, "node_modules/@babel/template": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.18.10", @@ -461,9 +429,8 @@ }, "node_modules/@babel/traverse": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", - "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.19.0", @@ -482,9 +449,8 @@ }, "node_modules/@babel/types": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", @@ -494,27 +460,10 @@ "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", - "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -525,68 +474,51 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "version": "4.3.0-beta.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.3.0-beta.4.tgz", + "integrity": "sha512-GFtngk07PTj3WX1P0sN2hnb/z+Y+CnGtwJv2gdDepZ5M87vgaTb2y9qqd6HDpMswTAmEqjBbrNp7X/LCBZkY+A==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/solid-query": { - "version": "4.2.3", - "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", - "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "4.2.3" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "solid-js": "^1.5.4" - } + "resolved": ".yalc/@tanstack/solid-query", + "link": true }, "node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -596,9 +528,8 @@ }, "node_modules/babel-plugin-jsx-dom-expressions": { "version": "0.34.7", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", - "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "7.16.0", "@babel/plugin-syntax-jsx": "^7.16.5", @@ -611,9 +542,8 @@ }, "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.16.0" }, @@ -623,9 +553,8 @@ }, "node_modules/babel-preset-solid": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", - "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.34.5" }, @@ -635,8 +564,6 @@ }, "node_modules/browserslist": { "version": "4.21.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", - "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "funding": [ { @@ -648,6 +575,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001370", "electron-to-chromium": "^1.4.202", @@ -663,8 +591,6 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001393", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", - "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "dev": true, "funding": [ { @@ -675,13 +601,13 @@ "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -693,38 +619,33 @@ }, "node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.1" } }, "node_modules/csstype": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "license": "MIT" }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -739,16 +660,14 @@ }, "node_modules/electron-to-chromium": { "version": "1.4.245", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", - "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/esbuild": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", - "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -779,46 +698,13 @@ "esbuild-windows-arm64": "0.15.7" } }, - "node_modules/esbuild-android-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", - "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", - "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/esbuild-darwin-64": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", - "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -827,302 +713,26 @@ "node": ">=12" } }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", - "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", - "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", - "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", - "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", - "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", - "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", - "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", - "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", - "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", - "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", - "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", - "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", - "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", - "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", - "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", - "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", - "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1133,33 +743,29 @@ }, "node_modules/function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.1" }, @@ -1169,24 +775,21 @@ }, "node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-core-module": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, + "license": "MIT", "dependencies": { "has": "^1.0.3" }, @@ -1196,9 +799,8 @@ }, "node_modules/is-what": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", - "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.13" }, @@ -1208,15 +810,13 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -1226,9 +826,8 @@ }, "node_modules/json5": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -1238,9 +837,8 @@ }, "node_modules/merge-anything": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", - "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", "dev": true, + "license": "MIT", "dependencies": { "is-what": "^4.1.7", "ts-toolbelt": "^9.6.0" @@ -1254,15 +852,13 @@ }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true, + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1272,26 +868,21 @@ }, "node_modules/node-releases": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/postcss": { "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "funding": [ { @@ -1303,6 +894,7 @@ "url": "https://tidelift.com/funding/github/npm/postcss" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -1314,9 +906,8 @@ }, "node_modules/resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -1331,9 +922,8 @@ }, "node_modules/rollup": { "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "dev": true, + "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -1346,32 +936,28 @@ }, "node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/solid-js": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", - "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "license": "MIT", "dependencies": { "csstype": "^3.1.0" } }, "node_modules/solid-refresh": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", - "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/generator": "^7.18.2", "@babel/helper-module-imports": "^7.16.7", @@ -1383,18 +969,16 @@ }, "node_modules/source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -1404,9 +988,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1416,24 +999,21 @@ }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/ts-toolbelt": { "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/typescript": { "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1444,8 +1024,6 @@ }, "node_modules/update-browserslist-db": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", - "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "dev": true, "funding": [ { @@ -1457,6 +1035,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -1470,9 +1049,8 @@ }, "node_modules/vite": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", - "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.15.6", "postcss": "^8.4.16", @@ -1511,9 +1089,8 @@ }, "node_modules/vite-plugin-solid": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", - "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.18.6", "@babel/preset-typescript": "^7.18.6", @@ -1530,8 +1107,6 @@ "dependencies": { "@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", @@ -1540,8 +1115,6 @@ }, "@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" @@ -1549,14 +1122,10 @@ }, "@babel/compat-data": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", - "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", "dev": true }, "@babel/core": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", - "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", @@ -1578,8 +1147,6 @@ }, "@babel/generator": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "dev": true, "requires": { "@babel/types": "^7.19.0", @@ -1589,8 +1156,6 @@ "dependencies": { "@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", @@ -1602,8 +1167,6 @@ }, "@babel/helper-annotate-as-pure": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1611,8 +1174,6 @@ }, "@babel/helper-compilation-targets": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", - "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", "dev": true, "requires": { "@babel/compat-data": "^7.19.0", @@ -1623,8 +1184,6 @@ }, "@babel/helper-create-class-features-plugin": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", @@ -1638,14 +1197,10 @@ }, "@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true }, "@babel/helper-function-name": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "requires": { "@babel/template": "^7.18.10", @@ -1654,8 +1209,6 @@ }, "@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1663,8 +1216,6 @@ }, "@babel/helper-member-expression-to-functions": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, "requires": { "@babel/types": "^7.18.9" @@ -1672,8 +1223,6 @@ }, "@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1681,8 +1230,6 @@ }, "@babel/helper-module-transforms": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1697,8 +1244,6 @@ }, "@babel/helper-optimise-call-expression": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1706,14 +1251,10 @@ }, "@babel/helper-plugin-utils": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true }, "@babel/helper-replace-supers": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", - "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1725,8 +1266,6 @@ }, "@babel/helper-simple-access": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1734,8 +1273,6 @@ }, "@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1743,26 +1280,18 @@ }, "@babel/helper-string-parser": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "dev": true }, "@babel/helper-validator-identifier": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true }, "@babel/helper-validator-option": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helpers": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, "requires": { "@babel/template": "^7.18.10", @@ -1772,8 +1301,6 @@ }, "@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.18.6", @@ -1783,14 +1310,10 @@ }, "@babel/parser": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", - "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", "dev": true }, "@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" @@ -1798,8 +1321,6 @@ }, "@babel/plugin-syntax-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" @@ -1807,8 +1328,6 @@ }, "@babel/plugin-transform-typescript": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", - "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.19.0", @@ -1818,8 +1337,6 @@ }, "@babel/preset-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", @@ -1829,8 +1346,6 @@ }, "@babel/template": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", @@ -1840,8 +1355,6 @@ }, "@babel/traverse": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", - "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", @@ -1858,8 +1371,6 @@ }, "@babel/types": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.18.10", @@ -1867,17 +1378,8 @@ "to-fast-properties": "^2.0.0" } }, - "@esbuild/linux-loong64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", - "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", - "dev": true, - "optional": true - }, "@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", @@ -1886,26 +1388,18 @@ }, "@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true }, "@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", @@ -1913,21 +1407,18 @@ } }, "@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + "version": "4.3.0-beta.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.3.0-beta.4.tgz", + "integrity": "sha512-GFtngk07PTj3WX1P0sN2hnb/z+Y+CnGtwJv2gdDepZ5M87vgaTb2y9qqd6HDpMswTAmEqjBbrNp7X/LCBZkY+A==" }, "@tanstack/solid-query": { - "version": "4.2.3", - "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "version": "file:.yalc/@tanstack/solid-query", "requires": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" } }, "ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -1935,8 +1426,6 @@ }, "babel-plugin-jsx-dom-expressions": { "version": "0.34.7", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", - "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", "dev": true, "requires": { "@babel/helper-module-imports": "7.16.0", @@ -1947,8 +1436,6 @@ "dependencies": { "@babel/helper-module-imports": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, "requires": { "@babel/types": "^7.16.0" @@ -1958,8 +1445,6 @@ }, "babel-preset-solid": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", - "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", "dev": true, "requires": { "babel-plugin-jsx-dom-expressions": "^0.34.5" @@ -1967,8 +1452,6 @@ }, "browserslist": { "version": "4.21.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", - "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "requires": { "caniuse-lite": "^1.0.30001370", @@ -1979,14 +1462,10 @@ }, "caniuse-lite": { "version": "1.0.30001393", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", - "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "dev": true }, "chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -1996,8 +1475,6 @@ }, "color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -2005,28 +1482,20 @@ }, "color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" } }, "csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "version": "3.1.0" }, "debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -2034,14 +1503,10 @@ }, "electron-to-chromium": { "version": "1.4.245", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", - "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", "dev": true }, "esbuild": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", - "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "requires": { "@esbuild/linux-loong64": "0.15.7", @@ -2067,187 +1532,38 @@ "esbuild-windows-arm64": "0.15.7" } }, - "esbuild-android-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", - "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", - "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", - "dev": true, - "optional": true - }, "esbuild-darwin-64": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", - "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", - "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", - "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", - "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", - "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", - "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", - "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", - "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", - "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", - "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", - "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", - "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", - "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", - "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", - "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", - "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", - "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", - "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", "dev": true, "optional": true }, "escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, "has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -2255,20 +1571,14 @@ }, "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", "dev": true }, "is-core-module": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, "requires": { "has": "^1.0.3" @@ -2276,32 +1586,22 @@ }, "is-what": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", - "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", "dev": true }, "js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, "json5": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true }, "merge-anything": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", - "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", "dev": true, "requires": { "is-what": "^4.1.7", @@ -2310,38 +1610,26 @@ }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "nanoid": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, "node-releases": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "postcss": { "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "requires": { "nanoid": "^3.3.4", @@ -2351,8 +1639,6 @@ }, "resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "requires": { "is-core-module": "^2.9.0", @@ -2362,8 +1648,6 @@ }, "rollup": { "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -2371,28 +1655,20 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "solid-js": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", - "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", "requires": { "csstype": "^3.1.0" } }, "solid-refresh": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", - "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", "dev": true, "requires": { "@babel/generator": "^7.18.2", @@ -2402,14 +1678,10 @@ }, "source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, "supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -2417,32 +1689,22 @@ }, "supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, "to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "ts-toolbelt": { "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", "dev": true }, "typescript": { "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", "dev": true }, "update-browserslist-db": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", - "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "dev": true, "requires": { "escalade": "^3.1.1", @@ -2451,8 +1713,6 @@ }, "vite": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", - "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", "dev": true, "requires": { "esbuild": "^0.15.6", @@ -2464,8 +1724,6 @@ }, "vite-plugin-solid": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", - "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", "dev": true, "requires": { "@babel/core": "^7.18.6", diff --git a/examples/solid/basic-typescript/package.json b/examples/solid/basic-typescript/package.json index 158e03b8563..ae64607c9a9 100644 --- a/examples/solid/basic-typescript/package.json +++ b/examples/solid/basic-typescript/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@tanstack/solid-query": "^4.2.3", + "@tanstack/solid-query": "^4.3.0-beta.4", "solid-js": "^1.5.1" }, "devDependencies": { diff --git a/examples/solid/default-query-function/package-lock.json b/examples/solid/default-query-function/package-lock.json index 09f8fa1320d..ea1b378a048 100644 --- a/examples/solid/default-query-function/package-lock.json +++ b/examples/solid/default-query-function/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "@tanstack/solid-query": "^4.2.3", + "@tanstack/solid-query": "^4.3.0-beta.4", "solid-js": "^1.5.1" }, "devDependencies": { @@ -19,11 +19,10 @@ } }, ".yalc/@tanstack/solid-query": { - "version": "4.2.3", - "extraneous": true, + "version": "4.3.0-beta.4", "license": "MIT", "dependencies": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" }, "funding": { "type": "github", @@ -35,9 +34,8 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -48,9 +46,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -60,18 +57,16 @@ }, "node_modules/@babel/compat-data": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", - "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", - "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", @@ -99,9 +94,8 @@ }, "node_modules/@babel/generator": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.19.0", "@jridgewell/gen-mapping": "^0.3.2", @@ -113,9 +107,8 @@ }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -127,9 +120,8 @@ }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -139,9 +131,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", - "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.19.0", "@babel/helper-validator-option": "^7.18.6", @@ -157,9 +148,8 @@ }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", @@ -178,18 +168,16 @@ }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" @@ -200,9 +188,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -212,9 +199,8 @@ }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.9" }, @@ -224,9 +210,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -236,9 +221,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", @@ -255,9 +239,8 @@ }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -267,18 +250,16 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", - "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-member-expression-to-functions": "^7.18.9", @@ -292,9 +273,8 @@ }, "node_modules/@babel/helper-simple-access": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -304,9 +284,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -316,36 +295,32 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.19.0", @@ -357,9 +332,8 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -371,9 +345,8 @@ }, "node_modules/@babel/parser": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", - "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -383,9 +356,8 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -398,9 +370,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -413,9 +384,8 @@ }, "node_modules/@babel/plugin-transform-typescript": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", - "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.19.0", "@babel/helper-plugin-utils": "^7.19.0", @@ -430,9 +400,8 @@ }, "node_modules/@babel/preset-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-validator-option": "^7.18.6", @@ -447,9 +416,8 @@ }, "node_modules/@babel/template": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.18.10", @@ -461,9 +429,8 @@ }, "node_modules/@babel/traverse": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", - "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.19.0", @@ -482,9 +449,8 @@ }, "node_modules/@babel/types": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", @@ -494,27 +460,10 @@ "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", - "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -525,68 +474,51 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "version": "4.3.0-beta.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.3.0-beta.4.tgz", + "integrity": "sha512-GFtngk07PTj3WX1P0sN2hnb/z+Y+CnGtwJv2gdDepZ5M87vgaTb2y9qqd6HDpMswTAmEqjBbrNp7X/LCBZkY+A==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/solid-query": { - "version": "4.2.3", - "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", - "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "4.2.3" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "solid-js": "^1.5.4" - } + "resolved": ".yalc/@tanstack/solid-query", + "link": true }, "node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -596,9 +528,8 @@ }, "node_modules/babel-plugin-jsx-dom-expressions": { "version": "0.34.7", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", - "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "7.16.0", "@babel/plugin-syntax-jsx": "^7.16.5", @@ -611,9 +542,8 @@ }, "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.16.0" }, @@ -623,9 +553,8 @@ }, "node_modules/babel-preset-solid": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", - "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.34.5" }, @@ -635,8 +564,6 @@ }, "node_modules/browserslist": { "version": "4.21.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", - "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "funding": [ { @@ -648,6 +575,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001370", "electron-to-chromium": "^1.4.202", @@ -663,8 +591,6 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001393", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", - "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "dev": true, "funding": [ { @@ -675,13 +601,13 @@ "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -693,38 +619,33 @@ }, "node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.1" } }, "node_modules/csstype": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "license": "MIT" }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -739,16 +660,14 @@ }, "node_modules/electron-to-chromium": { "version": "1.4.245", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", - "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/esbuild": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", - "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -779,46 +698,13 @@ "esbuild-windows-arm64": "0.15.7" } }, - "node_modules/esbuild-android-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", - "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", - "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/esbuild-darwin-64": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", - "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -827,302 +713,26 @@ "node": ">=12" } }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", - "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", - "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", - "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", - "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", - "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", - "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", - "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", - "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", - "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", - "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", - "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", - "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", - "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", - "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", - "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", - "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", - "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1133,33 +743,29 @@ }, "node_modules/function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.1" }, @@ -1169,24 +775,21 @@ }, "node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-core-module": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, + "license": "MIT", "dependencies": { "has": "^1.0.3" }, @@ -1196,9 +799,8 @@ }, "node_modules/is-what": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", - "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.13" }, @@ -1208,15 +810,13 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -1226,9 +826,8 @@ }, "node_modules/json5": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -1238,9 +837,8 @@ }, "node_modules/merge-anything": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", - "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", "dev": true, + "license": "MIT", "dependencies": { "is-what": "^4.1.7", "ts-toolbelt": "^9.6.0" @@ -1254,15 +852,13 @@ }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true, + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1272,26 +868,21 @@ }, "node_modules/node-releases": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/postcss": { "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "funding": [ { @@ -1303,6 +894,7 @@ "url": "https://tidelift.com/funding/github/npm/postcss" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -1314,9 +906,8 @@ }, "node_modules/resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -1331,9 +922,8 @@ }, "node_modules/rollup": { "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "dev": true, + "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -1346,32 +936,28 @@ }, "node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/solid-js": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", - "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "license": "MIT", "dependencies": { "csstype": "^3.1.0" } }, "node_modules/solid-refresh": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", - "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/generator": "^7.18.2", "@babel/helper-module-imports": "^7.16.7", @@ -1383,18 +969,16 @@ }, "node_modules/source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -1404,9 +988,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1416,24 +999,21 @@ }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/ts-toolbelt": { "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/typescript": { "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1444,8 +1024,6 @@ }, "node_modules/update-browserslist-db": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", - "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "dev": true, "funding": [ { @@ -1457,6 +1035,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -1470,9 +1049,8 @@ }, "node_modules/vite": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", - "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.15.6", "postcss": "^8.4.16", @@ -1511,9 +1089,8 @@ }, "node_modules/vite-plugin-solid": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", - "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.18.6", "@babel/preset-typescript": "^7.18.6", @@ -1530,8 +1107,6 @@ "dependencies": { "@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", @@ -1540,8 +1115,6 @@ }, "@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" @@ -1549,14 +1122,10 @@ }, "@babel/compat-data": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", - "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", "dev": true }, "@babel/core": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", - "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", @@ -1578,8 +1147,6 @@ }, "@babel/generator": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "dev": true, "requires": { "@babel/types": "^7.19.0", @@ -1589,8 +1156,6 @@ "dependencies": { "@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", @@ -1602,8 +1167,6 @@ }, "@babel/helper-annotate-as-pure": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1611,8 +1174,6 @@ }, "@babel/helper-compilation-targets": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", - "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", "dev": true, "requires": { "@babel/compat-data": "^7.19.0", @@ -1623,8 +1184,6 @@ }, "@babel/helper-create-class-features-plugin": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", @@ -1638,14 +1197,10 @@ }, "@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true }, "@babel/helper-function-name": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "requires": { "@babel/template": "^7.18.10", @@ -1654,8 +1209,6 @@ }, "@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1663,8 +1216,6 @@ }, "@babel/helper-member-expression-to-functions": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, "requires": { "@babel/types": "^7.18.9" @@ -1672,8 +1223,6 @@ }, "@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1681,8 +1230,6 @@ }, "@babel/helper-module-transforms": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1697,8 +1244,6 @@ }, "@babel/helper-optimise-call-expression": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1706,14 +1251,10 @@ }, "@babel/helper-plugin-utils": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true }, "@babel/helper-replace-supers": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", - "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1725,8 +1266,6 @@ }, "@babel/helper-simple-access": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1734,8 +1273,6 @@ }, "@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1743,26 +1280,18 @@ }, "@babel/helper-string-parser": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "dev": true }, "@babel/helper-validator-identifier": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true }, "@babel/helper-validator-option": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helpers": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, "requires": { "@babel/template": "^7.18.10", @@ -1772,8 +1301,6 @@ }, "@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.18.6", @@ -1783,14 +1310,10 @@ }, "@babel/parser": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", - "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", "dev": true }, "@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" @@ -1798,8 +1321,6 @@ }, "@babel/plugin-syntax-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" @@ -1807,8 +1328,6 @@ }, "@babel/plugin-transform-typescript": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", - "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.19.0", @@ -1818,8 +1337,6 @@ }, "@babel/preset-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", @@ -1829,8 +1346,6 @@ }, "@babel/template": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", @@ -1840,8 +1355,6 @@ }, "@babel/traverse": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", - "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", @@ -1858,8 +1371,6 @@ }, "@babel/types": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.18.10", @@ -1867,17 +1378,8 @@ "to-fast-properties": "^2.0.0" } }, - "@esbuild/linux-loong64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", - "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", - "dev": true, - "optional": true - }, "@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", @@ -1886,26 +1388,18 @@ }, "@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true }, "@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", @@ -1913,21 +1407,18 @@ } }, "@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + "version": "4.3.0-beta.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.3.0-beta.4.tgz", + "integrity": "sha512-GFtngk07PTj3WX1P0sN2hnb/z+Y+CnGtwJv2gdDepZ5M87vgaTb2y9qqd6HDpMswTAmEqjBbrNp7X/LCBZkY+A==" }, "@tanstack/solid-query": { - "version": "4.2.3", - "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "version": "file:.yalc/@tanstack/solid-query", "requires": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" } }, "ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -1935,8 +1426,6 @@ }, "babel-plugin-jsx-dom-expressions": { "version": "0.34.7", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", - "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", "dev": true, "requires": { "@babel/helper-module-imports": "7.16.0", @@ -1947,8 +1436,6 @@ "dependencies": { "@babel/helper-module-imports": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, "requires": { "@babel/types": "^7.16.0" @@ -1958,8 +1445,6 @@ }, "babel-preset-solid": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", - "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", "dev": true, "requires": { "babel-plugin-jsx-dom-expressions": "^0.34.5" @@ -1967,8 +1452,6 @@ }, "browserslist": { "version": "4.21.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", - "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "requires": { "caniuse-lite": "^1.0.30001370", @@ -1979,14 +1462,10 @@ }, "caniuse-lite": { "version": "1.0.30001393", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", - "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "dev": true }, "chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -1996,8 +1475,6 @@ }, "color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -2005,28 +1482,20 @@ }, "color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" } }, "csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "version": "3.1.0" }, "debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -2034,14 +1503,10 @@ }, "electron-to-chromium": { "version": "1.4.245", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", - "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", "dev": true }, "esbuild": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", - "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "requires": { "@esbuild/linux-loong64": "0.15.7", @@ -2067,187 +1532,38 @@ "esbuild-windows-arm64": "0.15.7" } }, - "esbuild-android-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", - "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", - "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", - "dev": true, - "optional": true - }, "esbuild-darwin-64": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", - "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", - "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", - "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", - "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", - "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", - "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", - "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", - "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", - "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", - "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", - "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", - "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", - "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", - "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", - "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", - "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", - "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", - "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", "dev": true, "optional": true }, "escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, "has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -2255,20 +1571,14 @@ }, "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", "dev": true }, "is-core-module": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, "requires": { "has": "^1.0.3" @@ -2276,32 +1586,22 @@ }, "is-what": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", - "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", "dev": true }, "js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, "json5": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true }, "merge-anything": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", - "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", "dev": true, "requires": { "is-what": "^4.1.7", @@ -2310,38 +1610,26 @@ }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "nanoid": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, "node-releases": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "postcss": { "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "requires": { "nanoid": "^3.3.4", @@ -2351,8 +1639,6 @@ }, "resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "requires": { "is-core-module": "^2.9.0", @@ -2362,8 +1648,6 @@ }, "rollup": { "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -2371,28 +1655,20 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "solid-js": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", - "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", "requires": { "csstype": "^3.1.0" } }, "solid-refresh": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", - "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", "dev": true, "requires": { "@babel/generator": "^7.18.2", @@ -2402,14 +1678,10 @@ }, "source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, "supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -2417,32 +1689,22 @@ }, "supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, "to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "ts-toolbelt": { "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", "dev": true }, "typescript": { "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", "dev": true }, "update-browserslist-db": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", - "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "dev": true, "requires": { "escalade": "^3.1.1", @@ -2451,8 +1713,6 @@ }, "vite": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", - "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", "dev": true, "requires": { "esbuild": "^0.15.6", @@ -2464,8 +1724,6 @@ }, "vite-plugin-solid": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", - "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", "dev": true, "requires": { "@babel/core": "^7.18.6", diff --git a/examples/solid/default-query-function/package.json b/examples/solid/default-query-function/package.json index a3cbd144f0c..7e89141ba8b 100644 --- a/examples/solid/default-query-function/package.json +++ b/examples/solid/default-query-function/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@tanstack/solid-query": "^4.2.3", + "@tanstack/solid-query": "^4.3.0-beta.4", "solid-js": "^1.5.1" }, "devDependencies": { diff --git a/examples/solid/simple/package-lock.json b/examples/solid/simple/package-lock.json index beeb2f12554..9b5514a3d87 100644 --- a/examples/solid/simple/package-lock.json +++ b/examples/solid/simple/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "@tanstack/solid-query": "^4.2.3", + "@tanstack/solid-query": "^4.3.0-beta.4", "solid-js": "^1.5.1" }, "devDependencies": { @@ -19,11 +19,10 @@ } }, ".yalc/@tanstack/solid-query": { - "version": "4.2.3", - "extraneous": true, + "version": "4.3.0-beta.4", "license": "MIT", "dependencies": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" }, "funding": { "type": "github", @@ -35,9 +34,8 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -48,9 +46,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -60,18 +57,16 @@ }, "node_modules/@babel/compat-data": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", - "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", - "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", @@ -99,9 +94,8 @@ }, "node_modules/@babel/generator": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.19.0", "@jridgewell/gen-mapping": "^0.3.2", @@ -113,9 +107,8 @@ }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -127,9 +120,8 @@ }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -139,9 +131,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", - "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.19.0", "@babel/helper-validator-option": "^7.18.6", @@ -157,9 +148,8 @@ }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", @@ -178,18 +168,16 @@ }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" @@ -200,9 +188,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -212,9 +199,8 @@ }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.9" }, @@ -224,9 +210,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -236,9 +221,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", @@ -255,9 +239,8 @@ }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -267,18 +250,16 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", - "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-member-expression-to-functions": "^7.18.9", @@ -292,9 +273,8 @@ }, "node_modules/@babel/helper-simple-access": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -304,9 +284,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -316,36 +295,32 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.19.0", @@ -357,9 +332,8 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -371,9 +345,8 @@ }, "node_modules/@babel/parser": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", - "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -383,9 +356,8 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -398,9 +370,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -413,9 +384,8 @@ }, "node_modules/@babel/plugin-transform-typescript": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", - "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.19.0", "@babel/helper-plugin-utils": "^7.19.0", @@ -430,9 +400,8 @@ }, "node_modules/@babel/preset-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-validator-option": "^7.18.6", @@ -447,9 +416,8 @@ }, "node_modules/@babel/template": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.18.10", @@ -461,9 +429,8 @@ }, "node_modules/@babel/traverse": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", - "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.19.0", @@ -482,9 +449,8 @@ }, "node_modules/@babel/types": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", @@ -494,27 +460,10 @@ "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", - "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -525,68 +474,51 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==", + "version": "4.3.0-beta.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.3.0-beta.4.tgz", + "integrity": "sha512-GFtngk07PTj3WX1P0sN2hnb/z+Y+CnGtwJv2gdDepZ5M87vgaTb2y9qqd6HDpMswTAmEqjBbrNp7X/LCBZkY+A==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/solid-query": { - "version": "4.2.3", - "resolved": "file:../../../../../../../../tmp/registry/tanstack-solid-query-4.2.3.tgz", - "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "4.2.3" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "solid-js": "^1.5.4" - } + "resolved": ".yalc/@tanstack/solid-query", + "link": true }, "node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -596,9 +528,8 @@ }, "node_modules/babel-plugin-jsx-dom-expressions": { "version": "0.34.7", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", - "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "7.16.0", "@babel/plugin-syntax-jsx": "^7.16.5", @@ -611,9 +542,8 @@ }, "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.16.0" }, @@ -623,9 +553,8 @@ }, "node_modules/babel-preset-solid": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", - "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.34.5" }, @@ -635,8 +564,6 @@ }, "node_modules/browserslist": { "version": "4.21.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", - "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "funding": [ { @@ -648,6 +575,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001370", "electron-to-chromium": "^1.4.202", @@ -663,8 +591,6 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001393", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", - "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "dev": true, "funding": [ { @@ -675,13 +601,13 @@ "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -693,38 +619,33 @@ }, "node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.1" } }, "node_modules/csstype": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "license": "MIT" }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -739,16 +660,14 @@ }, "node_modules/electron-to-chromium": { "version": "1.4.245", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", - "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/esbuild": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", - "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -779,46 +698,13 @@ "esbuild-windows-arm64": "0.15.7" } }, - "node_modules/esbuild-android-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", - "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", - "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/esbuild-darwin-64": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", - "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -827,302 +713,26 @@ "node": ">=12" } }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", - "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", - "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", - "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", - "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", - "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", - "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", - "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", - "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", - "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", - "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", - "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", - "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", - "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", - "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", - "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", - "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", - "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1133,33 +743,29 @@ }, "node_modules/function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.1" }, @@ -1169,24 +775,21 @@ }, "node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-core-module": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, + "license": "MIT", "dependencies": { "has": "^1.0.3" }, @@ -1196,9 +799,8 @@ }, "node_modules/is-what": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", - "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.13" }, @@ -1208,15 +810,13 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -1226,9 +826,8 @@ }, "node_modules/json5": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -1238,9 +837,8 @@ }, "node_modules/merge-anything": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", - "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", "dev": true, + "license": "MIT", "dependencies": { "is-what": "^4.1.7", "ts-toolbelt": "^9.6.0" @@ -1254,15 +852,13 @@ }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true, + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1272,26 +868,21 @@ }, "node_modules/node-releases": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/postcss": { "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "funding": [ { @@ -1303,6 +894,7 @@ "url": "https://tidelift.com/funding/github/npm/postcss" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -1314,9 +906,8 @@ }, "node_modules/resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -1331,9 +922,8 @@ }, "node_modules/rollup": { "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "dev": true, + "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -1346,32 +936,28 @@ }, "node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/solid-js": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", - "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", + "license": "MIT", "dependencies": { "csstype": "^3.1.0" } }, "node_modules/solid-refresh": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", - "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/generator": "^7.18.2", "@babel/helper-module-imports": "^7.16.7", @@ -1383,18 +969,16 @@ }, "node_modules/source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -1404,9 +988,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1416,24 +999,21 @@ }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/ts-toolbelt": { "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/typescript": { "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1444,8 +1024,6 @@ }, "node_modules/update-browserslist-db": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", - "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "dev": true, "funding": [ { @@ -1457,6 +1035,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -1470,9 +1049,8 @@ }, "node_modules/vite": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", - "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.15.6", "postcss": "^8.4.16", @@ -1511,9 +1089,8 @@ }, "node_modules/vite-plugin-solid": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", - "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.18.6", "@babel/preset-typescript": "^7.18.6", @@ -1530,8 +1107,6 @@ "dependencies": { "@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", @@ -1540,8 +1115,6 @@ }, "@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" @@ -1549,14 +1122,10 @@ }, "@babel/compat-data": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.0.tgz", - "integrity": "sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==", "dev": true }, "@babel/core": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz", - "integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", @@ -1578,8 +1147,6 @@ }, "@babel/generator": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "dev": true, "requires": { "@babel/types": "^7.19.0", @@ -1589,8 +1156,6 @@ "dependencies": { "@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", @@ -1602,8 +1167,6 @@ }, "@babel/helper-annotate-as-pure": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1611,8 +1174,6 @@ }, "@babel/helper-compilation-targets": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz", - "integrity": "sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==", "dev": true, "requires": { "@babel/compat-data": "^7.19.0", @@ -1623,8 +1184,6 @@ }, "@babel/helper-create-class-features-plugin": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", @@ -1638,14 +1197,10 @@ }, "@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true }, "@babel/helper-function-name": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "requires": { "@babel/template": "^7.18.10", @@ -1654,8 +1209,6 @@ }, "@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1663,8 +1216,6 @@ }, "@babel/helper-member-expression-to-functions": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, "requires": { "@babel/types": "^7.18.9" @@ -1672,8 +1223,6 @@ }, "@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1681,8 +1230,6 @@ }, "@babel/helper-module-transforms": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1697,8 +1244,6 @@ }, "@babel/helper-optimise-call-expression": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1706,14 +1251,10 @@ }, "@babel/helper-plugin-utils": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true }, "@babel/helper-replace-supers": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", - "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1725,8 +1266,6 @@ }, "@babel/helper-simple-access": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1734,8 +1273,6 @@ }, "@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { "@babel/types": "^7.18.6" @@ -1743,26 +1280,18 @@ }, "@babel/helper-string-parser": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "dev": true }, "@babel/helper-validator-identifier": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true }, "@babel/helper-validator-option": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helpers": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, "requires": { "@babel/template": "^7.18.10", @@ -1772,8 +1301,6 @@ }, "@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.18.6", @@ -1783,14 +1310,10 @@ }, "@babel/parser": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.0.tgz", - "integrity": "sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==", "dev": true }, "@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" @@ -1798,8 +1321,6 @@ }, "@babel/plugin-syntax-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" @@ -1807,8 +1328,6 @@ }, "@babel/plugin-transform-typescript": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.0.tgz", - "integrity": "sha512-DOOIywxPpkQHXijXv+s9MDAyZcLp12oYRl3CMWZ6u7TjSoCBq/KqHR/nNFR3+i2xqheZxoF0H2XyL7B6xeSRuA==", "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.19.0", @@ -1818,8 +1337,6 @@ }, "@babel/preset-typescript": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", @@ -1829,8 +1346,6 @@ }, "@babel/template": { "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", @@ -1840,8 +1355,6 @@ }, "@babel/traverse": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.0.tgz", - "integrity": "sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", @@ -1858,8 +1371,6 @@ }, "@babel/types": { "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.18.10", @@ -1867,17 +1378,8 @@ "to-fast-properties": "^2.0.0" } }, - "@esbuild/linux-loong64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz", - "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", - "dev": true, - "optional": true - }, "@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", @@ -1886,26 +1388,18 @@ }, "@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true }, "@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", @@ -1913,21 +1407,18 @@ } }, "@tanstack/query-core": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.2.3.tgz", - "integrity": "sha512-zdt5lYWs1dZaA3IxJbCgtAfHZJScRZONpiLL7YkeOkrme5MfjQqTpjq7LYbzpyuwPOh2Jx68le0PLl57JFv5hQ==" + "version": "4.3.0-beta.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.3.0-beta.4.tgz", + "integrity": "sha512-GFtngk07PTj3WX1P0sN2hnb/z+Y+CnGtwJv2gdDepZ5M87vgaTb2y9qqd6HDpMswTAmEqjBbrNp7X/LCBZkY+A==" }, "@tanstack/solid-query": { - "version": "4.2.3", - "integrity": "sha512-5SKHlnkaA+wAmQroJTx8u6s6fiSYqH6rRoMSXD7Mc/i3fYaBn5FEtsnXmVTwqkBUtERAK7ji43L4JT/KR2wGow==", + "version": "file:.yalc/@tanstack/solid-query", "requires": { - "@tanstack/query-core": "4.2.3" + "@tanstack/query-core": "4.3.0-beta.4" } }, "ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -1935,8 +1426,6 @@ }, "babel-plugin-jsx-dom-expressions": { "version": "0.34.7", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.34.7.tgz", - "integrity": "sha512-jTxBhu/MQscWdOcLfqKAY8lIiRsv1ivrMQShlePoa4G8S2cFNb93HTWN4FFdp3SpILaibygFXWU3H+aHpoGH/w==", "dev": true, "requires": { "@babel/helper-module-imports": "7.16.0", @@ -1947,8 +1436,6 @@ "dependencies": { "@babel/helper-module-imports": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, "requires": { "@babel/types": "^7.16.0" @@ -1958,8 +1445,6 @@ }, "babel-preset-solid": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.5.4.tgz", - "integrity": "sha512-pangM+KhBx8J6gRHiaRO4yD/J5gK3sydX+TIoC1TaYjxtVV78GIHRtg/HHtCAfg/iRQCJyiGR9TrN0brG8eDZA==", "dev": true, "requires": { "babel-plugin-jsx-dom-expressions": "^0.34.5" @@ -1967,8 +1452,6 @@ }, "browserslist": { "version": "4.21.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", - "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "requires": { "caniuse-lite": "^1.0.30001370", @@ -1979,14 +1462,10 @@ }, "caniuse-lite": { "version": "1.0.30001393", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", - "integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "dev": true }, "chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -1996,8 +1475,6 @@ }, "color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -2005,28 +1482,20 @@ }, "color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" } }, "csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "version": "3.1.0" }, "debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -2034,14 +1503,10 @@ }, "electron-to-chromium": { "version": "1.4.245", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.245.tgz", - "integrity": "sha512-kUN8QXmqHAN8phxjF3QpHeX7CbXGXadSngx9r1O/S9jt+uC0O/vjPi/9+8/Mk3sKewLLMrjpBJZMfVpPCdkG3g==", "dev": true }, "esbuild": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz", - "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "requires": { "@esbuild/linux-loong64": "0.15.7", @@ -2067,187 +1532,38 @@ "esbuild-windows-arm64": "0.15.7" } }, - "esbuild-android-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", - "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", - "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", - "dev": true, - "optional": true - }, "esbuild-darwin-64": { "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", - "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", - "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", - "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", - "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", - "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", - "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", - "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", - "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", - "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", - "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", - "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", - "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", - "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", - "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", - "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", - "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", - "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", - "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", "dev": true, "optional": true }, "escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, "has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -2255,20 +1571,14 @@ }, "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", "dev": true }, "is-core-module": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "dev": true, "requires": { "has": "^1.0.3" @@ -2276,32 +1586,22 @@ }, "is-what": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz", - "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==", "dev": true }, "js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, "json5": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true }, "merge-anything": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz", - "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==", "dev": true, "requires": { "is-what": "^4.1.7", @@ -2310,38 +1610,26 @@ }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "nanoid": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, "node-releases": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "postcss": { "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", "dev": true, "requires": { "nanoid": "^3.3.4", @@ -2351,8 +1639,6 @@ }, "resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "requires": { "is-core-module": "^2.9.0", @@ -2362,8 +1648,6 @@ }, "rollup": { "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -2371,28 +1655,20 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "solid-js": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.5.4.tgz", - "integrity": "sha512-+65anSHhH27htkhP5LuC912fviMIckgc7/yN+WWrKhS9Kp3dvtDNl5/m4GWX1lpCvcubjShqJjGt16HET5z5Ig==", "requires": { "csstype": "^3.1.0" } }, "solid-refresh": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz", - "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==", "dev": true, "requires": { "@babel/generator": "^7.18.2", @@ -2402,14 +1678,10 @@ }, "source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, "supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -2417,32 +1689,22 @@ }, "supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, "to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "ts-toolbelt": { "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", "dev": true }, "typescript": { "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", "dev": true }, "update-browserslist-db": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", - "integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "dev": true, "requires": { "escalade": "^3.1.1", @@ -2451,8 +1713,6 @@ }, "vite": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.0.tgz", - "integrity": "sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==", "dev": true, "requires": { "esbuild": "^0.15.6", @@ -2464,8 +1724,6 @@ }, "vite-plugin-solid": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.3.0.tgz", - "integrity": "sha512-N2sa54C3UZC2nN5vpj5o6YP+XdIAZW6n6xv8OasxNAcAJPFeZT7EOVvumL0V4c8hBz1yuYniMWdESY8807fVSg==", "dev": true, "requires": { "@babel/core": "^7.18.6", diff --git a/examples/solid/simple/package.json b/examples/solid/simple/package.json index 0568cc4e257..b363f54f492 100644 --- a/examples/solid/simple/package.json +++ b/examples/solid/simple/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@tanstack/solid-query": "^4.2.3", + "@tanstack/solid-query": "^4.3.0-beta.4", "solid-js": "^1.5.1" }, "devDependencies": { From 1cf1791b9b61ed3211df936892d63698cca90fa7 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 12:41:35 -0400 Subject: [PATCH 215/221] document lack of SSR support --- docs/adapters/solid-query.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/adapters/solid-query.md b/docs/adapters/solid-query.md index 388d5fdd360..b3f8b1964fa 100644 --- a/docs/adapters/solid-query.md +++ b/docs/adapters/solid-query.md @@ -42,6 +42,8 @@ function App() { In general solid query follows the same API as React Query, but there are some important differences to be aware of. Keep these in mind as you read the tanstack query documentation. +- Solid Query does not support server side rendering yet! Please reach out in the solid query channel on the tanstack query discord if you would like to help contribute to solid query's SSR support. + - Exports follow the solid naming convention `createX` instead of `useX` *unless* the export is used to access `context`. For example, `useQuery` becomes `createQuery`, `useMutation` becomes `createMutation`, but `useQueryClient` is `useQueryClient` because it accesses the `client` from the `QueryClientProvider` context. - Query keys passed to `createQuery` and `createQueries` are Accessor functions which return arrays. This change makes it easy to implement reactive query keys. From dc39c08be14914534aa867c153591437d3621fa8 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 18:53:24 -0400 Subject: [PATCH 216/221] fix missing import in suspense tests --- packages/solid-query/src/__tests__/suspense.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index 7c887df590e..8c726f40c4f 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -8,6 +8,7 @@ import { CreateInfiniteQueryResult, createInfiniteQuery, QueryClientProvider, + CreateQueryResult, } from '..' import { createRenderEffect, From 1703769055e8377df88ea6eb77a2081c42cc1635 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 18:53:45 -0400 Subject: [PATCH 217/221] fix bug where disabled queries triggered suspense --- .../src/__tests__/suspense.test.tsx | 46 +++++++++++++++++++ packages/solid-query/src/createBaseQuery.ts | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/packages/solid-query/src/__tests__/suspense.test.tsx b/packages/solid-query/src/__tests__/suspense.test.tsx index 8c726f40c4f..c3d0816e213 100644 --- a/packages/solid-query/src/__tests__/suspense.test.tsx +++ b/packages/solid-query/src/__tests__/suspense.test.tsx @@ -807,6 +807,52 @@ describe("useQuery's in Suspense mode", () => { expect(queryFn).toHaveBeenCalledTimes(1) }) + it('should not render suspense fallback when not enabled', async () => { + const key = queryKey() + + function Page() { + const [enabled, setEnabled] = createSignal(false) + const result = createQuery( + key, + () => { + sleep(10) + return 'data' + }, + { + suspense: true, + get enabled() { + return enabled() + }, + }, + ) + + return ( +
+ +

{result.data ?? 'default'}

+
+ ) + } + + render(() => ( + + + + + + )) + + expect(screen.queryByText('Loading...')).toBeNull() + expect(screen.getByRole('heading').textContent).toBe('default') + await sleep(5) + fireEvent.click(screen.getByRole('button', { name: /fire/i })) + await waitFor(() => screen.getByText('Loading...')) + + await waitFor(() => { + expect(screen.getByRole('heading').textContent).toBe('data') + }) + }) + it('should error catched in error boundary without infinite loop', async () => { const key = queryKey() diff --git a/packages/solid-query/src/createBaseQuery.ts b/packages/solid-query/src/createBaseQuery.ts index 3fb4008c271..e345f3d4dda 100644 --- a/packages/solid-query/src/createBaseQuery.ts +++ b/packages/solid-query/src/createBaseQuery.ts @@ -98,7 +98,7 @@ export function createBaseQuery< target: QueryObserverResult, prop: keyof QueryObserverResult, ): any { - if (prop === 'data') { + if (prop === 'data' && target.isLoading && target.isFetching) { return dataResource() } return Reflect.get(target, prop) From b0a53c54c04d364a8b1f63fc5e355c27c2d34a3a Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 20:40:21 -0400 Subject: [PATCH 218/221] fix build - mark solid/store as external dep - mark @tanstack/solid-query as side effect free for tree shaking --- packages/solid-query/package.json | 1 + rollup.config.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json index 625e3923c34..a0549de04c4 100644 --- a/packages/solid-query/package.json +++ b/packages/solid-query/package.json @@ -20,6 +20,7 @@ }, "./package.json": "./package.json" }, + "sideEffects": false, "scripts": { "clean": "rm -rf ./build", "test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src", diff --git a/rollup.config.ts b/rollup.config.ts index 890ead5a6db..18a156eddb1 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -145,6 +145,7 @@ export default function rollup(options: RollupOptions): RollupOptions[] { outputFile: 'index', entryFile: 'src/index.ts', globals: { + 'solid-js/store': 'SolidStore', 'solid-js': 'Solid', '@tanstack/query-core': 'QueryCore', }, From 4e1dd28bfa52c2082b8be7ca888c15ac6d9d3068 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 22:05:06 -0400 Subject: [PATCH 219/221] add exports from solid preset --- packages/solid-query/package.json | 9 ++++++++- packages/solid-query/tsconfig.json | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json index a0549de04c4..9186625f672 100644 --- a/packages/solid-query/package.json +++ b/packages/solid-query/package.json @@ -14,9 +14,16 @@ "main": "build/lib/index.js", "exports": { ".": { + "solid": "./build/lib/solid/index.js", "types": "./build/lib/index.d.ts", "import": "./build/lib/index.mjs", - "default": "./build/lib/index.js" + "default": "./build/lib/index.js", + "browser": { + "import": "./build/lib/index.mjs", + "require": "./build/lib/index.js" + }, + "require": "./build/lib/index.js", + "node": "./build/lib/index.js" }, "./package.json": "./package.json" }, diff --git a/packages/solid-query/tsconfig.json b/packages/solid-query/tsconfig.json index 7aad9785f9d..487fed1758c 100644 --- a/packages/solid-query/tsconfig.json +++ b/packages/solid-query/tsconfig.json @@ -3,10 +3,12 @@ "compilerOptions": { "composite": true, "rootDir": "./src", - "outDir": "./build/lib", + "outDir": "./build/solid", + "declarationDir": "./build/lib", "tsBuildInfoFile": "./build/.tsbuildinfo", "jsx": "preserve", - "jsxImportSource": "solid-js" + "jsxImportSource": "solid-js", + "emitDeclarationOnly": false }, "include": ["src"], // comment this out to fix errors in tests during development From 47cea89f5494bee9e36c5d54606e8d973b831ff0 Mon Sep 17 00:00:00 2001 From: Luke Murray Date: Mon, 19 Sep 2022 23:32:09 -0400 Subject: [PATCH 220/221] fix build issues - make type come first - make browser valid - make default come last - fix path to solid export - include solid files in files --- packages/solid-query/package.json | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/solid-query/package.json b/packages/solid-query/package.json index 9186625f672..388bff80b54 100644 --- a/packages/solid-query/package.json +++ b/packages/solid-query/package.json @@ -14,16 +14,13 @@ "main": "build/lib/index.js", "exports": { ".": { - "solid": "./build/lib/solid/index.js", "types": "./build/lib/index.d.ts", + "solid": "./build/solid/index.js", "import": "./build/lib/index.mjs", - "default": "./build/lib/index.js", - "browser": { - "import": "./build/lib/index.mjs", - "require": "./build/lib/index.js" - }, + "browser": "./build/lib/index.mjs", "require": "./build/lib/index.js", - "node": "./build/lib/index.js" + "node": "./build/lib/index.js", + "default": "./build/lib/index.js" }, "./package.json": "./package.json" }, @@ -37,6 +34,7 @@ "files": [ "build/lib/*", "build/umd/*", + "build/solid/*", "src", "codemods", "!codemods/jest.config.js", From 4a6586abe0714903f5b0f1650b887c530356d140 Mon Sep 17 00:00:00 2001 From: Aryan Deora Date: Wed, 21 Sep 2022 00:13:41 -0400 Subject: [PATCH 221/221] Updated adapter docs Thanks to all these amazing folks who helped in making solid-query a reality Co-Authored-By: Luke Murray <34020210+lukesmurray@users.noreply.github.com> Co-Authored-By: Jen Kaplan <25395806+jennyckaplan@users.noreply.github.com> Co-Authored-By: Oscar Beaumont --- docs/adapters/solid-query.md | 127 +++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 57 deletions(-) diff --git a/docs/adapters/solid-query.md b/docs/adapters/solid-query.md index b3f8b1964fa..bf495388316 100644 --- a/docs/adapters/solid-query.md +++ b/docs/adapters/solid-query.md @@ -1,14 +1,14 @@ --- -title: Solid Query (Coming Soon) +title: Solid Query --- -The `@tanstack/solid-query` package offers a 1st-class API for using TanStack Query via Solid. However, all of the primitives you receive from this API are core APIs that are shared across all of the TanStack Adapters including the Query Client, query results, query subscriptions, etc. +The `@tanstack/solid-query` package provides a 1st-class API for using TanStack Query with SolidJS. ## Example ```tsx import { QueryClient, QueryClientProvider, createQuery } from '@tanstack/solid-query' -import { For } from 'solid-js' +import { Switch, Match, For } from 'solid-js' const queryClient = new QueryClient() @@ -17,13 +17,19 @@ function Example() { return (
- {query.isLoading ? ( - 'Loading...' - ) : query.isError ? ( - 'Error!' - ) : query.data ? ( - {(todo) =>
{todo.title}
}
- ) : null} + + +

Loading...

+
+ +

Error: {query.error.message}

+
+ + + {(todo) =>

{todo.title}

} +
+
+
) } @@ -38,38 +44,58 @@ function App() { ``` -## Important Differences with React Query +## Available Functions + +Solid Query offers useful primitives and functions that will make managing server state in SolidJS apps easier. + +- `createQuery` +- `createQueries` +- `createInfiniteQueries` +- `createMutation` +- `useIsFetching` +- `useIsMutating` +- `useQueryClient` +- `QueryClient` +- `QueryClientProvider` -In general solid query follows the same API as React Query, but there are some important differences to be aware of. Keep these in mind as you read the tanstack query documentation. -- Solid Query does not support server side rendering yet! Please reach out in the solid query channel on the tanstack query discord if you would like to help contribute to solid query's SSR support. -- Exports follow the solid naming convention `createX` instead of `useX` *unless* the export is used to access `context`. For example, `useQuery` becomes `createQuery`, `useMutation` becomes `createMutation`, but `useQueryClient` is `useQueryClient` because it accesses the `client` from the `QueryClientProvider` context. -- Query keys passed to `createQuery` and `createQueries` are Accessor functions which return arrays. This change makes it easy to implement reactive query keys. +## Important Differences between Solid Query & React Query + +Solid Query offers an API similar to React Query, but there are some key differences to be mindful of. + +- To maintain their reactivity, Query keys need to be wrapped inside a function while using `createQuery`, `createQueries`, `createInfiniteQuery` and `useIsFetching`. ```tsx // ❌ react version -useQuery(["todos"], fetchTodos) +useQuery(["todos", todo], fetchTodos) // ✅ solid version -createQuery(() => ["todos"], fetchTodos) +createQuery(() => ["todos", todo()], fetchTodos) ``` -> Mutation keys are not accessors. Why? Because it is impossible to differentiate the `createMutation` overloads `createMutation(mutationFn, options)` and `createMutation(mutationKey, options)` if the mutation key is an accessor function. -> If you need reactivity in a mutation key you can pass the mutation key as an option with an object getter. -> ```tsx -> createMutation(updateTodos, { -> // ✅ reactive mutation key passed as an object getter -> get mutationKey() { -> return ["todos"] -> } -> }) -> ``` +- Suspense works for queries out of the box if you access the query data inside a `` boundary. -- Solid Query does not export a `QueryErrorResetBoundary`. Instead wrap your components in a solid ``. +```tsx +import { For, Suspense } from 'solid-js' + +function Example() { + const query = createQuery(() => ['todos'], fetchTodos) + return ( +
+ {/* ✅ Will trigger loading fallback, data accessed in a suspense context. */} + + {(todo) =>
{todo.title}
}
+
+ {/* ❌ Will not trigger loading fallback, data not accessed in a suspense context. */} + {(todo) =>
{todo.title}
}
+
+ ) +} +``` -- `createQuery` does not support destructuring outside of a reactive context. The return value of `createQuery` is a store, and accessing values in the store is only reactive in a reactive context. +- Solid Query primitives (`createX`) do not support destructuring. The return value from these functions is a store, and their properties are only tracked in a reactive context. ```tsx import { QueryClient, QueryClientProvider, createQuery } from '@tanstack/solid-query' @@ -147,13 +173,19 @@ function Example() { return (
- {query.isLoading ? ( - 'Loading...' - ) : query.isError ? ( - 'Error!' - ) : query.data ? ( - {(todo) =>
{todo.title}
}
- ) : null} + + +

Loading...

+
+ +

Error: {query.error.message}

+
+ + + {(todo) =>

{todo.title}

} +
+
+
) @@ -168,25 +200,6 @@ function App() { } ``` -- You do not need to provide `suspense: true` to query options. Suspense works for queries out of the box if you access the query data in a `` context. - - -```tsx -import { For, Suspense } from 'solid-js' - -function Example() { - const query = createQuery(() => ['todos'], fetchTodos) - return ( -
- {/* ✅ Will trigger loading fallback, data accessed in a suspense context. */} - - {(todo) =>
{todo.title}
}
-
- {/* ❌ Will not trigger loading fallback, data not accessed in a suspense context. */} - {(todo) =>
{todo.title}
}
-
- ) -} -``` +- Errors can be caught and reset using SolidJS' native `ErrorBoundary` component. `QueryErrorResetBoundary` is not needed with Solid Query -- Property tracking is handled through solid's fine grained reactivity, so `notifyOnChange` options are not used. \ No newline at end of file +- Since Property tracking is handled through Solid's fine grained reactivity, options like `notifyOnChangeProps` are not needed \ No newline at end of file