@nano_kit/query 1.0.0-alpha.1 → 1.0.0-alpha.11

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