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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,951 +1,1064 @@
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
-
3
- const abortControllers = /* @__PURE__ */ new WeakMap();
4
- // @__NO_SIDE_EFFECTS__
1
+ import { $$insert, $getMapKey, Hydratables$, Hydrator$, TasksRunner$, action, batch, clearMap, computed, deleteMapKey, effect, effectScope, external, fireMapEvent, inject, listen, mountable, onMount, onStart, readonly, setMapKey, signal, subMapEvent, taskPromise, untracked } from "@nano_kit/store";
2
+ //#region src/settings/abortable.ts
3
+ var abortControllers = /* @__PURE__ */ new WeakMap();
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: typeof newValue === "function" ? 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
-
81
- const ENTITY_KEY = "#entity";
82
- const EntityKey = queryKey(ENTITY_KEY);
115
+ //#endregion
116
+ //#region src/settings/entities.ts
117
+ var ENTITY_KEY = "#entity";
118
+ var 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;
89
- }
90
- 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__
124
+ return ENTITY_KEY in value;
125
+ }
126
+ var currentCtx = null;
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
-
200
- const DEFAULT_DEDUPE_TIME = 4e3;
201
- const DEFAULT_CACHE_TIME = Infinity;
202
- const UNSET_REV = Infinity;
203
- // @__NO_SIDE_EFFECTS__
226
+ //#endregion
227
+ //#region src/CacheStorage.ts
228
+ var DEFAULT_DEDUPE_TIME = 4e3;
229
+ var DEFAULT_CACHE_TIME = Infinity;
230
+ var UNSET_REV = Infinity;
231
+ /* @__NO_SIDE_EFFECTS__ */
204
232
  function revLock(rev) {
205
- return rev > 0 ? rev * -1 : rev;
233
+ return rev > 0 ? rev * -1 : rev;
206
234
  }
207
- // @__NO_SIDE_EFFECTS__
235
+ /* @__NO_SIDE_EFFECTS__ */
208
236
  function revLocked(rev) {
209
- return rev < 0;
210
- }
211
- 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
- }
237
+ return rev < 0;
284
238
  }
285
-
286
- const DB_NAME = "nano_kit";
287
- const STORE_NAME = "query";
288
- const DB_VERSION = 1;
239
+ var revCounter = 0;
240
+ var CacheStorage = class {
241
+ dedupeTime = DEFAULT_DEDUPE_TIME;
242
+ cacheTime = DEFAULT_CACHE_TIME;
243
+ cache = /* @__PURE__ */ new Map();
244
+ initial() {
245
+ return {
246
+ rev: UNSET_REV,
247
+ dedupes: 0,
248
+ expires: 0,
249
+ data: null,
250
+ error: null,
251
+ loading: false
252
+ };
253
+ }
254
+ $get(key) {
255
+ const cache = this.cache;
256
+ if (!/* @__PURE__ */ hasShardedMapKey(cache, key)) setShardedMapKey(cache, key, this.initial());
257
+ return $getShardedMapKey(cache, key);
258
+ }
259
+ set(key, entry) {
260
+ setShardedMapKey(this.cache, key, entry);
261
+ }
262
+ /**
263
+ * Invalidate cache entry for the given key.
264
+ * If shard key is used, invalidate all entries in the shard.
265
+ * @param key - The cache key to invalidate.
266
+ */
267
+ invalidate(key) {
268
+ deleteShardedMapKey(this.cache, key);
269
+ }
270
+ /**
271
+ * Revalidate cache entry for the given key.
272
+ * If shard key is used, revalidate all entries in the shard.
273
+ * @param key - The cache key to revalidate.
274
+ */
275
+ revalidate(key) {
276
+ if (key.key === void 0 || /* @__PURE__ */ hasShardedMapKey(this.cache, key)) this.set(key, (entry) => ({
277
+ ...entry,
278
+ rev: UNSET_REV,
279
+ dedupes: 0
280
+ }));
281
+ }
282
+ mute(entry, loadingDedupe = true, timeDedupe = true) {
283
+ return loadingDedupe && entry.loading || timeDedupe && entry.dedupes > Date.now() || /* @__PURE__ */ revLocked(entry.rev);
284
+ }
285
+ loading(key) {
286
+ const rev = ++revCounter;
287
+ this.set(key, (entry = this.initial()) => ({
288
+ ...entry,
289
+ rev,
290
+ data: entry.expires > Date.now() ? entry.data : null,
291
+ error: null,
292
+ loading: true
293
+ }));
294
+ return rev;
295
+ }
296
+ settled(key, data, error, rev) {
297
+ const now = Date.now();
298
+ this.set(key, (entry = this.initial()) => rev !== void 0 && rev !== entry.rev ? entry : {
299
+ ...entry,
300
+ dedupes: now + this.dedupeTime,
301
+ expires: now + this.cacheTime,
302
+ data: error === null ? data : entry.data,
303
+ error,
304
+ loading: false
305
+ });
306
+ }
307
+ };
308
+ //#endregion
309
+ //#region src/settings/persistence.ts
310
+ /**
311
+ * Generic persistent storage client setting.
312
+ * @param storage - The storage implementation to use for persistence.
313
+ * @param lifetime - How long to keep entries in storage in milliseconds.
314
+ * @returns The client setting function.
315
+ */
316
+ /* @__NO_SIDE_EFFECTS__ */
317
+ function persistence(storage, lifetime) {
318
+ return (ctx) => {
319
+ if (!storage) return;
320
+ if (ctx.persistenceLifetime === void 0) {
321
+ const superGet = ctx.$get;
322
+ const superSet = ctx.set;
323
+ const superInvalidate = ctx.invalidate;
324
+ ctx.$get = function(key) {
325
+ const cache = this.cache;
326
+ const hasKey = /* @__PURE__ */ hasShardedMapKey(cache, key);
327
+ const entry = superGet.call(this, key);
328
+ if (hasKey) return entry;
329
+ superSet.call(this, key, {
330
+ ...entry,
331
+ rev: /* @__PURE__ */ revLock(entry.rev)
332
+ });
333
+ this.task(storage.get(key).then((storedEntry) => superSet.call(this, key, {
334
+ ...entry,
335
+ ...storedEntry,
336
+ rev: UNSET_REV
337
+ })));
338
+ return superGet.call(this, key);
339
+ };
340
+ function saveSingleEntry(key) {
341
+ const entry = untracked(superGet.bind(this, key));
342
+ if (entry && !entry.loading && !entry.error && !/* @__PURE__ */ revLocked(entry.rev)) this.task(storage.set(key, entry, this.persistenceLifetime));
343
+ }
344
+ ctx.set = function(cacheKey, entry) {
345
+ superSet.call(this, cacheKey, entry);
346
+ const { shard, key } = cacheKey;
347
+ if (key !== void 0) saveSingleEntry.call(this, cacheKey);
348
+ else {
349
+ const shardMap = this.cache.get(shard);
350
+ if (shardMap) for (const key of shardMap.keys()) saveSingleEntry.call(this, {
351
+ shard,
352
+ key
353
+ });
354
+ }
355
+ };
356
+ ctx.invalidate = function(key) {
357
+ superInvalidate.call(this, key);
358
+ this.task(storage.delete(key));
359
+ };
360
+ }
361
+ ctx.persistenceLifetime = lifetime;
362
+ };
363
+ }
364
+ //#endregion
365
+ //#region src/settings/indexedDbStorage.ts
366
+ var DB_NAME = "nano_kit";
367
+ var STORE_NAME = "query";
289
368
  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
- });
369
+ return new Promise((resolve) => {
370
+ const request = indexedDB.open(DB_NAME, 1);
371
+ request.onerror = () => resolve(null);
372
+ request.onsuccess = () => resolve(request.result);
373
+ request.onupgradeneeded = () => {
374
+ const db = request.result;
375
+ if (!db.objectStoreNames.contains("query")) db.createObjectStore(STORE_NAME, { keyPath: ["shard", "key"] }).createIndex("shard", "shard", { unique: false });
376
+ };
377
+ });
306
378
  }
307
379
  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
- });
380
+ const db = await connection;
381
+ if (!db) return null;
382
+ return new Promise((resolve) => {
383
+ const request = db.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME).get([key.shard, key.key]);
384
+ request.onerror = () => resolve(null);
385
+ request.onsuccess = () => {
386
+ const result = request.result;
387
+ if (!result) {
388
+ resolve(null);
389
+ return;
390
+ }
391
+ const now = Date.now();
392
+ if (result.expires < now || result.data.expires < now) {
393
+ DELETE(connection, key);
394
+ resolve(null);
395
+ return;
396
+ }
397
+ resolve(result.data);
398
+ };
399
+ });
332
400
  }
333
401
  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
- });
402
+ const db = await connection;
403
+ if (!db) return;
404
+ return new Promise((resolve) => {
405
+ const { shard, key } = cacheKey;
406
+ const store = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME);
407
+ const storedEntry = {
408
+ shard,
409
+ key,
410
+ data: entry,
411
+ expires: Date.now() + lifetime
412
+ };
413
+ const request = store.put(storedEntry);
414
+ request.onerror = () => resolve();
415
+ request.onsuccess = () => resolve();
416
+ });
355
417
  }
356
418
  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
- };
419
+ const db = await connection;
420
+ if (!db) return;
421
+ return new Promise((resolve) => {
422
+ const { shard, key } = cacheKey;
423
+ const store = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME);
424
+ if (key === void 0) {
425
+ const index = store.index("shard");
426
+ const range = IDBKeyRange.only(shard);
427
+ const request = index.openCursor(range);
428
+ request.onerror = () => resolve();
429
+ request.onsuccess = () => {
430
+ const cursor = request.result;
431
+ if (cursor) {
432
+ cursor.delete();
433
+ cursor.continue();
434
+ } else resolve();
435
+ };
436
+ } else {
437
+ const request = store.delete([shard, key]);
438
+ request.onerror = () => resolve();
439
+ request.onsuccess = () => resolve();
440
+ }
441
+ });
451
442
  }
452
-
453
- // @__NO_SIDE_EFFECTS__
443
+ /**
444
+ * IndexedDB adapter for persistent storage.
445
+ * @returns IndexedDB storage implementation or null if IndexedDB is not supported.
446
+ */
447
+ /* @__NO_SIDE_EFFECTS__ */
448
+ function indexedDbStorage() {
449
+ if (typeof indexedDB === "undefined") return null;
450
+ const db = connect();
451
+ return {
452
+ get(key) {
453
+ return SELECT(db, key);
454
+ },
455
+ set(cacheKey, entry, lifetime) {
456
+ return SET(db, cacheKey, entry, lifetime);
457
+ },
458
+ delete(cacheKey) {
459
+ return DELETE(db, cacheKey);
460
+ }
461
+ };
462
+ }
463
+ //#endregion
464
+ //#region src/utils.ts
465
+ /* @__NO_SIDE_EFFECTS__ */
454
466
  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
- };
467
+ if (prevFn === void 0) return fn;
468
+ return function(...args) {
469
+ prevFn.apply(this, args);
470
+ fn.apply(this, args);
471
+ };
462
472
  }
463
473
  function settle(promise, onSettled) {
464
- return promise.then(
465
- onSettled,
466
- (error) => onSettled(void 0, error)
467
- );
474
+ return promise.then(onSettled, (error) => onSettled(void 0, error));
468
475
  }
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
- });
476
+ //#endregion
477
+ //#region src/settings/revalidateOnFocus.ts
478
+ /**
479
+ * @todo Move to common extras package
480
+ */
481
+ var $windowVisible = external(($windowVisible) => {
482
+ if (typeof document === "undefined") {
483
+ $windowVisible(true);
484
+ return;
485
+ }
486
+ const set = () => $windowVisible(!document.hidden);
487
+ set();
488
+ onMount(mountable($windowVisible), () => {
489
+ document.addEventListener("visibilitychange", set);
490
+ return () => {
491
+ document.removeEventListener("visibilitychange", set);
492
+ };
493
+ });
483
494
  });
484
- // @__NO_SIDE_EFFECTS__
495
+ /**
496
+ * Revalidate the query when the window gains focus.
497
+ * @returns The client setting function.
498
+ */
499
+ /* @__NO_SIDE_EFFECTS__ */
485
500
  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
- };
501
+ return (ctx) => {
502
+ if (ctx.revalidateOnFocusEnabled === void 0) ctx.mounted = /* @__PURE__ */ addFn(ctx.mounted, function() {
503
+ listen($windowVisible, (visible) => {
504
+ if (visible) this.revalidate(this.$key());
505
+ });
506
+ });
507
+ ctx.revalidateOnFocusEnabled = true;
508
+ };
498
509
  }
499
-
500
- // @__NO_SIDE_EFFECTS__
510
+ //#endregion
511
+ //#region src/settings/revalidateOnInterval.ts
512
+ /**
513
+ * Revalidate the query on a specified interval.
514
+ * @param interval - The interval in milliseconds.
515
+ * @returns The client setting function.
516
+ */
517
+ /* @__NO_SIDE_EFFECTS__ */
501
518
  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
- };
519
+ return (ctx) => {
520
+ if (ctx.revalidateInterval === void 0) ctx.mounted = /* @__PURE__ */ addFn(ctx.mounted, function() {
521
+ effect(() => {
522
+ const id = setInterval(() => {
523
+ this.revalidate(this.$key());
524
+ }, this.revalidateInterval);
525
+ return () => clearInterval(id);
526
+ });
527
+ });
528
+ ctx.revalidateInterval = interval;
529
+ };
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
- });
531
+ //#endregion
532
+ //#region src/settings/revalidateOnReconnect.ts
533
+ /**
534
+ * @todo Move to common extras package
535
+ */
536
+ var $networkOnline = external(($networkOnline) => {
537
+ if (typeof navigator === "undefined") {
538
+ $networkOnline(true);
539
+ return;
540
+ }
541
+ const set = () => $networkOnline(navigator.onLine);
542
+ set();
543
+ onMount(mountable($networkOnline), () => {
544
+ window.addEventListener("online", set);
545
+ window.addEventListener("offline", set);
546
+ return () => {
547
+ window.removeEventListener("online", set);
548
+ window.removeEventListener("offline", set);
549
+ };
550
+ });
532
551
  });
533
- // @__NO_SIDE_EFFECTS__
552
+ /**
553
+ * Revalidate the query when the network reconnects.
554
+ * @returns The client setting function.
555
+ */
556
+ /* @__NO_SIDE_EFFECTS__ */
534
557
  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
- };
558
+ return (ctx) => {
559
+ if (ctx.revalidateOnReconnectEnabled === void 0) ctx.mounted = /* @__PURE__ */ addFn(ctx.mounted, function() {
560
+ listen($networkOnline, (online) => {
561
+ if (online) this.revalidate(this.$key());
562
+ });
563
+ });
564
+ ctx.revalidateOnReconnectEnabled = true;
565
+ };
547
566
  }
548
-
549
- // @__NO_SIDE_EFFECTS__
567
+ //#endregion
568
+ //#region src/settings/retryOnError.ts
569
+ /* @__NO_SIDE_EFFECTS__ */
550
570
  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
- );
571
+ return ~~((Math.random() + .5) * (1 << (retryCount < 8 ? retryCount : 8))) * 2e3;
555
572
  }
556
573
  function getRetryCount(ctx, key) {
557
- return ctx.retryCounts?.get(key.key) || 0;
574
+ return ctx.retryCounts?.get(key.key) || 0;
558
575
  }
559
576
  function setRetryCount(ctx, key, count) {
560
- (ctx.retryCounts ??= /* @__PURE__ */ new Map()).set(key.key, count);
577
+ (ctx.retryCounts ??= /* @__PURE__ */ new Map()).set(key.key, count);
561
578
  }
562
579
  function clearRetryCount(ctx, key) {
563
- ctx.retryCounts?.delete(key.key);
580
+ ctx.retryCounts?.delete(key.key);
564
581
  }
565
- // @__NO_SIDE_EFFECTS__
582
+ /**
583
+ * Retry the query on error with exponential backoff.
584
+ * @param calcRetryDelay - Function to calculate the delay before retrying.
585
+ * @returns The client setting function.
586
+ */
587
+ /* @__NO_SIDE_EFFECTS__ */
566
588
  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
- };
589
+ return (ctx) => {
590
+ if (ctx.calcRetryDelay === void 0) {
591
+ const superRun = ctx.run;
592
+ ctx.run = function(queryCtx, start, onSettled, interrupt) {
593
+ clearTimeout(this.retryTimeoutId);
594
+ const promise = superRun.call(this, queryCtx, start, onSettled, interrupt);
595
+ if (!("shard" in queryCtx)) return promise;
596
+ this.task(promise.then((result) => {
597
+ const error = result?.[1];
598
+ if (!error) clearRetryCount(this, queryCtx);
599
+ else {
600
+ const retryCount = getRetryCount(this, queryCtx) + 1;
601
+ const delay = this.calcRetryDelay(retryCount, error);
602
+ this.retryTimeoutId = setTimeout(() => {
603
+ this.invalidate(queryCtx);
604
+ setRetryCount(this, queryCtx, retryCount);
605
+ }, delay);
606
+ }
607
+ }));
608
+ return promise;
609
+ };
610
+ }
611
+ ctx.calcRetryDelay = calcRetryDelay;
612
+ };
596
613
  }
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__
614
+ //#endregion
615
+ //#region src/settings/hydratable.ts
616
+ var id = "@nano_kit/query";
617
+ function mapEntry(entry, map) {
618
+ return {
619
+ ...entry,
620
+ rev: map(entry.rev),
621
+ dedupes: map(entry.dedupes),
622
+ expires: map(entry.expires)
623
+ };
624
+ }
625
+ function serialize(cache) {
626
+ const serialized = [];
627
+ cache.forEach((shard, shardKey) => {
628
+ shard.forEach(($signal, key) => {
629
+ const value = $signal?.();
630
+ if (value !== void 0) serialized.push([
631
+ shardKey,
632
+ key,
633
+ mapEntry(value, String)
634
+ ]);
635
+ });
636
+ });
637
+ return serialized;
638
+ }
639
+ function deserialize(cache, serialized) {
640
+ serialized.forEach(([shard, key, value]) => {
641
+ setShardedMapKey(cache, {
642
+ shard,
643
+ key
644
+ }, mapEntry(value, Number));
645
+ });
646
+ }
647
+ /**
648
+ * Make client cache hydratable.
649
+ * Without arguments, it will try to inject {@link Hydrator$} and {@link Hydratables$} from the injection context.
650
+ * @param hydrator - Optional hydrator to use for rehydrating the cache. Pass `null` to skip hydration and only register for dehydration.
651
+ * @param hydratables - Optional map to register the cache serializer for dehydration.
652
+ * @returns The client setting function.
653
+ */
654
+ /* @__NO_SIDE_EFFECTS__ */
655
+ function hydratable(hydrator, hydratables) {
656
+ return (ctx) => {
657
+ if (!ctx.hydratable) {
658
+ const finalHydrator = hydrator === void 0 ? inject(Hydrator$) : hydrator;
659
+ if (finalHydrator) finalHydrator.pull(id, (value) => {
660
+ deserialize(ctx.cache, value);
661
+ });
662
+ else {
663
+ const finalHydratables = hydratables === void 0 ? inject(Hydratables$) : hydratables;
664
+ if (finalHydratables) finalHydratables.set(id, () => serialize(ctx.cache));
665
+ }
666
+ }
667
+ ctx.hydratable = true;
668
+ };
669
+ }
670
+ //#endregion
671
+ //#region src/ClientContext.ts
672
+ var ClientContext = class extends CacheStorage {
673
+ $key = void 0;
674
+ $disabled = void 0;
675
+ loadingDedupe = true;
676
+ timeDedupe = true;
677
+ onEveryError = void 0;
678
+ task(task) {
679
+ return taskPromise(task);
680
+ }
681
+ mapData(data) {
682
+ return data;
683
+ }
684
+ mapComputedData(data) {
685
+ return data;
686
+ }
687
+ mapError(error) {
688
+ return error?.message;
689
+ }
690
+ mounted() {}
691
+ mute(entry) {
692
+ return this.$disabled?.() === true || super.mute(entry, this.loadingDedupe, this.timeDedupe);
693
+ }
694
+ run(requestCtx, start, onSettled, interrupt) {
695
+ const { mapData, mapError } = this;
696
+ return this.task(settle(start(), (data, error) => {
697
+ if (error && interrupt?.(error)) return;
698
+ onSettled(error ? null : mapData(data), error ? mapError(error) : null);
699
+ requestCtx.settled(data, error);
700
+ this.handleError(error, requestCtx.stopErrorPropagation);
701
+ return [data, error];
702
+ }));
703
+ }
704
+ handleError(error, stopped) {
705
+ if (error !== void 0) this.onEveryError?.(error, stopped);
706
+ }
707
+ };
708
+ /* @__NO_SIDE_EFFECTS__ */
645
709
  function forkMutationClient(ctx, settings = []) {
646
- const child = Object.create(ctx);
647
- for (const setting of settings) {
648
- setting(child);
649
- }
650
- return child;
710
+ const child = Object.create(ctx);
711
+ for (const setting of settings) setting(child);
712
+ return child;
651
713
  }
652
- // @__NO_SIDE_EFFECTS__
714
+ /* @__NO_SIDE_EFFECTS__ */
653
715
  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__
716
+ const child = Object.create(ctx);
717
+ child.$key = $key;
718
+ for (const setting of settings) setting(child);
719
+ return child;
720
+ }
721
+ /**
722
+ * Set dedupe time in which identical requests are deduped.
723
+ * @param time - Dedupe time in milliseconds.
724
+ * @returns The client setting function.
725
+ */
726
+ /* @__NO_SIDE_EFFECTS__ */
662
727
  function dedupeTime(time) {
663
- return (ctx) => ctx.dedupeTime = time;
728
+ return (ctx) => ctx.dedupeTime = time;
664
729
  }
665
- // @__NO_SIDE_EFFECTS__
730
+ /**
731
+ * Set cache time for cached query results.
732
+ * @param time - Cache time in milliseconds.
733
+ * @returns The client setting function.
734
+ */
735
+ /* @__NO_SIDE_EFFECTS__ */
666
736
  function cacheTime(time) {
667
- return (ctx) => ctx.cacheTime = time;
737
+ return (ctx) => ctx.cacheTime = time;
668
738
  }
669
- // @__NO_SIDE_EFFECTS__
739
+ /**
740
+ * Map error object to string.
741
+ * @param fn - Function to map error to string.
742
+ * @returns The client setting function.
743
+ */
744
+ /* @__NO_SIDE_EFFECTS__ */
670
745
  function mapError(fn) {
671
- return (ctx) => ctx.mapError = fn;
746
+ return (ctx) => ctx.mapError = fn;
672
747
  }
673
- // @__NO_SIDE_EFFECTS__
748
+ /**
749
+ * Register a callback to be called on every error.
750
+ * @param fn - The error callback.
751
+ * @returns The client setting function.
752
+ */
753
+ /* @__NO_SIDE_EFFECTS__ */
674
754
  function onEveryError(fn) {
675
- return (ctx) => ctx.onEveryError = addFn(ctx.onEveryError, fn);
755
+ return (ctx) => ctx.onEveryError = /* @__PURE__ */ addFn(ctx.onEveryError, fn);
676
756
  }
677
- // @__NO_SIDE_EFFECTS__
757
+ /**
758
+ * Disable requests when the signal is true.
759
+ * @param $disabled - Readable signal indicating whether requests are disabled.
760
+ * @returns The client setting function.
761
+ */
762
+ /* @__NO_SIDE_EFFECTS__ */
678
763
  function disabled($disabled) {
679
- return (ctx) => ctx.$disabled = $disabled;
764
+ return (ctx) => ctx.$disabled = $disabled;
680
765
  }
681
- // @__NO_SIDE_EFFECTS__
766
+ /* @__NO_SIDE_EFFECTS__ */
682
767
  function dedupe(loading, time = loading) {
683
- return (ctx) => {
684
- ctx.loadingDedupe = loading;
685
- ctx.timeDedupe = time;
686
- };
768
+ return (ctx) => {
769
+ ctx.loadingDedupe = loading;
770
+ ctx.timeDedupe = time;
771
+ };
687
772
  }
688
- // @__NO_SIDE_EFFECTS__
689
- function tasks(runner) {
690
- return (ctx) => ctx.task = runner;
773
+ /**
774
+ * Set task runner for handling tasks.
775
+ * Without arguments, it will try to inject tasks runner from context.
776
+ * @param runner - The tasks runner function.
777
+ * @returns The client setting function.
778
+ */
779
+ /* @__NO_SIDE_EFFECTS__ */
780
+ function tasks(runner = inject(TasksRunner$)) {
781
+ return (ctx) => ctx.task = runner;
691
782
  }
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
- }
783
+ //#endregion
784
+ //#region src/settings/ssr.ts
785
+ /**
786
+ * Client setting for enabling SSR support.
787
+ * 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.
788
+ * Should be called inside injection context.
789
+ * @returns The client setting function.
790
+ */
791
+ function ssr() {
792
+ const tasksSetting = /* @__PURE__ */ tasks();
793
+ const hydratableSetting = /* @__PURE__ */ hydratable();
794
+ return (ctx) => {
795
+ tasksSetting(ctx);
796
+ hydratableSetting(ctx);
797
+ };
723
798
  }
799
+ //#endregion
800
+ //#region src/RequestContext.ts
801
+ var RequestContext = class {
802
+ onSuccess = void 0;
803
+ onError = void 0;
804
+ onSettled = void 0;
805
+ stopErrorPropagation = false;
806
+ prevCtx = void 0;
807
+ constructor(prevCtx) {
808
+ if (this.prevCtx = prevCtx) prevCtx.prevCtx = void 0;
809
+ }
810
+ settled(data, error) {
811
+ this.onSettled?.(data, error);
812
+ if (error !== void 0) this.onError?.(error);
813
+ else this.onSuccess?.(data);
814
+ }
815
+ };
816
+ var QueryContext = class extends RequestContext {
817
+ shard;
818
+ key;
819
+ P;
820
+ R;
821
+ constructor(key, prevCtx) {
822
+ super(prevCtx);
823
+ this.shard = key.shard;
824
+ this.key = key.key;
825
+ }
826
+ };
827
+ /**
828
+ * Add a success callback to the query context.
829
+ * @param ctx - The query context.
830
+ * @param fn - The success callback.
831
+ */
724
832
  function onSuccess(ctx, fn) {
725
- ctx.onSuccess = addFn(ctx.onSuccess, fn);
833
+ ctx.onSuccess = /* @__PURE__ */ addFn(ctx.onSuccess, fn);
726
834
  }
835
+ /**
836
+ * Add an error callback to the query context.
837
+ * @param ctx - The query context.
838
+ * @param fn - The error callback.
839
+ */
727
840
  function onError(ctx, fn) {
728
- ctx.onError = addFn(ctx.onError, fn);
841
+ ctx.onError = /* @__PURE__ */ addFn(ctx.onError, fn);
729
842
  }
843
+ /**
844
+ * Add a settled callback to the query context.
845
+ * @param ctx - The query context.
846
+ * @param fn - The settled callback.
847
+ */
730
848
  function onSettled(ctx, fn) {
731
- ctx.onSettled = addFn(ctx.onSettled, fn);
849
+ ctx.onSettled = /* @__PURE__ */ addFn(ctx.onSettled, fn);
732
850
  }
851
+ /**
852
+ * Mark error as "stopped", so error will be passed to onEveryError with stopped=true.
853
+ * @param ctx - The query context.
854
+ */
733
855
  function stopErrorPropagation(ctx) {
734
- ctx.stopErrorPropagation = true;
856
+ ctx.stopErrorPropagation = true;
735
857
  }
736
-
737
- // @__NO_SIDE_EFFECTS__
858
+ //#endregion
859
+ //#region src/queries/base.ts
860
+ /* @__NO_SIDE_EFFECTS__ */
738
861
  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
- };
862
+ const $params = computed(() => params.map(($signal) => $signal()));
863
+ const $key = computed((prevKey) => {
864
+ const nextKey = key(...$params());
865
+ if (prevKey && prevKey.shard === nextKey.shard && prevKey.key === nextKey.key) return prevKey;
866
+ return nextKey;
867
+ });
868
+ const clientCtx = /* @__PURE__ */ forkQueryClient(rootCtx, $key, settings);
869
+ const $entry = computed(() => clientCtx.$get($key()));
870
+ /**
871
+ * Changes on every entry rev reset
872
+ */
873
+ const $rev = computed((v = 0) => $entry().rev === Infinity ? v + 1 : v);
874
+ const { mapComputedData } = clientCtx;
875
+ const $data = mountable(computed(() => mapComputedData($entry().data)));
876
+ const $error = computed(() => $entry().error);
877
+ const $loading = computed(() => $entry().loading);
878
+ let prevQueryCtx;
879
+ return {
880
+ clientCtx,
881
+ fetch: action((...extraParams) => {
882
+ if (clientCtx.mute($entry())) return Promise.resolve();
883
+ const key = $key();
884
+ const params = $params();
885
+ const queryCtx = prevQueryCtx = new QueryContext(key, prevQueryCtx);
886
+ let rev;
887
+ return clientCtx.run(queryCtx, () => {
888
+ rev = clientCtx.loading(key);
889
+ return fn(...params, ...extraParams, queryCtx);
890
+ }, (data, error) => clientCtx.settled(key, data, error, rev));
891
+ }),
892
+ $params,
893
+ $key,
894
+ $rev,
895
+ $data,
896
+ $error,
897
+ $loading
898
+ };
782
899
  }
783
-
784
- // @__NO_SIDE_EFFECTS__
900
+ //#endregion
901
+ //#region src/queries/query.ts
902
+ /* @__NO_SIDE_EFFECTS__ */
785
903
  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];
904
+ const { clientCtx, fetch, $params, $key, $rev, $data, $error, $loading } = /* @__PURE__ */ baseQuery(this, key, params, fn, settings);
905
+ onStart($data, () => effectScope(() => {
906
+ effect(() => {
907
+ $rev();
908
+ $params();
909
+ clientCtx.$disabled?.();
910
+ fetch();
911
+ });
912
+ clientCtx.mounted();
913
+ }));
914
+ return [
915
+ $data,
916
+ $error,
917
+ $loading,
918
+ $key
919
+ ];
806
920
  }
807
-
808
- // @__NO_SIDE_EFFECTS__
921
+ //#endregion
922
+ //#region src/queries/infinite.ts
923
+ /* @__NO_SIDE_EFFECTS__ */
809
924
  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];
925
+ const { clientCtx, fetch, $params, $key, $rev, $data, $error, $loading } = /* @__PURE__ */ baseQuery(this, key, params, async (...args) => {
926
+ const queryCtx = args[args.length - 1];
927
+ const cursor = args[args.length - 2];
928
+ const data = clientCtx.$get(queryCtx).data;
929
+ const page = await fn(...args);
930
+ const nextValue = next(page);
931
+ return {
932
+ pages: cursor === void 0 ? [page] : [...data?.pages || [], page],
933
+ next: nextValue,
934
+ more: Boolean(nextValue)
935
+ };
936
+ }, settings);
937
+ const initialTimeDedupe = clientCtx.timeDedupe;
938
+ const fetchNext = action(() => {
939
+ const data = $data();
940
+ if (!data?.more) return Promise.resolve();
941
+ clientCtx.timeDedupe = false;
942
+ return fetch(data.next);
943
+ });
944
+ onStart($data, () => effectScope(() => {
945
+ effect(() => {
946
+ $rev();
947
+ $params();
948
+ clientCtx.$disabled?.();
949
+ clientCtx.timeDedupe = initialTimeDedupe;
950
+ fetch(void 0);
951
+ });
952
+ clientCtx.mounted();
953
+ }));
954
+ return [
955
+ fetchNext,
956
+ $data,
957
+ $error,
958
+ $loading,
959
+ $key
960
+ ];
850
961
  }
851
-
852
- // @__NO_SIDE_EFFECTS__
962
+ //#endregion
963
+ //#region src/queries/operation.ts
964
+ /* @__NO_SIDE_EFFECTS__ */
853
965
  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];
966
+ const { clientCtx, fetch, $key, $data, $error, $loading } = /* @__PURE__ */ baseQuery(this, key, params, fn, [/* @__PURE__ */ dedupe(true, false), ...settings]);
967
+ onStart($data, () => effectScope(() => clientCtx.mounted()));
968
+ return [
969
+ fetch,
970
+ $data,
971
+ $error,
972
+ $loading,
973
+ $key
974
+ ];
864
975
  }
865
-
866
- // @__NO_SIDE_EFFECTS__
976
+ //#endregion
977
+ //#region src/queries/mutation.ts
978
+ /* @__NO_SIDE_EFFECTS__ */
867
979
  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
- ];
980
+ const clientCtx = /* @__PURE__ */ forkMutationClient(this, settings);
981
+ const { mapComputedData, $disabled, loadingDedupe } = clientCtx;
982
+ const $result = signal(null);
983
+ const $data = computed(() => mapComputedData($result()));
984
+ const $error = signal(null);
985
+ const $loading = signal(false);
986
+ let prevRequestCtx;
987
+ return [
988
+ action((...params) => {
989
+ if ($disabled?.() === true || loadingDedupe && $loading()) return Promise.resolve();
990
+ const requestCtx = prevRequestCtx = new RequestContext(prevRequestCtx);
991
+ return clientCtx.run(requestCtx, () => {
992
+ $loading(true);
993
+ return fn(...params, requestCtx);
994
+ }, (data, error) => {
995
+ if (prevRequestCtx === requestCtx) batch(() => {
996
+ if (error === null) $result(data);
997
+ $error(error);
998
+ $loading(false);
999
+ });
1000
+ });
1001
+ }),
1002
+ $data,
1003
+ readonly($error),
1004
+ readonly($loading)
1005
+ ];
909
1006
  }
910
-
911
- // @__NO_SIDE_EFFECTS__
1007
+ //#endregion
1008
+ //#region src/client.ts
1009
+ /**
1010
+ * Create a query client with optional settings and extensions.
1011
+ * @param settings - The client settings and extensions.
1012
+ * @returns The query client.
1013
+ */
1014
+ /* @__NO_SIDE_EFFECTS__ */
912
1015
  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__
1016
+ const ctx = new ClientContext();
1017
+ const client = {
1018
+ query: query.bind(ctx),
1019
+ invalidate: ((key) => ctx.invalidate(key)),
1020
+ revalidate: ((key) => ctx.revalidate(key)),
1021
+ $data: /* @__PURE__ */ dataCacheFacade(ctx),
1022
+ $error: /* @__PURE__ */ errorCacheFacade(ctx),
1023
+ $loading: /* @__PURE__ */ loadingCacheFacade(ctx)
1024
+ };
1025
+ for (const setting of settings) setting(ctx, client);
1026
+ return client;
1027
+ }
1028
+ /**
1029
+ * Extend client with infinite query capability.
1030
+ * @returns The client extension.
1031
+ */
1032
+ /* @__NO_SIDE_EFFECTS__ */
929
1033
  function infinites() {
930
- return ((ctx, client2) => {
931
- client2.infinite = infinite.bind(ctx);
932
- return client2;
933
- });
1034
+ return ((ctx, client) => {
1035
+ client.infinite = infinite.bind(ctx);
1036
+ return client;
1037
+ });
934
1038
  }
935
- // @__NO_SIDE_EFFECTS__
1039
+ /**
1040
+ * Extend client with operation capability.
1041
+ * @returns The client extension.
1042
+ */
1043
+ /* @__NO_SIDE_EFFECTS__ */
936
1044
  function operations() {
937
- return ((ctx, client2) => {
938
- client2.operation = operation.bind(ctx);
939
- return client2;
940
- });
1045
+ return ((ctx, client) => {
1046
+ client.operation = operation.bind(ctx);
1047
+ return client;
1048
+ });
941
1049
  }
942
- // @__NO_SIDE_EFFECTS__
1050
+ /**
1051
+ * Extend client with mutation capability.
1052
+ * @returns The client extension.
1053
+ */
1054
+ /* @__NO_SIDE_EFFECTS__ */
943
1055
  function mutations() {
944
- return ((ctx, client2) => {
945
- client2.mutation = mutation.bind(ctx);
946
- return client2;
947
- });
1056
+ return ((ctx, client) => {
1057
+ client.mutation = mutation.bind(ctx);
1058
+ return client;
1059
+ });
948
1060
  }
1061
+ //#endregion
1062
+ export { $networkOnline, $windowVisible, ClientContext, DEFAULT_CACHE_TIME, DEFAULT_DEDUPE_TIME, QueryContext, RequestContext, abort, abortPrevious, abortSignal, abortable, cacheTime, client, dedupe, dedupeTime, defaultCalcRetryDelay, disabled, entities, entity, hydratable, indexedDbStorage, infinites, mapError, mutations, onError, onEveryError, onSettled, onSuccess, operationKey, operations, persistence, queryKey, retryOnError, revalidateOnFocus, revalidateOnInterval, revalidateOnReconnect, ssr, stopErrorPropagation, tasks };
949
1063
 
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
1064
+ //# sourceMappingURL=index.js.map