@nano_kit/query 1.0.0-alpha.0 → 1.0.0-alpha.10

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.
Files changed (53) hide show
  1. package/README.md +2 -2
  2. package/dist/CacheStorage.d.ts +2 -2
  3. package/dist/CacheStorage.d.ts.map +1 -1
  4. package/dist/CacheStorage.types.d.ts +5 -0
  5. package/dist/CacheStorage.types.d.ts.map +1 -1
  6. package/dist/ClientContext.d.ts +7 -5
  7. package/dist/ClientContext.d.ts.map +1 -1
  8. package/dist/RequestContext.d.ts.map +1 -1
  9. package/dist/cache.d.ts +1 -1
  10. package/dist/cache.d.ts.map +1 -1
  11. package/dist/cache.types.d.ts.map +1 -1
  12. package/dist/client.d.ts +7 -6
  13. package/dist/client.d.ts.map +1 -1
  14. package/dist/client.mock.d.ts.map +1 -1
  15. package/dist/client.types.d.ts.map +1 -1
  16. package/dist/index.d.ts +2 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +929 -840
  19. package/dist/index.js.map +1 -1
  20. package/dist/map.d.ts +5 -0
  21. package/dist/map.d.ts.map +1 -1
  22. package/dist/queries/base.d.ts +9 -9
  23. package/dist/queries/base.d.ts.map +1 -1
  24. package/dist/queries/index.d.ts.map +1 -1
  25. package/dist/queries/infinite.d.ts.map +1 -1
  26. package/dist/queries/mutation.d.ts.map +1 -1
  27. package/dist/queries/operation.d.ts.map +1 -1
  28. package/dist/queries/query.d.ts.map +1 -1
  29. package/dist/settings/abortable.d.ts.map +1 -1
  30. package/dist/settings/codec.d.ts +16 -0
  31. package/dist/settings/codec.d.ts.map +1 -0
  32. package/dist/settings/entities.d.ts.map +1 -1
  33. package/dist/settings/hydratable.d.ts +11 -0
  34. package/dist/settings/hydratable.d.ts.map +1 -0
  35. package/dist/settings/index.d.ts +5 -3
  36. package/dist/settings/index.d.ts.map +1 -1
  37. package/dist/settings/indexedDbStorage.d.ts +5 -7
  38. package/dist/settings/indexedDbStorage.d.ts.map +1 -1
  39. package/dist/settings/persistence.d.ts +16 -0
  40. package/dist/settings/persistence.d.ts.map +1 -0
  41. package/dist/settings/retryOnError.d.ts.map +1 -1
  42. package/dist/settings/revalidateOn.d.ts +9 -0
  43. package/dist/settings/revalidateOn.d.ts.map +1 -0
  44. package/dist/settings/ssr.d.ts +9 -0
  45. package/dist/settings/ssr.d.ts.map +1 -0
  46. package/dist/utils.d.ts.map +1 -1
  47. package/package.json +5 -5
  48. package/dist/settings/revalidateOnFocus.d.ts +0 -12
  49. package/dist/settings/revalidateOnFocus.d.ts.map +0 -1
  50. package/dist/settings/revalidateOnInterval.d.ts +0 -9
  51. package/dist/settings/revalidateOnInterval.d.ts.map +0 -1
  52. package/dist/settings/revalidateOnReconnect.d.ts +0 -12
  53. package/dist/settings/revalidateOnReconnect.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,951 +1,1040 @@
1
- import { batch, setMapKey, fireMapEvent, $$insert, subMapEvent, $getMapKey, clearMap, deleteMapKey, untracked, external, onMount, mountable, listen, effect, taskPromise, computed, action, onStart, effectScope, signal, readonly } from '@nano_kit/store';
2
-
1
+ import { $$insert, $get, $getMapKey, Hydratables$, Hydrator$, NoopCodec, TasksRunner$, action, batch, clearMap, computed, deleteMapKey, effect, effectScope, fireMapEvent, identity, inject, isFunction, listen, mountable, onStart, readonly, setMapKey, signal, subMapEvent, taskPromise, untracked } from "@nano_kit/store";
2
+ //#region src/settings/abortable.ts
3
3
  const abortControllers = /* @__PURE__ */ new WeakMap();
4
- // @__NO_SIDE_EFFECTS__
4
+ /**
5
+ * Returns the AbortSignal for the given RequestContext
6
+ * @param ctx - RequestContext
7
+ * @returns AbortSignal
8
+ */
9
+ /* @__NO_SIDE_EFFECTS__ */
5
10
  function abortSignal(ctx) {
6
- let controller = abortControllers.get(ctx);
7
- if (!controller) {
8
- abortControllers.set(ctx, controller = new AbortController());
9
- }
10
- return controller.signal;
11
+ let controller = abortControllers.get(ctx);
12
+ if (!controller) abortControllers.set(ctx, controller = new AbortController());
13
+ return controller.signal;
11
14
  }
15
+ /**
16
+ * Aborts request associated with the given Promise or RequestContext
17
+ * @param promiseOrCtx - Promise or RequestContext
18
+ */
12
19
  function abort(promiseOrCtx) {
13
- abortControllers.get(promiseOrCtx)?.abort();
20
+ abortControllers.get(promiseOrCtx)?.abort();
14
21
  }
22
+ /**
23
+ * Aborts previous request associated with the given RequestContext
24
+ * @param ctx - RequestContext
25
+ */
15
26
  function abortPrevious(ctx) {
16
- abort(ctx.prevCtx);
27
+ abort(ctx.prevCtx);
17
28
  }
18
- // @__NO_SIDE_EFFECTS__
29
+ /**
30
+ * Make requests abortable.
31
+ * @returns The client setting function.
32
+ */
33
+ /* @__NO_SIDE_EFFECTS__ */
19
34
  function abortable() {
20
- return (ctx) => {
21
- if (ctx.abortable === void 0) {
22
- const superRun = ctx.run;
23
- ctx.run = function(requestCtx, start, onSettled, interrupt) {
24
- let abortController;
25
- const promise = superRun.call(
26
- this,
27
- requestCtx,
28
- start,
29
- onSettled,
30
- (error) => interrupt?.(error) || abortController?.signal.aborted === true
31
- );
32
- if (abortController = abortControllers.get(requestCtx)) {
33
- abortControllers.set(promise, abortController);
34
- void promise.finally(() => abortControllers.delete(promise));
35
- }
36
- return promise;
37
- };
38
- }
39
- ctx.abortable = true;
40
- };
35
+ return (ctx) => {
36
+ if (ctx.abortable === void 0) {
37
+ const superRun = ctx.run;
38
+ ctx.run = function(requestCtx, start, onSettled, interrupt) {
39
+ let abortController;
40
+ const promise = superRun.call(this, requestCtx, start, onSettled, (error) => interrupt?.(error) || abortController?.signal.aborted === true);
41
+ if (abortController = abortControllers.get(requestCtx)) {
42
+ abortControllers.set(promise, abortController);
43
+ promise.finally(() => abortControllers.delete(promise));
44
+ }
45
+ return promise;
46
+ };
47
+ }
48
+ ctx.abortable = true;
49
+ };
41
50
  }
42
-
43
- // @__NO_SIDE_EFFECTS__
51
+ //#endregion
52
+ //#region src/cache.ts
53
+ /**
54
+ * Create a query cache key builder.
55
+ * @param name - The cache shard name.
56
+ * @param filter - Optional filter to process parameters before building the key.
57
+ * @returns The cache key builder.
58
+ */
59
+ /* @__NO_SIDE_EFFECTS__ */
44
60
  function queryKey(name, filter = (params) => params) {
45
- const key = ((...params) => ({
46
- shard: name,
47
- key: JSON.stringify(filter(params))
48
- }));
49
- key.shard = name;
50
- key.key = void 0;
51
- return key;
52
- }
53
- // @__NO_SIDE_EFFECTS__
61
+ const key = ((...params) => ({
62
+ shard: name,
63
+ key: JSON.stringify(filter(params))
64
+ }));
65
+ key.shard = name;
66
+ key.key = void 0;
67
+ return key;
68
+ }
69
+ /**
70
+ * Create an operation cache key builder with extra parameters.
71
+ * @param name - The cache shard name.
72
+ * @param filter - Optional filter to process parameters before building the key.
73
+ * @returns The extras cache key builder.
74
+ */
75
+ /* @__NO_SIDE_EFFECTS__ */
54
76
  function operationKey(name, filter) {
55
- return /* @__PURE__ */ queryKey(name, filter);
77
+ return /* @__PURE__ */ queryKey(name, filter);
56
78
  }
57
- // @__NO_SIDE_EFFECTS__
79
+ /**
80
+ * Create cache getter/setter for data.
81
+ * @param cache - The cache map.
82
+ * @returns The data getter/setter.
83
+ */
84
+ /* @__NO_SIDE_EFFECTS__ */
58
85
  function dataCacheFacade(cache) {
59
- return dataCacheGetterSetter.bind(cache);
86
+ return dataCacheGetterSetter.bind(cache);
60
87
  }
61
88
  function dataCacheGetterSetter(key, ...value) {
62
- if (value.length) {
63
- const newValue = value[0];
64
- this.set(key, (entry = this.initial()) => ({
65
- ...entry,
66
- data: typeof newValue === "function" ? newValue(entry.data) : newValue
67
- }));
68
- } else {
69
- return this.$get(key).data;
70
- }
71
- }
72
- // @__NO_SIDE_EFFECTS__
89
+ if (value.length) {
90
+ const newValue = value[0];
91
+ this.set(key, (entry = this.initial()) => ({
92
+ ...entry,
93
+ data: isFunction(newValue) ? newValue(entry.data) : newValue
94
+ }));
95
+ } else return this.$get(key).data;
96
+ }
97
+ /**
98
+ * Create cache getter for loading state.
99
+ * @param cache - The cache map.
100
+ * @returns The loading state getter.
101
+ */
102
+ /* @__NO_SIDE_EFFECTS__ */
73
103
  function loadingCacheFacade(cache) {
74
- return (key) => cache.$get(key).loading;
104
+ return (key) => cache.$get(key).loading;
75
105
  }
76
- // @__NO_SIDE_EFFECTS__
106
+ /**
107
+ * Create cache getter for error state.
108
+ * @param cache - The cache map.
109
+ * @returns The error state getter.
110
+ */
111
+ /* @__NO_SIDE_EFFECTS__ */
77
112
  function errorCacheFacade(cache) {
78
- return (key) => cache.$get(key).error;
113
+ return (key) => cache.$get(key).error;
79
114
  }
80
-
115
+ //#endregion
116
+ //#region src/settings/entities.ts
81
117
  const ENTITY_KEY = "#entity";
82
- const EntityKey = queryKey(ENTITY_KEY);
118
+ const EntityKey = /* @__PURE__ */ queryKey(ENTITY_KEY);
83
119
  function isIdentifier(value) {
84
- const type = typeof value;
85
- return type === "number" || type === "string";
120
+ const type = typeof value;
121
+ return type === "number" || type === "string";
86
122
  }
87
123
  function isEntityRef(value) {
88
- return ENTITY_KEY in value;
124
+ return ENTITY_KEY in value;
89
125
  }
90
126
  let currentCtx = null;
91
- // @__NO_SIDE_EFFECTS__
92
- function entity(name, id = (entity2) => entity2.id) {
93
- return (idOrRefOrEntity) => {
94
- if (isIdentifier(idOrRefOrEntity)) {
95
- return EntityKey(name, idOrRefOrEntity);
96
- }
97
- if (!idOrRefOrEntity || !currentCtx) {
98
- return idOrRefOrEntity;
99
- }
100
- if (isEntityRef(idOrRefOrEntity)) {
101
- return currentCtx.$get(idOrRefOrEntity[ENTITY_KEY]).data;
102
- }
103
- const key = EntityKey(name, id(idOrRefOrEntity));
104
- currentCtx.set(key, {
105
- ...currentCtx.initial(),
106
- data: idOrRefOrEntity
107
- });
108
- return {
109
- ...idOrRefOrEntity,
110
- [ENTITY_KEY]: key
111
- };
112
- };
113
- }
114
- // @__NO_SIDE_EFFECTS__
127
+ /* @__NO_SIDE_EFFECTS__ */
128
+ function entity(name, id = (entity) => entity.id) {
129
+ return (idOrRefOrEntity) => {
130
+ if (isIdentifier(idOrRefOrEntity)) return EntityKey(name, idOrRefOrEntity);
131
+ if (!idOrRefOrEntity || !currentCtx) return idOrRefOrEntity;
132
+ if (isEntityRef(idOrRefOrEntity)) return currentCtx.$get(idOrRefOrEntity[ENTITY_KEY]).data;
133
+ const key = EntityKey(name, id(idOrRefOrEntity));
134
+ currentCtx.set(key, {
135
+ ...currentCtx.initial(),
136
+ data: idOrRefOrEntity
137
+ });
138
+ return {
139
+ ...idOrRefOrEntity,
140
+ [ENTITY_KEY]: key
141
+ };
142
+ };
143
+ }
144
+ /* @__NO_SIDE_EFFECTS__ */
115
145
  function entities(mapper) {
116
- return (ctx) => {
117
- const safeMapper = (data) => {
118
- if (data) {
119
- try {
120
- currentCtx = ctx;
121
- return mapper(data);
122
- } finally {
123
- currentCtx = null;
124
- }
125
- }
126
- return data;
127
- };
128
- ctx.mapComputedData = ctx.mapData = safeMapper;
129
- };
146
+ return (ctx) => {
147
+ const safeMapper = (data) => {
148
+ if (data) try {
149
+ currentCtx = ctx;
150
+ return mapper(data);
151
+ } finally {
152
+ currentCtx = null;
153
+ }
154
+ return data;
155
+ };
156
+ ctx.mapComputedData = ctx.mapData = safeMapper;
157
+ };
130
158
  }
131
-
132
- // @__NO_SIDE_EFFECTS__
159
+ //#endregion
160
+ //#region src/map.ts
161
+ /**
162
+ * Check if sharded map has the key.
163
+ * Checks full key.
164
+ * @param map - The sharded map.
165
+ * @param shardedKey - The sharded key.
166
+ * @returns True if the sharded map has the key, false otherwise.
167
+ */
168
+ /* @__NO_SIDE_EFFECTS__ */
133
169
  function hasShardedMapKey(map, shardedKey) {
134
- const {
135
- shard,
136
- key
137
- } = shardedKey;
138
- if (key === void 0) {
139
- return map.has(shard);
140
- }
141
- return map.get(shard)?.has(key) || false;
142
- }
143
- // @__NO_SIDE_EFFECTS__
170
+ const { shard, key } = shardedKey;
171
+ if (key === void 0) return map.has(shard);
172
+ return map.get(shard)?.has(key) || false;
173
+ }
174
+ /**
175
+ * Get value from sharded map by key.
176
+ * @param map - The sharded map.
177
+ * @param shardedKey - The sharded key.
178
+ * @returns The value or undefined if not found.
179
+ */
144
180
  function $getShardedMapKey(map, shardedKey) {
145
- const {
146
- shard,
147
- key
148
- } = shardedKey;
149
- let shardMap;
150
- if ((shardMap = map.get(shard)) === void 0) {
151
- subMapEvent(map, $$insert);
152
- return void 0;
153
- }
154
- return $getMapKey(shardMap, key);
181
+ const { shard, key } = shardedKey;
182
+ let shardMap;
183
+ if ((shardMap = map.get(shard)) === void 0) {
184
+ subMapEvent(map, $$insert);
185
+ return;
186
+ }
187
+ return $getMapKey(shardMap, key);
155
188
  }
189
+ /**
190
+ * Set value in sharded map by key.
191
+ * If sharded key contains only shard name, sets value for all entries in the shard.
192
+ * @param map - The sharded map.
193
+ * @param shardedKey - The sharded key.
194
+ * @param value - The value to set.
195
+ */
156
196
  function setShardedMapKey(map, shardedKey, value) {
157
- const {
158
- shard,
159
- key
160
- } = shardedKey;
161
- let shardMap = map.get(shard);
162
- const shardExists = shardMap !== void 0;
163
- if (key === void 0) {
164
- if (shardExists) {
165
- batch(() => {
166
- for (const params of shardMap.keys()) {
167
- setMapKey(shardMap, params, value);
168
- }
169
- });
170
- }
171
- return;
172
- }
173
- if (!shardExists) {
174
- map.set(
175
- shard,
176
- shardMap = /* @__PURE__ */ new Map()
177
- );
178
- }
179
- setMapKey(shardMap, key, value);
180
- if (!shardExists) {
181
- fireMapEvent(map, $$insert);
182
- }
197
+ const { shard, key } = shardedKey;
198
+ let shardMap = map.get(shard);
199
+ const shardExists = shardMap !== void 0;
200
+ if (key === void 0) {
201
+ if (shardExists) batch(() => {
202
+ for (const params of shardMap.keys()) setMapKey(shardMap, params, value);
203
+ });
204
+ return;
205
+ }
206
+ if (!shardExists) map.set(shard, shardMap = /* @__PURE__ */ new Map());
207
+ setMapKey(shardMap, key, value);
208
+ if (!shardExists) fireMapEvent(map, $$insert);
183
209
  }
210
+ /**
211
+ * Delete sharded map key.
212
+ * If sharded key contains only shard name, deletes all entries in the shard.
213
+ * @param map - The sharded map.
214
+ * @param shardedKey - The sharded key.
215
+ */
184
216
  function deleteShardedMapKey(map, shardedKey) {
185
- const {
186
- shard,
187
- key
188
- } = shardedKey;
189
- const shardMap = map.get(shard);
190
- if (shardMap === void 0) {
191
- return;
192
- }
193
- if (key === void 0) {
194
- clearMap(shardMap);
195
- return;
196
- }
197
- deleteMapKey(shardMap, key);
217
+ const { shard, key } = shardedKey;
218
+ const shardMap = map.get(shard);
219
+ if (shardMap === void 0) return;
220
+ if (key === void 0) {
221
+ clearMap(shardMap);
222
+ return;
223
+ }
224
+ deleteMapKey(shardMap, key);
198
225
  }
199
-
226
+ /**
227
+ * Clear the sharded map.
228
+ * @param map - The sharded map.
229
+ */
230
+ function clearShardedMap(map) {
231
+ batch(() => map.forEach(clearMap));
232
+ map.clear();
233
+ }
234
+ //#endregion
235
+ //#region src/CacheStorage.ts
200
236
  const DEFAULT_DEDUPE_TIME = 4e3;
201
237
  const DEFAULT_CACHE_TIME = Infinity;
202
238
  const UNSET_REV = Infinity;
203
- // @__NO_SIDE_EFFECTS__
239
+ /* @__NO_SIDE_EFFECTS__ */
204
240
  function revLock(rev) {
205
- return rev > 0 ? rev * -1 : rev;
241
+ return rev > 0 ? rev * -1 : rev;
206
242
  }
207
- // @__NO_SIDE_EFFECTS__
243
+ /* @__NO_SIDE_EFFECTS__ */
208
244
  function revLocked(rev) {
209
- return rev < 0;
245
+ return rev < 0;
210
246
  }
211
247
  let revCounter = 0;
212
- class CacheStorage {
213
- dedupeTime = DEFAULT_DEDUPE_TIME;
214
- cacheTime = DEFAULT_CACHE_TIME;
215
- cache = /* @__PURE__ */ new Map();
216
- initial() {
217
- return {
218
- rev: UNSET_REV,
219
- dedupes: 0,
220
- expires: 0,
221
- data: null,
222
- error: null,
223
- loading: false
224
- };
225
- }
226
- $get(key) {
227
- const cache = this.cache;
228
- if (!hasShardedMapKey(cache, key)) {
229
- setShardedMapKey(cache, key, this.initial());
230
- }
231
- const result = $getShardedMapKey(cache, key);
232
- return result;
233
- }
234
- set(key, entry) {
235
- setShardedMapKey(this.cache, key, entry);
236
- }
237
- /**
238
- * Invalidate cache entry for the given key.
239
- * If shard key is used, invalidate all entries in the shard.
240
- * @param key - The cache key to invalidate.
241
- */
242
- invalidate(key) {
243
- deleteShardedMapKey(this.cache, key);
244
- }
245
- /**
246
- * Revalidate cache entry for the given key.
247
- * If shard key is used, revalidate all entries in the shard.
248
- * @param key - The cache key to revalidate.
249
- */
250
- revalidate(key) {
251
- if (key.key === void 0 || hasShardedMapKey(this.cache, key)) {
252
- this.set(key, (entry) => ({
253
- ...entry,
254
- rev: UNSET_REV,
255
- dedupes: 0
256
- }));
257
- }
258
- }
259
- mute(entry, loadingDedupe = true, timeDedupe = true) {
260
- return loadingDedupe && entry.loading || timeDedupe && entry.dedupes > Date.now() || /* @__PURE__ */ revLocked(entry.rev);
261
- }
262
- loading(key) {
263
- const rev = ++revCounter;
264
- this.set(key, (entry = this.initial()) => ({
265
- ...entry,
266
- rev,
267
- data: entry.expires > Date.now() ? entry.data : null,
268
- error: null,
269
- loading: true
270
- }));
271
- return rev;
272
- }
273
- settled(key, data, error, rev) {
274
- const now = Date.now();
275
- this.set(key, (entry = this.initial()) => rev !== void 0 && rev !== entry.rev ? entry : {
276
- ...entry,
277
- dedupes: now + this.dedupeTime,
278
- expires: now + this.cacheTime,
279
- data: error === null ? data : entry.data,
280
- error,
281
- loading: false
282
- });
283
- }
248
+ var CacheStorage = class {
249
+ dedupeTime = DEFAULT_DEDUPE_TIME;
250
+ cacheTime = DEFAULT_CACHE_TIME;
251
+ cache = /* @__PURE__ */ new Map();
252
+ initial() {
253
+ return {
254
+ rev: UNSET_REV,
255
+ dedupes: 0,
256
+ expires: 0,
257
+ data: null,
258
+ error: null,
259
+ loading: false
260
+ };
261
+ }
262
+ $get(key) {
263
+ const cache = this.cache;
264
+ if (!/* @__PURE__ */ hasShardedMapKey(cache, key)) setShardedMapKey(cache, key, this.initial());
265
+ return $getShardedMapKey(cache, key);
266
+ }
267
+ set(key, entry) {
268
+ setShardedMapKey(this.cache, key, entry);
269
+ }
270
+ /**
271
+ * Invalidate cache entry for the given key.
272
+ * If shard key is used, invalidate all entries in the shard.
273
+ * @param key - The cache key to invalidate.
274
+ */
275
+ invalidate(key) {
276
+ if (key) deleteShardedMapKey(this.cache, key);
277
+ else clearShardedMap(this.cache);
278
+ }
279
+ /**
280
+ * Revalidate cache entry for the given key.
281
+ * If shard key is used, revalidate all entries in the shard.
282
+ * @param key - The cache key to revalidate.
283
+ */
284
+ revalidate(key) {
285
+ if (key.key === void 0 || /* @__PURE__ */ hasShardedMapKey(this.cache, key)) this.set(key, (entry) => ({
286
+ ...entry,
287
+ rev: UNSET_REV,
288
+ dedupes: 0
289
+ }));
290
+ }
291
+ mute(entry, loadingDedupe = true, timeDedupe = true) {
292
+ return loadingDedupe && entry.loading || timeDedupe && entry.dedupes > Date.now() || /* @__PURE__ */ revLocked(entry.rev);
293
+ }
294
+ loading(key) {
295
+ const rev = ++revCounter;
296
+ this.set(key, (entry = this.initial()) => ({
297
+ ...entry,
298
+ rev,
299
+ data: entry.expires > Date.now() ? entry.data : null,
300
+ error: null,
301
+ loading: true
302
+ }));
303
+ return rev;
304
+ }
305
+ settled(key, data, error, rev) {
306
+ const now = Date.now();
307
+ this.set(key, (entry = this.initial()) => rev !== void 0 && rev !== entry.rev ? entry : {
308
+ ...entry,
309
+ dedupes: now + this.dedupeTime,
310
+ expires: now + this.cacheTime,
311
+ data: error === null ? data : entry.data,
312
+ error,
313
+ loading: false
314
+ });
315
+ }
316
+ };
317
+ //#endregion
318
+ //#region src/settings/codec.ts
319
+ function mapEntry(entry, mapDetail, mapData) {
320
+ return {
321
+ ...entry,
322
+ data: mapData(entry.data),
323
+ rev: mapDetail(entry.rev),
324
+ dedupes: mapDetail(entry.dedupes),
325
+ expires: mapDetail(entry.expires)
326
+ };
284
327
  }
285
-
328
+ function encodeEntryData(entry, codec) {
329
+ return mapEntry(entry, identity, codec.encode);
330
+ }
331
+ function decodeEntryData(entry, codec) {
332
+ return mapEntry(entry, identity, codec.decode);
333
+ }
334
+ function encodeEntryDetails(entry) {
335
+ return mapEntry(entry, String, identity);
336
+ }
337
+ function decodeEntryDetails(entry) {
338
+ return mapEntry(entry, Number, identity);
339
+ }
340
+ function encodeEntry(entry, codec) {
341
+ return mapEntry(entry, String, codec.encode);
342
+ }
343
+ function decodeEntry(entry, codec) {
344
+ return mapEntry(entry, Number, codec.decode);
345
+ }
346
+ /**
347
+ * Set cache entry data codec for query client.
348
+ * @param codec - Codec used to encode and decode cached data.
349
+ * @returns The client setting function.
350
+ */
351
+ /* @__NO_SIDE_EFFECTS__ */
352
+ function codec(codec) {
353
+ return (ctx) => {
354
+ ctx.codec = codec;
355
+ };
356
+ }
357
+ //#endregion
358
+ //#region src/settings/persistence.ts
359
+ /**
360
+ * Generic persistent storage client setting.
361
+ * @param storage - The storage implementation to use for persistence.
362
+ * @param lifetime - How long to keep entries in storage in milliseconds.
363
+ * @returns The client setting function.
364
+ */
365
+ /* @__NO_SIDE_EFFECTS__ */
366
+ function persistence(storage, lifetime) {
367
+ return (ctx) => {
368
+ if (!storage) return;
369
+ if (ctx.persistenceLifetime === void 0) {
370
+ const superGet = ctx.$get;
371
+ const superSet = ctx.set;
372
+ const superInvalidate = ctx.invalidate;
373
+ ctx.$get = function(key) {
374
+ const cache = this.cache;
375
+ const hasKey = /* @__PURE__ */ hasShardedMapKey(cache, key);
376
+ const entry = superGet.call(this, key);
377
+ if (hasKey) return entry;
378
+ superSet.call(this, key, {
379
+ ...entry,
380
+ rev: /* @__PURE__ */ revLock(entry.rev)
381
+ });
382
+ this.task(storage.get(key).then((storedEntry) => superSet.call(this, key, {
383
+ ...entry,
384
+ ...storedEntry && decodeEntryData(storedEntry, this.codec),
385
+ rev: UNSET_REV
386
+ })));
387
+ return superGet.call(this, key);
388
+ };
389
+ function saveSingleEntry(key) {
390
+ const entry = untracked(superGet.bind(this, key));
391
+ if (entry && !entry.loading && !entry.error && !/* @__PURE__ */ revLocked(entry.rev)) this.task(storage.set(key, encodeEntryData(entry, this.codec), this.persistenceLifetime));
392
+ }
393
+ ctx.set = function(cacheKey, entry) {
394
+ superSet.call(this, cacheKey, entry);
395
+ const { shard, key } = cacheKey;
396
+ if (key !== void 0) saveSingleEntry.call(this, cacheKey);
397
+ else {
398
+ const shardMap = this.cache.get(shard);
399
+ if (shardMap) for (const key of shardMap.keys()) saveSingleEntry.call(this, {
400
+ shard,
401
+ key
402
+ });
403
+ }
404
+ };
405
+ ctx.invalidate = function(key) {
406
+ superInvalidate.call(this, key);
407
+ this.task(storage.delete(key));
408
+ };
409
+ }
410
+ ctx.persistenceLifetime = lifetime;
411
+ };
412
+ }
413
+ //#endregion
414
+ //#region src/settings/indexedDbStorage.ts
286
415
  const DB_NAME = "nano_kit";
287
416
  const STORE_NAME = "query";
288
- const DB_VERSION = 1;
289
417
  function connect() {
290
- return new Promise((resolve) => {
291
- const request = indexedDB.open(DB_NAME, DB_VERSION);
292
- request.onerror = () => resolve(null);
293
- request.onsuccess = () => resolve(request.result);
294
- request.onupgradeneeded = () => {
295
- const db = request.result;
296
- if (!db.objectStoreNames.contains(STORE_NAME)) {
297
- const store = db.createObjectStore(STORE_NAME, {
298
- keyPath: ["shard", "key"]
299
- });
300
- store.createIndex("shard", "shard", {
301
- unique: false
302
- });
303
- }
304
- };
305
- });
418
+ return new Promise((resolve) => {
419
+ const request = indexedDB.open(DB_NAME, 1);
420
+ request.onerror = () => resolve(null);
421
+ request.onsuccess = () => resolve(request.result);
422
+ request.onupgradeneeded = () => {
423
+ const db = request.result;
424
+ if (!db.objectStoreNames.contains("query")) db.createObjectStore(STORE_NAME, { keyPath: ["shard", "key"] }).createIndex("shard", "shard", { unique: false });
425
+ };
426
+ });
306
427
  }
307
428
  async function SELECT(connection, key) {
308
- const db = await connection;
309
- if (!db) {
310
- return null;
311
- }
312
- return new Promise((resolve) => {
313
- const transaction = db.transaction(STORE_NAME, "readonly");
314
- const store = transaction.objectStore(STORE_NAME);
315
- const request = store.get([key.shard, key.key]);
316
- request.onerror = () => resolve(null);
317
- request.onsuccess = () => {
318
- const result = request.result;
319
- if (!result) {
320
- resolve(null);
321
- return;
322
- }
323
- const now = Date.now();
324
- if (result.expires < now || result.data.expires < now) {
325
- void DELETE(connection, key);
326
- resolve(null);
327
- return;
328
- }
329
- resolve(result.data);
330
- };
331
- });
429
+ const db = await connection;
430
+ if (!db) return null;
431
+ return new Promise((resolve) => {
432
+ const request = db.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME).get([key.shard, key.key]);
433
+ request.onerror = () => resolve(null);
434
+ request.onsuccess = () => {
435
+ const result = request.result;
436
+ if (!result) {
437
+ resolve(null);
438
+ return;
439
+ }
440
+ const now = Date.now();
441
+ if (result.expires < now || result.data.expires < now) {
442
+ DELETE(connection, key);
443
+ resolve(null);
444
+ return;
445
+ }
446
+ resolve(result.data);
447
+ };
448
+ });
332
449
  }
333
450
  async function SET(connection, cacheKey, entry, lifetime) {
334
- const db = await connection;
335
- if (!db) {
336
- return;
337
- }
338
- return new Promise((resolve) => {
339
- const {
340
- shard,
341
- key
342
- } = cacheKey;
343
- const transaction = db.transaction(STORE_NAME, "readwrite");
344
- const store = transaction.objectStore(STORE_NAME);
345
- const storedEntry = {
346
- shard,
347
- key,
348
- data: entry,
349
- expires: Date.now() + lifetime
350
- };
351
- const request = store.put(storedEntry);
352
- request.onerror = () => resolve();
353
- request.onsuccess = () => resolve();
354
- });
451
+ const db = await connection;
452
+ if (!db) return;
453
+ return new Promise((resolve) => {
454
+ const { shard, key } = cacheKey;
455
+ const store = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME);
456
+ const storedEntry = {
457
+ shard,
458
+ key,
459
+ data: entry,
460
+ expires: Date.now() + lifetime
461
+ };
462
+ const request = store.put(storedEntry);
463
+ request.onerror = () => resolve();
464
+ request.onsuccess = () => resolve();
465
+ });
355
466
  }
356
467
  async function DELETE(connection, cacheKey) {
357
- const db = await connection;
358
- if (!db) {
359
- return;
360
- }
361
- return new Promise((resolve) => {
362
- const {
363
- shard,
364
- key
365
- } = cacheKey;
366
- const transaction = db.transaction(STORE_NAME, "readwrite");
367
- const store = transaction.objectStore(STORE_NAME);
368
- if (key === void 0) {
369
- const index = store.index("shard");
370
- const range = IDBKeyRange.only(shard);
371
- const request = index.openCursor(range);
372
- request.onerror = () => resolve();
373
- request.onsuccess = () => {
374
- const cursor = request.result;
375
- if (cursor) {
376
- cursor.delete();
377
- cursor.continue();
378
- } else {
379
- resolve();
380
- }
381
- };
382
- } else {
383
- const request = store.delete([shard, key]);
384
- request.onerror = () => resolve();
385
- request.onsuccess = () => resolve();
386
- }
387
- });
388
- }
389
- // @__NO_SIDE_EFFECTS__
390
- function indexedDbStorage(lifetime) {
391
- return (ctx) => {
392
- if (typeof indexedDB === "undefined") {
393
- return;
394
- }
395
- if (ctx.indexedDbStorageLifetime === void 0) {
396
- let saveSingleEntry = function(key) {
397
- const entry = untracked(() => superGet.call(this, key));
398
- if (entry && !entry.loading && !revLocked(entry.rev)) {
399
- void this.task(SET(db, key, entry, this.indexedDbStorageLifetime));
400
- }
401
- };
402
- const superGet = ctx.$get;
403
- const superSet = ctx.set;
404
- const superInvalidate = ctx.invalidate;
405
- const db = connect();
406
- ctx.$get = function(key) {
407
- const cache = this.cache;
408
- const hasKey = hasShardedMapKey(cache, key);
409
- const entry = superGet.call(this, key);
410
- if (hasKey) {
411
- return entry;
412
- }
413
- superSet.call(this, key, {
414
- ...entry,
415
- rev: revLock(entry.rev)
416
- });
417
- void this.task(SELECT(db, key).then((storedEntry) => superSet.call(this, key, {
418
- ...entry,
419
- ...storedEntry,
420
- rev: UNSET_REV
421
- })));
422
- return superGet.call(this, key);
423
- };
424
- ctx.set = function(cacheKey, entry) {
425
- superSet.call(this, cacheKey, entry);
426
- const {
427
- shard,
428
- key
429
- } = cacheKey;
430
- if (key !== void 0) {
431
- saveSingleEntry.call(this, cacheKey);
432
- } else {
433
- const shardMap = this.cache.get(shard);
434
- if (shardMap) {
435
- for (const key2 of shardMap.keys()) {
436
- saveSingleEntry.call(this, {
437
- shard,
438
- key: key2
439
- });
440
- }
441
- }
442
- }
443
- };
444
- ctx.invalidate = function(key) {
445
- superInvalidate.call(this, key);
446
- void this.task(DELETE(db, key));
447
- };
448
- }
449
- ctx.indexedDbStorageLifetime = lifetime;
450
- };
468
+ const db = await connection;
469
+ if (!db) return;
470
+ return new Promise((resolve) => {
471
+ const store = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME);
472
+ if (!cacheKey) {
473
+ const request = store.clear();
474
+ request.onerror = () => resolve();
475
+ request.onsuccess = () => resolve();
476
+ } else {
477
+ const { shard, key } = cacheKey;
478
+ if (key === void 0) {
479
+ const index = store.index("shard");
480
+ const range = IDBKeyRange.only(shard);
481
+ const request = index.openCursor(range);
482
+ request.onerror = () => resolve();
483
+ request.onsuccess = () => {
484
+ const cursor = request.result;
485
+ if (cursor) {
486
+ cursor.delete();
487
+ cursor.continue();
488
+ } else resolve();
489
+ };
490
+ } else {
491
+ const request = store.delete([shard, key]);
492
+ request.onerror = () => resolve();
493
+ request.onsuccess = () => resolve();
494
+ }
495
+ }
496
+ });
451
497
  }
452
-
453
- // @__NO_SIDE_EFFECTS__
498
+ /**
499
+ * IndexedDB adapter for persistent storage.
500
+ * @returns IndexedDB storage implementation or null if IndexedDB is not supported.
501
+ */
502
+ /* @__NO_SIDE_EFFECTS__ */
503
+ function indexedDbStorage() {
504
+ if (typeof indexedDB === "undefined") return null;
505
+ const db = connect();
506
+ return {
507
+ get(key) {
508
+ return SELECT(db, key);
509
+ },
510
+ set(cacheKey, entry, lifetime) {
511
+ return SET(db, cacheKey, entry, lifetime);
512
+ },
513
+ delete(cacheKey) {
514
+ return DELETE(db, cacheKey);
515
+ }
516
+ };
517
+ }
518
+ //#endregion
519
+ //#region src/utils.ts
520
+ /* @__NO_SIDE_EFFECTS__ */
454
521
  function addFn(prevFn, fn) {
455
- if (prevFn === void 0) {
456
- return fn;
457
- }
458
- return function(...args) {
459
- prevFn.apply(this, args);
460
- fn.apply(this, args);
461
- };
522
+ if (prevFn === void 0) return fn;
523
+ return function(...args) {
524
+ prevFn.apply(this, args);
525
+ fn.apply(this, args);
526
+ };
462
527
  }
463
528
  function settle(promise, onSettled) {
464
- return promise.then(
465
- onSettled,
466
- (error) => onSettled(void 0, error)
467
- );
468
- }
469
-
470
- const $windowVisible = external(($windowVisible2) => {
471
- if (typeof document === "undefined") {
472
- $windowVisible2(true);
473
- return;
474
- }
475
- const set = () => $windowVisible2(!document.hidden);
476
- set();
477
- onMount(mountable($windowVisible2), () => {
478
- document.addEventListener("visibilitychange", set);
479
- return () => {
480
- document.removeEventListener("visibilitychange", set);
481
- };
482
- });
483
- });
484
- // @__NO_SIDE_EFFECTS__
485
- function revalidateOnFocus() {
486
- return (ctx) => {
487
- if (ctx.revalidateOnFocusEnabled === void 0) {
488
- ctx.mounted = addFn(ctx.mounted, function() {
489
- listen($windowVisible, (visible) => {
490
- if (visible) {
491
- this.revalidate(this.$key());
492
- }
493
- });
494
- });
495
- }
496
- ctx.revalidateOnFocusEnabled = true;
497
- };
498
- }
499
-
500
- // @__NO_SIDE_EFFECTS__
501
- function revalidateOnInterval(interval) {
502
- return (ctx) => {
503
- if (ctx.revalidateInterval === void 0) {
504
- ctx.mounted = addFn(ctx.mounted, function() {
505
- effect(() => {
506
- const id = setInterval(() => {
507
- this.revalidate(this.$key());
508
- }, this.revalidateInterval);
509
- return () => clearInterval(id);
510
- });
511
- });
512
- }
513
- ctx.revalidateInterval = interval;
514
- };
529
+ return promise.then(onSettled, (error) => onSettled(void 0, error));
515
530
  }
516
-
517
- const $networkOnline = external(($networkOnline2) => {
518
- if (typeof navigator === "undefined") {
519
- $networkOnline2(true);
520
- return;
521
- }
522
- const set = () => $networkOnline2(navigator.onLine);
523
- set();
524
- onMount(mountable($networkOnline2), () => {
525
- window.addEventListener("online", set);
526
- window.addEventListener("offline", set);
527
- return () => {
528
- window.removeEventListener("online", set);
529
- window.removeEventListener("offline", set);
530
- };
531
- });
532
- });
533
- // @__NO_SIDE_EFFECTS__
534
- function revalidateOnReconnect() {
535
- return (ctx) => {
536
- if (ctx.revalidateOnReconnectEnabled === void 0) {
537
- ctx.mounted = addFn(ctx.mounted, function() {
538
- listen($networkOnline, (online) => {
539
- if (online) {
540
- this.revalidate(this.$key());
541
- }
542
- });
543
- });
544
- }
545
- ctx.revalidateOnReconnectEnabled = true;
546
- };
531
+ //#endregion
532
+ //#region src/settings/revalidateOn.ts
533
+ /**
534
+ * Revalidate the query when the reactive condition becomes true.
535
+ * @returns The client setting function.
536
+ */
537
+ /* @__NO_SIDE_EFFECTS__ */
538
+ function revalidateOn(...conditions) {
539
+ return (ctx) => {
540
+ if (ctx.revalidateOn === void 0) ctx.revalidateOn = /* @__PURE__ */ new Set();
541
+ conditions.forEach(($condition) => {
542
+ if (!ctx.revalidateOn.has($condition)) {
543
+ ctx.mounted = /* @__PURE__ */ addFn(ctx.mounted, function() {
544
+ listen($condition, (visible) => {
545
+ if (visible) this.revalidate(this.$key());
546
+ });
547
+ });
548
+ ctx.revalidateOn.add($condition);
549
+ }
550
+ });
551
+ };
547
552
  }
548
-
549
- // @__NO_SIDE_EFFECTS__
553
+ //#endregion
554
+ //#region src/settings/retryOnError.ts
555
+ /* @__NO_SIDE_EFFECTS__ */
550
556
  function defaultCalcRetryDelay(retryCount) {
551
- return (
552
- // eslint-disable-next-line @typescript-eslint/no-magic-numbers
553
- ~~((Math.random() + 0.5) * (1 << (retryCount < 8 ? retryCount : 8))) * 2e3
554
- );
557
+ return ~~((Math.random() + .5) * (1 << (retryCount < 8 ? retryCount : 8))) * 2e3;
555
558
  }
556
559
  function getRetryCount(ctx, key) {
557
- return ctx.retryCounts?.get(key.key) || 0;
560
+ return ctx.retryCounts?.get(key.key) || 0;
558
561
  }
559
562
  function setRetryCount(ctx, key, count) {
560
- (ctx.retryCounts ??= /* @__PURE__ */ new Map()).set(key.key, count);
563
+ (ctx.retryCounts ??= /* @__PURE__ */ new Map()).set(key.key, count);
561
564
  }
562
565
  function clearRetryCount(ctx, key) {
563
- ctx.retryCounts?.delete(key.key);
566
+ ctx.retryCounts?.delete(key.key);
564
567
  }
565
- // @__NO_SIDE_EFFECTS__
568
+ /**
569
+ * Retry the query on error with exponential backoff.
570
+ * @param calcRetryDelay - Function to calculate the delay before retrying.
571
+ * @returns The client setting function.
572
+ */
573
+ /* @__NO_SIDE_EFFECTS__ */
566
574
  function retryOnError(calcRetryDelay = defaultCalcRetryDelay) {
567
- return (ctx) => {
568
- if (ctx.calcRetryDelay === void 0) {
569
- const superRun = ctx.run;
570
- ctx.run = function(queryCtx, start, onSettled, interrupt) {
571
- clearTimeout(this.retryTimeoutId);
572
- const promise = superRun.call(this, queryCtx, start, onSettled, interrupt);
573
- if (!("shard" in queryCtx)) {
574
- return promise;
575
- }
576
- void this.task(promise.then(
577
- (result) => {
578
- const error = result?.[1];
579
- if (!error) {
580
- clearRetryCount(this, queryCtx);
581
- } else {
582
- const retryCount = getRetryCount(this, queryCtx) + 1;
583
- const delay = this.calcRetryDelay(retryCount, error);
584
- this.retryTimeoutId = setTimeout(() => {
585
- this.invalidate(queryCtx);
586
- setRetryCount(this, queryCtx, retryCount);
587
- }, delay);
588
- }
589
- }
590
- ));
591
- return promise;
592
- };
593
- }
594
- ctx.calcRetryDelay = calcRetryDelay;
595
- };
575
+ return (ctx) => {
576
+ if (ctx.calcRetryDelay === void 0) {
577
+ const superRun = ctx.run;
578
+ ctx.run = function(queryCtx, start, onSettled, interrupt) {
579
+ clearTimeout(this.retryTimeoutId);
580
+ const promise = superRun.call(this, queryCtx, start, onSettled, interrupt);
581
+ if (!("shard" in queryCtx)) return promise;
582
+ this.task(promise.then((result) => {
583
+ const error = result?.[1];
584
+ if (!error) clearRetryCount(this, queryCtx);
585
+ else {
586
+ const retryCount = getRetryCount(this, queryCtx) + 1;
587
+ const delay = this.calcRetryDelay(retryCount, error);
588
+ this.retryTimeoutId = setTimeout(() => {
589
+ this.invalidate(queryCtx);
590
+ setRetryCount(this, queryCtx, retryCount);
591
+ }, delay);
592
+ }
593
+ }));
594
+ return promise;
595
+ };
596
+ }
597
+ ctx.calcRetryDelay = calcRetryDelay;
598
+ };
596
599
  }
597
-
598
- class ClientContext extends CacheStorage {
599
- $key = void 0;
600
- $disabled = void 0;
601
- loadingDedupe = true;
602
- timeDedupe = true;
603
- onEveryError = void 0;
604
- task(task) {
605
- return taskPromise(task);
606
- }
607
- mapData(data) {
608
- return data;
609
- }
610
- mapComputedData(data) {
611
- return data;
612
- }
613
- mapError(error) {
614
- return error?.message;
615
- }
616
- mounted() {
617
- }
618
- mute(entry) {
619
- return this.$disabled?.() === true || super.mute(entry, this.loadingDedupe, this.timeDedupe);
620
- }
621
- run(requestCtx, start, onSettled, interrupt) {
622
- const {
623
- mapData,
624
- mapError: mapError2
625
- } = this;
626
- return this.task(settle(start(), (data, error) => {
627
- if (error && interrupt?.(error)) {
628
- return;
629
- }
630
- const dataOrNull = error ? null : mapData(data);
631
- const errorString = error ? mapError2(error) : null;
632
- onSettled(dataOrNull, errorString);
633
- requestCtx.settled(data, error);
634
- this.handleError(error, requestCtx.stopErrorPropagation);
635
- return [data, error];
636
- }));
637
- }
638
- handleError(error, stopped) {
639
- if (error !== void 0) {
640
- this.onEveryError?.(error, stopped);
641
- }
642
- }
643
- }
644
- // @__NO_SIDE_EFFECTS__
600
+ //#endregion
601
+ //#region src/settings/hydratable.ts
602
+ const id = "@nano_kit/query";
603
+ function encode({ cache, codec }) {
604
+ const encoded = [];
605
+ cache.forEach((shard, shardKey) => {
606
+ shard.forEach(($signal, key) => {
607
+ const value = $signal?.();
608
+ if (value !== void 0) encoded.push([
609
+ shardKey,
610
+ key,
611
+ encodeEntry(value, codec)
612
+ ]);
613
+ });
614
+ });
615
+ return encoded;
616
+ }
617
+ function decode({ cache, codec }, encoded) {
618
+ encoded.forEach(([shard, key, value]) => setShardedMapKey(cache, {
619
+ shard,
620
+ key
621
+ }, decodeEntry(value, codec)));
622
+ }
623
+ /**
624
+ * Make client cache hydratable.
625
+ * Without arguments, it will try to resolve {@link Hydrator$} and {@link Hydratables$} from the injection context.
626
+ * @param hydrator - Optional hydrator to use for rehydrating the cache. Pass `null` to skip hydration and only register for dehydration.
627
+ * @param hydratables - Optional map to register the cache collector for dehydration.
628
+ * @returns The client setting function.
629
+ */
630
+ /* @__NO_SIDE_EFFECTS__ */
631
+ function hydratable(hydrator, hydratables) {
632
+ return (ctx) => {
633
+ if (!ctx.hydratable) {
634
+ const finalHydrator = hydrator === void 0 ? inject(Hydrator$) : hydrator;
635
+ if (finalHydrator) finalHydrator.pull(id, (value) => decode(ctx, value));
636
+ else {
637
+ const finalHydratables = hydratables === void 0 ? inject(Hydratables$) : hydratables;
638
+ if (finalHydratables) finalHydratables.set(id, () => encode(ctx));
639
+ }
640
+ }
641
+ ctx.hydratable = true;
642
+ };
643
+ }
644
+ //#endregion
645
+ //#region src/ClientContext.ts
646
+ var ClientContext = class extends CacheStorage {
647
+ $key = void 0;
648
+ $disabled = void 0;
649
+ loadingDedupe = true;
650
+ timeDedupe = true;
651
+ onEveryError = void 0;
652
+ codec = NoopCodec;
653
+ task(task) {
654
+ return taskPromise(task);
655
+ }
656
+ mapData(data) {
657
+ return data;
658
+ }
659
+ mapComputedData(data) {
660
+ return data;
661
+ }
662
+ mapError(error) {
663
+ return error?.message;
664
+ }
665
+ mounted() {}
666
+ mute(entry) {
667
+ return this.$disabled?.() === true || super.mute(entry, this.loadingDedupe, this.timeDedupe);
668
+ }
669
+ run(requestCtx, start, onSettled, interrupt) {
670
+ const { mapData, mapError } = this;
671
+ return this.task(settle(start(), (data, error) => {
672
+ if (error && interrupt?.(error)) return;
673
+ const mappedData = mapData(data);
674
+ onSettled(error ? null : mappedData, error ? mapError(error) : null);
675
+ requestCtx.settled(mappedData, error);
676
+ this.handleError(error, requestCtx.stopErrorPropagation);
677
+ return [mappedData, error];
678
+ }));
679
+ }
680
+ handleError(error, stopped) {
681
+ if (error !== void 0) this.onEveryError?.(error, stopped);
682
+ }
683
+ };
684
+ /* @__NO_SIDE_EFFECTS__ */
645
685
  function forkMutationClient(ctx, settings = []) {
646
- const child = Object.create(ctx);
647
- for (const setting of settings) {
648
- setting(child);
649
- }
650
- return child;
686
+ const child = Object.create(ctx);
687
+ for (const setting of settings) setting(child);
688
+ return child;
651
689
  }
652
- // @__NO_SIDE_EFFECTS__
690
+ /* @__NO_SIDE_EFFECTS__ */
653
691
  function forkQueryClient(ctx, $key, settings = []) {
654
- const child = Object.create(ctx);
655
- child.$key = $key;
656
- for (const setting of settings) {
657
- setting(child);
658
- }
659
- return child;
660
- }
661
- // @__NO_SIDE_EFFECTS__
692
+ const child = Object.create(ctx);
693
+ child.$key = $key;
694
+ for (const setting of settings) setting(child);
695
+ return child;
696
+ }
697
+ /**
698
+ * Set dedupe time in which identical requests are deduped.
699
+ * @param time - Dedupe time in milliseconds.
700
+ * @returns The client setting function.
701
+ */
702
+ /* @__NO_SIDE_EFFECTS__ */
662
703
  function dedupeTime(time) {
663
- return (ctx) => ctx.dedupeTime = time;
704
+ return (ctx) => ctx.dedupeTime = time;
664
705
  }
665
- // @__NO_SIDE_EFFECTS__
706
+ /**
707
+ * Set cache time for cached query results.
708
+ * @param time - Cache time in milliseconds.
709
+ * @returns The client setting function.
710
+ */
711
+ /* @__NO_SIDE_EFFECTS__ */
666
712
  function cacheTime(time) {
667
- return (ctx) => ctx.cacheTime = time;
713
+ return (ctx) => ctx.cacheTime = time;
668
714
  }
669
- // @__NO_SIDE_EFFECTS__
715
+ /**
716
+ * Map error object to string.
717
+ * @param fn - Function to map error to string.
718
+ * @returns The client setting function.
719
+ */
720
+ /* @__NO_SIDE_EFFECTS__ */
670
721
  function mapError(fn) {
671
- return (ctx) => ctx.mapError = fn;
722
+ return (ctx) => ctx.mapError = fn;
672
723
  }
673
- // @__NO_SIDE_EFFECTS__
724
+ /**
725
+ * Register a callback to be called on every error.
726
+ * @param fn - The error callback.
727
+ * @returns The client setting function.
728
+ */
729
+ /* @__NO_SIDE_EFFECTS__ */
674
730
  function onEveryError(fn) {
675
- return (ctx) => ctx.onEveryError = addFn(ctx.onEveryError, fn);
731
+ return (ctx) => ctx.onEveryError = /* @__PURE__ */ addFn(ctx.onEveryError, fn);
676
732
  }
677
- // @__NO_SIDE_EFFECTS__
733
+ /**
734
+ * Disable requests when the signal is true.
735
+ * @param $disabled - Readable signal indicating whether requests are disabled.
736
+ * @returns The client setting function.
737
+ */
738
+ /* @__NO_SIDE_EFFECTS__ */
678
739
  function disabled($disabled) {
679
- return (ctx) => ctx.$disabled = $disabled;
740
+ return (ctx) => ctx.$disabled = $disabled;
680
741
  }
681
- // @__NO_SIDE_EFFECTS__
742
+ /* @__NO_SIDE_EFFECTS__ */
682
743
  function dedupe(loading, time = loading) {
683
- return (ctx) => {
684
- ctx.loadingDedupe = loading;
685
- ctx.timeDedupe = time;
686
- };
744
+ return (ctx) => {
745
+ ctx.loadingDedupe = loading;
746
+ ctx.timeDedupe = time;
747
+ };
687
748
  }
688
- // @__NO_SIDE_EFFECTS__
689
- function tasks(runner) {
690
- return (ctx) => ctx.task = runner;
749
+ /**
750
+ * Set task runner for handling tasks.
751
+ * Without arguments, it will try to resolve a tasks runner from the current injection context.
752
+ * @param runner - The tasks runner function.
753
+ * @returns The client setting function.
754
+ */
755
+ /* @__NO_SIDE_EFFECTS__ */
756
+ function tasks(runner = inject(TasksRunner$)) {
757
+ return (ctx) => ctx.task = runner;
691
758
  }
692
-
693
- class RequestContext {
694
- onSuccess = void 0;
695
- onError = void 0;
696
- onSettled = void 0;
697
- stopErrorPropagation = false;
698
- prevCtx = void 0;
699
- constructor(prevCtx) {
700
- if (this.prevCtx = prevCtx) {
701
- prevCtx.prevCtx = void 0;
702
- }
703
- }
704
- settled(data, error) {
705
- this.onSettled?.(data, error);
706
- if (error !== void 0) {
707
- this.onError?.(error);
708
- } else {
709
- this.onSuccess?.(data);
710
- }
711
- }
712
- }
713
- class QueryContext extends RequestContext {
714
- shard;
715
- key;
716
- P;
717
- R;
718
- constructor(key, prevCtx) {
719
- super(prevCtx);
720
- this.shard = key.shard;
721
- this.key = key.key;
722
- }
759
+ //#endregion
760
+ //#region src/settings/ssr.ts
761
+ /**
762
+ * Client setting for enabling SSR support.
763
+ * It combines tasks management and cache hydration to ensure that queries can be executed on the server and their results can be sent to the client for hydration.
764
+ * Should be called inside injection context.
765
+ * @returns The client setting function.
766
+ */
767
+ function ssr() {
768
+ const tasksSetting = /* @__PURE__ */ tasks();
769
+ const hydratableSetting = /* @__PURE__ */ hydratable();
770
+ return (ctx) => {
771
+ tasksSetting(ctx);
772
+ hydratableSetting(ctx);
773
+ };
723
774
  }
775
+ //#endregion
776
+ //#region src/RequestContext.ts
777
+ var RequestContext = class {
778
+ onSuccess = void 0;
779
+ onError = void 0;
780
+ onSettled = void 0;
781
+ stopErrorPropagation = false;
782
+ prevCtx = void 0;
783
+ constructor(prevCtx) {
784
+ if (this.prevCtx = prevCtx) prevCtx.prevCtx = void 0;
785
+ }
786
+ settled(data, error) {
787
+ this.onSettled?.(data, error);
788
+ if (error !== void 0) this.onError?.(error);
789
+ else this.onSuccess?.(data);
790
+ }
791
+ };
792
+ var QueryContext = class extends RequestContext {
793
+ shard;
794
+ key;
795
+ P;
796
+ R;
797
+ constructor(key, prevCtx) {
798
+ super(prevCtx);
799
+ this.shard = key.shard;
800
+ this.key = key.key;
801
+ }
802
+ };
803
+ /**
804
+ * Add a success callback to the query context.
805
+ * @param ctx - The query context.
806
+ * @param fn - The success callback.
807
+ */
724
808
  function onSuccess(ctx, fn) {
725
- ctx.onSuccess = addFn(ctx.onSuccess, fn);
809
+ ctx.onSuccess = /* @__PURE__ */ addFn(ctx.onSuccess, fn);
726
810
  }
811
+ /**
812
+ * Add an error callback to the query context.
813
+ * @param ctx - The query context.
814
+ * @param fn - The error callback.
815
+ */
727
816
  function onError(ctx, fn) {
728
- ctx.onError = addFn(ctx.onError, fn);
817
+ ctx.onError = /* @__PURE__ */ addFn(ctx.onError, fn);
729
818
  }
819
+ /**
820
+ * Add a settled callback to the query context.
821
+ * @param ctx - The query context.
822
+ * @param fn - The settled callback.
823
+ */
730
824
  function onSettled(ctx, fn) {
731
- ctx.onSettled = addFn(ctx.onSettled, fn);
825
+ ctx.onSettled = /* @__PURE__ */ addFn(ctx.onSettled, fn);
732
826
  }
827
+ /**
828
+ * Mark error as "stopped", so error will be passed to onEveryError with stopped=true.
829
+ * @param ctx - The query context.
830
+ */
733
831
  function stopErrorPropagation(ctx) {
734
- ctx.stopErrorPropagation = true;
832
+ ctx.stopErrorPropagation = true;
735
833
  }
736
-
737
- // @__NO_SIDE_EFFECTS__
834
+ //#endregion
835
+ //#region src/queries/base.ts
836
+ /* @__NO_SIDE_EFFECTS__ */
738
837
  function baseQuery(rootCtx, key, params, fn, settings) {
739
- const $params = computed(() => params.map(($signal) => $signal()));
740
- const $key = computed((prevKey) => {
741
- const nextKey = key(...$params());
742
- if (prevKey && prevKey.shard === nextKey.shard && prevKey.key === nextKey.key) {
743
- return prevKey;
744
- }
745
- return nextKey;
746
- });
747
- const clientCtx = forkQueryClient(rootCtx, $key, settings);
748
- const $entry = computed(() => clientCtx.$get($key()));
749
- const $rev = computed((v = 0) => $entry().rev === UNSET_REV ? v + 1 : v);
750
- const { mapComputedData } = clientCtx;
751
- const $data = mountable(computed(() => mapComputedData($entry().data)));
752
- const $error = computed(() => $entry().error);
753
- const $loading = computed(() => $entry().loading);
754
- let prevQueryCtx;
755
- const fetch = action((...extraParams) => {
756
- if (clientCtx.mute($entry())) {
757
- return Promise.resolve();
758
- }
759
- const key2 = $key();
760
- const params2 = $params();
761
- const queryCtx = prevQueryCtx = new QueryContext(key2, prevQueryCtx);
762
- let rev;
763
- return clientCtx.run(
764
- queryCtx,
765
- () => {
766
- rev = clientCtx.loading(key2);
767
- return fn(...params2, ...extraParams, queryCtx);
768
- },
769
- (data, error) => clientCtx.settled(key2, data, error, rev)
770
- );
771
- });
772
- return {
773
- clientCtx,
774
- fetch,
775
- $params,
776
- $key,
777
- $rev,
778
- $data,
779
- $error,
780
- $loading
781
- };
838
+ const $params = computed(() => params.map($get));
839
+ const $key = computed((prevKey) => {
840
+ const nextKey = key(...$params());
841
+ if (prevKey && prevKey.shard === nextKey.shard && prevKey.key === nextKey.key) return prevKey;
842
+ return nextKey;
843
+ });
844
+ const clientCtx = /* @__PURE__ */ forkQueryClient(rootCtx, $key, settings);
845
+ const $entry = computed(() => clientCtx.$get($key()));
846
+ /**
847
+ * Changes on every entry rev reset
848
+ */
849
+ const $rev = computed((v = 0) => $entry().rev === Infinity ? v + 1 : v);
850
+ const { mapComputedData } = clientCtx;
851
+ const $data = mountable(computed(() => mapComputedData($entry().data)));
852
+ const $error = computed(() => $entry().error);
853
+ const $loading = computed(() => $entry().loading);
854
+ let prevQueryCtx;
855
+ return {
856
+ clientCtx,
857
+ fetch: action((...extraParams) => {
858
+ if (clientCtx.mute($entry())) return Promise.resolve();
859
+ const key = $key();
860
+ const params = $params();
861
+ const queryCtx = prevQueryCtx = new QueryContext(key, prevQueryCtx);
862
+ let rev;
863
+ return clientCtx.run(queryCtx, () => {
864
+ rev = clientCtx.loading(key);
865
+ return fn(...params, ...extraParams, queryCtx);
866
+ }, (data, error) => clientCtx.settled(key, data, error, rev));
867
+ }),
868
+ $params,
869
+ $key,
870
+ $rev,
871
+ $data,
872
+ $error,
873
+ $loading
874
+ };
782
875
  }
783
-
784
- // @__NO_SIDE_EFFECTS__
876
+ //#endregion
877
+ //#region src/queries/query.ts
878
+ /* @__NO_SIDE_EFFECTS__ */
785
879
  function query(key, params, fn, settings) {
786
- const {
787
- clientCtx,
788
- fetch,
789
- $params,
790
- $key,
791
- $rev,
792
- $data,
793
- $error,
794
- $loading
795
- } = baseQuery(this, key, params, fn, settings);
796
- onStart($data, () => effectScope(() => {
797
- effect(() => {
798
- $rev();
799
- $params();
800
- clientCtx.$disabled?.();
801
- void fetch();
802
- });
803
- clientCtx.mounted();
804
- }));
805
- return [$data, $error, $loading, $key];
880
+ const { clientCtx, fetch, $params, $key, $rev, $data, $error, $loading } = /* @__PURE__ */ baseQuery(this, key, params, fn, settings);
881
+ onStart($data, () => effectScope(() => {
882
+ effect(() => {
883
+ $rev();
884
+ $params();
885
+ clientCtx.$disabled?.();
886
+ fetch();
887
+ });
888
+ clientCtx.mounted();
889
+ }));
890
+ return [
891
+ $data,
892
+ $error,
893
+ $loading,
894
+ $key
895
+ ];
806
896
  }
807
-
808
- // @__NO_SIDE_EFFECTS__
897
+ //#endregion
898
+ //#region src/queries/infinite.ts
899
+ /* @__NO_SIDE_EFFECTS__ */
809
900
  function infinite(key, params, next, fn, settings) {
810
- const {
811
- clientCtx,
812
- fetch,
813
- $params,
814
- $key,
815
- $rev,
816
- $data,
817
- $error,
818
- $loading
819
- } = baseQuery(this, key, params, async (...args) => {
820
- const queryCtx = args[args.length - 1];
821
- const data = clientCtx.$get(queryCtx).data;
822
- const page = await fn(...args);
823
- const nextValue = next(page);
824
- return {
825
- pages: [...data?.pages || [], page],
826
- next: nextValue,
827
- more: Boolean(nextValue)
828
- };
829
- }, settings);
830
- const initialTimeDedupe = clientCtx.timeDedupe;
831
- const fetchNext = action(() => {
832
- const data = $data();
833
- if (!data?.more) {
834
- return Promise.resolve();
835
- }
836
- clientCtx.timeDedupe = false;
837
- return fetch(data.next);
838
- });
839
- onStart($data, () => effectScope(() => {
840
- effect(() => {
841
- $rev();
842
- $params();
843
- clientCtx.$disabled?.();
844
- clientCtx.timeDedupe = initialTimeDedupe;
845
- void fetch(void 0);
846
- });
847
- clientCtx.mounted();
848
- }));
849
- return [fetchNext, $data, $error, $loading, $key];
901
+ const { clientCtx, fetch, $params, $key, $rev, $data, $error, $loading } = /* @__PURE__ */ baseQuery(this, key, params, async (...args) => {
902
+ const queryCtx = args[args.length - 1];
903
+ const cursor = args[args.length - 2];
904
+ const data = clientCtx.$get(queryCtx).data;
905
+ const page = await fn(...args);
906
+ const nextValue = next(page);
907
+ return {
908
+ pages: cursor === void 0 ? [page] : [...data?.pages || [], page],
909
+ next: nextValue,
910
+ more: Boolean(nextValue)
911
+ };
912
+ }, settings);
913
+ const initialTimeDedupe = clientCtx.timeDedupe;
914
+ const fetchNext = action(() => {
915
+ const data = $data();
916
+ if (!data?.more) return Promise.resolve();
917
+ clientCtx.timeDedupe = false;
918
+ return fetch(data.next);
919
+ });
920
+ onStart($data, () => effectScope(() => {
921
+ effect(() => {
922
+ $rev();
923
+ $params();
924
+ clientCtx.$disabled?.();
925
+ clientCtx.timeDedupe = initialTimeDedupe;
926
+ fetch(void 0);
927
+ });
928
+ clientCtx.mounted();
929
+ }));
930
+ return [
931
+ fetchNext,
932
+ $data,
933
+ $error,
934
+ $loading,
935
+ $key
936
+ ];
850
937
  }
851
-
852
- // @__NO_SIDE_EFFECTS__
938
+ //#endregion
939
+ //#region src/queries/operation.ts
940
+ /* @__NO_SIDE_EFFECTS__ */
853
941
  function operation(key, params, fn, settings = []) {
854
- const {
855
- clientCtx,
856
- fetch,
857
- $key,
858
- $data,
859
- $error,
860
- $loading
861
- } = baseQuery(this, key, params, fn, [dedupe(true, false), ...settings]);
862
- onStart($data, () => effectScope(() => clientCtx.mounted()));
863
- return [fetch, $data, $error, $loading, $key];
942
+ const { clientCtx, fetch, $key, $data, $error, $loading } = /* @__PURE__ */ baseQuery(this, key, params, fn, [/* @__PURE__ */ dedupe(true, false), ...settings]);
943
+ onStart($data, () => effectScope(() => clientCtx.mounted()));
944
+ return [
945
+ fetch,
946
+ $data,
947
+ $error,
948
+ $loading,
949
+ $key
950
+ ];
864
951
  }
865
-
866
- // @__NO_SIDE_EFFECTS__
952
+ //#endregion
953
+ //#region src/queries/mutation.ts
954
+ /* @__NO_SIDE_EFFECTS__ */
867
955
  function mutation(fn, settings = []) {
868
- const clientCtx = forkMutationClient(this, settings);
869
- const {
870
- mapComputedData,
871
- $disabled,
872
- loadingDedupe
873
- } = clientCtx;
874
- const $result = signal(null);
875
- const $data = computed(() => mapComputedData($result()));
876
- const $error = signal(null);
877
- const $loading = signal(false);
878
- let prevRequestCtx;
879
- const fetch = action((...params) => {
880
- if ($disabled?.() === true || loadingDedupe && $loading()) {
881
- return Promise.resolve();
882
- }
883
- const requestCtx = prevRequestCtx = new RequestContext(prevRequestCtx);
884
- return clientCtx.run(
885
- requestCtx,
886
- () => {
887
- $loading(true);
888
- return fn(...params, requestCtx);
889
- },
890
- (data, error) => {
891
- if (prevRequestCtx === requestCtx) {
892
- batch(() => {
893
- if (error === null) {
894
- $result(data);
895
- }
896
- $error(error);
897
- $loading(false);
898
- });
899
- }
900
- }
901
- );
902
- });
903
- return [
904
- fetch,
905
- $data,
906
- readonly($error),
907
- readonly($loading)
908
- ];
956
+ const clientCtx = /* @__PURE__ */ forkMutationClient(this, settings);
957
+ const { mapComputedData, $disabled, loadingDedupe } = clientCtx;
958
+ const $result = signal(null);
959
+ const $data = computed(() => mapComputedData($result()));
960
+ const $error = signal(null);
961
+ const $loading = signal(false);
962
+ let prevRequestCtx;
963
+ return [
964
+ action((...params) => {
965
+ if ($disabled?.() === true || loadingDedupe && $loading()) return Promise.resolve();
966
+ const requestCtx = prevRequestCtx = new RequestContext(prevRequestCtx);
967
+ return clientCtx.run(requestCtx, () => {
968
+ $loading(true);
969
+ return fn(...params, requestCtx);
970
+ }, (data, error) => {
971
+ if (prevRequestCtx === requestCtx) batch(() => {
972
+ if (error === null) $result(data);
973
+ $error(error);
974
+ $loading(false);
975
+ });
976
+ });
977
+ }),
978
+ $data,
979
+ readonly($error),
980
+ readonly($loading)
981
+ ];
909
982
  }
910
-
911
- // @__NO_SIDE_EFFECTS__
983
+ //#endregion
984
+ //#region src/client.ts
985
+ /**
986
+ * Create a query client with optional settings and extensions.
987
+ * @param settings - The client settings and extensions.
988
+ * @returns The query client.
989
+ */
990
+ /* @__NO_SIDE_EFFECTS__ */
912
991
  function client(...settings) {
913
- const ctx = new ClientContext();
914
- const client2 = {
915
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
916
- query: query.bind(ctx),
917
- invalidate: ((key) => ctx.invalidate(key)),
918
- revalidate: ((key) => ctx.revalidate(key)),
919
- $data: dataCacheFacade(ctx),
920
- $error: errorCacheFacade(ctx),
921
- $loading: loadingCacheFacade(ctx)
922
- };
923
- for (const setting of settings) {
924
- setting(ctx, client2);
925
- }
926
- return client2;
927
- }
928
- // @__NO_SIDE_EFFECTS__
992
+ const ctx = new ClientContext();
993
+ const client = {
994
+ query: query.bind(ctx),
995
+ invalidate: ((key) => ctx.invalidate(key)),
996
+ revalidate: ((key) => ctx.revalidate(key)),
997
+ $data: /* @__PURE__ */ dataCacheFacade(ctx),
998
+ $error: /* @__PURE__ */ errorCacheFacade(ctx),
999
+ $loading: /* @__PURE__ */ loadingCacheFacade(ctx)
1000
+ };
1001
+ for (const setting of settings) setting(ctx, client);
1002
+ return client;
1003
+ }
1004
+ /**
1005
+ * Extend client with infinite query capability.
1006
+ * @returns The client extension.
1007
+ */
1008
+ /* @__NO_SIDE_EFFECTS__ */
929
1009
  function infinites() {
930
- return ((ctx, client2) => {
931
- client2.infinite = infinite.bind(ctx);
932
- return client2;
933
- });
1010
+ return ((ctx, client) => {
1011
+ client.infinite = infinite.bind(ctx);
1012
+ return client;
1013
+ });
934
1014
  }
935
- // @__NO_SIDE_EFFECTS__
1015
+ /**
1016
+ * Extend client with operation capability.
1017
+ * @returns The client extension.
1018
+ */
1019
+ /* @__NO_SIDE_EFFECTS__ */
936
1020
  function operations() {
937
- return ((ctx, client2) => {
938
- client2.operation = operation.bind(ctx);
939
- return client2;
940
- });
1021
+ return ((ctx, client) => {
1022
+ client.operation = operation.bind(ctx);
1023
+ return client;
1024
+ });
941
1025
  }
942
- // @__NO_SIDE_EFFECTS__
1026
+ /**
1027
+ * Extend client with mutation capability.
1028
+ * @returns The client extension.
1029
+ */
1030
+ /* @__NO_SIDE_EFFECTS__ */
943
1031
  function mutations() {
944
- return ((ctx, client2) => {
945
- client2.mutation = mutation.bind(ctx);
946
- return client2;
947
- });
1032
+ return ((ctx, client) => {
1033
+ client.mutation = mutation.bind(ctx);
1034
+ return client;
1035
+ });
948
1036
  }
1037
+ //#endregion
1038
+ export { ClientContext, DEFAULT_CACHE_TIME, DEFAULT_DEDUPE_TIME, QueryContext, RequestContext, abort, abortPrevious, abortSignal, abortable, cacheTime, client, codec, decodeEntry, decodeEntryData, decodeEntryDetails, dedupe, dedupeTime, defaultCalcRetryDelay, disabled, encodeEntry, encodeEntryData, encodeEntryDetails, entities, entity, hydratable, indexedDbStorage, infinites, mapError, mutations, onError, onEveryError, onSettled, onSuccess, operationKey, operations, persistence, queryKey, retryOnError, revalidateOn, ssr, stopErrorPropagation, tasks };
949
1039
 
950
- export { $networkOnline, $windowVisible, ClientContext, DEFAULT_CACHE_TIME, DEFAULT_DEDUPE_TIME, QueryContext, RequestContext, abort, abortPrevious, abortSignal, abortable, cacheTime, client, dedupe, dedupeTime, defaultCalcRetryDelay, disabled, entities, entity, indexedDbStorage, infinites, mapError, mutations, onError, onEveryError, onSettled, onSuccess, operationKey, operations, queryKey, retryOnError, revalidateOnFocus, revalidateOnInterval, revalidateOnReconnect, stopErrorPropagation, tasks };
951
- //# sourceMappingURL=index.js.map
1040
+ //# sourceMappingURL=index.js.map