@studiolambda/query 1.4.0 → 1.5.4
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.
- package/dist/query-CGIqlfYX.js +185 -0
- package/dist/query-CGIqlfYX.js.map +1 -0
- package/dist/query-Do4OvbxG.cjs +2 -0
- package/dist/query-Do4OvbxG.cjs.map +1 -0
- package/dist/query.cjs +1 -2
- package/dist/query.js +2 -193
- package/dist/query_react.cjs +3 -19
- package/dist/query_react.cjs.map +1 -1
- package/dist/query_react.js +255 -418
- package/dist/query_react.js.map +1 -1
- package/dist/src/query/options.d.ts +78 -4
- package/dist/src/react/components/QueryPrefetch.d.ts +30 -1
- package/dist/src/react/components/QueryPrefetchTags.d.ts +34 -1
- package/dist/src/react/components/QueryProvider.d.ts +30 -0
- package/dist/src/react/components/QueryTransition.d.ts +35 -0
- package/dist/src/react/context.d.ts +17 -0
- package/dist/src/react/hooks/useQuery.d.ts +44 -2
- package/dist/src/react/hooks/useQueryActions.d.ts +55 -1
- package/dist/src/react/hooks/useQueryBasic.d.ts +42 -2
- package/dist/src/react/hooks/useQueryContext.d.ts +13 -0
- package/dist/src/react/hooks/useQueryInstance.d.ts +27 -0
- package/dist/src/react/hooks/useQueryPrefetch.d.ts +15 -1
- package/dist/src/react/hooks/useQueryStatus.d.ts +40 -0
- package/dist/src/react/hooks/useQueryTransitionContext.d.ts +14 -0
- package/dist/src/react/transition.d.ts +17 -0
- package/package.json +57 -59
- package/dist/query.cjs.map +0 -1
- package/dist/query.js.map +0 -1
|
@@ -1,9 +1,49 @@
|
|
|
1
1
|
import { ContextValue } from '../context';
|
|
2
2
|
import { Options } from '../../query/index';
|
|
3
3
|
import { QueryInstance } from './useQueryInstance';
|
|
4
|
+
/**
|
|
5
|
+
* The return type of the useQueryBasic hook, providing access to
|
|
6
|
+
* the fetched data and the current pending state.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The type of the fetched data.
|
|
9
|
+
*/
|
|
4
10
|
export interface BasicResource<T = unknown> {
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
/**
|
|
12
|
+
* The fetched data for the given key.
|
|
13
|
+
*/
|
|
14
|
+
readonly data: T;
|
|
15
|
+
/**
|
|
16
|
+
* Indicates whether a transition is currently pending.
|
|
17
|
+
*/
|
|
18
|
+
readonly isPending: boolean;
|
|
7
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Configuration options for the useQueryBasic hook, combining context values,
|
|
22
|
+
* query options, and an optional query instance override.
|
|
23
|
+
*
|
|
24
|
+
* @template T - The type of the fetched data.
|
|
25
|
+
*/
|
|
8
26
|
export type BasicResourceOptions<T = unknown> = ContextValue & Options<T> & QueryInstance;
|
|
27
|
+
/**
|
|
28
|
+
* A foundational React hook for fetching and subscribing to cached data.
|
|
29
|
+
* Automatically handles data fetching, caching, and updates when the cache
|
|
30
|
+
* changes. Uses React transitions for smooth UI updates during refetches.
|
|
31
|
+
*
|
|
32
|
+
* This hook provides the core data fetching functionality without the
|
|
33
|
+
* additional actions (refetch, mutate, forget) or status information.
|
|
34
|
+
* Use useQuery for a more complete solution.
|
|
35
|
+
*
|
|
36
|
+
* @template T - The type of the fetched data.
|
|
37
|
+
* @param key - A unique string identifier for the cached resource.
|
|
38
|
+
* @param options - Optional configuration for the query behavior.
|
|
39
|
+
* @returns An object containing the fetched data and pending state.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* const { data, isPending } = useQueryBasic<User>('/api/user/1')
|
|
44
|
+
*
|
|
45
|
+
* if (isPending) return <Loading />
|
|
46
|
+
* return <UserProfile user={data} />
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
9
49
|
export declare function useQueryBasic<T = unknown>(key: string, options?: BasicResourceOptions<T>): BasicResource<T>;
|
|
@@ -1,2 +1,15 @@
|
|
|
1
1
|
import { ContextValue } from '../context';
|
|
2
|
+
/**
|
|
3
|
+
* A React hook that retrieves the current query context value from the
|
|
4
|
+
* nearest QueryProvider ancestor. Returns the context configuration
|
|
5
|
+
* including the query instance and options like clearOnForget.
|
|
6
|
+
*
|
|
7
|
+
* @returns The current query context value containing the query instance
|
|
8
|
+
* and configuration options.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const { query, clearOnForget } = useQueryContext()
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
2
15
|
export declare function useQueryContext(): ContextValue;
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
import { Query } from '../../query/index';
|
|
2
|
+
/**
|
|
3
|
+
* Options interface that allows providing a custom query instance,
|
|
4
|
+
* overriding the one from the context.
|
|
5
|
+
*/
|
|
2
6
|
export interface QueryInstance {
|
|
7
|
+
/**
|
|
8
|
+
* An optional query instance to use instead of the context query.
|
|
9
|
+
*/
|
|
3
10
|
readonly query?: Query;
|
|
4
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Error thrown when no query instance is available from either
|
|
14
|
+
* the options or the context.
|
|
15
|
+
*/
|
|
16
|
+
export declare const ErrNoQueryInstanceFound: Error;
|
|
17
|
+
/**
|
|
18
|
+
* A React hook that resolves the query instance to use, preferring the
|
|
19
|
+
* instance from options over the one from context. Throws an error if
|
|
20
|
+
* no instance is available.
|
|
21
|
+
*
|
|
22
|
+
* @param options - Optional configuration containing a query instance.
|
|
23
|
+
* @returns The resolved query instance.
|
|
24
|
+
* @throws Error if no query instance is found in options or context.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* const query = useQueryInstance()
|
|
29
|
+
* const data = await query('key')
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
5
32
|
export declare function useQueryInstance(options?: QueryInstance): Query;
|
|
@@ -1,2 +1,16 @@
|
|
|
1
1
|
import { QueryInstance } from './useQueryInstance';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* A React hook that prefetches multiple query keys on mount. Useful for
|
|
4
|
+
* warming the cache with data that will be needed soon, improving perceived
|
|
5
|
+
* performance when the user navigates to views that use these keys.
|
|
6
|
+
*
|
|
7
|
+
* @param keys - An array of cache keys to prefetch.
|
|
8
|
+
* @param options - Optional configuration containing a query instance.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* // Prefetch user data when the dashboard loads
|
|
13
|
+
* useQueryPrefetch(['/api/user/1', '/api/user/2', '/api/user/3'])
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function useQueryPrefetch(keys: readonly string[], options?: QueryInstance): void;
|
|
@@ -1,8 +1,48 @@
|
|
|
1
1
|
import { QueryInstance } from './useQueryInstance';
|
|
2
|
+
/**
|
|
3
|
+
* The return type of the useQueryStatus hook, providing real-time
|
|
4
|
+
* information about the cache status for a specific key.
|
|
5
|
+
*/
|
|
2
6
|
export interface Status {
|
|
7
|
+
/**
|
|
8
|
+
* The timestamp when the cached data will expire. After this time,
|
|
9
|
+
* the next query will trigger a background refetch.
|
|
10
|
+
*/
|
|
3
11
|
readonly expiresAt: Date;
|
|
12
|
+
/**
|
|
13
|
+
* Indicates whether the cached data has expired. When true, the data
|
|
14
|
+
* is considered stale and will be refetched on the next query.
|
|
15
|
+
*/
|
|
4
16
|
readonly isExpired: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Indicates whether the data is currently being refetched in the
|
|
19
|
+
* background while serving stale data.
|
|
20
|
+
*/
|
|
5
21
|
readonly isRefetching: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Indicates whether a mutation is currently in progress for this key.
|
|
24
|
+
*/
|
|
6
25
|
readonly isMutating: boolean;
|
|
7
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* A React hook that subscribes to and returns the real-time status of a
|
|
29
|
+
* cached query. Useful for displaying loading indicators, staleness
|
|
30
|
+
* warnings, or optimistic UI updates.
|
|
31
|
+
*
|
|
32
|
+
* @param key - A unique string identifier for the cached resource.
|
|
33
|
+
* @param options - Optional configuration containing a query instance.
|
|
34
|
+
* @returns An object containing cache expiration and loading status.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* const { isExpired, isRefetching, isMutating } = useQueryStatus('/api/user/1')
|
|
39
|
+
*
|
|
40
|
+
* return (
|
|
41
|
+
* <div>
|
|
42
|
+
* {isRefetching && <RefreshIndicator />}
|
|
43
|
+
* {isExpired && <StaleWarning />}
|
|
44
|
+
* </div>
|
|
45
|
+
* )
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
8
48
|
export declare function useQueryStatus(key: string, options?: QueryInstance): Status;
|
|
@@ -1,2 +1,16 @@
|
|
|
1
1
|
import { QueryTransitionContextValue } from '../transition';
|
|
2
|
+
/**
|
|
3
|
+
* A React hook that retrieves the current transition context value from the
|
|
4
|
+
* nearest QueryTransition ancestor. Provides access to the shared transition
|
|
5
|
+
* state and startTransition function for coordinating UI updates across
|
|
6
|
+
* multiple query components.
|
|
7
|
+
*
|
|
8
|
+
* @returns The current transition context value containing isPending state
|
|
9
|
+
* and startTransition function.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const { isPending, startTransition } = useQueryTransitionContext()
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
2
16
|
export declare function useQueryTransitionContext(): QueryTransitionContextValue;
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { TransitionStartFunction } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The value type for the transition context, providing shared transition
|
|
4
|
+
* state and control function for coordinating UI updates across multiple
|
|
5
|
+
* query components.
|
|
6
|
+
*/
|
|
2
7
|
export interface QueryTransitionContextValue {
|
|
8
|
+
/**
|
|
9
|
+
* Indicates whether a transition is currently pending. When true,
|
|
10
|
+
* components can show loading indicators or reduce visual updates.
|
|
11
|
+
*/
|
|
3
12
|
readonly isPending?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* The function to start a transition, allowing components to wrap
|
|
15
|
+
* state updates in a transition for smoother UI behavior.
|
|
16
|
+
*/
|
|
4
17
|
readonly startTransition?: TransitionStartFunction;
|
|
5
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* React context that provides shared transition state and control
|
|
21
|
+
* to all descendant query components. Created with default undefined values.
|
|
22
|
+
*/
|
|
6
23
|
export declare const TransitionContext: import('react').Context<QueryTransitionContextValue>;
|
package/package.json
CHANGED
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@studiolambda/query",
|
|
3
|
-
"version": "1.4
|
|
4
|
-
"
|
|
3
|
+
"version": "1.5.4",
|
|
4
|
+
"description": "Lightweight, isomorphic and framework agnostic asynchronous data management for modern UIs",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"swr",
|
|
8
|
-
"react-query",
|
|
9
|
-
"isomorphic",
|
|
6
|
+
"data-management",
|
|
10
7
|
"fetch",
|
|
8
|
+
"isomorphic",
|
|
11
9
|
"query",
|
|
12
|
-
"
|
|
10
|
+
"react",
|
|
11
|
+
"react-query",
|
|
12
|
+
"stale-while-revalidate",
|
|
13
|
+
"swr",
|
|
13
14
|
"ui",
|
|
14
|
-
"vanilla"
|
|
15
|
-
"react"
|
|
15
|
+
"vanilla"
|
|
16
16
|
],
|
|
17
|
-
"
|
|
17
|
+
"homepage": "https://erik.cat/blog/query-docs",
|
|
18
|
+
"license": "MIT",
|
|
18
19
|
"author": {
|
|
19
20
|
"name": "Erik C. Forés",
|
|
20
21
|
"email": "soc@erik.cat",
|
|
21
22
|
"url": "https://erik.cat"
|
|
22
23
|
},
|
|
23
|
-
"homepage": "https://erik.cat/blog/query-docs",
|
|
24
24
|
"repository": {
|
|
25
25
|
"type": "git",
|
|
26
26
|
"url": "https://github.com/StudioLambda/Query.git"
|
|
27
27
|
},
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"package.json"
|
|
31
|
+
],
|
|
31
32
|
"type": "module",
|
|
32
|
-
"
|
|
33
|
+
"sideEffects": false,
|
|
33
34
|
"main": "./dist/query.cjs",
|
|
34
35
|
"module": "./dist/query.js",
|
|
36
|
+
"types": "./dist/src/query/index.d.ts",
|
|
35
37
|
"exports": {
|
|
36
38
|
"./package.json": "./package.json",
|
|
37
39
|
".": {
|
|
@@ -45,36 +47,46 @@
|
|
|
45
47
|
"require": "./dist/query_react.cjs"
|
|
46
48
|
}
|
|
47
49
|
},
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
],
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
52
53
|
"scripts": {
|
|
53
54
|
"build:only": "vite build",
|
|
54
55
|
"build": "npm run build:only",
|
|
55
56
|
"prebuild": "npm run format:check && npm run lint",
|
|
56
|
-
"lint": "
|
|
57
|
-
"format": "
|
|
58
|
-
"format:check": "
|
|
57
|
+
"lint": "oxlint --deny-warnings",
|
|
58
|
+
"format": "oxfmt --write .",
|
|
59
|
+
"format:check": "oxfmt --check .",
|
|
59
60
|
"dev": "vitest",
|
|
60
61
|
"test": "vitest run",
|
|
61
62
|
"test:ui": "vitest --ui --coverage",
|
|
62
63
|
"test:cover": "vitest run --coverage",
|
|
63
64
|
"prepack": "npm run build"
|
|
64
65
|
},
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@rolldown/plugin-babel": "^0.2.2",
|
|
68
|
+
"@types/node": "^25.5.0",
|
|
69
|
+
"@types/react": "19.2.14",
|
|
70
|
+
"@types/react-dom": "19.2.3",
|
|
71
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
72
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
73
|
+
"babel-plugin-react-compiler": "^1.0.0",
|
|
74
|
+
"happy-dom": "^20.8.4",
|
|
75
|
+
"oxfmt": "^0.41.0",
|
|
76
|
+
"oxlint": "^1.56.0",
|
|
77
|
+
"react": "^19.2.4",
|
|
78
|
+
"react-dom": "^19.2.4",
|
|
79
|
+
"react-error-boundary": "^6.1.1",
|
|
80
|
+
"solid-js": "^1.9.11",
|
|
81
|
+
"typescript": "~5.9.3",
|
|
82
|
+
"vite": "^8.0.2",
|
|
83
|
+
"vite-plugin-dts": "^4.5.4",
|
|
84
|
+
"vite-plugin-solid": "^2.11.11",
|
|
85
|
+
"vitest": "^4.1.0"
|
|
74
86
|
},
|
|
75
87
|
"peerDependencies": {
|
|
76
|
-
"react": "^19.
|
|
77
|
-
"react-dom": "^19.
|
|
88
|
+
"react": "^19.2.0",
|
|
89
|
+
"react-dom": "^19.2.0",
|
|
78
90
|
"solid-js": "^1.9.0"
|
|
79
91
|
},
|
|
80
92
|
"peerDependenciesMeta": {
|
|
@@ -88,31 +100,17 @@
|
|
|
88
100
|
"optional": true
|
|
89
101
|
}
|
|
90
102
|
},
|
|
91
|
-
"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
"
|
|
103
|
-
"eslint-plugin-react-refresh": "^0.4.24",
|
|
104
|
-
"eslint-plugin-solid": "^0.14.5",
|
|
105
|
-
"globals": "^16.4.0",
|
|
106
|
-
"happy-dom": "^20.0.8",
|
|
107
|
-
"prettier": "^3.6.2",
|
|
108
|
-
"react": "^19.1.1",
|
|
109
|
-
"react-dom": "^19.1.1",
|
|
110
|
-
"solid-js": "^1.9.9",
|
|
111
|
-
"typescript": "~5.9.3",
|
|
112
|
-
"typescript-eslint": "^8.46.2",
|
|
113
|
-
"vite": "^7.1.12",
|
|
114
|
-
"vite-plugin-dts": "^4.5.4",
|
|
115
|
-
"vite-plugin-solid": "^2.11.10",
|
|
116
|
-
"vitest": "^4.0.3"
|
|
103
|
+
"devEngines": {
|
|
104
|
+
"packageManager": {
|
|
105
|
+
"name": "npm",
|
|
106
|
+
"version": ">=11.0.0"
|
|
107
|
+
},
|
|
108
|
+
"runtime": {
|
|
109
|
+
"name": "node",
|
|
110
|
+
"version": ">=24.0.0"
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"engines": {
|
|
114
|
+
"node": ">=18.0.0"
|
|
117
115
|
}
|
|
118
116
|
}
|
package/dist/query.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query.cjs","sources":["../src/query/query.ts"],"sourcesContent":["import {\n type Caches,\n type CacheType,\n type ItemsCacheItem,\n type ResolversCacheItem,\n} from 'query:cache'\nimport {\n type BroadcastPayload,\n type Configuration,\n type FetcherAdditional,\n type FetcherFunction,\n type HydrateOptions,\n type MutateOptions,\n type MutationFunction,\n type MutationValue,\n type Options,\n type Query,\n type QueryEvent,\n type SubscribeListener,\n type TriggerFunction,\n type Unsubscriber,\n} from 'query:options'\n\n/**\n * Stores the default fetcher function.\n */\nexport function defaultFetcher<T>(\n fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>\n): FetcherFunction<T> {\n return async function (key: string, { signal }: FetcherAdditional): Promise<T> {\n const response = await fetch(key, { signal })\n\n if (!response.ok) {\n throw new Error('Unable to fetch the data: ' + response.statusText)\n }\n\n return (await response.json()) as T\n }\n}\n\n/**\n * Creates a new query instance.\n */\nexport function createQuery(instanceOptions?: Configuration): Query {\n /**\n * Stores the default expiration function.\n */\n function defaultExpiration() {\n return 2000\n }\n\n /**\n * Stores the items cache.\n */\n let itemsCache = instanceOptions?.itemsCache ?? new Map<string, ItemsCacheItem>()\n\n /**\n * Stores the resolvers cache.\n */\n let resolversCache = instanceOptions?.resolversCache ?? new Map<string, ResolversCacheItem>()\n\n /**\n * Event manager.\n */\n let events = instanceOptions?.events ?? new EventTarget()\n\n /**\n * Broadcast channel. This is useful for communicating\n * between tabs and windows (browser contexts).\n *\n * By default it does not use any broadcast channel.\n * If a broadcast channel is provided, query\n * won't close automatically, therefore, the responsability\n * of closing the broadcast channel is up to the user.\n */\n let broadcast = instanceOptions?.broadcast\n\n /**\n * Stores the expiration time of an item.\n */\n let instanceExpiration = instanceOptions?.expiration ?? defaultExpiration\n\n /**\n * Determines the fetcher function to use.\n */\n let instanceFetcher = instanceOptions?.fetcher ?? defaultFetcher(fetch)\n\n /**\n * Determines if we can return a stale item.\n * If `true`, it will return the previous stale item\n * stored in the cache if it has expired. It will attempt\n * to revalidate it in the background. If `false`, the returned\n * promise will be the revalidation promise.\n */\n let instanceStale = instanceOptions?.stale ?? true\n\n /**\n * Removes the stored item if there is an error in the request.\n * By default, we don't remove the item upon failure, only the resolver\n * is removed from the cache.\n */\n let instanceRemoveOnError = instanceOptions?.removeOnError ?? false\n\n /**\n * Determines if the result should be a fresh fetched\n * instance regardless of any cached value or its expiration time.\n */\n let instanceFresh = instanceOptions?.fresh ?? false\n\n /**\n * Configures the current instance of query.\n */\n function configure(options?: Configuration): void {\n itemsCache = options?.itemsCache ?? itemsCache\n resolversCache = options?.resolversCache ?? resolversCache\n events = options?.events ?? events\n broadcast = options?.broadcast ?? broadcast\n instanceExpiration = options?.expiration ?? instanceExpiration\n instanceFetcher = options?.fetcher ?? instanceFetcher\n instanceStale = options?.stale ?? instanceStale\n instanceRemoveOnError = options?.removeOnError ?? instanceRemoveOnError\n instanceFresh = options?.fresh ?? instanceFresh\n }\n\n function emit<T = unknown>(key: string, event: QueryEvent, detail: T) {\n events.dispatchEvent(new CustomEvent(`${event}:${key}`, { detail }))\n\n switch (event) {\n case 'mutated':\n case 'resolved':\n case 'hydrated':\n case 'forgotten':\n broadcast?.postMessage({ event: `${event}:${key}`, detail })\n }\n }\n\n /**\n * Subscribes to a given keyed event. The event handler\n * does have a payload parameter that will contain relevant\n * information depending on the event type.\n * If there's a pending resolver for that key, the `refetching`\n * event is fired immediatly.\n */\n\n function subscribe<T = unknown>(\n key: string,\n event: QueryEvent,\n listener: SubscribeListener<T>\n ): Unsubscriber {\n events.addEventListener(`${event}:${key}`, listener)\n const value = resolversCache.get(key)\n\n // For the refetching event, we want to immediatly return if there's\n // a pending resolver.\n if (event === 'refetching' && value !== undefined) {\n emit(key, event, value.item)\n }\n\n return function () {\n events.removeEventListener(`${event}:${key}`, listener)\n }\n }\n\n /**\n * Mutates the key with a given optimistic value.\n * The mutated value is considered expired and will be\n * replaced immediatly if a refetch happens when expired\n * is true. If expired is false, the value expiration time\n * is added as if it was a valid data refetched. Alternatively\n * you can provide a Date to decide when the expiration happens.\n */\n async function mutate<T = unknown>(\n key: string,\n resolver: MutationValue<T>,\n options?: MutateOptions<T>\n ): Promise<T> {\n async function action(resolver: MutationValue<T>) {\n if (typeof resolver === 'function') {\n const fn = resolver as MutationFunction<T>\n const value = itemsCache.get(key)\n const item = (await value?.item) as T\n\n resolver = await fn(item, value?.expiresAt)\n }\n\n return resolver\n }\n\n const result = action(resolver)\n\n emit(key, 'mutating', result)\n\n const item = await result\n const expiresAt = new Date()\n\n expiresAt.setMilliseconds(expiresAt.getMilliseconds() + (options?.expiration?.(item) ?? 0))\n\n itemsCache.set(key, { item: result, expiresAt: expiresAt })\n\n emit(key, 'mutated', item)\n\n return item\n }\n\n /**\n * Returns the current snapshot of the given key.\n * If the item is not in the items cache, it will return `undefined`.\n */\n async function snapshot<T = unknown>(key: string): Promise<T | undefined> {\n return (await itemsCache.get(key)?.item) as T\n }\n\n /**\n * Determines if the given key is currently resolving.\n */\n function keys(type: CacheType = 'items'): string[] {\n return Array.from(type === 'items' ? itemsCache.keys() : resolversCache.keys())\n }\n\n /**\n * Aborts the active resolvers on each key\n * by calling `.abort()` on the `AbortController`.\n * The fetcher is responsible for using the\n * `AbortSignal` to cancel the job.\n * If no keys are provided, all resolvers are aborted.\n */\n function abort(cacheKeys?: string | string[], reason?: unknown): void {\n const resolverKeys =\n typeof cacheKeys === 'string' ? [cacheKeys] : (cacheKeys ?? keys('resolvers'))\n\n for (const key of resolverKeys) {\n const resolver = resolversCache.get(key)\n\n if (resolver !== undefined) {\n resolver.controller.abort(reason)\n resolversCache.delete(key)\n\n emit(key, 'aborted', reason)\n }\n }\n }\n\n /**\n * Forgets the given keys from the items cache.\n * Does not remove any resolvers.\n * If no keys are provided the items cache is cleared.\n */\n async function forget(cacheKeys?: string | string[] | RegExp): Promise<void> {\n let itemKeys: string[]\n\n if (typeof cacheKeys === 'string') {\n itemKeys = [cacheKeys]\n } else if (Array.isArray(cacheKeys)) {\n itemKeys = cacheKeys\n } else if (cacheKeys instanceof RegExp) {\n itemKeys = keys('items').filter((key) => key.match(cacheKeys))\n } else {\n itemKeys = keys('items')\n }\n\n for (const key of itemKeys) {\n const item = itemsCache.get(key)\n\n if (item !== undefined) {\n itemsCache.delete(key)\n emit(key, 'forgotten', await item.item)\n }\n }\n }\n\n /**\n * Hydrates the given keys on the cache\n * with the given value. Hydrate should only\n * be used when you want to populate the cache.\n * Please use mutate() in most cases unless you\n * know what you are doing.\n */\n function hydrate<T = unknown>(\n keys: string | string[],\n item: T,\n options?: HydrateOptions<T>\n ): void {\n const expiresAt = new Date()\n const result = Promise.resolve(item)\n\n expiresAt.setMilliseconds(expiresAt.getMilliseconds() + (options?.expiration?.(item) ?? 0))\n\n for (const key of typeof keys === 'string' ? [keys] : keys) {\n itemsCache.set(key, { item: result, expiresAt: expiresAt })\n emit(key, 'hydrated', item)\n }\n }\n\n /**\n * Returns the expiration date of a given key item.\n * If the item is not in the cache, it will return `undefined`.\n */\n function expiration(key: string): Date | undefined {\n return itemsCache.get(key)?.expiresAt\n }\n\n /**\n * Fetches the key information using a fetcher.\n * The returned promise contains the result item.\n */\n function query<T = unknown>(key: string, options?: Options<T>): Promise<T> {\n /**\n * Stores the expiration time of an item.\n */\n const expiration = options?.expiration ?? instanceExpiration\n\n /**\n * Determines the fetcher function to use.\n */\n const fetcher = (options?.fetcher ?? instanceFetcher) as FetcherFunction<T>\n\n /**\n * Determines if we can return a sale item\n * If true, it will return the previous stale item\n * stored in the cache if it has expired. It will attempt\n * to revalidate it in the background. If false, the returned\n * promise will be the revalidation promise.\n */\n const stale = options?.stale ?? instanceStale\n\n /**\n * Removes the stored item if there is an error in the request.\n * By default, we don't remove the item upon failure, only the resolver\n * is removed from the cache.\n */\n const removeOnError = options?.removeOnError ?? instanceRemoveOnError\n\n /**\n * Determines if the result should be a fresh fetched\n * instance regardless of any cached value or its expiration time.\n */\n const fresh = options?.fresh ?? instanceOptions?.fresh\n\n // Force fetching of the data.\n function refetch(key: string): Promise<T> {\n // Check if there's a pending resolver for that data.\n const pending = resolversCache.get(key)\n\n if (pending !== undefined) {\n return pending.item as Promise<T>\n }\n\n // Create the abort controller that will be\n // called when a query is aborted.\n const controller = new AbortController()\n\n let trigger: TriggerFunction = undefined\n\n // Initiate the fetching request.\n const result = new Promise<T>(function (resolve, reject) {\n trigger = async function () {\n try {\n const result = fetcher(key, { signal: controller.signal })\n\n // Awaits the fetching to get the result item.\n const item = await result\n\n const promise =\n (resolversCache.get(key)?.item as Promise<T> | undefined) ?? Promise.resolve(item)\n\n // Removes the resolver from the cache.\n resolversCache.delete(key)\n\n // Create the expiration time for the item.\n const expiresAt = new Date()\n expiresAt.setMilliseconds(expiresAt.getMilliseconds() + expiration(item))\n\n // Set the item to the cache.\n itemsCache.set(key, { item: promise, expiresAt })\n\n // Notify of the resolved item.\n emit(key, 'resolved', item)\n\n resolve(item)\n } catch (error) {\n // Remove the resolver.\n resolversCache.delete(key)\n\n // Check if the item should be removed as well.\n if (removeOnError) {\n itemsCache.delete(key)\n }\n\n // Notify of the error.\n emit(key, 'error', error)\n\n // Throw back the error.\n reject(error as Error)\n }\n }\n })\n\n // Adds the resolver to the cache.\n resolversCache.set(key, { item: result, controller })\n emit(key, 'refetching', result)\n\n trigger = trigger as TriggerFunction\n\n while (trigger === undefined) {\n // This ensures that the trigger\n // has been defined, as it is defined\n // inside the promise.\n }\n\n void trigger()\n\n return result\n }\n\n // We want to force a fresh item ignoring any current cached\n // value or its expiration time.\n if (fresh) {\n return refetch(key)\n }\n\n // Check if there's an item in the cache for the given key.\n const cached = itemsCache.get(key)\n\n if (cached === undefined) {\n // The item is not found in the items cache.\n // We need to perform a revalidation of the item.\n return refetch(key)\n }\n\n // We must check if that item has actually expired.\n // to trigger a revalidation if needed.\n const hasExpired = cached.expiresAt <= new Date()\n\n // The item has expired and the fetch is able\n // to return a stale item while revalidating\n // in the background.\n if (hasExpired && stale) {\n // We have to silence the error to avoid unhandled promises.\n // Refer to the error event if you need full controll of errors.\n refetch(key).catch(() => {})\n\n return cached.item as Promise<T>\n }\n\n // The item has expired but we dont allow stale\n // responses so we need to wait for the revalidation.\n if (hasExpired) {\n return refetch(key)\n }\n\n // The item has not yet expired, so we can return it and\n // assume it's valid since it's not yet considered stale.\n return cached.item as Promise<T>\n }\n\n /**\n * Returns the current cache instances.\n */\n function caches(): Caches {\n return { items: itemsCache, resolvers: resolversCache }\n }\n\n /**\n * Returns the event system.\n */\n function localEvents() {\n return events\n }\n\n /**\n * Returns the broadcast channel.\n */\n function localBroadcast() {\n return broadcast\n }\n\n /**\n * Subscribes to the broadcast channel\n * to listen for other browser context\n * events and reproduce them in the current\n * context.\n */\n function subscribeBroadcast(): Unsubscriber {\n function onBroadcastMessage(message: MessageEvent<BroadcastPayload>) {\n events.dispatchEvent(new CustomEvent(message.data.event, { detail: message.data.detail }))\n }\n\n broadcast?.addEventListener('message', onBroadcastMessage)\n\n return function () {\n broadcast?.removeEventListener('message', onBroadcastMessage)\n }\n }\n\n async function next<T = unknown>(keys: string | { [K in keyof T]: string }): Promise<T> {\n const iterator = (Array.isArray(keys) ? keys : [keys]) as string[]\n const promises = iterator.map((key) => once(key, 'refetching'))\n const events = await Promise.all(promises)\n const details = events.map((event) => event.detail as Promise<T>)\n\n return (await (Array.isArray(keys) ? Promise.all(details) : details[0])) as T\n }\n\n async function* stream<T = unknown>(keys: string | { [K in keyof T]: string }) {\n for (;;) {\n yield await next<T>(keys)\n }\n }\n\n function once<T = unknown>(key: string, event: QueryEvent) {\n return new Promise<CustomEventInit<T>>(function (resolve) {\n const unsubscribe = subscribe<T>(key, event, function (event) {\n resolve(event)\n unsubscribe()\n })\n })\n }\n\n async function* sequence<T = unknown>(key: string, event: QueryEvent) {\n for (;;) {\n yield await once<T>(key, event)\n }\n }\n\n return {\n query,\n emit,\n subscribe,\n subscribeBroadcast,\n mutate,\n configure,\n abort,\n forget,\n keys,\n expiration,\n hydrate,\n snapshot,\n once,\n sequence,\n next,\n stream,\n caches,\n events: localEvents,\n broadcast: localBroadcast,\n }\n}\n"],"names":["defaultFetcher","fetch","key","signal","response","__name","createQuery","instanceOptions","defaultExpiration","itemsCache","resolversCache","events","broadcast","instanceExpiration","instanceFetcher","instanceStale","instanceRemoveOnError","instanceFresh","configure","options","emit","event","detail","subscribe","listener","value","mutate","resolver","action","fn","item","result","expiresAt","snapshot","keys","type","abort","cacheKeys","reason","resolverKeys","forget","itemKeys","hydrate","expiration","query","fetcher","stale","removeOnError","fresh","refetch","pending","controller","trigger","resolve","reject","promise","error","cached","hasExpired","caches","localEvents","localBroadcast","subscribeBroadcast","onBroadcastMessage","message","next","promises","once","details","stream","unsubscribe","sequence"],"mappings":"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"}
|
package/dist/query.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sources":["../src/query/query.ts"],"sourcesContent":["import {\n type Caches,\n type CacheType,\n type ItemsCacheItem,\n type ResolversCacheItem,\n} from 'query:cache'\nimport {\n type BroadcastPayload,\n type Configuration,\n type FetcherAdditional,\n type FetcherFunction,\n type HydrateOptions,\n type MutateOptions,\n type MutationFunction,\n type MutationValue,\n type Options,\n type Query,\n type QueryEvent,\n type SubscribeListener,\n type TriggerFunction,\n type Unsubscriber,\n} from 'query:options'\n\n/**\n * Stores the default fetcher function.\n */\nexport function defaultFetcher<T>(\n fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>\n): FetcherFunction<T> {\n return async function (key: string, { signal }: FetcherAdditional): Promise<T> {\n const response = await fetch(key, { signal })\n\n if (!response.ok) {\n throw new Error('Unable to fetch the data: ' + response.statusText)\n }\n\n return (await response.json()) as T\n }\n}\n\n/**\n * Creates a new query instance.\n */\nexport function createQuery(instanceOptions?: Configuration): Query {\n /**\n * Stores the default expiration function.\n */\n function defaultExpiration() {\n return 2000\n }\n\n /**\n * Stores the items cache.\n */\n let itemsCache = instanceOptions?.itemsCache ?? new Map<string, ItemsCacheItem>()\n\n /**\n * Stores the resolvers cache.\n */\n let resolversCache = instanceOptions?.resolversCache ?? new Map<string, ResolversCacheItem>()\n\n /**\n * Event manager.\n */\n let events = instanceOptions?.events ?? new EventTarget()\n\n /**\n * Broadcast channel. This is useful for communicating\n * between tabs and windows (browser contexts).\n *\n * By default it does not use any broadcast channel.\n * If a broadcast channel is provided, query\n * won't close automatically, therefore, the responsability\n * of closing the broadcast channel is up to the user.\n */\n let broadcast = instanceOptions?.broadcast\n\n /**\n * Stores the expiration time of an item.\n */\n let instanceExpiration = instanceOptions?.expiration ?? defaultExpiration\n\n /**\n * Determines the fetcher function to use.\n */\n let instanceFetcher = instanceOptions?.fetcher ?? defaultFetcher(fetch)\n\n /**\n * Determines if we can return a stale item.\n * If `true`, it will return the previous stale item\n * stored in the cache if it has expired. It will attempt\n * to revalidate it in the background. If `false`, the returned\n * promise will be the revalidation promise.\n */\n let instanceStale = instanceOptions?.stale ?? true\n\n /**\n * Removes the stored item if there is an error in the request.\n * By default, we don't remove the item upon failure, only the resolver\n * is removed from the cache.\n */\n let instanceRemoveOnError = instanceOptions?.removeOnError ?? false\n\n /**\n * Determines if the result should be a fresh fetched\n * instance regardless of any cached value or its expiration time.\n */\n let instanceFresh = instanceOptions?.fresh ?? false\n\n /**\n * Configures the current instance of query.\n */\n function configure(options?: Configuration): void {\n itemsCache = options?.itemsCache ?? itemsCache\n resolversCache = options?.resolversCache ?? resolversCache\n events = options?.events ?? events\n broadcast = options?.broadcast ?? broadcast\n instanceExpiration = options?.expiration ?? instanceExpiration\n instanceFetcher = options?.fetcher ?? instanceFetcher\n instanceStale = options?.stale ?? instanceStale\n instanceRemoveOnError = options?.removeOnError ?? instanceRemoveOnError\n instanceFresh = options?.fresh ?? instanceFresh\n }\n\n function emit<T = unknown>(key: string, event: QueryEvent, detail: T) {\n events.dispatchEvent(new CustomEvent(`${event}:${key}`, { detail }))\n\n switch (event) {\n case 'mutated':\n case 'resolved':\n case 'hydrated':\n case 'forgotten':\n broadcast?.postMessage({ event: `${event}:${key}`, detail })\n }\n }\n\n /**\n * Subscribes to a given keyed event. The event handler\n * does have a payload parameter that will contain relevant\n * information depending on the event type.\n * If there's a pending resolver for that key, the `refetching`\n * event is fired immediatly.\n */\n\n function subscribe<T = unknown>(\n key: string,\n event: QueryEvent,\n listener: SubscribeListener<T>\n ): Unsubscriber {\n events.addEventListener(`${event}:${key}`, listener)\n const value = resolversCache.get(key)\n\n // For the refetching event, we want to immediatly return if there's\n // a pending resolver.\n if (event === 'refetching' && value !== undefined) {\n emit(key, event, value.item)\n }\n\n return function () {\n events.removeEventListener(`${event}:${key}`, listener)\n }\n }\n\n /**\n * Mutates the key with a given optimistic value.\n * The mutated value is considered expired and will be\n * replaced immediatly if a refetch happens when expired\n * is true. If expired is false, the value expiration time\n * is added as if it was a valid data refetched. Alternatively\n * you can provide a Date to decide when the expiration happens.\n */\n async function mutate<T = unknown>(\n key: string,\n resolver: MutationValue<T>,\n options?: MutateOptions<T>\n ): Promise<T> {\n async function action(resolver: MutationValue<T>) {\n if (typeof resolver === 'function') {\n const fn = resolver as MutationFunction<T>\n const value = itemsCache.get(key)\n const item = (await value?.item) as T\n\n resolver = await fn(item, value?.expiresAt)\n }\n\n return resolver\n }\n\n const result = action(resolver)\n\n emit(key, 'mutating', result)\n\n const item = await result\n const expiresAt = new Date()\n\n expiresAt.setMilliseconds(expiresAt.getMilliseconds() + (options?.expiration?.(item) ?? 0))\n\n itemsCache.set(key, { item: result, expiresAt: expiresAt })\n\n emit(key, 'mutated', item)\n\n return item\n }\n\n /**\n * Returns the current snapshot of the given key.\n * If the item is not in the items cache, it will return `undefined`.\n */\n async function snapshot<T = unknown>(key: string): Promise<T | undefined> {\n return (await itemsCache.get(key)?.item) as T\n }\n\n /**\n * Determines if the given key is currently resolving.\n */\n function keys(type: CacheType = 'items'): string[] {\n return Array.from(type === 'items' ? itemsCache.keys() : resolversCache.keys())\n }\n\n /**\n * Aborts the active resolvers on each key\n * by calling `.abort()` on the `AbortController`.\n * The fetcher is responsible for using the\n * `AbortSignal` to cancel the job.\n * If no keys are provided, all resolvers are aborted.\n */\n function abort(cacheKeys?: string | string[], reason?: unknown): void {\n const resolverKeys =\n typeof cacheKeys === 'string' ? [cacheKeys] : (cacheKeys ?? keys('resolvers'))\n\n for (const key of resolverKeys) {\n const resolver = resolversCache.get(key)\n\n if (resolver !== undefined) {\n resolver.controller.abort(reason)\n resolversCache.delete(key)\n\n emit(key, 'aborted', reason)\n }\n }\n }\n\n /**\n * Forgets the given keys from the items cache.\n * Does not remove any resolvers.\n * If no keys are provided the items cache is cleared.\n */\n async function forget(cacheKeys?: string | string[] | RegExp): Promise<void> {\n let itemKeys: string[]\n\n if (typeof cacheKeys === 'string') {\n itemKeys = [cacheKeys]\n } else if (Array.isArray(cacheKeys)) {\n itemKeys = cacheKeys\n } else if (cacheKeys instanceof RegExp) {\n itemKeys = keys('items').filter((key) => key.match(cacheKeys))\n } else {\n itemKeys = keys('items')\n }\n\n for (const key of itemKeys) {\n const item = itemsCache.get(key)\n\n if (item !== undefined) {\n itemsCache.delete(key)\n emit(key, 'forgotten', await item.item)\n }\n }\n }\n\n /**\n * Hydrates the given keys on the cache\n * with the given value. Hydrate should only\n * be used when you want to populate the cache.\n * Please use mutate() in most cases unless you\n * know what you are doing.\n */\n function hydrate<T = unknown>(\n keys: string | string[],\n item: T,\n options?: HydrateOptions<T>\n ): void {\n const expiresAt = new Date()\n const result = Promise.resolve(item)\n\n expiresAt.setMilliseconds(expiresAt.getMilliseconds() + (options?.expiration?.(item) ?? 0))\n\n for (const key of typeof keys === 'string' ? [keys] : keys) {\n itemsCache.set(key, { item: result, expiresAt: expiresAt })\n emit(key, 'hydrated', item)\n }\n }\n\n /**\n * Returns the expiration date of a given key item.\n * If the item is not in the cache, it will return `undefined`.\n */\n function expiration(key: string): Date | undefined {\n return itemsCache.get(key)?.expiresAt\n }\n\n /**\n * Fetches the key information using a fetcher.\n * The returned promise contains the result item.\n */\n function query<T = unknown>(key: string, options?: Options<T>): Promise<T> {\n /**\n * Stores the expiration time of an item.\n */\n const expiration = options?.expiration ?? instanceExpiration\n\n /**\n * Determines the fetcher function to use.\n */\n const fetcher = (options?.fetcher ?? instanceFetcher) as FetcherFunction<T>\n\n /**\n * Determines if we can return a sale item\n * If true, it will return the previous stale item\n * stored in the cache if it has expired. It will attempt\n * to revalidate it in the background. If false, the returned\n * promise will be the revalidation promise.\n */\n const stale = options?.stale ?? instanceStale\n\n /**\n * Removes the stored item if there is an error in the request.\n * By default, we don't remove the item upon failure, only the resolver\n * is removed from the cache.\n */\n const removeOnError = options?.removeOnError ?? instanceRemoveOnError\n\n /**\n * Determines if the result should be a fresh fetched\n * instance regardless of any cached value or its expiration time.\n */\n const fresh = options?.fresh ?? instanceOptions?.fresh\n\n // Force fetching of the data.\n function refetch(key: string): Promise<T> {\n // Check if there's a pending resolver for that data.\n const pending = resolversCache.get(key)\n\n if (pending !== undefined) {\n return pending.item as Promise<T>\n }\n\n // Create the abort controller that will be\n // called when a query is aborted.\n const controller = new AbortController()\n\n let trigger: TriggerFunction = undefined\n\n // Initiate the fetching request.\n const result = new Promise<T>(function (resolve, reject) {\n trigger = async function () {\n try {\n const result = fetcher(key, { signal: controller.signal })\n\n // Awaits the fetching to get the result item.\n const item = await result\n\n const promise =\n (resolversCache.get(key)?.item as Promise<T> | undefined) ?? Promise.resolve(item)\n\n // Removes the resolver from the cache.\n resolversCache.delete(key)\n\n // Create the expiration time for the item.\n const expiresAt = new Date()\n expiresAt.setMilliseconds(expiresAt.getMilliseconds() + expiration(item))\n\n // Set the item to the cache.\n itemsCache.set(key, { item: promise, expiresAt })\n\n // Notify of the resolved item.\n emit(key, 'resolved', item)\n\n resolve(item)\n } catch (error) {\n // Remove the resolver.\n resolversCache.delete(key)\n\n // Check if the item should be removed as well.\n if (removeOnError) {\n itemsCache.delete(key)\n }\n\n // Notify of the error.\n emit(key, 'error', error)\n\n // Throw back the error.\n reject(error as Error)\n }\n }\n })\n\n // Adds the resolver to the cache.\n resolversCache.set(key, { item: result, controller })\n emit(key, 'refetching', result)\n\n trigger = trigger as TriggerFunction\n\n while (trigger === undefined) {\n // This ensures that the trigger\n // has been defined, as it is defined\n // inside the promise.\n }\n\n void trigger()\n\n return result\n }\n\n // We want to force a fresh item ignoring any current cached\n // value or its expiration time.\n if (fresh) {\n return refetch(key)\n }\n\n // Check if there's an item in the cache for the given key.\n const cached = itemsCache.get(key)\n\n if (cached === undefined) {\n // The item is not found in the items cache.\n // We need to perform a revalidation of the item.\n return refetch(key)\n }\n\n // We must check if that item has actually expired.\n // to trigger a revalidation if needed.\n const hasExpired = cached.expiresAt <= new Date()\n\n // The item has expired and the fetch is able\n // to return a stale item while revalidating\n // in the background.\n if (hasExpired && stale) {\n // We have to silence the error to avoid unhandled promises.\n // Refer to the error event if you need full controll of errors.\n refetch(key).catch(() => {})\n\n return cached.item as Promise<T>\n }\n\n // The item has expired but we dont allow stale\n // responses so we need to wait for the revalidation.\n if (hasExpired) {\n return refetch(key)\n }\n\n // The item has not yet expired, so we can return it and\n // assume it's valid since it's not yet considered stale.\n return cached.item as Promise<T>\n }\n\n /**\n * Returns the current cache instances.\n */\n function caches(): Caches {\n return { items: itemsCache, resolvers: resolversCache }\n }\n\n /**\n * Returns the event system.\n */\n function localEvents() {\n return events\n }\n\n /**\n * Returns the broadcast channel.\n */\n function localBroadcast() {\n return broadcast\n }\n\n /**\n * Subscribes to the broadcast channel\n * to listen for other browser context\n * events and reproduce them in the current\n * context.\n */\n function subscribeBroadcast(): Unsubscriber {\n function onBroadcastMessage(message: MessageEvent<BroadcastPayload>) {\n events.dispatchEvent(new CustomEvent(message.data.event, { detail: message.data.detail }))\n }\n\n broadcast?.addEventListener('message', onBroadcastMessage)\n\n return function () {\n broadcast?.removeEventListener('message', onBroadcastMessage)\n }\n }\n\n async function next<T = unknown>(keys: string | { [K in keyof T]: string }): Promise<T> {\n const iterator = (Array.isArray(keys) ? keys : [keys]) as string[]\n const promises = iterator.map((key) => once(key, 'refetching'))\n const events = await Promise.all(promises)\n const details = events.map((event) => event.detail as Promise<T>)\n\n return (await (Array.isArray(keys) ? Promise.all(details) : details[0])) as T\n }\n\n async function* stream<T = unknown>(keys: string | { [K in keyof T]: string }) {\n for (;;) {\n yield await next<T>(keys)\n }\n }\n\n function once<T = unknown>(key: string, event: QueryEvent) {\n return new Promise<CustomEventInit<T>>(function (resolve) {\n const unsubscribe = subscribe<T>(key, event, function (event) {\n resolve(event)\n unsubscribe()\n })\n })\n }\n\n async function* sequence<T = unknown>(key: string, event: QueryEvent) {\n for (;;) {\n yield await once<T>(key, event)\n }\n }\n\n return {\n query,\n emit,\n subscribe,\n subscribeBroadcast,\n mutate,\n configure,\n abort,\n forget,\n keys,\n expiration,\n hydrate,\n snapshot,\n once,\n sequence,\n next,\n stream,\n caches,\n events: localEvents,\n broadcast: localBroadcast,\n }\n}\n"],"names":["defaultFetcher","fetch","key","signal","response","__name","createQuery","instanceOptions","defaultExpiration","itemsCache","resolversCache","events","broadcast","instanceExpiration","instanceFetcher","instanceStale","instanceRemoveOnError","instanceFresh","configure","options","emit","event","detail","subscribe","listener","value","mutate","resolver","action","fn","item","result","expiresAt","snapshot","keys","type","abort","cacheKeys","reason","resolverKeys","forget","itemKeys","hydrate","expiration","query","fetcher","stale","removeOnError","fresh","refetch","pending","controller","trigger","resolve","reject","promise","error","cached","hasExpired","caches","localEvents","localBroadcast","subscribeBroadcast","onBroadcastMessage","message","next","promises","once","details","stream","unsubscribe","sequence"],"mappings":"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"}
|