@tanstack/svelte-query 4.39.0 → 4.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ <script>import { useHydrate } from "./useHydrate";
2
+ export let state;
3
+ export let options = void 0;
4
+ useHydrate(state, options);
5
+ </script>
6
+
7
+ <slot />
@@ -1,5 +1,5 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import type { DehydratedState, HydrateOptions } from '@tanstack/query-core';
2
+ import type { HydrateOptions } from '@tanstack/query-core';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  state: DehydratedState;
@@ -0,0 +1,14 @@
1
+ <script>import { onDestroy, onMount } from "svelte";
2
+ import { QueryClient } from "@tanstack/query-core";
3
+ import { setQueryClientContext } from "./context";
4
+ export let client = new QueryClient();
5
+ onMount(() => {
6
+ client.mount();
7
+ });
8
+ setQueryClientContext(client);
9
+ onDestroy(() => {
10
+ client.unmount();
11
+ });
12
+ </script>
13
+
14
+ <slot />
@@ -1,8 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import { QueryClient } from '@tanstack/query-core';
3
2
  declare const __propDef: {
4
3
  props: {
5
- client?: QueryClient | undefined;
4
+ client?: any;
6
5
  };
7
6
  events: {
8
7
  [evt: string]: CustomEvent<any>;
@@ -0,0 +1,10 @@
1
+ <script>import { QueryClient } from "@tanstack/query-core";
2
+ import { setQueryClientContext } from "../context";
3
+ import { createMutation } from "../createMutation";
4
+ export let options;
5
+ const queryClient = new QueryClient();
6
+ setQueryClientContext(queryClient);
7
+ const mutation = createMutation(options);
8
+ </script>
9
+
10
+ <button on:click={() => $mutation.mutate()}>Click</button>
@@ -0,0 +1,14 @@
1
+ <script>import { QueryClient } from "@tanstack/query-core";
2
+ import { setQueryClientContext } from "../context";
3
+ import { createQueries } from "../createQueries";
4
+ export let options;
5
+ const queryClient = new QueryClient();
6
+ setQueryClientContext(queryClient);
7
+ const queries = createQueries(options);
8
+ </script>
9
+
10
+ {#each $queries as query}
11
+ {#if query.isSuccess}
12
+ <p>{query.data}</p>
13
+ {/if}
14
+ {/each}
@@ -0,0 +1,16 @@
1
+ <script>import { QueryClient } from "@tanstack/query-core";
2
+ import { setQueryClientContext } from "../context";
3
+ import { createQuery } from "../createQuery";
4
+ export let options;
5
+ const queryClient = new QueryClient();
6
+ setQueryClientContext(queryClient);
7
+ const query = createQuery(options);
8
+ </script>
9
+
10
+ {#if $query.isLoading}
11
+ <p>Loading</p>
12
+ {:else if $query.isError}
13
+ <p>Error</p>
14
+ {:else if $query.isSuccess}
15
+ <p>Success</p>
16
+ {/if}
@@ -0,0 +1,19 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { fireEvent, render, waitFor } from '@testing-library/svelte';
3
+ import CreateMutation from './CreateMutation.svelte';
4
+ describe('createMutation', () => {
5
+ it('Call mutate and check function runs', async () => {
6
+ const mutationFn = vi.fn();
7
+ const rendered = render(CreateMutation, {
8
+ props: {
9
+ options: {
10
+ mutationFn,
11
+ },
12
+ },
13
+ });
14
+ fireEvent.click(rendered.getByRole('button'));
15
+ await waitFor(() => {
16
+ expect(mutationFn).toHaveBeenCalledTimes(1);
17
+ });
18
+ });
19
+ });
@@ -0,0 +1,36 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { render, waitFor } from '@testing-library/svelte';
3
+ import CreateQueries from './CreateQueries.svelte';
4
+ import { sleep } from './utils';
5
+ describe('createQueries', () => {
6
+ it('Render and wait for success', async () => {
7
+ const rendered = render(CreateQueries, {
8
+ props: {
9
+ options: [
10
+ {
11
+ queryKey: ['key-1'],
12
+ queryFn: async () => {
13
+ await sleep(10);
14
+ return 'Success 1';
15
+ },
16
+ },
17
+ {
18
+ queryKey: ['key-2'],
19
+ queryFn: async () => {
20
+ await sleep(10);
21
+ return 'Success 2';
22
+ },
23
+ },
24
+ ],
25
+ },
26
+ });
27
+ await waitFor(() => {
28
+ expect(rendered.queryByText('Success 1')).not.toBeInTheDocument();
29
+ expect(rendered.queryByText('Success 2')).not.toBeInTheDocument();
30
+ });
31
+ await waitFor(() => {
32
+ expect(rendered.queryByText('Success 1')).toBeInTheDocument();
33
+ expect(rendered.queryByText('Success 2')).toBeInTheDocument();
34
+ });
35
+ });
36
+ });
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { render, waitFor } from '@testing-library/svelte';
3
+ import CreateQuery from './CreateQuery.svelte';
4
+ import { sleep } from './utils';
5
+ describe('createQuery', () => {
6
+ it('Render and wait for success', async () => {
7
+ const rendered = render(CreateQuery, {
8
+ props: {
9
+ options: {
10
+ queryKey: ['test'],
11
+ queryFn: async () => {
12
+ await sleep(10);
13
+ return 'Success';
14
+ },
15
+ },
16
+ },
17
+ });
18
+ await waitFor(() => {
19
+ expect(rendered.getByText('Loading')).toBeInTheDocument();
20
+ });
21
+ await waitFor(() => {
22
+ expect(rendered.getByText('Success')).toBeInTheDocument();
23
+ });
24
+ });
25
+ });
@@ -0,0 +1,54 @@
1
+ import { vi } from 'vitest';
2
+ import { act } from '@testing-library/svelte';
3
+ import { QueryClient, } from '../index';
4
+ export function createQueryClient(config) {
5
+ vi.spyOn(console, 'error').mockImplementation(() => undefined);
6
+ return new QueryClient({ logger: mockLogger, ...config });
7
+ }
8
+ export function mockVisibilityState(value) {
9
+ return vi.spyOn(document, 'visibilityState', 'get').mockReturnValue(value);
10
+ }
11
+ export function mockNavigatorOnLine(value) {
12
+ return vi.spyOn(navigator, 'onLine', 'get').mockReturnValue(value);
13
+ }
14
+ export const mockLogger = {
15
+ log: vi.fn(),
16
+ warn: vi.fn(),
17
+ error: vi.fn(),
18
+ };
19
+ let queryKeyCount = 0;
20
+ export function queryKey() {
21
+ queryKeyCount++;
22
+ return [`query_${queryKeyCount}`];
23
+ }
24
+ export function sleep(timeout) {
25
+ return new Promise((resolve, _reject) => {
26
+ setTimeout(resolve, timeout);
27
+ });
28
+ }
29
+ export async function simplefetcher() {
30
+ await sleep(10);
31
+ return 'test';
32
+ }
33
+ export function setActTimeout(fn, ms) {
34
+ return setTimeout(() => {
35
+ act(() => {
36
+ fn();
37
+ });
38
+ }, ms);
39
+ }
40
+ /**
41
+ * Assert the parameter is of a specific type.
42
+ */
43
+ export function expectType(_) {
44
+ return undefined;
45
+ }
46
+ /**
47
+ * Assert the parameter is not typed as `any`
48
+ */
49
+ export function expectTypeNotAny(_) {
50
+ return undefined;
51
+ }
52
+ export function executeMutation(queryClient, options) {
53
+ return queryClient.getMutationCache().build(queryClient, options).execute();
54
+ }
@@ -1,4 +1,3 @@
1
- import type { QueryClient } from '@tanstack/query-core';
2
1
  /** Retrieves a Client from Svelte's context */
3
2
  export declare const getQueryClientContext: () => QueryClient;
4
3
  /** Sets a QueryClient on Svelte's context */
@@ -0,0 +1,14 @@
1
+ import { getContext, setContext } from 'svelte';
2
+ const _contextKey = '$$_queryClient';
3
+ /** Retrieves a Client from Svelte's context */
4
+ export const getQueryClientContext = () => {
5
+ const client = getContext(_contextKey);
6
+ if (!client) {
7
+ throw new Error('No QueryClient was found in Svelte context. Did you forget to wrap your component with QueryClientProvider?');
8
+ }
9
+ return client;
10
+ };
11
+ /** Sets a QueryClient on Svelte's context */
12
+ export const setQueryClientContext = (client) => {
13
+ setContext(_contextKey, client);
14
+ };
@@ -0,0 +1,35 @@
1
+ import { notifyManager, } from '@tanstack/query-core';
2
+ import { derived, readable } from 'svelte/store';
3
+ import { useQueryClient } from './useQueryClient';
4
+ export function createBaseQuery(options, Observer) {
5
+ const queryClient = useQueryClient();
6
+ const defaultedOptions = queryClient.defaultQueryOptions(options);
7
+ defaultedOptions._optimisticResults = 'optimistic';
8
+ let observer = new Observer(queryClient, defaultedOptions);
9
+ // Include callbacks in batch renders
10
+ if (defaultedOptions.onError) {
11
+ defaultedOptions.onError = notifyManager.batchCalls(defaultedOptions.onError);
12
+ }
13
+ if (defaultedOptions.onSuccess) {
14
+ defaultedOptions.onSuccess = notifyManager.batchCalls(defaultedOptions.onSuccess);
15
+ }
16
+ if (defaultedOptions.onSettled) {
17
+ defaultedOptions.onSettled = notifyManager.batchCalls(defaultedOptions.onSettled);
18
+ }
19
+ readable(observer).subscribe(($observer) => {
20
+ observer = $observer;
21
+ // Do not notify on updates because of changes in the options because
22
+ // these changes should already be reflected in the optimistic result.
23
+ observer.setOptions(defaultedOptions, { listeners: false });
24
+ });
25
+ const result = readable(observer.getCurrentResult(), (set) => {
26
+ return observer.subscribe(notifyManager.batchCalls(set));
27
+ });
28
+ const { subscribe } = derived(result, ($result) => {
29
+ $result = observer.getOptimisticResult(defaultedOptions);
30
+ return !defaultedOptions.notifyOnChangeProps
31
+ ? observer.trackResult($result)
32
+ : $result;
33
+ });
34
+ return { subscribe };
35
+ }
@@ -0,0 +1,6 @@
1
+ import { InfiniteQueryObserver, parseQueryArgs, } from '@tanstack/query-core';
2
+ import { createBaseQuery } from './createBaseQuery';
3
+ export function createInfiniteQuery(arg1, arg2, arg3) {
4
+ const options = parseQueryArgs(arg1, arg2, arg3);
5
+ return createBaseQuery(options, InfiniteQueryObserver);
6
+ }
@@ -0,0 +1,27 @@
1
+ import { derived, readable } from 'svelte/store';
2
+ import { MutationObserver, notifyManager, parseMutationArgs, } from '@tanstack/query-core';
3
+ import { useQueryClient } from './useQueryClient';
4
+ export function createMutation(arg1, arg2, arg3) {
5
+ const options = parseMutationArgs(arg1, arg2, arg3);
6
+ const queryClient = useQueryClient();
7
+ let observer = new MutationObserver(queryClient, options);
8
+ let mutate;
9
+ readable(observer).subscribe(($observer) => {
10
+ observer = $observer;
11
+ mutate = (variables, mutateOptions) => {
12
+ observer.mutate(variables, mutateOptions).catch(noop);
13
+ };
14
+ observer.setOptions(options);
15
+ });
16
+ const result = readable(observer.getCurrentResult(), (set) => {
17
+ return observer.subscribe(notifyManager.batchCalls((val) => set(val)));
18
+ });
19
+ const { subscribe } = derived(result, ($result) => ({
20
+ ...$result,
21
+ mutate,
22
+ mutateAsync: $result.mutate,
23
+ }));
24
+ return { subscribe };
25
+ }
26
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
27
+ function noop() { }
@@ -0,0 +1,27 @@
1
+ import { QueriesObserver, notifyManager } from '@tanstack/query-core';
2
+ import { readable } from 'svelte/store';
3
+ import { useQueryClient } from './useQueryClient';
4
+ export function createQueries(queries) {
5
+ const client = useQueryClient();
6
+ // const isRestoring = useIsRestoring()
7
+ function getDefaultQuery(newQueries) {
8
+ return newQueries.map((options) => {
9
+ const defaultedOptions = client.defaultQueryOptions(options);
10
+ // Make sure the results are already in fetching state before subscribing or updating options
11
+ defaultedOptions._optimisticResults = 'optimistic';
12
+ return defaultedOptions;
13
+ });
14
+ }
15
+ const defaultedQueries = getDefaultQuery(queries);
16
+ let observer = new QueriesObserver(client, defaultedQueries);
17
+ readable(observer).subscribe(($observer) => {
18
+ observer = $observer;
19
+ // Do not notify on updates because of changes in the options because
20
+ // these changes should already be reflected in the optimistic result.
21
+ observer.setQueries(defaultedQueries, { listeners: false });
22
+ });
23
+ const { subscribe } = readable(observer.getOptimisticResult(defaultedQueries), (set) => {
24
+ return observer.subscribe(notifyManager.batchCalls(set));
25
+ });
26
+ return { subscribe };
27
+ }
@@ -0,0 +1,7 @@
1
+ import { QueryObserver, parseQueryArgs } from '@tanstack/query-core';
2
+ import { createBaseQuery } from './createBaseQuery';
3
+ export function createQuery(arg1, arg2, arg3) {
4
+ const parsedOptions = parseQueryArgs(arg1, arg2, arg3);
5
+ const result = createBaseQuery(parsedOptions, QueryObserver);
6
+ return result;
7
+ }
@@ -0,0 +1,16 @@
1
+ /* istanbul ignore file */
2
+ // Re-export core
3
+ export * from '@tanstack/query-core';
4
+ // Svelte Query
5
+ export * from './types';
6
+ export * from './context';
7
+ export { createQuery } from './createQuery';
8
+ export { createQueries } from './createQueries';
9
+ export { createInfiniteQuery } from './createInfiniteQuery';
10
+ export { createMutation } from './createMutation';
11
+ export { useQueryClient } from './useQueryClient';
12
+ export { useIsFetching } from './useIsFetching';
13
+ export { useIsMutating } from './useIsMutating';
14
+ export { useHydrate } from './useHydrate';
15
+ export { default as Hydrate } from './Hydrate.svelte';
16
+ export { default as QueryClientProvider } from './QueryClientProvider.svelte';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { hydrate, } from '@tanstack/query-core';
2
+ import { useQueryClient } from './useQueryClient';
3
+ export function useHydrate(state, options) {
4
+ const client = useQueryClient();
5
+ if (state) {
6
+ hydrate(client, state, options);
7
+ }
8
+ }
@@ -0,0 +1,21 @@
1
+ import { notifyManager, parseFilterArgs, } from '@tanstack/query-core';
2
+ import { readable } from 'svelte/store';
3
+ import { useQueryClient } from './useQueryClient';
4
+ export function useIsFetching(arg1, arg2) {
5
+ const [filters] = parseFilterArgs(arg1, arg2);
6
+ const client = useQueryClient();
7
+ const cache = client.getQueryCache();
8
+ // isFetching is the prev value initialized on mount *
9
+ let isFetching = client.isFetching(filters);
10
+ const { subscribe } = readable(isFetching, (set) => {
11
+ return cache.subscribe(notifyManager.batchCalls(() => {
12
+ const newIsFetching = client.isFetching(filters);
13
+ if (isFetching !== newIsFetching) {
14
+ // * and update with each change
15
+ isFetching = newIsFetching;
16
+ set(isFetching);
17
+ }
18
+ }));
19
+ });
20
+ return { subscribe };
21
+ }
@@ -0,0 +1,21 @@
1
+ import { notifyManager, parseMutationFilterArgs, } from '@tanstack/query-core';
2
+ import { readable } from 'svelte/store';
3
+ import { useQueryClient } from './useQueryClient';
4
+ export function useIsMutating(arg1, arg2) {
5
+ const [filters] = parseMutationFilterArgs(arg1, arg2);
6
+ const client = useQueryClient();
7
+ const cache = client.getMutationCache();
8
+ // isMutating is the prev value initialized on mount *
9
+ let isMutating = client.isMutating(filters);
10
+ const { subscribe } = readable(isMutating, (set) => {
11
+ return cache.subscribe(notifyManager.batchCalls(() => {
12
+ const newIisMutating = client.isMutating(filters);
13
+ if (isMutating !== newIisMutating) {
14
+ // * and update with each change
15
+ isMutating = newIisMutating;
16
+ set(isMutating);
17
+ }
18
+ }));
19
+ });
20
+ return { subscribe };
21
+ }
@@ -0,0 +1,5 @@
1
+ import { getQueryClientContext } from './context';
2
+ export function useQueryClient() {
3
+ const queryClient = getQueryClientContext();
4
+ return queryClient;
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/svelte-query",
3
- "version": "4.39.0",
3
+ "version": "4.39.1",
4
4
  "description": "Primitives for managing, caching and syncing asynchronous and remote data in Svelte",
5
5
  "author": "Lachlan Collins",
6
6
  "license": "MIT",
@@ -48,7 +48,7 @@
48
48
  "vitest": "^0.27.1"
49
49
  },
50
50
  "dependencies": {
51
- "@tanstack/query-core": "4.39.0"
51
+ "@tanstack/query-core": "4.39.1"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "svelte": ">=3 <5"