@echojs-ecosystem/query 0.1.0
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/README.md +80 -0
- package/dist/index.d.ts +822 -0
- package/dist/index.js +2140 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2140 @@
|
|
|
1
|
+
import { signal, effect, computed } from '@echojs-ecosystem/reactivity';
|
|
2
|
+
|
|
3
|
+
// src/provider/context.ts
|
|
4
|
+
var activeProvider = null;
|
|
5
|
+
var getQueryProvider = () => activeProvider;
|
|
6
|
+
var requireQueryProvider = () => {
|
|
7
|
+
if (!activeProvider) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
"Query provider is not installed. Call app.use(createQueryProvider(...)) before using queries."
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return activeProvider;
|
|
13
|
+
};
|
|
14
|
+
var setActiveQueryProvider = (provider) => {
|
|
15
|
+
activeProvider = provider;
|
|
16
|
+
};
|
|
17
|
+
var resetQueryProvider = () => {
|
|
18
|
+
activeProvider = null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/client/default-client.ts
|
|
22
|
+
var defaultClient = null;
|
|
23
|
+
var pendingFactory = null;
|
|
24
|
+
var setDefaultQueryClient = (client) => {
|
|
25
|
+
defaultClient = client;
|
|
26
|
+
};
|
|
27
|
+
var registerDefaultQueryClientFactory = (factory) => {
|
|
28
|
+
pendingFactory = factory;
|
|
29
|
+
};
|
|
30
|
+
var getDefaultQueryClient = () => {
|
|
31
|
+
if (!defaultClient) {
|
|
32
|
+
if (!pendingFactory) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"@echojs-ecosystem/query: no default QueryClient. Call createQueryClient() first or pass { client } to .with()."
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
defaultClient = pendingFactory();
|
|
38
|
+
pendingFactory = null;
|
|
39
|
+
}
|
|
40
|
+
return defaultClient;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// src/core/cancelled-error.ts
|
|
44
|
+
var CancelledError = class extends Error {
|
|
45
|
+
revert;
|
|
46
|
+
silent;
|
|
47
|
+
constructor(options) {
|
|
48
|
+
super("CancelledError");
|
|
49
|
+
this.name = "CancelledError";
|
|
50
|
+
this.revert = options?.revert;
|
|
51
|
+
this.silent = options?.silent;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var isCancelledError = (value) => value instanceof CancelledError;
|
|
55
|
+
var isAbortError = (value) => {
|
|
56
|
+
if (isCancelledError(value)) return true;
|
|
57
|
+
if (!value || typeof value !== "object") return false;
|
|
58
|
+
if (value instanceof DOMException && value.name === "AbortError") return true;
|
|
59
|
+
return value.name === "AbortError";
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// src/core/removable.ts
|
|
63
|
+
var Removable = class {
|
|
64
|
+
gcTimeoutId;
|
|
65
|
+
gcTimeMs = Number.POSITIVE_INFINITY;
|
|
66
|
+
scheduleGc(onRemove) {
|
|
67
|
+
this.clearGcTimeout();
|
|
68
|
+
if (!Number.isFinite(this.gcTimeMs)) return;
|
|
69
|
+
this.gcTimeoutId = setTimeout(() => {
|
|
70
|
+
onRemove();
|
|
71
|
+
}, this.gcTimeMs);
|
|
72
|
+
}
|
|
73
|
+
clearGcTimeout() {
|
|
74
|
+
if (this.gcTimeoutId !== void 0) {
|
|
75
|
+
clearTimeout(this.gcTimeoutId);
|
|
76
|
+
this.gcTimeoutId = void 0;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
updateGcTime(cacheTimeMs) {
|
|
80
|
+
this.gcTimeMs = cacheTimeMs;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// src/utils/sleep.ts
|
|
85
|
+
var sleep = (ms) => new Promise((resolve) => {
|
|
86
|
+
setTimeout(resolve, ms);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// src/core/retryer.ts
|
|
90
|
+
var defaultRetryDelay = (failureCount) => Math.min(1e3 * 2 ** failureCount, 3e4);
|
|
91
|
+
var shouldRetry = (failureCount, error, retry) => {
|
|
92
|
+
if (retry === false || retry === void 0) return false;
|
|
93
|
+
if (typeof retry === "number") return failureCount < retry;
|
|
94
|
+
if (retry === true) return true;
|
|
95
|
+
return retry(failureCount, error);
|
|
96
|
+
};
|
|
97
|
+
var getRetryDelay = (failureCount, error, retryDelay) => {
|
|
98
|
+
if (typeof retryDelay === "function") return retryDelay(failureCount, error);
|
|
99
|
+
if (typeof retryDelay === "number") return retryDelay;
|
|
100
|
+
return defaultRetryDelay(failureCount);
|
|
101
|
+
};
|
|
102
|
+
var createRetryer = (config) => {
|
|
103
|
+
let failureCount = 0;
|
|
104
|
+
let rejectFn;
|
|
105
|
+
let resolveFn;
|
|
106
|
+
let settled = false;
|
|
107
|
+
const promise = new Promise((resolve, reject) => {
|
|
108
|
+
resolveFn = resolve;
|
|
109
|
+
rejectFn = reject;
|
|
110
|
+
});
|
|
111
|
+
const cancel = (options) => {
|
|
112
|
+
if (settled) return;
|
|
113
|
+
const error = new CancelledError({ silent: options?.silent });
|
|
114
|
+
config.onCancel?.(error);
|
|
115
|
+
settled = true;
|
|
116
|
+
rejectFn(error);
|
|
117
|
+
};
|
|
118
|
+
const run = () => {
|
|
119
|
+
if (settled) return;
|
|
120
|
+
const initialPromise = failureCount === 0 ? config.initialPromise : void 0;
|
|
121
|
+
Promise.resolve(initialPromise ?? config.fn()).then((value) => {
|
|
122
|
+
if (settled) return;
|
|
123
|
+
settled = true;
|
|
124
|
+
resolveFn(value);
|
|
125
|
+
}).catch(async (error) => {
|
|
126
|
+
if (settled) return;
|
|
127
|
+
if (isCancelledError(error) || isAbortError(error)) {
|
|
128
|
+
settled = true;
|
|
129
|
+
rejectFn(error);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (shouldRetry(failureCount, error, config.retry)) {
|
|
133
|
+
failureCount += 1;
|
|
134
|
+
config.onFail?.(failureCount, error);
|
|
135
|
+
await sleep(getRetryDelay(failureCount, error, config.retryDelay));
|
|
136
|
+
if (!settled) run();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
settled = true;
|
|
140
|
+
rejectFn(error);
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
return {
|
|
144
|
+
promise,
|
|
145
|
+
cancel,
|
|
146
|
+
start: () => {
|
|
147
|
+
run();
|
|
148
|
+
return promise;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// src/core/query-state.ts
|
|
154
|
+
var defaultQueryState = () => ({
|
|
155
|
+
data: void 0,
|
|
156
|
+
error: null,
|
|
157
|
+
status: "idle",
|
|
158
|
+
fetchStatus: "idle",
|
|
159
|
+
dataUpdatedAt: 0,
|
|
160
|
+
errorUpdatedAt: 0,
|
|
161
|
+
fetchFailureCount: 0,
|
|
162
|
+
isInvalidated: false,
|
|
163
|
+
hadSuccess: false
|
|
164
|
+
});
|
|
165
|
+
var queryReducer = (state, action) => {
|
|
166
|
+
switch (action.type) {
|
|
167
|
+
case "fetch":
|
|
168
|
+
return {
|
|
169
|
+
...state,
|
|
170
|
+
fetchStatus: "fetching",
|
|
171
|
+
...state.data === void 0 && state.status === "idle" ? { status: "pending", error: null } : {}
|
|
172
|
+
};
|
|
173
|
+
case "success":
|
|
174
|
+
return {
|
|
175
|
+
...state,
|
|
176
|
+
data: action.data,
|
|
177
|
+
error: null,
|
|
178
|
+
status: "success",
|
|
179
|
+
fetchStatus: "idle",
|
|
180
|
+
dataUpdatedAt: Date.now(),
|
|
181
|
+
fetchFailureCount: 0,
|
|
182
|
+
isInvalidated: false,
|
|
183
|
+
hadSuccess: true
|
|
184
|
+
};
|
|
185
|
+
case "error":
|
|
186
|
+
return {
|
|
187
|
+
...state,
|
|
188
|
+
error: action.error,
|
|
189
|
+
status: "error",
|
|
190
|
+
fetchStatus: "idle",
|
|
191
|
+
errorUpdatedAt: Date.now(),
|
|
192
|
+
fetchFailureCount: state.fetchFailureCount + 1,
|
|
193
|
+
isInvalidated: true
|
|
194
|
+
};
|
|
195
|
+
case "failed":
|
|
196
|
+
return {
|
|
197
|
+
...state,
|
|
198
|
+
fetchFailureCount: action.failureCount,
|
|
199
|
+
error: action.error
|
|
200
|
+
};
|
|
201
|
+
case "invalidate":
|
|
202
|
+
return {
|
|
203
|
+
...state,
|
|
204
|
+
isInvalidated: true
|
|
205
|
+
};
|
|
206
|
+
case "setState":
|
|
207
|
+
return {
|
|
208
|
+
...state,
|
|
209
|
+
...action.state
|
|
210
|
+
};
|
|
211
|
+
default:
|
|
212
|
+
return state;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
var timeUntilStale = (updatedAt, staleTimeMs = 0) => Math.max(updatedAt + staleTimeMs - Date.now(), 0);
|
|
216
|
+
var isStaleByTime = (dataUpdatedAt, staleTimeMs, isInvalidated, hasData) => {
|
|
217
|
+
if (!hasData) return true;
|
|
218
|
+
if (isInvalidated) return true;
|
|
219
|
+
if (!Number.isFinite(staleTimeMs)) return false;
|
|
220
|
+
return timeUntilStale(dataUpdatedAt, staleTimeMs) === 0;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// src/async/lifecycle.ts
|
|
224
|
+
var runLifecycle = async (hooks, phase, ctx) => {
|
|
225
|
+
if (phase === "start") hooks.onStart?.(ctx);
|
|
226
|
+
if (phase === "success") hooks.onSuccess?.(ctx);
|
|
227
|
+
if (phase === "error") hooks.onError?.(ctx);
|
|
228
|
+
if (phase === "settled") hooks.onSettled?.(ctx);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// src/async/abort-control.ts
|
|
232
|
+
var resolveAbortInput = (input) => {
|
|
233
|
+
if (!input) return void 0;
|
|
234
|
+
if (typeof input === "function") return input();
|
|
235
|
+
return input;
|
|
236
|
+
};
|
|
237
|
+
var abortWithReason = (controller, reason) => {
|
|
238
|
+
if (!controller || controller.signal.aborted) return;
|
|
239
|
+
try {
|
|
240
|
+
controller.abort(reason);
|
|
241
|
+
} catch {
|
|
242
|
+
controller.abort();
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
var linkSignal = (source, target) => {
|
|
246
|
+
if (source.aborted) {
|
|
247
|
+
abortWithReason(target, source.reason);
|
|
248
|
+
return () => {
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
const listener = () => abortWithReason(target, source.reason);
|
|
252
|
+
source.addEventListener("abort", listener, { once: true });
|
|
253
|
+
return () => source.removeEventListener("abort", listener);
|
|
254
|
+
};
|
|
255
|
+
var mergeFetchAbortSource = (...sources) => {
|
|
256
|
+
let abortController;
|
|
257
|
+
let signal8;
|
|
258
|
+
for (const source of sources) {
|
|
259
|
+
if (!source) continue;
|
|
260
|
+
if (source.abortController !== void 0) abortController = source.abortController;
|
|
261
|
+
if (source.signal !== void 0) signal8 = source.signal;
|
|
262
|
+
}
|
|
263
|
+
return { abortController, signal: signal8 };
|
|
264
|
+
};
|
|
265
|
+
var createFetchAbortHandle = (source) => {
|
|
266
|
+
const controllerInput = resolveAbortInput(source?.abortController);
|
|
267
|
+
const signalInput = resolveAbortInput(source?.signal);
|
|
268
|
+
const unlinks = [];
|
|
269
|
+
let controller;
|
|
270
|
+
let ownsController;
|
|
271
|
+
if (controllerInput instanceof AbortController) {
|
|
272
|
+
controller = controllerInput;
|
|
273
|
+
ownsController = false;
|
|
274
|
+
} else if (controllerInput instanceof AbortSignal) {
|
|
275
|
+
controller = new AbortController();
|
|
276
|
+
ownsController = true;
|
|
277
|
+
unlinks.push(linkSignal(controllerInput, controller));
|
|
278
|
+
} else {
|
|
279
|
+
controller = new AbortController();
|
|
280
|
+
ownsController = true;
|
|
281
|
+
}
|
|
282
|
+
if (signalInput) {
|
|
283
|
+
const external = signalInput instanceof AbortSignal ? signalInput : signalInput.signal;
|
|
284
|
+
if (external !== controller.signal) {
|
|
285
|
+
unlinks.push(linkSignal(external, controller));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
controller,
|
|
290
|
+
signal: controller.signal,
|
|
291
|
+
ownsController,
|
|
292
|
+
abort: (reason) => abortWithReason(controller, reason),
|
|
293
|
+
dispose: () => {
|
|
294
|
+
for (const unlink of unlinks) unlink();
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// src/utils/hash.ts
|
|
300
|
+
var hasObjectPrototype = (value) => Object.prototype.toString.call(value) === "[object Object]";
|
|
301
|
+
var isPlainObject = (value) => {
|
|
302
|
+
if (!hasObjectPrototype(value)) return false;
|
|
303
|
+
const record = value;
|
|
304
|
+
const ctor = record.constructor;
|
|
305
|
+
if (ctor === void 0) return true;
|
|
306
|
+
const prot = ctor.prototype;
|
|
307
|
+
if (!hasObjectPrototype(prot)) return false;
|
|
308
|
+
if (!Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf")) return false;
|
|
309
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) return false;
|
|
310
|
+
return true;
|
|
311
|
+
};
|
|
312
|
+
var hashKey = (queryKey) => JSON.stringify(
|
|
313
|
+
queryKey,
|
|
314
|
+
(_, val) => isPlainObject(val) ? Object.keys(val).sort().reduce((result, key) => {
|
|
315
|
+
result[key] = val[key];
|
|
316
|
+
return result;
|
|
317
|
+
}, {}) : val
|
|
318
|
+
);
|
|
319
|
+
var partialMatchKey = (a, b) => {
|
|
320
|
+
if (a === b) return true;
|
|
321
|
+
if (typeof a !== typeof b) return false;
|
|
322
|
+
if (a && b && typeof a === "object" && typeof b === "object") {
|
|
323
|
+
const bRecord = b;
|
|
324
|
+
const aRecord = a;
|
|
325
|
+
return Object.keys(bRecord).every(
|
|
326
|
+
(key) => partialMatchKey(aRecord[key], bRecord[key])
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
return false;
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// src/utils/functional-update.ts
|
|
333
|
+
var functionalUpdate = (updater, input) => typeof updater === "function" ? updater(input) : updater;
|
|
334
|
+
|
|
335
|
+
// src/core/query.ts
|
|
336
|
+
var Query = class extends Removable {
|
|
337
|
+
queryKey;
|
|
338
|
+
queryHash;
|
|
339
|
+
definition;
|
|
340
|
+
client;
|
|
341
|
+
params;
|
|
342
|
+
options;
|
|
343
|
+
state;
|
|
344
|
+
observers = /* @__PURE__ */ new Set();
|
|
345
|
+
$data;
|
|
346
|
+
$error;
|
|
347
|
+
$status;
|
|
348
|
+
$fetchStatus;
|
|
349
|
+
$pendingCount;
|
|
350
|
+
$updatedAt;
|
|
351
|
+
$isInvalidated;
|
|
352
|
+
#retryer;
|
|
353
|
+
#abortController;
|
|
354
|
+
#abortDispose;
|
|
355
|
+
#cache;
|
|
356
|
+
constructor(config) {
|
|
357
|
+
super();
|
|
358
|
+
this.client = config.client;
|
|
359
|
+
this.#cache = config.cache;
|
|
360
|
+
this.definition = config.definition;
|
|
361
|
+
this.params = config.params;
|
|
362
|
+
this.queryKey = config.queryKey;
|
|
363
|
+
this.queryHash = hashKey(config.queryKey);
|
|
364
|
+
this.options = config.options;
|
|
365
|
+
this.state = defaultQueryState();
|
|
366
|
+
this.updateGcTime(this.options.cacheTimeMs);
|
|
367
|
+
this.$data = signal(void 0);
|
|
368
|
+
this.$error = signal(null);
|
|
369
|
+
this.$status = signal("idle");
|
|
370
|
+
this.$fetchStatus = signal("idle");
|
|
371
|
+
this.$pendingCount = signal(0);
|
|
372
|
+
this.$updatedAt = signal(null);
|
|
373
|
+
this.$isInvalidated = signal(false);
|
|
374
|
+
}
|
|
375
|
+
get promise() {
|
|
376
|
+
return this.#retryer?.promise;
|
|
377
|
+
}
|
|
378
|
+
isActive() {
|
|
379
|
+
return this.observers.size > 0;
|
|
380
|
+
}
|
|
381
|
+
isStale() {
|
|
382
|
+
return isStaleByTime(
|
|
383
|
+
this.state.dataUpdatedAt,
|
|
384
|
+
this.options.staleTimeMs,
|
|
385
|
+
this.state.isInvalidated,
|
|
386
|
+
this.state.data !== void 0
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
isStaleByTime(staleTimeMs = this.options.staleTimeMs) {
|
|
390
|
+
return isStaleByTime(
|
|
391
|
+
this.state.dataUpdatedAt,
|
|
392
|
+
staleTimeMs,
|
|
393
|
+
this.state.isInvalidated,
|
|
394
|
+
this.state.data !== void 0
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
hasData() {
|
|
398
|
+
return this.state.data !== void 0;
|
|
399
|
+
}
|
|
400
|
+
addObserver(observer) {
|
|
401
|
+
if (!this.observers.has(observer)) {
|
|
402
|
+
this.observers.add(observer);
|
|
403
|
+
this.clearGcTimeout();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
removeObserver(observer) {
|
|
407
|
+
if (this.observers.delete(observer) && this.observers.size === 0) {
|
|
408
|
+
this.scheduleGc(() => this.#cache.remove(this));
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
setData(updater) {
|
|
412
|
+
const next = functionalUpdate(updater, this.state.data);
|
|
413
|
+
this.#dispatch({ type: "success", data: next });
|
|
414
|
+
return next;
|
|
415
|
+
}
|
|
416
|
+
invalidate() {
|
|
417
|
+
if (!this.state.isInvalidated) {
|
|
418
|
+
this.#dispatch({ type: "invalidate" });
|
|
419
|
+
this.#cache.emit({
|
|
420
|
+
type: "queryInvalidated",
|
|
421
|
+
queryKey: this.queryKey,
|
|
422
|
+
hash: this.queryHash
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
getAbortController() {
|
|
427
|
+
return this.#abortController;
|
|
428
|
+
}
|
|
429
|
+
getAbortSignal() {
|
|
430
|
+
return this.#abortController?.signal;
|
|
431
|
+
}
|
|
432
|
+
cancel(options) {
|
|
433
|
+
abortWithReason(this.#abortController, options?.reason);
|
|
434
|
+
const promise = this.#retryer?.promise;
|
|
435
|
+
if (promise) {
|
|
436
|
+
void promise.catch(() => void 0);
|
|
437
|
+
}
|
|
438
|
+
this.#retryer?.cancel(options);
|
|
439
|
+
this.#retryer = void 0;
|
|
440
|
+
this.#clearAbortHandle();
|
|
441
|
+
this.#dispatch({ type: "setState", state: { fetchStatus: "idle" } });
|
|
442
|
+
return promise ? promise.then(() => void 0).catch(() => void 0) : Promise.resolve();
|
|
443
|
+
}
|
|
444
|
+
async fetch(options) {
|
|
445
|
+
if (this.state.fetchStatus !== "idle" && this.#retryer) {
|
|
446
|
+
if (options?.cancelRefetch) {
|
|
447
|
+
await this.cancel({ silent: true });
|
|
448
|
+
} else {
|
|
449
|
+
return this.#retryer.promise;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
const abortHandle = createFetchAbortHandle(
|
|
453
|
+
mergeFetchAbortSource(this.options, options)
|
|
454
|
+
);
|
|
455
|
+
this.#abortController = abortHandle.controller;
|
|
456
|
+
this.#abortDispose = abortHandle.dispose;
|
|
457
|
+
const { controller: abortController, signal: signal8 } = abortHandle;
|
|
458
|
+
const lifecycleCtx = {
|
|
459
|
+
params: this.params,
|
|
460
|
+
queryKey: this.queryKey,
|
|
461
|
+
queryClient: this.client
|
|
462
|
+
};
|
|
463
|
+
this.#dispatch({ type: "fetch" });
|
|
464
|
+
this.$pendingCount.set(this.$pendingCount.peek() + 1);
|
|
465
|
+
void runLifecycle(this.options, "start", lifecycleCtx);
|
|
466
|
+
this.#retryer = createRetryer({
|
|
467
|
+
fn: async () => {
|
|
468
|
+
const raw = await this.definition.options.queryFn({
|
|
469
|
+
params: this.params,
|
|
470
|
+
signal: signal8,
|
|
471
|
+
abortController,
|
|
472
|
+
queryClient: this.client,
|
|
473
|
+
queryKey: this.queryKey
|
|
474
|
+
});
|
|
475
|
+
if (signal8.aborted) {
|
|
476
|
+
throw new CancelledError({ silent: true });
|
|
477
|
+
}
|
|
478
|
+
const transform = this.definition.options.transform;
|
|
479
|
+
return transform ? await transform(raw) : raw;
|
|
480
|
+
},
|
|
481
|
+
onCancel: () => abortHandle.abort(),
|
|
482
|
+
onFail: (failureCount, error) => {
|
|
483
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
484
|
+
this.#dispatch({
|
|
485
|
+
type: "failed",
|
|
486
|
+
failureCount,
|
|
487
|
+
error: err
|
|
488
|
+
});
|
|
489
|
+
},
|
|
490
|
+
retry: this.options.retry,
|
|
491
|
+
retryDelay: this.options.retryDelay
|
|
492
|
+
});
|
|
493
|
+
try {
|
|
494
|
+
const data = await this.#retryer.start();
|
|
495
|
+
this.#dispatch({ type: "success", data });
|
|
496
|
+
this.#cache.emit({
|
|
497
|
+
type: "queryFetched",
|
|
498
|
+
queryKey: this.queryKey,
|
|
499
|
+
hash: this.queryHash,
|
|
500
|
+
data
|
|
501
|
+
});
|
|
502
|
+
await runLifecycle(this.options, "success", { ...lifecycleCtx, data });
|
|
503
|
+
await runLifecycle(this.options, "settled", { ...lifecycleCtx, data });
|
|
504
|
+
return data;
|
|
505
|
+
} catch (error) {
|
|
506
|
+
if (isCancelledError(error)) {
|
|
507
|
+
if (error.silent) {
|
|
508
|
+
return this.state.data;
|
|
509
|
+
}
|
|
510
|
+
throw error;
|
|
511
|
+
}
|
|
512
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
513
|
+
this.#dispatch({ type: "error", error: err });
|
|
514
|
+
await runLifecycle(this.options, "error", { ...lifecycleCtx, error: err });
|
|
515
|
+
await runLifecycle(this.options, "settled", { ...lifecycleCtx, error: err });
|
|
516
|
+
throw error;
|
|
517
|
+
} finally {
|
|
518
|
+
this.$pendingCount.set(Math.max(0, this.$pendingCount.peek() - 1));
|
|
519
|
+
this.#retryer = void 0;
|
|
520
|
+
this.#clearAbortHandle();
|
|
521
|
+
this.scheduleGc(() => {
|
|
522
|
+
if (this.observers.size === 0) this.#cache.remove(this);
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
#clearAbortHandle() {
|
|
527
|
+
this.#abortDispose?.();
|
|
528
|
+
this.#abortDispose = void 0;
|
|
529
|
+
this.#abortController = void 0;
|
|
530
|
+
}
|
|
531
|
+
onFocus() {
|
|
532
|
+
if (this.isActive() && this.isStale() && this.options.refetchOnWindowFocus) {
|
|
533
|
+
void this.fetch();
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
onOnline() {
|
|
537
|
+
if (this.isActive() && this.isStale() && this.options.refetchOnReconnect) {
|
|
538
|
+
void this.fetch();
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
#dispatch(action) {
|
|
542
|
+
this.state = queryReducer(this.state, action);
|
|
543
|
+
this.syncSignals();
|
|
544
|
+
this.#cache.emit({
|
|
545
|
+
type: "queryUpdated",
|
|
546
|
+
queryKey: this.queryKey,
|
|
547
|
+
hash: this.queryHash
|
|
548
|
+
});
|
|
549
|
+
for (const observer of this.observers) {
|
|
550
|
+
observer.onQueryUpdate();
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
syncSignals() {
|
|
554
|
+
this.$data.set(this.state.data);
|
|
555
|
+
this.$error.set(this.state.error);
|
|
556
|
+
this.$status.set(this.state.status);
|
|
557
|
+
this.$fetchStatus.set(this.state.fetchStatus);
|
|
558
|
+
this.$updatedAt.set(this.state.dataUpdatedAt || null);
|
|
559
|
+
this.$isInvalidated.set(this.state.isInvalidated);
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
// src/query/query-options.ts
|
|
564
|
+
var DEFAULT_CACHE_TIME_MS = 5 * 6e4;
|
|
565
|
+
var defaultQueryOptions = (config) => ({
|
|
566
|
+
staleTime: config?.defaultOptions?.queries?.staleTime ?? 0,
|
|
567
|
+
cacheTime: config?.defaultOptions?.queries?.cacheTime ?? DEFAULT_CACHE_TIME_MS,
|
|
568
|
+
retry: config?.defaultOptions?.queries?.retry ?? false,
|
|
569
|
+
retryDelay: config?.defaultOptions?.queries?.retryDelay ?? 1e3,
|
|
570
|
+
keepPreviousData: config?.defaultOptions?.queries?.keepPreviousData ?? false,
|
|
571
|
+
abortPrevious: config?.defaultOptions?.queries?.abortPrevious ?? true
|
|
572
|
+
});
|
|
573
|
+
var mergeQueryDefinitionOptions = (options, config, provider) => ({
|
|
574
|
+
...defaultQueryOptions(config),
|
|
575
|
+
...provider?.config.defaultOptions?.queries,
|
|
576
|
+
...options
|
|
577
|
+
});
|
|
578
|
+
var toMs = (value, fallback) => {
|
|
579
|
+
if (value === void 0) return fallback;
|
|
580
|
+
if (!Number.isFinite(value)) return Number.POSITIVE_INFINITY;
|
|
581
|
+
return value;
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
// src/query/query-status.ts
|
|
585
|
+
var DEFAULT_CACHE_TIME_MS2 = 5 * 6e4;
|
|
586
|
+
var resolveQueryOptions = (options) => {
|
|
587
|
+
const staleTime = options.staleTime ?? 0;
|
|
588
|
+
const cacheTime = options.cacheTime ?? DEFAULT_CACHE_TIME_MS2;
|
|
589
|
+
return {
|
|
590
|
+
...options,
|
|
591
|
+
staleTime,
|
|
592
|
+
cacheTime,
|
|
593
|
+
retry: options.retry ?? false,
|
|
594
|
+
retryDelay: options.retryDelay ?? 1e3,
|
|
595
|
+
keepPreviousData: options.keepPreviousData ?? false,
|
|
596
|
+
abortPrevious: options.abortPrevious ?? true,
|
|
597
|
+
staleTimeMs: toMs(staleTime, 0),
|
|
598
|
+
cacheTimeMs: toMs(cacheTime, DEFAULT_CACHE_TIME_MS2)
|
|
599
|
+
};
|
|
600
|
+
};
|
|
601
|
+
var resolveInstanceOptions = (definitionOptions, instanceOptions) => {
|
|
602
|
+
const staleTime = instanceOptions?.staleTime ?? definitionOptions.staleTime ?? 0;
|
|
603
|
+
const cacheTime = instanceOptions?.cacheTime ?? definitionOptions.cacheTime ?? DEFAULT_CACHE_TIME_MS2;
|
|
604
|
+
return {
|
|
605
|
+
...definitionOptions,
|
|
606
|
+
...instanceOptions,
|
|
607
|
+
staleTime,
|
|
608
|
+
cacheTime,
|
|
609
|
+
staleTimeMs: toMs(staleTime, 0),
|
|
610
|
+
cacheTimeMs: toMs(cacheTime, DEFAULT_CACHE_TIME_MS2),
|
|
611
|
+
enabled: instanceOptions?.enabled ?? true,
|
|
612
|
+
refetchOnMount: instanceOptions?.refetchOnMount ?? true,
|
|
613
|
+
refetchOnWindowFocus: instanceOptions?.refetchOnWindowFocus ?? true,
|
|
614
|
+
refetchOnReconnect: instanceOptions?.refetchOnReconnect ?? true,
|
|
615
|
+
keepPreviousData: instanceOptions?.keepPreviousData ?? definitionOptions.keepPreviousData ?? false,
|
|
616
|
+
abortPrevious: instanceOptions?.abortPrevious ?? definitionOptions.abortPrevious ?? true,
|
|
617
|
+
retry: instanceOptions?.retry ?? definitionOptions.retry ?? false,
|
|
618
|
+
retryDelay: instanceOptions?.retryDelay ?? definitionOptions.retryDelay ?? 1e3,
|
|
619
|
+
onStart: instanceOptions?.onStart ?? definitionOptions.onStart,
|
|
620
|
+
onSuccess: instanceOptions?.onSuccess ?? definitionOptions.onSuccess,
|
|
621
|
+
onError: instanceOptions?.onError ?? definitionOptions.onError,
|
|
622
|
+
onSettled: instanceOptions?.onSettled ?? definitionOptions.onSettled
|
|
623
|
+
};
|
|
624
|
+
};
|
|
625
|
+
var isEnabled = (enabled) => typeof enabled === "function" ? enabled() : enabled;
|
|
626
|
+
var isQueryPending = (status) => status === "pending";
|
|
627
|
+
var isQueryFetching = (fetchStatus) => fetchStatus === "fetching";
|
|
628
|
+
var isQuerySuccess = (status) => status === "success";
|
|
629
|
+
var isQueryError = (status) => status === "error";
|
|
630
|
+
var isQueryIdle = (status) => status === "idle";
|
|
631
|
+
var isQueryPaused = (fetchStatus) => fetchStatus === "paused";
|
|
632
|
+
var resolveDefinitionOptions = (definition) => resolveQueryOptions(definition.options);
|
|
633
|
+
|
|
634
|
+
// src/query/query-observer.ts
|
|
635
|
+
var QueryObserver = class {
|
|
636
|
+
definition;
|
|
637
|
+
client;
|
|
638
|
+
options;
|
|
639
|
+
#query = null;
|
|
640
|
+
#previousQuery = null;
|
|
641
|
+
#params;
|
|
642
|
+
#disposeParams = null;
|
|
643
|
+
#destroyed = false;
|
|
644
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
645
|
+
#currentHash = null;
|
|
646
|
+
constructor(definition, client, params, instanceOptions) {
|
|
647
|
+
this.definition = definition;
|
|
648
|
+
this.client = client;
|
|
649
|
+
this.options = resolveInstanceOptions(
|
|
650
|
+
resolveDefinitionOptions(definition),
|
|
651
|
+
instanceOptions
|
|
652
|
+
);
|
|
653
|
+
if (typeof params === "function") {
|
|
654
|
+
this.#disposeParams = effect(() => {
|
|
655
|
+
this.setParams(params());
|
|
656
|
+
});
|
|
657
|
+
} else {
|
|
658
|
+
this.setParams(params);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
getQuery() {
|
|
662
|
+
return this.#query;
|
|
663
|
+
}
|
|
664
|
+
getPreviousQuery() {
|
|
665
|
+
return this.#previousQuery;
|
|
666
|
+
}
|
|
667
|
+
getParams() {
|
|
668
|
+
return this.#params;
|
|
669
|
+
}
|
|
670
|
+
onQueryUpdate() {
|
|
671
|
+
for (const listener of this.#listeners) listener();
|
|
672
|
+
}
|
|
673
|
+
subscribe(listener) {
|
|
674
|
+
this.#listeners.add(listener);
|
|
675
|
+
return () => this.#listeners.delete(listener);
|
|
676
|
+
}
|
|
677
|
+
setParams(params) {
|
|
678
|
+
if (this.#destroyed) return;
|
|
679
|
+
this.#params = params;
|
|
680
|
+
const queryKey = this.definition.queryKey(params);
|
|
681
|
+
const hash = hashKey(queryKey);
|
|
682
|
+
if (this.#currentHash === hash) {
|
|
683
|
+
void this.maybeFetch(false);
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
if (this.#query) {
|
|
687
|
+
if (this.options.abortPrevious) {
|
|
688
|
+
void this.#query.cancel({ silent: true });
|
|
689
|
+
}
|
|
690
|
+
this.#detach(this.#query);
|
|
691
|
+
this.#previousQuery = this.options.keepPreviousData ? this.#query : null;
|
|
692
|
+
}
|
|
693
|
+
this.#currentHash = hash;
|
|
694
|
+
this.#query = this.client.queryCache.build({
|
|
695
|
+
client: this.client,
|
|
696
|
+
cache: this.client.queryCache,
|
|
697
|
+
definition: this.definition,
|
|
698
|
+
params,
|
|
699
|
+
queryKey,
|
|
700
|
+
options: this.options
|
|
701
|
+
});
|
|
702
|
+
this.#query.addObserver(this);
|
|
703
|
+
void this.maybeFetch(true);
|
|
704
|
+
this.onQueryUpdate();
|
|
705
|
+
}
|
|
706
|
+
maybeFetch(paramsChanged) {
|
|
707
|
+
if (!this.#query || !isEnabled(this.options.enabled)) return;
|
|
708
|
+
const stale = this.#query.isStale();
|
|
709
|
+
const hasData = this.#query.hasData();
|
|
710
|
+
if (!hasData || stale) {
|
|
711
|
+
void this.fetch();
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
if (paramsChanged && this.options.refetchOnMount === true) {
|
|
715
|
+
void this.fetch();
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
async fetch(options) {
|
|
719
|
+
if (!this.#query) throw new Error("QueryObserver has no active query");
|
|
720
|
+
try {
|
|
721
|
+
return await this.#query.fetch(options);
|
|
722
|
+
} catch (error) {
|
|
723
|
+
if (isCancelledError(error) && !options?.throwOnError) {
|
|
724
|
+
throw error;
|
|
725
|
+
}
|
|
726
|
+
if (options?.throwOnError) throw error;
|
|
727
|
+
throw error;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
async refetch(options) {
|
|
731
|
+
return this.fetch(options);
|
|
732
|
+
}
|
|
733
|
+
invalidate() {
|
|
734
|
+
this.#query?.invalidate();
|
|
735
|
+
if (this.#query?.isActive()) {
|
|
736
|
+
void this.fetch();
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
cancel(options) {
|
|
740
|
+
return this.#query?.cancel(options) ?? Promise.resolve();
|
|
741
|
+
}
|
|
742
|
+
remove() {
|
|
743
|
+
if (!this.#query) return;
|
|
744
|
+
this.#detach(this.#query);
|
|
745
|
+
this.client.queryCache.remove(this.#query);
|
|
746
|
+
this.#query = null;
|
|
747
|
+
this.#currentHash = null;
|
|
748
|
+
this.onQueryUpdate();
|
|
749
|
+
}
|
|
750
|
+
destroy() {
|
|
751
|
+
if (this.#destroyed) return;
|
|
752
|
+
this.#destroyed = true;
|
|
753
|
+
this.#disposeParams?.();
|
|
754
|
+
if (this.#query) this.#detach(this.#query);
|
|
755
|
+
this.#listeners.clear();
|
|
756
|
+
}
|
|
757
|
+
#detach(query) {
|
|
758
|
+
query.removeObserver(this);
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
// src/query/query-instance.ts
|
|
763
|
+
var effectiveQuery = (observer) => {
|
|
764
|
+
const query = observer.getQuery();
|
|
765
|
+
if (!query) return observer.getPreviousQuery();
|
|
766
|
+
if (query.hasData()) return query;
|
|
767
|
+
const prev = observer.getPreviousQuery();
|
|
768
|
+
if (prev && observer.options.keepPreviousData) return prev;
|
|
769
|
+
return query;
|
|
770
|
+
};
|
|
771
|
+
var createQueryInstance = (definition, client, params, instanceOptions) => {
|
|
772
|
+
const observer = new QueryObserver(definition, client, params, instanceOptions);
|
|
773
|
+
const $params = signal(observer.getParams());
|
|
774
|
+
observer.subscribe(() => $params.set(observer.getParams()));
|
|
775
|
+
const readQuery = () => effectiveQuery(observer);
|
|
776
|
+
const $data = computed(() => readQuery()?.$data.value());
|
|
777
|
+
const $error = computed(() => readQuery()?.$error.value() ?? null);
|
|
778
|
+
const $status = computed(() => readQuery()?.$status.value() ?? "idle");
|
|
779
|
+
const $fetchStatus = computed(() => observer.getQuery()?.$fetchStatus.value() ?? "idle");
|
|
780
|
+
const $pendingCount = computed(() => observer.getQuery()?.$pendingCount.value() ?? 0);
|
|
781
|
+
const $updatedAt = computed(() => observer.getQuery()?.$updatedAt.value() ?? null);
|
|
782
|
+
const $isStale = computed(() => observer.getQuery()?.isStale() ?? true);
|
|
783
|
+
const $abortSignal = computed(() => readQuery()?.getAbortSignal() ?? null);
|
|
784
|
+
return {
|
|
785
|
+
kind: "query-instance",
|
|
786
|
+
value: () => $data.value(),
|
|
787
|
+
data: () => $data.value(),
|
|
788
|
+
error: () => $error.value(),
|
|
789
|
+
params: () => $params.value(),
|
|
790
|
+
status: () => $status.value(),
|
|
791
|
+
fetchStatus: () => $fetchStatus.value(),
|
|
792
|
+
pending: () => isQueryPending($status.value()),
|
|
793
|
+
isPending: () => isQueryPending($status.value()),
|
|
794
|
+
isFirstPending: () => {
|
|
795
|
+
const q = observer.getQuery();
|
|
796
|
+
return q ? q.state.status === "pending" && !q.state.hadSuccess : false;
|
|
797
|
+
},
|
|
798
|
+
isRefetching: () => {
|
|
799
|
+
const q = observer.getQuery();
|
|
800
|
+
return q ? q.state.fetchStatus === "fetching" && q.hasData() : false;
|
|
801
|
+
},
|
|
802
|
+
isFetching: () => isQueryFetching($fetchStatus.value()),
|
|
803
|
+
isSuccess: () => isQuerySuccess($status.value()),
|
|
804
|
+
isError: () => isQueryError($status.value()),
|
|
805
|
+
isIdle: () => isQueryIdle($status.value()),
|
|
806
|
+
isStale: () => $isStale.value(),
|
|
807
|
+
isPaused: () => isQueryPaused($fetchStatus.value()),
|
|
808
|
+
hasData: () => $data.value() !== void 0,
|
|
809
|
+
hasError: () => $error.value() !== null,
|
|
810
|
+
refetch: (options) => observer.refetch(options),
|
|
811
|
+
invalidate: () => observer.invalidate(),
|
|
812
|
+
cancel: (options) => observer.cancel(options),
|
|
813
|
+
abort: (reason) => observer.cancel({ reason }),
|
|
814
|
+
abortController: () => observer.getQuery()?.getAbortController() ?? null,
|
|
815
|
+
abortSignal: () => observer.getQuery()?.getAbortSignal() ?? null,
|
|
816
|
+
remove: () => {
|
|
817
|
+
observer.remove();
|
|
818
|
+
observer.destroy();
|
|
819
|
+
},
|
|
820
|
+
subscribe(listener) {
|
|
821
|
+
return observer.subscribe(() => listener($data.value()));
|
|
822
|
+
},
|
|
823
|
+
$data,
|
|
824
|
+
$error,
|
|
825
|
+
$params,
|
|
826
|
+
$status,
|
|
827
|
+
$fetchStatus,
|
|
828
|
+
$pendingCount,
|
|
829
|
+
$isStale,
|
|
830
|
+
$updatedAt,
|
|
831
|
+
$abortSignal
|
|
832
|
+
};
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
// src/query/create-query.ts
|
|
836
|
+
var createQuery = (options, meta) => {
|
|
837
|
+
const provider = meta?.provider ?? getQueryProvider();
|
|
838
|
+
const mergedOptions = mergeQueryDefinitionOptions(
|
|
839
|
+
options,
|
|
840
|
+
provider?.config,
|
|
841
|
+
provider
|
|
842
|
+
);
|
|
843
|
+
resolveQueryOptions(mergedOptions);
|
|
844
|
+
const definition = {
|
|
845
|
+
kind: "query-definition",
|
|
846
|
+
name: options.name,
|
|
847
|
+
options: mergedOptions,
|
|
848
|
+
queryKey(params) {
|
|
849
|
+
return mergedOptions.queryKey(params);
|
|
850
|
+
},
|
|
851
|
+
with(params, instanceOptions) {
|
|
852
|
+
const client = instanceOptions?.client ?? provider?.client ?? getDefaultQueryClient();
|
|
853
|
+
return createQueryInstance(definition, client, params, instanceOptions);
|
|
854
|
+
},
|
|
855
|
+
withStore(store, map, instanceOptions) {
|
|
856
|
+
const client = instanceOptions?.client ?? provider?.client ?? getDefaultQueryClient();
|
|
857
|
+
return createQueryInstance(
|
|
858
|
+
definition,
|
|
859
|
+
client,
|
|
860
|
+
() => map(store.value()),
|
|
861
|
+
instanceOptions
|
|
862
|
+
);
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
return definition;
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
// src/core/infinite-query-state.ts
|
|
869
|
+
var defaultInfiniteQueryState = () => ({
|
|
870
|
+
data: void 0,
|
|
871
|
+
error: null,
|
|
872
|
+
status: "idle",
|
|
873
|
+
fetchStatus: "idle",
|
|
874
|
+
dataUpdatedAt: 0,
|
|
875
|
+
errorUpdatedAt: 0,
|
|
876
|
+
fetchFailureCount: 0,
|
|
877
|
+
isInvalidated: false,
|
|
878
|
+
hadSuccess: false,
|
|
879
|
+
fetchingNextPage: false,
|
|
880
|
+
fetchingPreviousPage: false
|
|
881
|
+
});
|
|
882
|
+
var infiniteQueryReducer = (state, action) => {
|
|
883
|
+
switch (action.type) {
|
|
884
|
+
case "fetch":
|
|
885
|
+
return {
|
|
886
|
+
...state,
|
|
887
|
+
fetchStatus: "fetching",
|
|
888
|
+
fetchingNextPage: action.direction === "next" || action.direction === "initial",
|
|
889
|
+
fetchingPreviousPage: action.direction === "previous",
|
|
890
|
+
...state.data === void 0 && state.status === "idle" ? { status: "pending", error: null } : {}
|
|
891
|
+
};
|
|
892
|
+
case "success":
|
|
893
|
+
return {
|
|
894
|
+
...state,
|
|
895
|
+
data: action.data,
|
|
896
|
+
error: null,
|
|
897
|
+
status: "success",
|
|
898
|
+
fetchStatus: "idle",
|
|
899
|
+
dataUpdatedAt: Date.now(),
|
|
900
|
+
fetchFailureCount: 0,
|
|
901
|
+
isInvalidated: false,
|
|
902
|
+
hadSuccess: true,
|
|
903
|
+
fetchingNextPage: false,
|
|
904
|
+
fetchingPreviousPage: false
|
|
905
|
+
};
|
|
906
|
+
case "error":
|
|
907
|
+
return {
|
|
908
|
+
...state,
|
|
909
|
+
error: action.error,
|
|
910
|
+
status: "error",
|
|
911
|
+
fetchStatus: "idle",
|
|
912
|
+
errorUpdatedAt: Date.now(),
|
|
913
|
+
fetchFailureCount: state.fetchFailureCount + 1,
|
|
914
|
+
isInvalidated: true,
|
|
915
|
+
fetchingNextPage: false,
|
|
916
|
+
fetchingPreviousPage: false
|
|
917
|
+
};
|
|
918
|
+
case "failed":
|
|
919
|
+
return {
|
|
920
|
+
...state,
|
|
921
|
+
fetchFailureCount: action.failureCount,
|
|
922
|
+
error: action.error
|
|
923
|
+
};
|
|
924
|
+
case "invalidate":
|
|
925
|
+
return { ...state, isInvalidated: true };
|
|
926
|
+
case "reset":
|
|
927
|
+
return defaultInfiniteQueryState();
|
|
928
|
+
case "setState":
|
|
929
|
+
return { ...state, ...action.state };
|
|
930
|
+
default:
|
|
931
|
+
return state;
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
// src/core/infinite-query.ts
|
|
936
|
+
var hasInfiniteNextPage = (data, getNextPageParam) => {
|
|
937
|
+
if (!data || data.pages.length === 0) return true;
|
|
938
|
+
const lastPage = data.pages[data.pages.length - 1];
|
|
939
|
+
const next = getNextPageParam(lastPage, data.pages);
|
|
940
|
+
return next !== void 0 && next !== null;
|
|
941
|
+
};
|
|
942
|
+
var hasInfinitePreviousPage = (data, getPreviousPageParam) => {
|
|
943
|
+
if (!getPreviousPageParam || !data || data.pages.length === 0) return false;
|
|
944
|
+
const firstPage = data.pages[0];
|
|
945
|
+
const prev = getPreviousPageParam(firstPage, data.pages);
|
|
946
|
+
return prev !== void 0 && prev !== null;
|
|
947
|
+
};
|
|
948
|
+
var InfiniteQuery = class extends Removable {
|
|
949
|
+
queryKey;
|
|
950
|
+
queryHash;
|
|
951
|
+
definition;
|
|
952
|
+
client;
|
|
953
|
+
params;
|
|
954
|
+
options;
|
|
955
|
+
state;
|
|
956
|
+
observers = /* @__PURE__ */ new Set();
|
|
957
|
+
$data;
|
|
958
|
+
$error;
|
|
959
|
+
$status;
|
|
960
|
+
$fetchStatus;
|
|
961
|
+
$pendingCount;
|
|
962
|
+
$updatedAt;
|
|
963
|
+
$isInvalidated;
|
|
964
|
+
$fetchingNextPage;
|
|
965
|
+
$fetchingPreviousPage;
|
|
966
|
+
#retryer;
|
|
967
|
+
#abortController;
|
|
968
|
+
#abortDispose;
|
|
969
|
+
#cache;
|
|
970
|
+
#requestId = 0;
|
|
971
|
+
constructor(config) {
|
|
972
|
+
super();
|
|
973
|
+
this.client = config.client;
|
|
974
|
+
this.#cache = config.cache;
|
|
975
|
+
this.definition = config.definition;
|
|
976
|
+
this.params = config.params;
|
|
977
|
+
this.queryKey = config.queryKey;
|
|
978
|
+
this.queryHash = hashKey(config.queryKey);
|
|
979
|
+
this.options = config.options;
|
|
980
|
+
this.state = defaultInfiniteQueryState();
|
|
981
|
+
this.updateGcTime(this.options.cacheTimeMs);
|
|
982
|
+
this.$data = signal(void 0);
|
|
983
|
+
this.$error = signal(null);
|
|
984
|
+
this.$status = signal("idle");
|
|
985
|
+
this.$fetchStatus = signal("idle");
|
|
986
|
+
this.$pendingCount = signal(0);
|
|
987
|
+
this.$updatedAt = signal(null);
|
|
988
|
+
this.$isInvalidated = signal(false);
|
|
989
|
+
this.$fetchingNextPage = signal(false);
|
|
990
|
+
this.$fetchingPreviousPage = signal(false);
|
|
991
|
+
}
|
|
992
|
+
isActive() {
|
|
993
|
+
return this.observers.size > 0;
|
|
994
|
+
}
|
|
995
|
+
isStale() {
|
|
996
|
+
return isStaleByTime(
|
|
997
|
+
this.state.dataUpdatedAt,
|
|
998
|
+
this.options.staleTimeMs,
|
|
999
|
+
this.state.isInvalidated,
|
|
1000
|
+
this.state.data !== void 0
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
hasData() {
|
|
1004
|
+
return this.state.data !== void 0 && this.state.data.pages.length > 0;
|
|
1005
|
+
}
|
|
1006
|
+
hasNextPage() {
|
|
1007
|
+
return hasInfiniteNextPage(this.state.data, this.definition.options.getNextPageParam);
|
|
1008
|
+
}
|
|
1009
|
+
hasPreviousPage() {
|
|
1010
|
+
return hasInfinitePreviousPage(this.state.data, this.definition.options.getPreviousPageParam);
|
|
1011
|
+
}
|
|
1012
|
+
addObserver(observer) {
|
|
1013
|
+
if (!this.observers.has(observer)) {
|
|
1014
|
+
this.observers.add(observer);
|
|
1015
|
+
this.clearGcTimeout();
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
removeObserver(observer) {
|
|
1019
|
+
if (this.observers.delete(observer) && this.observers.size === 0) {
|
|
1020
|
+
this.scheduleGc(() => this.#cache.remove(this));
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
reset() {
|
|
1024
|
+
this.#requestId += 1;
|
|
1025
|
+
void this.cancel({ silent: true });
|
|
1026
|
+
this.#dispatch({ type: "reset" });
|
|
1027
|
+
}
|
|
1028
|
+
getAbortController() {
|
|
1029
|
+
return this.#abortController;
|
|
1030
|
+
}
|
|
1031
|
+
getAbortSignal() {
|
|
1032
|
+
return this.#abortController?.signal;
|
|
1033
|
+
}
|
|
1034
|
+
cancel(options) {
|
|
1035
|
+
this.#requestId += 1;
|
|
1036
|
+
abortWithReason(this.#abortController, options?.reason);
|
|
1037
|
+
const promise = this.#retryer?.promise;
|
|
1038
|
+
this.#retryer?.cancel(options);
|
|
1039
|
+
this.#retryer = void 0;
|
|
1040
|
+
this.#clearAbortHandle();
|
|
1041
|
+
this.#dispatch({
|
|
1042
|
+
type: "setState",
|
|
1043
|
+
state: {
|
|
1044
|
+
fetchStatus: "idle",
|
|
1045
|
+
fetchingNextPage: false,
|
|
1046
|
+
fetchingPreviousPage: false
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
return promise ? promise.then(() => void 0).catch(() => void 0) : Promise.resolve();
|
|
1050
|
+
}
|
|
1051
|
+
async refetch(options) {
|
|
1052
|
+
await this.cancel({ silent: true });
|
|
1053
|
+
this.#dispatch({ type: "reset" });
|
|
1054
|
+
await this.fetchPage("initial", options);
|
|
1055
|
+
if (!this.state.data) {
|
|
1056
|
+
throw new Error("Infinite query refetch failed");
|
|
1057
|
+
}
|
|
1058
|
+
return this.state.data;
|
|
1059
|
+
}
|
|
1060
|
+
async fetchNextPage(options) {
|
|
1061
|
+
if (!this.hasNextPage()) return null;
|
|
1062
|
+
const direction = this.hasData() ? "next" : "initial";
|
|
1063
|
+
return this.fetchPage(direction, options);
|
|
1064
|
+
}
|
|
1065
|
+
async fetchPreviousPage(options) {
|
|
1066
|
+
if (!this.hasPreviousPage()) return null;
|
|
1067
|
+
return this.fetchPage("previous", options);
|
|
1068
|
+
}
|
|
1069
|
+
async fetchPage(direction, abortSource) {
|
|
1070
|
+
if (direction === "next" && !this.hasNextPage()) return null;
|
|
1071
|
+
if (direction === "previous" && !this.hasPreviousPage()) return null;
|
|
1072
|
+
const requestId = ++this.#requestId;
|
|
1073
|
+
const abortHandle = createFetchAbortHandle(
|
|
1074
|
+
mergeFetchAbortSource(this.options, abortSource)
|
|
1075
|
+
);
|
|
1076
|
+
this.#abortController = abortHandle.controller;
|
|
1077
|
+
this.#abortDispose = abortHandle.dispose;
|
|
1078
|
+
const { controller: abortController, signal: signal8 } = abortHandle;
|
|
1079
|
+
const { initialPageParam, getNextPageParam, getPreviousPageParam } = this.definition.options;
|
|
1080
|
+
const current = this.state.data;
|
|
1081
|
+
let pageParam;
|
|
1082
|
+
if (direction === "initial") {
|
|
1083
|
+
pageParam = initialPageParam;
|
|
1084
|
+
} else if (direction === "next") {
|
|
1085
|
+
const lastPage = current.pages[current.pages.length - 1];
|
|
1086
|
+
pageParam = getNextPageParam(lastPage, current.pages);
|
|
1087
|
+
} else {
|
|
1088
|
+
const firstPage = current.pages[0];
|
|
1089
|
+
pageParam = getPreviousPageParam(firstPage, current.pages);
|
|
1090
|
+
}
|
|
1091
|
+
const lifecycleCtx = {
|
|
1092
|
+
params: this.params,
|
|
1093
|
+
queryKey: this.queryKey,
|
|
1094
|
+
queryClient: this.client
|
|
1095
|
+
};
|
|
1096
|
+
this.#dispatch({ type: "fetch", direction });
|
|
1097
|
+
this.$pendingCount.set(this.$pendingCount.peek() + 1);
|
|
1098
|
+
void runLifecycle(this.options, "start", lifecycleCtx);
|
|
1099
|
+
this.#retryer = createRetryer({
|
|
1100
|
+
fn: async () => {
|
|
1101
|
+
const page = await this.definition.options.queryFn({
|
|
1102
|
+
params: this.params,
|
|
1103
|
+
pageParam,
|
|
1104
|
+
signal: signal8,
|
|
1105
|
+
abortController,
|
|
1106
|
+
queryClient: this.client,
|
|
1107
|
+
queryKey: this.queryKey
|
|
1108
|
+
});
|
|
1109
|
+
if (signal8.aborted) {
|
|
1110
|
+
throw new CancelledError({ silent: true });
|
|
1111
|
+
}
|
|
1112
|
+
return page;
|
|
1113
|
+
},
|
|
1114
|
+
onCancel: () => abortHandle.abort(),
|
|
1115
|
+
onFail: (failureCount, error) => {
|
|
1116
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1117
|
+
this.#dispatch({ type: "failed", failureCount, error: err });
|
|
1118
|
+
},
|
|
1119
|
+
retry: this.options.retry,
|
|
1120
|
+
retryDelay: this.options.retryDelay
|
|
1121
|
+
});
|
|
1122
|
+
try {
|
|
1123
|
+
const page = await this.#retryer.start();
|
|
1124
|
+
if (requestId !== this.#requestId) {
|
|
1125
|
+
return null;
|
|
1126
|
+
}
|
|
1127
|
+
const nextData = this.#mergePage(direction, pageParam, page);
|
|
1128
|
+
this.#dispatch({ type: "success", data: nextData });
|
|
1129
|
+
this.#cache.emit({
|
|
1130
|
+
type: "infiniteQueryFetched",
|
|
1131
|
+
queryKey: this.queryKey,
|
|
1132
|
+
hash: this.queryHash
|
|
1133
|
+
});
|
|
1134
|
+
await runLifecycle(this.options, "success", { ...lifecycleCtx, data: nextData });
|
|
1135
|
+
await runLifecycle(this.options, "settled", { ...lifecycleCtx, data: nextData });
|
|
1136
|
+
return page;
|
|
1137
|
+
} catch (error) {
|
|
1138
|
+
if (requestId !== this.#requestId) {
|
|
1139
|
+
return null;
|
|
1140
|
+
}
|
|
1141
|
+
if (isCancelledError(error)) {
|
|
1142
|
+
if (error.silent) {
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
throw error;
|
|
1146
|
+
}
|
|
1147
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1148
|
+
this.#dispatch({ type: "error", error: err });
|
|
1149
|
+
await runLifecycle(this.options, "error", { ...lifecycleCtx, error: err });
|
|
1150
|
+
await runLifecycle(this.options, "settled", { ...lifecycleCtx, error: err });
|
|
1151
|
+
throw error;
|
|
1152
|
+
} finally {
|
|
1153
|
+
if (requestId === this.#requestId) {
|
|
1154
|
+
this.$pendingCount.set(Math.max(0, this.$pendingCount.peek() - 1));
|
|
1155
|
+
this.#retryer = void 0;
|
|
1156
|
+
this.#clearAbortHandle();
|
|
1157
|
+
this.scheduleGc(() => {
|
|
1158
|
+
if (this.observers.size === 0) this.#cache.remove(this);
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
#clearAbortHandle() {
|
|
1164
|
+
this.#abortDispose?.();
|
|
1165
|
+
this.#abortDispose = void 0;
|
|
1166
|
+
this.#abortController = void 0;
|
|
1167
|
+
}
|
|
1168
|
+
onFocus() {
|
|
1169
|
+
if (this.isActive() && this.isStale() && this.options.refetchOnWindowFocus) {
|
|
1170
|
+
void this.refetch();
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
onOnline() {
|
|
1174
|
+
if (this.isActive() && this.isStale() && this.options.refetchOnReconnect) {
|
|
1175
|
+
void this.refetch();
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
#mergePage(direction, pageParam, page) {
|
|
1179
|
+
const current = this.state.data;
|
|
1180
|
+
if (direction === "initial" || !current) {
|
|
1181
|
+
return { pages: [page], pageParams: [pageParam] };
|
|
1182
|
+
}
|
|
1183
|
+
if (direction === "next") {
|
|
1184
|
+
return {
|
|
1185
|
+
pages: [...current.pages, page],
|
|
1186
|
+
pageParams: [...current.pageParams, pageParam]
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
return {
|
|
1190
|
+
pages: [page, ...current.pages],
|
|
1191
|
+
pageParams: [pageParam, ...current.pageParams]
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
#dispatch(action) {
|
|
1195
|
+
this.state = infiniteQueryReducer(this.state, action);
|
|
1196
|
+
this.syncSignals();
|
|
1197
|
+
this.#cache.emit({
|
|
1198
|
+
type: "infiniteQueryUpdated",
|
|
1199
|
+
queryKey: this.queryKey,
|
|
1200
|
+
hash: this.queryHash
|
|
1201
|
+
});
|
|
1202
|
+
for (const observer of this.observers) {
|
|
1203
|
+
observer.onInfiniteQueryUpdate();
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
syncSignals() {
|
|
1207
|
+
this.$data.set(this.state.data);
|
|
1208
|
+
this.$error.set(this.state.error);
|
|
1209
|
+
this.$status.set(this.state.status);
|
|
1210
|
+
this.$fetchStatus.set(this.state.fetchStatus);
|
|
1211
|
+
this.$updatedAt.set(this.state.dataUpdatedAt || null);
|
|
1212
|
+
this.$isInvalidated.set(this.state.isInvalidated);
|
|
1213
|
+
this.$fetchingNextPage.set(this.state.fetchingNextPage);
|
|
1214
|
+
this.$fetchingPreviousPage.set(this.state.fetchingPreviousPage);
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
|
|
1218
|
+
// src/query/infinite-query-status.ts
|
|
1219
|
+
var DEFAULT_CACHE_TIME_MS3 = 5 * 6e4;
|
|
1220
|
+
var resolveInfiniteQueryOptions = (options) => {
|
|
1221
|
+
const staleTime = options.staleTime ?? 0;
|
|
1222
|
+
const cacheTime = options.cacheTime ?? DEFAULT_CACHE_TIME_MS3;
|
|
1223
|
+
return {
|
|
1224
|
+
...options,
|
|
1225
|
+
staleTime,
|
|
1226
|
+
cacheTime,
|
|
1227
|
+
retry: options.retry ?? false,
|
|
1228
|
+
retryDelay: options.retryDelay ?? 1e3,
|
|
1229
|
+
keepPreviousData: options.keepPreviousData ?? false,
|
|
1230
|
+
abortPrevious: options.abortPrevious ?? true,
|
|
1231
|
+
staleTimeMs: toMs(staleTime, 0),
|
|
1232
|
+
cacheTimeMs: toMs(cacheTime, DEFAULT_CACHE_TIME_MS3)
|
|
1233
|
+
};
|
|
1234
|
+
};
|
|
1235
|
+
var resolveInfiniteInstanceOptions = (definitionOptions, instanceOptions) => {
|
|
1236
|
+
const staleTime = instanceOptions?.staleTime ?? definitionOptions.staleTime ?? 0;
|
|
1237
|
+
const cacheTime = instanceOptions?.cacheTime ?? definitionOptions.cacheTime ?? DEFAULT_CACHE_TIME_MS3;
|
|
1238
|
+
return {
|
|
1239
|
+
...definitionOptions,
|
|
1240
|
+
...instanceOptions,
|
|
1241
|
+
staleTime,
|
|
1242
|
+
cacheTime,
|
|
1243
|
+
staleTimeMs: toMs(staleTime, 0),
|
|
1244
|
+
cacheTimeMs: toMs(cacheTime, DEFAULT_CACHE_TIME_MS3),
|
|
1245
|
+
enabled: instanceOptions?.enabled ?? true,
|
|
1246
|
+
refetchOnMount: instanceOptions?.refetchOnMount ?? true,
|
|
1247
|
+
refetchOnWindowFocus: instanceOptions?.refetchOnWindowFocus ?? true,
|
|
1248
|
+
refetchOnReconnect: instanceOptions?.refetchOnReconnect ?? true,
|
|
1249
|
+
keepPreviousData: instanceOptions?.keepPreviousData ?? definitionOptions.keepPreviousData ?? false,
|
|
1250
|
+
abortPrevious: instanceOptions?.abortPrevious ?? definitionOptions.abortPrevious ?? true,
|
|
1251
|
+
retry: instanceOptions?.retry ?? definitionOptions.retry ?? false,
|
|
1252
|
+
retryDelay: instanceOptions?.retryDelay ?? definitionOptions.retryDelay ?? 1e3,
|
|
1253
|
+
onStart: instanceOptions?.onStart ?? definitionOptions.onStart,
|
|
1254
|
+
onSuccess: instanceOptions?.onSuccess ?? definitionOptions.onSuccess,
|
|
1255
|
+
onError: instanceOptions?.onError ?? definitionOptions.onError,
|
|
1256
|
+
onSettled: instanceOptions?.onSettled ?? definitionOptions.onSettled
|
|
1257
|
+
};
|
|
1258
|
+
};
|
|
1259
|
+
var resolveInfiniteDefinitionOptions = (definition) => resolveInfiniteQueryOptions(definition.options);
|
|
1260
|
+
|
|
1261
|
+
// src/query/infinite-query-observer.ts
|
|
1262
|
+
var InfiniteQueryObserver = class {
|
|
1263
|
+
definition;
|
|
1264
|
+
client;
|
|
1265
|
+
options;
|
|
1266
|
+
#query = null;
|
|
1267
|
+
#previousQuery = null;
|
|
1268
|
+
#params;
|
|
1269
|
+
#disposeParams = null;
|
|
1270
|
+
#destroyed = false;
|
|
1271
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
1272
|
+
#currentHash = null;
|
|
1273
|
+
constructor(definition, client, params, instanceOptions) {
|
|
1274
|
+
this.definition = definition;
|
|
1275
|
+
this.client = client;
|
|
1276
|
+
this.options = resolveInfiniteInstanceOptions(
|
|
1277
|
+
resolveInfiniteDefinitionOptions(definition),
|
|
1278
|
+
instanceOptions
|
|
1279
|
+
);
|
|
1280
|
+
if (typeof params === "function") {
|
|
1281
|
+
this.#disposeParams = effect(() => {
|
|
1282
|
+
this.setParams(params());
|
|
1283
|
+
});
|
|
1284
|
+
} else {
|
|
1285
|
+
this.setParams(params);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
getQuery() {
|
|
1289
|
+
return this.#query;
|
|
1290
|
+
}
|
|
1291
|
+
getPreviousQuery() {
|
|
1292
|
+
return this.#previousQuery;
|
|
1293
|
+
}
|
|
1294
|
+
getParams() {
|
|
1295
|
+
return this.#params;
|
|
1296
|
+
}
|
|
1297
|
+
onInfiniteQueryUpdate() {
|
|
1298
|
+
for (const listener of this.#listeners) listener();
|
|
1299
|
+
}
|
|
1300
|
+
subscribe(listener) {
|
|
1301
|
+
this.#listeners.add(listener);
|
|
1302
|
+
return () => this.#listeners.delete(listener);
|
|
1303
|
+
}
|
|
1304
|
+
setParams(params) {
|
|
1305
|
+
if (this.#destroyed) return;
|
|
1306
|
+
this.#params = params;
|
|
1307
|
+
const queryKey = this.definition.queryKey(params);
|
|
1308
|
+
const hash = hashKey(queryKey);
|
|
1309
|
+
if (this.#currentHash === hash) {
|
|
1310
|
+
void this.maybeFetch(false);
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
if (this.#query) {
|
|
1314
|
+
if (this.options.abortPrevious) {
|
|
1315
|
+
void this.#query.cancel({ silent: true });
|
|
1316
|
+
}
|
|
1317
|
+
this.#detach(this.#query);
|
|
1318
|
+
this.#previousQuery = this.options.keepPreviousData ? this.#query : null;
|
|
1319
|
+
}
|
|
1320
|
+
this.#currentHash = hash;
|
|
1321
|
+
this.#query = this.client.infiniteQueryCache.build({
|
|
1322
|
+
client: this.client,
|
|
1323
|
+
cache: this.client.infiniteQueryCache,
|
|
1324
|
+
definition: this.definition,
|
|
1325
|
+
params,
|
|
1326
|
+
queryKey,
|
|
1327
|
+
options: this.options
|
|
1328
|
+
});
|
|
1329
|
+
this.#query.addObserver(this);
|
|
1330
|
+
void this.maybeFetch(true);
|
|
1331
|
+
this.onInfiniteQueryUpdate();
|
|
1332
|
+
}
|
|
1333
|
+
maybeFetch(paramsChanged) {
|
|
1334
|
+
if (!this.#query || !isEnabled(this.options.enabled)) return;
|
|
1335
|
+
const stale = this.#query.isStale();
|
|
1336
|
+
const hasData = this.#query.hasData();
|
|
1337
|
+
if (!hasData || stale) {
|
|
1338
|
+
void this.#query.fetchNextPage();
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
if (paramsChanged && this.options.refetchOnMount === true) {
|
|
1342
|
+
void this.#query.refetch();
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
cancel(options) {
|
|
1346
|
+
void this.#query?.cancel(options);
|
|
1347
|
+
}
|
|
1348
|
+
remove() {
|
|
1349
|
+
if (!this.#query) return;
|
|
1350
|
+
this.#detach(this.#query);
|
|
1351
|
+
this.client.infiniteQueryCache.remove(this.#query);
|
|
1352
|
+
this.#query = null;
|
|
1353
|
+
this.#currentHash = null;
|
|
1354
|
+
this.onInfiniteQueryUpdate();
|
|
1355
|
+
}
|
|
1356
|
+
destroy() {
|
|
1357
|
+
if (this.#destroyed) return;
|
|
1358
|
+
this.#destroyed = true;
|
|
1359
|
+
this.#disposeParams?.();
|
|
1360
|
+
if (this.#query) this.#detach(this.#query);
|
|
1361
|
+
this.#listeners.clear();
|
|
1362
|
+
}
|
|
1363
|
+
#detach(query) {
|
|
1364
|
+
query.removeObserver(this);
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
|
|
1368
|
+
// src/query/infinite-query-instance.ts
|
|
1369
|
+
var effectiveInfiniteQuery = (observer) => {
|
|
1370
|
+
const query = observer.getQuery();
|
|
1371
|
+
if (!query) return observer.getPreviousQuery();
|
|
1372
|
+
if (query.hasData()) return query;
|
|
1373
|
+
const prev = observer.getPreviousQuery();
|
|
1374
|
+
if (prev && observer.options.keepPreviousData) return prev;
|
|
1375
|
+
return query;
|
|
1376
|
+
};
|
|
1377
|
+
var createInfiniteQueryInstance = (definition, client, params, instanceOptions) => {
|
|
1378
|
+
const observer = new InfiniteQueryObserver(definition, client, params, instanceOptions);
|
|
1379
|
+
const $params = signal(observer.getParams());
|
|
1380
|
+
observer.subscribe(() => $params.set(observer.getParams()));
|
|
1381
|
+
const readQuery = () => effectiveInfiniteQuery(observer);
|
|
1382
|
+
const readData = () => {
|
|
1383
|
+
const data = readQuery()?.$data.value();
|
|
1384
|
+
return data ?? null;
|
|
1385
|
+
};
|
|
1386
|
+
const $data = computed(() => readData());
|
|
1387
|
+
const $pages = computed(() => readData()?.pages ?? []);
|
|
1388
|
+
const $pageParams = computed(() => readData()?.pageParams ?? []);
|
|
1389
|
+
const $error = computed(() => readQuery()?.$error.value() ?? null);
|
|
1390
|
+
const $pending = computed(() => {
|
|
1391
|
+
const q = readQuery();
|
|
1392
|
+
return q ? isQueryPending(q.$status.value()) : false;
|
|
1393
|
+
});
|
|
1394
|
+
const $fetching = computed(() => readQuery()?.$fetchStatus.value() === "fetching");
|
|
1395
|
+
const $fetchingNextPage = computed(() => readQuery()?.$fetchingNextPage.value() ?? false);
|
|
1396
|
+
const $fetchingPreviousPage = computed(
|
|
1397
|
+
() => readQuery()?.$fetchingPreviousPage.value() ?? false
|
|
1398
|
+
);
|
|
1399
|
+
const $abortSignal = computed(() => readQuery()?.getAbortSignal() ?? null);
|
|
1400
|
+
const getQuery = () => {
|
|
1401
|
+
const q = observer.getQuery();
|
|
1402
|
+
if (!q) throw new Error("InfiniteQueryObserver has no active query");
|
|
1403
|
+
return q;
|
|
1404
|
+
};
|
|
1405
|
+
return {
|
|
1406
|
+
kind: "infinite-query",
|
|
1407
|
+
pages: () => $pages.value(),
|
|
1408
|
+
pageParams: () => $pageParams.value(),
|
|
1409
|
+
data: () => $data.value(),
|
|
1410
|
+
flatMap: (selector) => $pages.value().flatMap((page) => selector(page)),
|
|
1411
|
+
fetchNextPage: (options) => getQuery().fetchNextPage(options),
|
|
1412
|
+
fetchPreviousPage: (options) => getQuery().fetchPreviousPage(options),
|
|
1413
|
+
refetch: (options) => getQuery().refetch(options),
|
|
1414
|
+
reset: () => getQuery().reset(),
|
|
1415
|
+
cancel: (options) => observer.cancel(options),
|
|
1416
|
+
abort: (reason) => observer.cancel({ reason }),
|
|
1417
|
+
abortController: () => readQuery()?.getAbortController() ?? null,
|
|
1418
|
+
abortSignal: () => readQuery()?.getAbortSignal() ?? null,
|
|
1419
|
+
remove: () => {
|
|
1420
|
+
observer.remove();
|
|
1421
|
+
observer.destroy();
|
|
1422
|
+
},
|
|
1423
|
+
hasNextPage: () => readQuery()?.hasNextPage() ?? true,
|
|
1424
|
+
hasPreviousPage: () => readQuery()?.hasPreviousPage() ?? false,
|
|
1425
|
+
pending: () => $pending.value(),
|
|
1426
|
+
fetching: () => $fetching.value(),
|
|
1427
|
+
fetchingNextPage: () => $fetchingNextPage.value(),
|
|
1428
|
+
fetchingPreviousPage: () => $fetchingPreviousPage.value(),
|
|
1429
|
+
error: () => $error.value(),
|
|
1430
|
+
params: () => $params.value(),
|
|
1431
|
+
subscribe(listener) {
|
|
1432
|
+
return observer.subscribe(() => listener($data.value()));
|
|
1433
|
+
},
|
|
1434
|
+
$data,
|
|
1435
|
+
$pages,
|
|
1436
|
+
$pageParams,
|
|
1437
|
+
$pending,
|
|
1438
|
+
$fetching,
|
|
1439
|
+
$fetchingNextPage,
|
|
1440
|
+
$fetchingPreviousPage,
|
|
1441
|
+
$error,
|
|
1442
|
+
$params,
|
|
1443
|
+
$abortSignal
|
|
1444
|
+
};
|
|
1445
|
+
};
|
|
1446
|
+
|
|
1447
|
+
// src/query/infinite-query-options.ts
|
|
1448
|
+
var mergeInfiniteQueryDefinitionOptions = (options, config, provider) => {
|
|
1449
|
+
const queryDefaults = defaultQueryOptions(config);
|
|
1450
|
+
const providerDefaults = provider?.config.defaultOptions?.queries;
|
|
1451
|
+
return {
|
|
1452
|
+
staleTime: queryDefaults.staleTime,
|
|
1453
|
+
cacheTime: queryDefaults.cacheTime,
|
|
1454
|
+
retry: queryDefaults.retry,
|
|
1455
|
+
retryDelay: queryDefaults.retryDelay,
|
|
1456
|
+
keepPreviousData: queryDefaults.keepPreviousData,
|
|
1457
|
+
abortPrevious: queryDefaults.abortPrevious,
|
|
1458
|
+
...providerDefaults,
|
|
1459
|
+
...options
|
|
1460
|
+
};
|
|
1461
|
+
};
|
|
1462
|
+
|
|
1463
|
+
// src/query/create-infinite-query.ts
|
|
1464
|
+
var createInfiniteQuery = (options, meta) => {
|
|
1465
|
+
const provider = meta?.provider ?? getQueryProvider();
|
|
1466
|
+
const mergedOptions = mergeInfiniteQueryDefinitionOptions(
|
|
1467
|
+
options,
|
|
1468
|
+
provider?.config,
|
|
1469
|
+
provider
|
|
1470
|
+
);
|
|
1471
|
+
resolveInfiniteQueryOptions(mergedOptions);
|
|
1472
|
+
const definition = {
|
|
1473
|
+
kind: "infinite-query-definition",
|
|
1474
|
+
name: options.name,
|
|
1475
|
+
options: mergedOptions,
|
|
1476
|
+
queryKey(params) {
|
|
1477
|
+
return mergedOptions.queryKey(params);
|
|
1478
|
+
},
|
|
1479
|
+
with(params, instanceOptions) {
|
|
1480
|
+
const client = instanceOptions?.client ?? provider?.client ?? getDefaultQueryClient();
|
|
1481
|
+
return createInfiniteQueryInstance(definition, client, params, instanceOptions);
|
|
1482
|
+
},
|
|
1483
|
+
withStore(store, map, instanceOptions) {
|
|
1484
|
+
const client = instanceOptions?.client ?? provider?.client ?? getDefaultQueryClient();
|
|
1485
|
+
return createInfiniteQueryInstance(
|
|
1486
|
+
definition,
|
|
1487
|
+
client,
|
|
1488
|
+
() => map(store.value()),
|
|
1489
|
+
instanceOptions
|
|
1490
|
+
);
|
|
1491
|
+
}
|
|
1492
|
+
};
|
|
1493
|
+
return definition;
|
|
1494
|
+
};
|
|
1495
|
+
|
|
1496
|
+
// src/core/subscribable.ts
|
|
1497
|
+
var Subscribable = class {
|
|
1498
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1499
|
+
subscribe(listener) {
|
|
1500
|
+
this.listeners.add(listener);
|
|
1501
|
+
return () => this.listeners.delete(listener);
|
|
1502
|
+
}
|
|
1503
|
+
notify(event) {
|
|
1504
|
+
for (const listener of this.listeners) {
|
|
1505
|
+
listener(event);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
hasListeners() {
|
|
1509
|
+
return this.listeners.size > 0;
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
|
|
1513
|
+
// src/utils/match-query.ts
|
|
1514
|
+
var matchQuery = (filters, query) => {
|
|
1515
|
+
const { exact, fetchStatus, predicate, queryKey, stale } = filters;
|
|
1516
|
+
if (queryKey) {
|
|
1517
|
+
if (exact) {
|
|
1518
|
+
if (query.queryHash !== hashKey(queryKey)) return false;
|
|
1519
|
+
} else if (!partialMatchKey(query.queryKey, queryKey)) {
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
if (typeof stale === "boolean" && query.isStale() !== stale) return false;
|
|
1524
|
+
if (fetchStatus && fetchStatus !== query.state.fetchStatus) return false;
|
|
1525
|
+
if (predicate && !predicate(query)) return false;
|
|
1526
|
+
return true;
|
|
1527
|
+
};
|
|
1528
|
+
|
|
1529
|
+
// src/core/query-cache.ts
|
|
1530
|
+
var QueryCache = class extends Subscribable {
|
|
1531
|
+
#queries = /* @__PURE__ */ new Map();
|
|
1532
|
+
get(queryHash) {
|
|
1533
|
+
return this.#queries.get(queryHash);
|
|
1534
|
+
}
|
|
1535
|
+
getByKey(queryKey) {
|
|
1536
|
+
return this.#queries.get(hashKey(queryKey));
|
|
1537
|
+
}
|
|
1538
|
+
getAll() {
|
|
1539
|
+
return [...this.#queries.values()];
|
|
1540
|
+
}
|
|
1541
|
+
build(config) {
|
|
1542
|
+
const hash = hashKey(config.queryKey);
|
|
1543
|
+
const cached = this.#queries.get(hash);
|
|
1544
|
+
if (cached) return cached;
|
|
1545
|
+
const query = new Query(config);
|
|
1546
|
+
this.add(query);
|
|
1547
|
+
return query;
|
|
1548
|
+
}
|
|
1549
|
+
add(query) {
|
|
1550
|
+
if (!this.#queries.has(query.queryHash)) {
|
|
1551
|
+
this.#queries.set(
|
|
1552
|
+
query.queryHash,
|
|
1553
|
+
query
|
|
1554
|
+
);
|
|
1555
|
+
this.emit({
|
|
1556
|
+
type: "queryAdded",
|
|
1557
|
+
queryKey: query.queryKey,
|
|
1558
|
+
hash: query.queryHash
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
remove(query) {
|
|
1563
|
+
const cached = this.#queries.get(query.queryHash);
|
|
1564
|
+
if (cached && cached.queryHash === query.queryHash) {
|
|
1565
|
+
void query.cancel({ silent: true });
|
|
1566
|
+
this.#queries.delete(query.queryHash);
|
|
1567
|
+
this.emit({
|
|
1568
|
+
type: "queryRemoved",
|
|
1569
|
+
queryKey: query.queryKey,
|
|
1570
|
+
hash: query.queryHash
|
|
1571
|
+
});
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
find(filters) {
|
|
1575
|
+
return this.getAll().find((query) => matchQuery(filters, query));
|
|
1576
|
+
}
|
|
1577
|
+
findAll(filter = []) {
|
|
1578
|
+
if (Array.isArray(filter)) {
|
|
1579
|
+
if (filter.length === 0) return this.getAll();
|
|
1580
|
+
return this.getAll().filter(
|
|
1581
|
+
(query) => matchQuery({ queryKey: filter }, query)
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
const objectFilter = filter;
|
|
1585
|
+
return this.getAll().filter(
|
|
1586
|
+
(query) => matchQuery(
|
|
1587
|
+
{ queryKey: objectFilter.queryKey, exact: objectFilter.exact },
|
|
1588
|
+
query
|
|
1589
|
+
)
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
1592
|
+
clear() {
|
|
1593
|
+
for (const query of [...this.getAll()]) {
|
|
1594
|
+
this.remove(query);
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
emit(event) {
|
|
1598
|
+
this.notify(event);
|
|
1599
|
+
}
|
|
1600
|
+
onFocus() {
|
|
1601
|
+
for (const query of this.getAll()) {
|
|
1602
|
+
query.onFocus();
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
onOnline() {
|
|
1606
|
+
for (const query of this.getAll()) {
|
|
1607
|
+
query.onOnline();
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
};
|
|
1611
|
+
var createQueryCache = () => new QueryCache();
|
|
1612
|
+
|
|
1613
|
+
// src/core/infinite-query-cache.ts
|
|
1614
|
+
var InfiniteQueryCache = class extends Subscribable {
|
|
1615
|
+
#queries = /* @__PURE__ */ new Map();
|
|
1616
|
+
get(queryHash) {
|
|
1617
|
+
return this.#queries.get(queryHash);
|
|
1618
|
+
}
|
|
1619
|
+
getByKey(queryKey) {
|
|
1620
|
+
return this.#queries.get(hashKey(queryKey));
|
|
1621
|
+
}
|
|
1622
|
+
getAll() {
|
|
1623
|
+
return [...this.#queries.values()];
|
|
1624
|
+
}
|
|
1625
|
+
build(config) {
|
|
1626
|
+
const hash = hashKey(config.queryKey);
|
|
1627
|
+
const cached = this.#queries.get(hash);
|
|
1628
|
+
if (cached) return cached;
|
|
1629
|
+
const query = new InfiniteQuery(config);
|
|
1630
|
+
this.add(query);
|
|
1631
|
+
return query;
|
|
1632
|
+
}
|
|
1633
|
+
add(query) {
|
|
1634
|
+
if (!this.#queries.has(query.queryHash)) {
|
|
1635
|
+
this.#queries.set(
|
|
1636
|
+
query.queryHash,
|
|
1637
|
+
query
|
|
1638
|
+
);
|
|
1639
|
+
this.emit({
|
|
1640
|
+
type: "infiniteQueryAdded",
|
|
1641
|
+
queryKey: query.queryKey,
|
|
1642
|
+
hash: query.queryHash
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
remove(query) {
|
|
1647
|
+
const cached = this.#queries.get(query.queryHash);
|
|
1648
|
+
if (cached && cached.queryHash === query.queryHash) {
|
|
1649
|
+
void query.cancel({ silent: true });
|
|
1650
|
+
this.#queries.delete(query.queryHash);
|
|
1651
|
+
this.emit({
|
|
1652
|
+
type: "infiniteQueryRemoved",
|
|
1653
|
+
queryKey: query.queryKey,
|
|
1654
|
+
hash: query.queryHash
|
|
1655
|
+
});
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
find(filters) {
|
|
1659
|
+
return this.getAll().find((query) => matchQuery(filters, query));
|
|
1660
|
+
}
|
|
1661
|
+
findAll(filter = []) {
|
|
1662
|
+
if (Array.isArray(filter)) {
|
|
1663
|
+
if (filter.length === 0) return this.getAll();
|
|
1664
|
+
return this.getAll().filter((query) => matchQuery({ queryKey: filter }, query));
|
|
1665
|
+
}
|
|
1666
|
+
const objectFilter = filter;
|
|
1667
|
+
return this.getAll().filter(
|
|
1668
|
+
(query) => matchQuery(
|
|
1669
|
+
{ queryKey: objectFilter.queryKey, exact: objectFilter.exact },
|
|
1670
|
+
query
|
|
1671
|
+
)
|
|
1672
|
+
);
|
|
1673
|
+
}
|
|
1674
|
+
clear() {
|
|
1675
|
+
for (const query of [...this.getAll()]) {
|
|
1676
|
+
this.remove(query);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
emit(event) {
|
|
1680
|
+
this.notify(event);
|
|
1681
|
+
}
|
|
1682
|
+
onFocus() {
|
|
1683
|
+
for (const query of this.getAll()) {
|
|
1684
|
+
query.onFocus();
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
onOnline() {
|
|
1688
|
+
for (const query of this.getAll()) {
|
|
1689
|
+
query.onOnline();
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
};
|
|
1693
|
+
var createInfiniteQueryCache = () => new InfiniteQueryCache();
|
|
1694
|
+
|
|
1695
|
+
// src/core/mutation-cache.ts
|
|
1696
|
+
var MutationCache = class extends Subscribable {
|
|
1697
|
+
emit(event) {
|
|
1698
|
+
this.notify(event);
|
|
1699
|
+
}
|
|
1700
|
+
clear() {
|
|
1701
|
+
this.listeners.clear();
|
|
1702
|
+
}
|
|
1703
|
+
};
|
|
1704
|
+
var createMutationCache = () => new MutationCache();
|
|
1705
|
+
|
|
1706
|
+
// src/managers/register-client.ts
|
|
1707
|
+
var clients = /* @__PURE__ */ new Set();
|
|
1708
|
+
var registerClientWithManagers = (client) => {
|
|
1709
|
+
clients.add(client);
|
|
1710
|
+
};
|
|
1711
|
+
var getRegisteredClients = () => clients;
|
|
1712
|
+
|
|
1713
|
+
// src/client/query-client.ts
|
|
1714
|
+
var resolveKeyAndParams = (keyOrDefinition, params) => {
|
|
1715
|
+
if (typeof keyOrDefinition === "object" && keyOrDefinition !== null && "kind" in keyOrDefinition) {
|
|
1716
|
+
return { key: keyOrDefinition.queryKey(params) };
|
|
1717
|
+
}
|
|
1718
|
+
return { key: keyOrDefinition };
|
|
1719
|
+
};
|
|
1720
|
+
var QueryClient = class {
|
|
1721
|
+
queryCache;
|
|
1722
|
+
infiniteQueryCache;
|
|
1723
|
+
mutationCache;
|
|
1724
|
+
constructor(config) {
|
|
1725
|
+
this.queryCache = createQueryCache();
|
|
1726
|
+
this.infiniteQueryCache = createInfiniteQueryCache();
|
|
1727
|
+
this.mutationCache = createMutationCache();
|
|
1728
|
+
registerClientWithManagers(this);
|
|
1729
|
+
}
|
|
1730
|
+
async fetchQuery(definition, params, options) {
|
|
1731
|
+
const resolvedParams = params ?? {};
|
|
1732
|
+
const queryKey = definition.queryKey(resolvedParams);
|
|
1733
|
+
const resolvedOptions = resolveInstanceOptions(
|
|
1734
|
+
resolveDefinitionOptions(definition),
|
|
1735
|
+
options
|
|
1736
|
+
);
|
|
1737
|
+
if (!isEnabled(resolvedOptions.enabled)) {
|
|
1738
|
+
const cached = this.getQueryData(definition, resolvedParams);
|
|
1739
|
+
if (cached === void 0) {
|
|
1740
|
+
throw new Error("Query is disabled and has no cached data");
|
|
1741
|
+
}
|
|
1742
|
+
return cached;
|
|
1743
|
+
}
|
|
1744
|
+
const query = this.queryCache.build({
|
|
1745
|
+
client: this,
|
|
1746
|
+
cache: this.queryCache,
|
|
1747
|
+
definition,
|
|
1748
|
+
params: resolvedParams,
|
|
1749
|
+
queryKey,
|
|
1750
|
+
options: resolvedOptions
|
|
1751
|
+
});
|
|
1752
|
+
if (query.hasData() && !query.isStale()) {
|
|
1753
|
+
return query.state.data;
|
|
1754
|
+
}
|
|
1755
|
+
return query.fetch();
|
|
1756
|
+
}
|
|
1757
|
+
async prefetchQuery(definition, params, options) {
|
|
1758
|
+
await this.fetchQuery(definition, params, options);
|
|
1759
|
+
}
|
|
1760
|
+
async ensureQueryData(definition, params, options) {
|
|
1761
|
+
return this.fetchQuery(definition, params, options);
|
|
1762
|
+
}
|
|
1763
|
+
getQueryData(keyOrDefinition, params) {
|
|
1764
|
+
const { key } = resolveKeyAndParams(keyOrDefinition, params);
|
|
1765
|
+
return this.queryCache.getByKey(key)?.state.data;
|
|
1766
|
+
}
|
|
1767
|
+
setQueryData(keyOrDefinition, paramsOrUpdater, updater) {
|
|
1768
|
+
let key;
|
|
1769
|
+
let nextUpdater;
|
|
1770
|
+
if (typeof keyOrDefinition === "object" && keyOrDefinition !== null && "kind" in keyOrDefinition) {
|
|
1771
|
+
key = keyOrDefinition.queryKey(paramsOrUpdater);
|
|
1772
|
+
nextUpdater = typeof updater === "function" ? updater : () => updater;
|
|
1773
|
+
} else {
|
|
1774
|
+
key = keyOrDefinition;
|
|
1775
|
+
nextUpdater = typeof paramsOrUpdater === "function" ? paramsOrUpdater : () => paramsOrUpdater;
|
|
1776
|
+
}
|
|
1777
|
+
const hash = hashKey(key);
|
|
1778
|
+
let query = this.queryCache.get(hash);
|
|
1779
|
+
if (!query) {
|
|
1780
|
+
throw new Error(`Query not found for key: ${JSON.stringify(key)}`);
|
|
1781
|
+
}
|
|
1782
|
+
query.setData(
|
|
1783
|
+
(prev) => functionalUpdate(nextUpdater, prev)
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
invalidateQueries(filter, options) {
|
|
1787
|
+
const refetchMode = options?.refetch ?? "active";
|
|
1788
|
+
const shouldRefetch = refetchMode !== false && refetchMode !== "none";
|
|
1789
|
+
for (const query of this.queryCache.findAll(filter)) {
|
|
1790
|
+
query.invalidate();
|
|
1791
|
+
if (!shouldRefetch) continue;
|
|
1792
|
+
if (refetchMode === "all" || query.isActive()) {
|
|
1793
|
+
void query.fetch().catch(() => void 0);
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
async refetchQueries(filter) {
|
|
1798
|
+
await Promise.allSettled(
|
|
1799
|
+
this.queryCache.findAll(filter).map((query) => query.fetch())
|
|
1800
|
+
);
|
|
1801
|
+
}
|
|
1802
|
+
cancelQueries(filter) {
|
|
1803
|
+
for (const query of this.queryCache.findAll(filter)) {
|
|
1804
|
+
void query.cancel();
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
removeQueries(filter) {
|
|
1808
|
+
for (const query of [...this.queryCache.findAll(filter)]) {
|
|
1809
|
+
this.queryCache.remove(query);
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
clear() {
|
|
1813
|
+
this.queryCache.clear();
|
|
1814
|
+
this.infiniteQueryCache.clear();
|
|
1815
|
+
this.mutationCache.clear();
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
var createQueryClient = (config) => {
|
|
1819
|
+
const client = new QueryClient(config);
|
|
1820
|
+
setDefaultQueryClient(client);
|
|
1821
|
+
registerDefaultQueryClientFactory(() => client);
|
|
1822
|
+
return client;
|
|
1823
|
+
};
|
|
1824
|
+
var mutationIdCounter = 0;
|
|
1825
|
+
var Mutation = class {
|
|
1826
|
+
id;
|
|
1827
|
+
definition;
|
|
1828
|
+
client;
|
|
1829
|
+
cache;
|
|
1830
|
+
$data;
|
|
1831
|
+
$error;
|
|
1832
|
+
$variables;
|
|
1833
|
+
$status;
|
|
1834
|
+
$pendingCount;
|
|
1835
|
+
#abortController;
|
|
1836
|
+
#abortDispose;
|
|
1837
|
+
constructor(definition, client, cache) {
|
|
1838
|
+
mutationIdCounter += 1;
|
|
1839
|
+
this.id = mutationIdCounter;
|
|
1840
|
+
this.definition = definition;
|
|
1841
|
+
this.client = client;
|
|
1842
|
+
this.cache = cache;
|
|
1843
|
+
this.$data = signal(void 0);
|
|
1844
|
+
this.$error = signal(null);
|
|
1845
|
+
this.$variables = signal(void 0);
|
|
1846
|
+
this.$status = signal("idle");
|
|
1847
|
+
this.$pendingCount = signal(0);
|
|
1848
|
+
}
|
|
1849
|
+
getAbortController() {
|
|
1850
|
+
return this.#abortController;
|
|
1851
|
+
}
|
|
1852
|
+
getAbortSignal() {
|
|
1853
|
+
return this.#abortController?.signal;
|
|
1854
|
+
}
|
|
1855
|
+
async run(variables, runOptions) {
|
|
1856
|
+
const abortHandle = createFetchAbortHandle(
|
|
1857
|
+
mergeFetchAbortSource(this.definition.options, runOptions)
|
|
1858
|
+
);
|
|
1859
|
+
this.#abortController = abortHandle.controller;
|
|
1860
|
+
this.#abortDispose = abortHandle.dispose;
|
|
1861
|
+
const { controller: abortController, signal: signal8 } = abortHandle;
|
|
1862
|
+
this.$variables.set(variables);
|
|
1863
|
+
this.$status.set("pending");
|
|
1864
|
+
this.$pendingCount.set(this.$pendingCount.peek() + 1);
|
|
1865
|
+
this.cache.emit({ type: "mutationAdded", mutationId: this.id });
|
|
1866
|
+
let rollback;
|
|
1867
|
+
const lifecycleCtx = {
|
|
1868
|
+
variables,
|
|
1869
|
+
queryClient: this.client
|
|
1870
|
+
};
|
|
1871
|
+
try {
|
|
1872
|
+
const mutateResult = await this.definition.options.onMutate?.({
|
|
1873
|
+
...lifecycleCtx
|
|
1874
|
+
});
|
|
1875
|
+
if (typeof mutateResult !== "undefined") {
|
|
1876
|
+
rollback = mutateResult;
|
|
1877
|
+
}
|
|
1878
|
+
const retryer = createRetryer({
|
|
1879
|
+
fn: () => this.definition.options.mutationFn({
|
|
1880
|
+
variables,
|
|
1881
|
+
signal: signal8,
|
|
1882
|
+
abortController,
|
|
1883
|
+
queryClient: this.client
|
|
1884
|
+
}),
|
|
1885
|
+
onCancel: () => abortHandle.abort(),
|
|
1886
|
+
retry: this.definition.options.retry,
|
|
1887
|
+
retryDelay: this.definition.options.retryDelay
|
|
1888
|
+
});
|
|
1889
|
+
const data = await retryer.start();
|
|
1890
|
+
this.$data.set(data);
|
|
1891
|
+
this.$error.set(null);
|
|
1892
|
+
this.$status.set("success");
|
|
1893
|
+
this.definition.options.onSuccess?.({
|
|
1894
|
+
...lifecycleCtx,
|
|
1895
|
+
data,
|
|
1896
|
+
rollback
|
|
1897
|
+
});
|
|
1898
|
+
this.cache.emit({ type: "mutationUpdated", mutationId: this.id });
|
|
1899
|
+
return data;
|
|
1900
|
+
} catch (error) {
|
|
1901
|
+
if (!isCancelledError(error) && !isAbortError(error)) {
|
|
1902
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1903
|
+
this.$error.set(err);
|
|
1904
|
+
this.$status.set("error");
|
|
1905
|
+
this.definition.options.onError?.({
|
|
1906
|
+
...lifecycleCtx,
|
|
1907
|
+
error: err,
|
|
1908
|
+
rollback
|
|
1909
|
+
});
|
|
1910
|
+
}
|
|
1911
|
+
throw error;
|
|
1912
|
+
} finally {
|
|
1913
|
+
this.$pendingCount.set(Math.max(0, this.$pendingCount.peek() - 1));
|
|
1914
|
+
this.#clearAbortHandle();
|
|
1915
|
+
this.definition.options.onSettled?.({
|
|
1916
|
+
...lifecycleCtx,
|
|
1917
|
+
data: this.$data.peek(),
|
|
1918
|
+
error: this.$error.peek(),
|
|
1919
|
+
rollback
|
|
1920
|
+
});
|
|
1921
|
+
this.cache.emit({ type: "mutationUpdated", mutationId: this.id });
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
cancel(options) {
|
|
1925
|
+
abortWithReason(this.#abortController, options?.reason);
|
|
1926
|
+
}
|
|
1927
|
+
#clearAbortHandle() {
|
|
1928
|
+
this.#abortDispose?.();
|
|
1929
|
+
this.#abortDispose = void 0;
|
|
1930
|
+
this.#abortController = void 0;
|
|
1931
|
+
}
|
|
1932
|
+
reset() {
|
|
1933
|
+
this.$data.set(void 0);
|
|
1934
|
+
this.$error.set(null);
|
|
1935
|
+
this.$variables.set(void 0);
|
|
1936
|
+
this.$status.set("idle");
|
|
1937
|
+
this.$pendingCount.set(0);
|
|
1938
|
+
}
|
|
1939
|
+
toInstance() {
|
|
1940
|
+
const mutation = this;
|
|
1941
|
+
const $data = computed(() => mutation.$data.value());
|
|
1942
|
+
const $error = computed(() => mutation.$error.value());
|
|
1943
|
+
const $variables = computed(
|
|
1944
|
+
() => mutation.$variables.value()
|
|
1945
|
+
);
|
|
1946
|
+
const $status = computed(() => mutation.$status.value());
|
|
1947
|
+
const $pendingCount = computed(() => mutation.$pendingCount.value());
|
|
1948
|
+
const $abortSignal = computed(() => mutation.getAbortSignal() ?? null);
|
|
1949
|
+
return {
|
|
1950
|
+
kind: "mutation-instance",
|
|
1951
|
+
run: (variables, options) => mutation.run(variables, options),
|
|
1952
|
+
reset: () => mutation.reset(),
|
|
1953
|
+
cancel: (options) => mutation.cancel(options),
|
|
1954
|
+
abort: (reason) => mutation.cancel({ reason }),
|
|
1955
|
+
abortController: () => mutation.getAbortController() ?? null,
|
|
1956
|
+
abortSignal: () => mutation.getAbortSignal() ?? null,
|
|
1957
|
+
data: () => $data.value(),
|
|
1958
|
+
error: () => $error.value(),
|
|
1959
|
+
variables: () => $variables.value(),
|
|
1960
|
+
status: () => $status.value(),
|
|
1961
|
+
pending: () => $status.value() === "pending",
|
|
1962
|
+
isPending: () => $status.value() === "pending",
|
|
1963
|
+
isSuccess: () => $status.value() === "success",
|
|
1964
|
+
isError: () => $status.value() === "error",
|
|
1965
|
+
isIdle: () => $status.value() === "idle",
|
|
1966
|
+
$data,
|
|
1967
|
+
$error,
|
|
1968
|
+
$variables,
|
|
1969
|
+
$status,
|
|
1970
|
+
$pendingCount,
|
|
1971
|
+
$abortSignal
|
|
1972
|
+
};
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
|
|
1976
|
+
// src/mutation/mutation-instance.ts
|
|
1977
|
+
var createMutationInstance = (definition, client) => {
|
|
1978
|
+
const mutation = new Mutation(definition, client, client.mutationCache);
|
|
1979
|
+
return mutation.toInstance();
|
|
1980
|
+
};
|
|
1981
|
+
|
|
1982
|
+
// src/mutation/create-mutation.ts
|
|
1983
|
+
var createMutation = (options, meta) => {
|
|
1984
|
+
const provider = meta?.provider ?? getQueryProvider();
|
|
1985
|
+
const mergedOptions = {
|
|
1986
|
+
...provider?.config.defaultOptions?.mutations,
|
|
1987
|
+
...options
|
|
1988
|
+
};
|
|
1989
|
+
return {
|
|
1990
|
+
kind: "mutation-definition",
|
|
1991
|
+
name: mergedOptions.name,
|
|
1992
|
+
options: mergedOptions,
|
|
1993
|
+
create(opts) {
|
|
1994
|
+
const client = opts?.client ?? provider?.client ?? getDefaultQueryClient();
|
|
1995
|
+
return createMutationInstance(
|
|
1996
|
+
{
|
|
1997
|
+
kind: "mutation-definition",
|
|
1998
|
+
name: mergedOptions.name,
|
|
1999
|
+
options: mergedOptions,
|
|
2000
|
+
create: this.create
|
|
2001
|
+
},
|
|
2002
|
+
client
|
|
2003
|
+
);
|
|
2004
|
+
}
|
|
2005
|
+
};
|
|
2006
|
+
};
|
|
2007
|
+
|
|
2008
|
+
// src/provider/query-provider.ts
|
|
2009
|
+
var QueryProvider = class {
|
|
2010
|
+
client;
|
|
2011
|
+
config;
|
|
2012
|
+
constructor(config = {}) {
|
|
2013
|
+
this.client = config.client ?? createQueryClient(config);
|
|
2014
|
+
this.config = { ...config, client: this.client };
|
|
2015
|
+
}
|
|
2016
|
+
createQuery = (options) => createQuery(options, { provider: this });
|
|
2017
|
+
createMutation = (options) => createMutation(options, { provider: this });
|
|
2018
|
+
createInfiniteQuery = (options) => createInfiniteQuery(options, { provider: this });
|
|
2019
|
+
invalidateQueries(filter, options) {
|
|
2020
|
+
this.client.invalidateQueries(filter, options);
|
|
2021
|
+
}
|
|
2022
|
+
refetchQueries(filter) {
|
|
2023
|
+
return this.client.refetchQueries(filter);
|
|
2024
|
+
}
|
|
2025
|
+
cancelQueries(filter) {
|
|
2026
|
+
this.client.cancelQueries(filter);
|
|
2027
|
+
}
|
|
2028
|
+
removeQueries(filter) {
|
|
2029
|
+
this.client.removeQueries(filter);
|
|
2030
|
+
}
|
|
2031
|
+
};
|
|
2032
|
+
var setQueryProvider = (provider) => {
|
|
2033
|
+
setActiveQueryProvider(provider);
|
|
2034
|
+
setDefaultQueryClient(provider.client);
|
|
2035
|
+
};
|
|
2036
|
+
|
|
2037
|
+
// src/plugin/query-plugin.ts
|
|
2038
|
+
var QUERY_PROVIDER_KEY = /* @__PURE__ */ Symbol.for("echojs.query.provider");
|
|
2039
|
+
var createQueryProvider = (config = {}) => {
|
|
2040
|
+
const provider = new QueryProvider(config);
|
|
2041
|
+
setQueryProvider(provider);
|
|
2042
|
+
return {
|
|
2043
|
+
name: "query",
|
|
2044
|
+
provider,
|
|
2045
|
+
setup(app) {
|
|
2046
|
+
app.provide?.(QUERY_PROVIDER_KEY, provider);
|
|
2047
|
+
}
|
|
2048
|
+
};
|
|
2049
|
+
};
|
|
2050
|
+
var createQueryPlugin = createQueryProvider;
|
|
2051
|
+
var queryPlugin = createQueryProvider;
|
|
2052
|
+
|
|
2053
|
+
// src/managers/refetch-stale.ts
|
|
2054
|
+
var refetchStaleActiveQueries = (_client, reason) => {
|
|
2055
|
+
for (const client of getRegisteredClients()) {
|
|
2056
|
+
if (reason === "focus") {
|
|
2057
|
+
client.queryCache.onFocus();
|
|
2058
|
+
client.infiniteQueryCache.onFocus();
|
|
2059
|
+
} else {
|
|
2060
|
+
client.queryCache.onOnline();
|
|
2061
|
+
client.infiniteQueryCache.onOnline();
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
};
|
|
2065
|
+
|
|
2066
|
+
// src/managers/focus-manager.ts
|
|
2067
|
+
var FocusManager = class {
|
|
2068
|
+
#focused = signal(
|
|
2069
|
+
typeof document !== "undefined" ? document.visibilityState === "visible" : true
|
|
2070
|
+
);
|
|
2071
|
+
constructor() {
|
|
2072
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
2073
|
+
const onVisibility = () => {
|
|
2074
|
+
this.setFocused(document.visibilityState === "visible");
|
|
2075
|
+
};
|
|
2076
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
2077
|
+
window.addEventListener("focus", () => this.setFocused(true));
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
isFocused() {
|
|
2081
|
+
return this.#focused.value();
|
|
2082
|
+
}
|
|
2083
|
+
setFocused(focused) {
|
|
2084
|
+
this.#focused.set(focused);
|
|
2085
|
+
if (focused) {
|
|
2086
|
+
for (const client of getRegisteredClients()) {
|
|
2087
|
+
refetchStaleActiveQueries(client, "focus");
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
subscribe(listener) {
|
|
2092
|
+
return this.#focused.subscribe(() => listener(this.#focused.value()));
|
|
2093
|
+
}
|
|
2094
|
+
onClientRegistered(client) {
|
|
2095
|
+
if (this.isFocused()) {
|
|
2096
|
+
refetchStaleActiveQueries(client, "focus");
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
};
|
|
2100
|
+
var focusManager = new FocusManager();
|
|
2101
|
+
var readOnline = () => {
|
|
2102
|
+
if (typeof navigator !== "undefined" && typeof navigator.onLine === "boolean") {
|
|
2103
|
+
return navigator.onLine;
|
|
2104
|
+
}
|
|
2105
|
+
return true;
|
|
2106
|
+
};
|
|
2107
|
+
var OnlineManager = class {
|
|
2108
|
+
#online = signal(readOnline());
|
|
2109
|
+
constructor() {
|
|
2110
|
+
if (typeof window !== "undefined") {
|
|
2111
|
+
window.addEventListener("online", () => this.setOnline(true));
|
|
2112
|
+
window.addEventListener("offline", () => this.setOnline(false));
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
isOnline() {
|
|
2116
|
+
return this.#online.value();
|
|
2117
|
+
}
|
|
2118
|
+
setOnline(online) {
|
|
2119
|
+
const prev = this.#online.peek();
|
|
2120
|
+
this.#online.set(online);
|
|
2121
|
+
if (!prev && online) {
|
|
2122
|
+
for (const client of getRegisteredClients()) {
|
|
2123
|
+
refetchStaleActiveQueries(client, "reconnect");
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
subscribe(listener) {
|
|
2128
|
+
return this.#online.subscribe(() => listener(this.#online.value()));
|
|
2129
|
+
}
|
|
2130
|
+
onClientRegistered(client) {
|
|
2131
|
+
if (this.isOnline()) {
|
|
2132
|
+
refetchStaleActiveQueries(client, "reconnect");
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
};
|
|
2136
|
+
var onlineManager = new OnlineManager();
|
|
2137
|
+
|
|
2138
|
+
export { CancelledError, FocusManager, InfiniteQuery, InfiniteQueryCache, InfiniteQueryObserver, Mutation, MutationCache, OnlineManager, QUERY_PROVIDER_KEY, Query, QueryCache, QueryClient, QueryObserver, QueryProvider, abortWithReason, createFetchAbortHandle, createInfiniteQuery, createMutation, createQuery, createQueryClient, createQueryPlugin, createQueryProvider, focusManager, getDefaultQueryClient, getQueryProvider, hasInfiniteNextPage, hasInfinitePreviousPage, hashKey, isCancelledError, matchQuery, mergeFetchAbortSource, onlineManager, partialMatchKey, queryPlugin, requireQueryProvider, resetQueryProvider, resolveAbortInput, setDefaultQueryClient, setQueryProvider };
|
|
2139
|
+
//# sourceMappingURL=index.js.map
|
|
2140
|
+
//# sourceMappingURL=index.js.map
|