@signalium/query 1.0.10 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/cjs/EntityMap.js +45 -7
- package/dist/cjs/EntityMap.js.map +1 -1
- package/dist/cjs/QueryClient.js +44 -3
- package/dist/cjs/QueryClient.js.map +1 -1
- package/dist/cjs/QueryResult.js +122 -79
- package/dist/cjs/QueryResult.js.map +1 -1
- package/dist/cjs/QueryStore.js +0 -573
- package/dist/cjs/QueryStore.js.map +1 -1
- package/dist/cjs/errors.js +17 -0
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/proxy.js +54 -14
- package/dist/cjs/proxy.js.map +1 -1
- package/dist/cjs/query.js +2 -1
- package/dist/cjs/query.js.map +1 -1
- package/dist/cjs/stores/async.js +38 -3
- package/dist/cjs/stores/async.js.map +1 -1
- package/dist/cjs/stores/shared.js +5 -1
- package/dist/cjs/stores/shared.js.map +1 -1
- package/dist/cjs/stores/sync.js +46 -10
- package/dist/cjs/stores/sync.js.map +1 -1
- package/dist/cjs/typeDefs.js +128 -5
- package/dist/cjs/typeDefs.js.map +1 -1
- package/dist/esm/EntityMap.d.ts +9 -3
- package/dist/esm/EntityMap.d.ts.map +1 -1
- package/dist/esm/EntityMap.js +46 -8
- package/dist/esm/EntityMap.js.map +1 -1
- package/dist/esm/QueryClient.d.ts +19 -1
- package/dist/esm/QueryClient.d.ts.map +1 -1
- package/dist/esm/QueryClient.js +43 -3
- package/dist/esm/QueryClient.js.map +1 -1
- package/dist/esm/QueryResult.d.ts +9 -3
- package/dist/esm/QueryResult.d.ts.map +1 -1
- package/dist/esm/QueryResult.js +122 -79
- package/dist/esm/QueryResult.js.map +1 -1
- package/dist/esm/QueryStore.d.ts +0 -104
- package/dist/esm/QueryStore.d.ts.map +1 -1
- package/dist/esm/QueryStore.js +1 -562
- package/dist/esm/QueryStore.js.map +1 -1
- package/dist/esm/errors.d.ts.map +1 -1
- package/dist/esm/errors.js +18 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/proxy.d.ts +1 -1
- package/dist/esm/proxy.d.ts.map +1 -1
- package/dist/esm/proxy.js +54 -14
- package/dist/esm/proxy.js.map +1 -1
- package/dist/esm/query.d.ts +2 -0
- package/dist/esm/query.d.ts.map +1 -1
- package/dist/esm/query.js +2 -1
- package/dist/esm/query.js.map +1 -1
- package/dist/esm/stores/async.d.ts +3 -1
- package/dist/esm/stores/async.d.ts.map +1 -1
- package/dist/esm/stores/async.js +39 -4
- package/dist/esm/stores/async.js.map +1 -1
- package/dist/esm/stores/shared.d.ts +2 -0
- package/dist/esm/stores/shared.d.ts.map +1 -1
- package/dist/esm/stores/shared.js +2 -0
- package/dist/esm/stores/shared.js.map +1 -1
- package/dist/esm/stores/sync.d.ts +4 -2
- package/dist/esm/stores/sync.d.ts.map +1 -1
- package/dist/esm/stores/sync.js +40 -5
- package/dist/esm/stores/sync.js.map +1 -1
- package/dist/esm/type-utils.d.ts +4 -0
- package/dist/esm/type-utils.d.ts.map +1 -1
- package/dist/esm/typeDefs.d.ts +53 -5
- package/dist/esm/typeDefs.d.ts.map +1 -1
- package/dist/esm/typeDefs.js +126 -5
- package/dist/esm/typeDefs.js.map +1 -1
- package/dist/esm/types.d.ts +36 -10
- package/dist/esm/types.d.ts.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @signalium/query
|
|
2
2
|
|
|
3
|
+
## 1.0.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7f94377: Fixup format registry and add global format type registry
|
|
8
|
+
- d1f9def: Add ability to defined cached methods to entities
|
|
9
|
+
- e0a4844: Add ability for Entities to subscribe to streams when in use
|
|
10
|
+
- 6b961f0: Add support for Signal query parameters and debounced updates
|
|
11
|
+
- Updated dependencies [2cf6766]
|
|
12
|
+
- signalium@2.1.4
|
|
13
|
+
|
|
3
14
|
## 1.0.10
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/dist/cjs/EntityMap.js
CHANGED
|
@@ -5,6 +5,10 @@ const signalium_1 = require("signalium");
|
|
|
5
5
|
const proxy_js_1 = require("./proxy.js");
|
|
6
6
|
class EntityStore {
|
|
7
7
|
map = new Map();
|
|
8
|
+
queryClient;
|
|
9
|
+
constructor(queryClient) {
|
|
10
|
+
this.queryClient = queryClient;
|
|
11
|
+
}
|
|
8
12
|
hasEntity(key) {
|
|
9
13
|
return this.map.has(key);
|
|
10
14
|
}
|
|
@@ -19,8 +23,7 @@ class EntityStore {
|
|
|
19
23
|
refIds.add(key);
|
|
20
24
|
// Entangle the signal value. Whenever the signal value is updated, refIds
|
|
21
25
|
// will also be updated, so no need for a second signal.
|
|
22
|
-
|
|
23
|
-
record.signal.value;
|
|
26
|
+
record.notifier.consume();
|
|
24
27
|
if (record.entityRefs !== undefined) {
|
|
25
28
|
for (const ref of record.entityRefs) {
|
|
26
29
|
this.getNestedEntityRefIds(ref, refIds);
|
|
@@ -33,14 +36,16 @@ class EntityStore {
|
|
|
33
36
|
if (record === undefined) {
|
|
34
37
|
throw new Error(`Entity ${key} not found`);
|
|
35
38
|
}
|
|
36
|
-
record.proxy =
|
|
39
|
+
record.proxy = this.createEntityProxy(record, shape);
|
|
37
40
|
return record;
|
|
38
41
|
}
|
|
39
|
-
setPreloadedEntity(key,
|
|
42
|
+
setPreloadedEntity(key, data) {
|
|
40
43
|
const record = {
|
|
41
44
|
key,
|
|
42
|
-
|
|
45
|
+
data,
|
|
46
|
+
notifier: (0, signalium_1.notifier)(),
|
|
43
47
|
cache: new Map(),
|
|
48
|
+
id: undefined,
|
|
44
49
|
proxy: undefined,
|
|
45
50
|
entityRefs: undefined,
|
|
46
51
|
};
|
|
@@ -51,15 +56,48 @@ class EntityStore {
|
|
|
51
56
|
let record = this.map.get(key);
|
|
52
57
|
if (record === undefined) {
|
|
53
58
|
record = this.setPreloadedEntity(key, obj);
|
|
54
|
-
record.proxy =
|
|
59
|
+
record.proxy = this.createEntityProxy(record, shape);
|
|
55
60
|
}
|
|
56
61
|
else {
|
|
57
|
-
record.
|
|
62
|
+
record.data = (0, proxy_js_1.mergeValues)(record.data, obj);
|
|
63
|
+
record.notifier.notify();
|
|
58
64
|
record.cache.clear();
|
|
59
65
|
}
|
|
60
66
|
record.entityRefs = entityRefs;
|
|
61
67
|
return record;
|
|
62
68
|
}
|
|
69
|
+
createEntityProxy(record, shape) {
|
|
70
|
+
const idField = shape.idField;
|
|
71
|
+
if (idField === undefined) {
|
|
72
|
+
throw new Error(`Entity id field is required ${shape.typenameValue}`);
|
|
73
|
+
}
|
|
74
|
+
const id = record.data[idField];
|
|
75
|
+
if (typeof id !== 'string' && typeof id !== 'number') {
|
|
76
|
+
console.log(record.data);
|
|
77
|
+
throw new Error(`Entity id must be string or number: ${shape.typenameValue}`);
|
|
78
|
+
}
|
|
79
|
+
record.id = id;
|
|
80
|
+
let entityRelay;
|
|
81
|
+
const entityConfig = shape._entityConfig;
|
|
82
|
+
if (entityConfig?.stream) {
|
|
83
|
+
entityRelay = (0, signalium_1.relay)(state => {
|
|
84
|
+
const context = this.queryClient.getContext();
|
|
85
|
+
const onUpdate = (update) => {
|
|
86
|
+
const currentValue = record.data;
|
|
87
|
+
const merged = (0, proxy_js_1.mergeValues)(currentValue, update);
|
|
88
|
+
record.data = merged;
|
|
89
|
+
record.notifier.notify();
|
|
90
|
+
record.cache.clear();
|
|
91
|
+
};
|
|
92
|
+
const unsubscribe = entityConfig.stream.subscribe(context, id, onUpdate);
|
|
93
|
+
// Set initial value to the proxy - this resolves the relay promise
|
|
94
|
+
// Proxy should always exist at this point since it's created before relay access
|
|
95
|
+
state.value = record.proxy;
|
|
96
|
+
return unsubscribe;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return (0, proxy_js_1.createEntityProxy)(record.key, record, shape, entityRelay, this.queryClient);
|
|
100
|
+
}
|
|
63
101
|
}
|
|
64
102
|
exports.EntityStore = EntityStore;
|
|
65
103
|
//# sourceMappingURL=EntityMap.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityMap.js","sourceRoot":"","sources":["../../src/EntityMap.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"EntityMap.js","sourceRoot":"","sources":["../../src/EntityMap.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/QueryClient.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.QueryClientContext = exports.QueryClient = exports.queryKeyFor = void 0;
|
|
16
|
+
exports.extractParamsForKey = extractParamsForKey;
|
|
16
17
|
exports.addOptimisticInsert = addOptimisticInsert;
|
|
17
18
|
exports.removeOptimisticInsert = removeOptimisticInsert;
|
|
18
19
|
const signalium_1 = require("signalium");
|
|
@@ -22,6 +23,41 @@ const NetworkManager_js_1 = require("./NetworkManager.js");
|
|
|
22
23
|
const QueryResult_js_1 = require("./QueryResult.js");
|
|
23
24
|
const RefetchManager_js_1 = require("./RefetchManager.js");
|
|
24
25
|
const MemoryEvictionManager_js_1 = require("./MemoryEvictionManager.js");
|
|
26
|
+
/**
|
|
27
|
+
* Checks if a value is a Signal instance
|
|
28
|
+
*/
|
|
29
|
+
function isSignal(value) {
|
|
30
|
+
return typeof value === 'object' && value !== null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extracts actual values from params that may contain Signals.
|
|
34
|
+
*/
|
|
35
|
+
function extractParamsForKey(params) {
|
|
36
|
+
if (params === undefined) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
const extracted = {};
|
|
40
|
+
for (const [key, value] of Object.entries(params)) {
|
|
41
|
+
if (isSignal(value)) {
|
|
42
|
+
extracted[key] = value.value;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
extracted[key] = value;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return extracted;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Computes the query key for instance lookup. This is used for two different keys:
|
|
52
|
+
*
|
|
53
|
+
* - Query instance key
|
|
54
|
+
* - Query storage key
|
|
55
|
+
*
|
|
56
|
+
* Instance keys are created by passing in the query definition and parameters WITHOUT
|
|
57
|
+
* extracting the Signal values, whereas storage keys are created by extracting the Signal values.
|
|
58
|
+
* This way, we can reuse the same instance for given Signals, but different underlying values
|
|
59
|
+
* will be stored and put into the LRU cache separately.
|
|
60
|
+
*/
|
|
25
61
|
const queryKeyFor = (queryDef, params) => {
|
|
26
62
|
return (0, utils_1.hashValue)([queryDef.id, queryDef.shapeKey, params]);
|
|
27
63
|
};
|
|
@@ -29,7 +65,7 @@ exports.queryKeyFor = queryKeyFor;
|
|
|
29
65
|
class QueryClient {
|
|
30
66
|
store;
|
|
31
67
|
context;
|
|
32
|
-
entityMap
|
|
68
|
+
entityMap;
|
|
33
69
|
queryInstances = new Map();
|
|
34
70
|
memoryEvictionManager;
|
|
35
71
|
refetchManager;
|
|
@@ -43,6 +79,7 @@ class QueryClient {
|
|
|
43
79
|
this.refetchManager = refetchManager ?? new RefetchManager_js_1.RefetchManager(this.context.refetchMultiplier);
|
|
44
80
|
this.networkManager = networkManager ?? new NetworkManager_js_1.NetworkManager();
|
|
45
81
|
this.isServer = typeof window === 'undefined';
|
|
82
|
+
this.entityMap = new EntityMap_js_1.EntityStore(this);
|
|
46
83
|
}
|
|
47
84
|
getContext() {
|
|
48
85
|
return this.context;
|
|
@@ -54,12 +91,14 @@ class QueryClient {
|
|
|
54
91
|
this.store.saveQuery(queryDef, queryKey, data, updatedAt, clonedRefs, extra);
|
|
55
92
|
}
|
|
56
93
|
activateQuery(queryInstance) {
|
|
57
|
-
const { def, queryKey } = queryInstance;
|
|
58
|
-
|
|
94
|
+
const { def, queryKey, storageKey } = queryInstance;
|
|
95
|
+
// Use storageKey for cache operations (store.activateQuery)
|
|
96
|
+
this.store.activateQuery(def, storageKey);
|
|
59
97
|
// Only add to refetch manager if it's not a stream
|
|
60
98
|
if (def.type !== "stream" /* QueryType.Stream */ && def.cache?.refetchInterval) {
|
|
61
99
|
this.refetchManager.addQuery(queryInstance);
|
|
62
100
|
}
|
|
101
|
+
// Use queryKey for instance eviction (memoryEvictionManager)
|
|
63
102
|
this.memoryEvictionManager.cancelEviction(queryKey);
|
|
64
103
|
}
|
|
65
104
|
loadCachedQuery(queryDef, queryKey) {
|
|
@@ -84,7 +123,9 @@ class QueryClient {
|
|
|
84
123
|
return this.entityMap.hydratePreloadedEntity(key, shape);
|
|
85
124
|
}
|
|
86
125
|
saveEntity(key, obj, shape, entityRefs) {
|
|
126
|
+
// console.log('saveEntity', key, JSON.stringify(obj, null, 2), shape, entityRefs, new Error().stack);
|
|
87
127
|
const record = this.entityMap.setEntity(key, obj, shape, entityRefs);
|
|
128
|
+
// console.log('saveEntity record', JSON.stringify(obj, null, 2), new Error().stack);
|
|
88
129
|
this.store.saveEntity(key, obj, entityRefs);
|
|
89
130
|
return record;
|
|
90
131
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryClient.js","sourceRoot":"","sources":["../../src/QueryClient.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;
|
|
1
|
+
{"version":3,"file":"QueryClient.js","sourceRoot":"","sources":["../../src/QueryClient.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/QueryResult.js
CHANGED
|
@@ -7,6 +7,7 @@ const types_js_1 = require("./types.js");
|
|
|
7
7
|
const proxy_js_1 = require("./proxy.js");
|
|
8
8
|
const parseEntities_js_1 = require("./parseEntities.js");
|
|
9
9
|
const typeDefs_js_1 = require("./typeDefs.js");
|
|
10
|
+
const QueryClient_js_1 = require("./QueryClient.js");
|
|
10
11
|
// ======================================================
|
|
11
12
|
// QueryResultExtra - Manages stream orphans and optimistic inserts
|
|
12
13
|
// ======================================================
|
|
@@ -257,7 +258,8 @@ class QueryResultExtra {
|
|
|
257
258
|
*/
|
|
258
259
|
class QueryResultImpl {
|
|
259
260
|
def;
|
|
260
|
-
queryKey;
|
|
261
|
+
queryKey; // Instance key (includes Signal identity)
|
|
262
|
+
storageKey = -1; // Storage key (extracted values only)
|
|
261
263
|
queryClient;
|
|
262
264
|
initialized = false;
|
|
263
265
|
isRefetchingSignal = (0, signalium_1.signal)(false);
|
|
@@ -268,12 +270,12 @@ class QueryResultImpl {
|
|
|
268
270
|
allNestedRefIdsSignal = undefined;
|
|
269
271
|
refetchPromise = undefined;
|
|
270
272
|
fetchMorePromise = undefined;
|
|
271
|
-
attemptCount = 0;
|
|
272
273
|
unsubscribe = undefined;
|
|
273
|
-
streamUnsubscribe = undefined;
|
|
274
274
|
relay;
|
|
275
275
|
_relayState = undefined;
|
|
276
|
-
|
|
276
|
+
wasPaused = false;
|
|
277
|
+
currentParams = undefined;
|
|
278
|
+
debounceTimer = undefined;
|
|
277
279
|
get relayState() {
|
|
278
280
|
const relayState = this._relayState;
|
|
279
281
|
if (!relayState) {
|
|
@@ -306,7 +308,7 @@ class QueryResultImpl {
|
|
|
306
308
|
else {
|
|
307
309
|
// Clone current params
|
|
308
310
|
let hasDefinedParams = false;
|
|
309
|
-
const clonedParams = { ...this.
|
|
311
|
+
const clonedParams = { ...this.currentParams };
|
|
310
312
|
// iterate over the next page params and copy any defined values to the
|
|
311
313
|
for (const [key, value] of Object.entries(nextParams)) {
|
|
312
314
|
if (value !== undefined && value !== null) {
|
|
@@ -323,91 +325,96 @@ class QueryResultImpl {
|
|
|
323
325
|
(0, utils_1.setReactivePromise)(this);
|
|
324
326
|
this.def = def;
|
|
325
327
|
this.queryClient = queryClient;
|
|
326
|
-
this.queryKey = queryKey;
|
|
328
|
+
this.queryKey = queryKey; // Instance key (Signal identity)
|
|
327
329
|
this.params = params;
|
|
328
330
|
// Create the relay and handle activation/deactivation
|
|
329
331
|
this.relay = (0, signalium_1.relay)(state => {
|
|
330
332
|
this._relayState = state;
|
|
333
|
+
// Extract params (reading Signal values establishes tracking)
|
|
334
|
+
this.currentParams = (0, QueryClient_js_1.extractParamsForKey)(this.params);
|
|
335
|
+
this.storageKey = (0, QueryClient_js_1.queryKeyFor)(this.def, this.currentParams);
|
|
331
336
|
// Load from cache first, then fetch fresh data
|
|
332
337
|
this.queryClient.activateQuery(this);
|
|
333
|
-
// Track network status for reconnect handling
|
|
334
|
-
const networkManager = this.queryClient.networkManager;
|
|
335
|
-
const isOnline = networkManager.getOnlineSignal().value;
|
|
336
338
|
// Store initial offline state
|
|
337
|
-
|
|
339
|
+
const isPaused = this.isPaused;
|
|
340
|
+
this.wasPaused = isPaused;
|
|
338
341
|
if (this.initialized) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
this.def.stream
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if (this.def.type !== "stream" /* QueryType.Stream */) {
|
|
345
|
-
// Check if we just came back online
|
|
346
|
-
if (!this.wasOffline && isOnline) {
|
|
347
|
-
// We're back online - check if we should refresh
|
|
348
|
-
const refreshStaleOnReconnect = this.def.cache?.refreshStaleOnReconnect ?? true;
|
|
349
|
-
if (refreshStaleOnReconnect && this.isStale) {
|
|
350
|
-
this.refetch();
|
|
351
|
-
}
|
|
352
|
-
// Reset attempt count on reconnect
|
|
353
|
-
this.attemptCount = 0;
|
|
342
|
+
if (!isPaused) {
|
|
343
|
+
// For any query with streams, resubscribe on reactivation
|
|
344
|
+
if (this.def.type === "stream" /* QueryType.Stream */ ||
|
|
345
|
+
this.def.stream) {
|
|
346
|
+
this.setupSubscription();
|
|
354
347
|
}
|
|
355
|
-
|
|
348
|
+
if (this.def.type !== "stream" /* QueryType.Stream */ && this.isStale) {
|
|
356
349
|
this.refetch();
|
|
357
350
|
}
|
|
358
351
|
}
|
|
359
|
-
// Update wasOffline for next check
|
|
360
|
-
this.wasOffline = !isOnline;
|
|
361
352
|
}
|
|
362
353
|
else {
|
|
363
354
|
this.initialize();
|
|
364
355
|
}
|
|
356
|
+
const deactivate = () => {
|
|
357
|
+
// Clear debounce timer if active
|
|
358
|
+
clearTimeout(this.debounceTimer);
|
|
359
|
+
this.debounceTimer = undefined;
|
|
360
|
+
// Last subscriber left, deactivate refetch and schedule memory eviction
|
|
361
|
+
// Unsubscribe from any active streams
|
|
362
|
+
this.unsubscribe?.();
|
|
363
|
+
this.unsubscribe = undefined;
|
|
364
|
+
// Remove from refetch manager if configured
|
|
365
|
+
if (this.def.type !== "stream" /* QueryType.Stream */ && this.def.cache?.refetchInterval) {
|
|
366
|
+
this.queryClient.refetchManager.removeQuery(this);
|
|
367
|
+
}
|
|
368
|
+
// Schedule removal from memory using the global eviction manager
|
|
369
|
+
// This allows quick reactivation from memory if needed again soon
|
|
370
|
+
// Disk cache (if configured) will still be available after eviction
|
|
371
|
+
// Use queryKey for instance eviction, storageKey for cache eviction
|
|
372
|
+
this.queryClient.memoryEvictionManager.scheduleEviction(this.queryKey);
|
|
373
|
+
};
|
|
365
374
|
// Return deactivation callback
|
|
366
375
|
return {
|
|
367
376
|
update: () => {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
// For StreamQuery, we're done - it doesn't react to network status
|
|
374
|
-
if (this.def.type === "stream" /* QueryType.Stream */) {
|
|
377
|
+
const { wasPaused, isPaused } = this;
|
|
378
|
+
this.wasPaused = isPaused;
|
|
379
|
+
if (isPaused) {
|
|
380
|
+
deactivate();
|
|
381
|
+
// TODO: Add abort signal
|
|
375
382
|
return;
|
|
376
383
|
}
|
|
377
|
-
//
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
//
|
|
386
|
-
this.
|
|
387
|
-
|
|
388
|
-
// Update wasOffline for next check
|
|
389
|
-
this.wasOffline = !currentlyOnline;
|
|
390
|
-
},
|
|
391
|
-
deactivate: () => {
|
|
392
|
-
// Last subscriber left, deactivate refetch and schedule memory eviction
|
|
393
|
-
// Unsubscribe from any active streams
|
|
394
|
-
if (this.unsubscribe) {
|
|
395
|
-
this.unsubscribe();
|
|
396
|
-
this.unsubscribe = undefined;
|
|
384
|
+
// Read Signal values again to establish tracking for any new Signals
|
|
385
|
+
// Extract params (reading Signal values establishes tracking)
|
|
386
|
+
const newExtractedParams = (0, QueryClient_js_1.extractParamsForKey)(this.params);
|
|
387
|
+
const newStorageKey = (0, QueryClient_js_1.queryKeyFor)(this.def, newExtractedParams);
|
|
388
|
+
const paramsDidChange = newStorageKey !== this.storageKey;
|
|
389
|
+
// Check if storage key changed (comparing hash values)
|
|
390
|
+
if (paramsDidChange) {
|
|
391
|
+
// Same storage key, just Signal instances changed but values are the same
|
|
392
|
+
// Update params and trigger debounced refetch
|
|
393
|
+
this.params = newExtractedParams;
|
|
394
|
+
this.storageKey = newStorageKey;
|
|
397
395
|
}
|
|
398
|
-
if (
|
|
399
|
-
this.
|
|
400
|
-
this.
|
|
396
|
+
if (wasPaused) {
|
|
397
|
+
this.queryClient.activateQuery(this);
|
|
398
|
+
if (this.def.type !== "stream" /* QueryType.Stream */) {
|
|
399
|
+
const refreshStaleOnReconnect = this.def.cache?.refreshStaleOnReconnect ?? true;
|
|
400
|
+
if (refreshStaleOnReconnect && this.isStale) {
|
|
401
|
+
state.setPromise(this.runQuery(this.currentParams, true));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
this.setupSubscription();
|
|
406
|
+
}
|
|
401
407
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
408
|
+
else if (paramsDidChange) {
|
|
409
|
+
if (this.def.type !== "stream" /* QueryType.Stream */) {
|
|
410
|
+
this.debouncedRefetch();
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
this.setupSubscription();
|
|
414
|
+
}
|
|
405
415
|
}
|
|
406
|
-
// Schedule removal from memory using the global eviction manager
|
|
407
|
-
// This allows quick reactivation from memory if needed again soon
|
|
408
|
-
// Disk cache (if configured) will still be available after eviction
|
|
409
|
-
this.queryClient.memoryEvictionManager.scheduleEviction(this.queryKey);
|
|
410
416
|
},
|
|
417
|
+
deactivate,
|
|
411
418
|
};
|
|
412
419
|
});
|
|
413
420
|
}
|
|
@@ -491,8 +498,8 @@ class QueryResultImpl {
|
|
|
491
498
|
const state = this.relayState;
|
|
492
499
|
try {
|
|
493
500
|
this.initialized = true;
|
|
494
|
-
// Load from cache first
|
|
495
|
-
const cached = await this.queryClient.loadCachedQuery(this.def, this.
|
|
501
|
+
// Load from cache first (use storage key for cache operations)
|
|
502
|
+
const cached = await this.queryClient.loadCachedQuery(this.def, this.storageKey);
|
|
496
503
|
if (cached !== undefined) {
|
|
497
504
|
// Set the cached timestamp
|
|
498
505
|
this.updatedAt = cached.updatedAt;
|
|
@@ -511,6 +518,9 @@ class QueryResultImpl {
|
|
|
511
518
|
? (0, parseEntities_js_1.parseEntities)(cached.value, shape, this.queryClient, new Set())
|
|
512
519
|
: (0, proxy_js_1.parseValue)(cached.value, shape, this.def.id);
|
|
513
520
|
}
|
|
521
|
+
if (this.isPaused) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
514
524
|
// Setup subscriptions (handles both StreamQuery and Query/InfiniteQuery with stream)
|
|
515
525
|
if (this.def.type === "stream" /* QueryType.Stream */ ||
|
|
516
526
|
this.def.stream) {
|
|
@@ -521,13 +531,19 @@ class QueryResultImpl {
|
|
|
521
531
|
if (cached !== undefined) {
|
|
522
532
|
// Check if data is stale
|
|
523
533
|
if (this.isStale) {
|
|
524
|
-
// Data is stale, trigger background refetch
|
|
525
|
-
this.
|
|
534
|
+
// Data is stale, trigger background refetch (with debounce if configured)
|
|
535
|
+
if (this.def.debounce !== undefined && this.def.debounce > 0) {
|
|
536
|
+
this.debouncedRefetch();
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
this.refetch();
|
|
540
|
+
}
|
|
526
541
|
}
|
|
527
542
|
}
|
|
528
543
|
else {
|
|
529
|
-
// No cached data, fetch fresh
|
|
530
|
-
|
|
544
|
+
// No cached data, fetch fresh immediately (don't debounce initial fetch)
|
|
545
|
+
// Debounce only applies to refetches triggered by parameter changes
|
|
546
|
+
state.setPromise(this.runQuery(this.currentParams, true));
|
|
531
547
|
}
|
|
532
548
|
}
|
|
533
549
|
}
|
|
@@ -557,14 +573,17 @@ class QueryResultImpl {
|
|
|
557
573
|
shapeDef = stream.shape;
|
|
558
574
|
subscribeFn = stream.subscribeFn;
|
|
559
575
|
}
|
|
560
|
-
|
|
576
|
+
// Extract params (reading Signal values establishes tracking)
|
|
577
|
+
const extractedParams = this.currentParams;
|
|
578
|
+
this.unsubscribe = subscribeFn(this.queryClient.getContext(), extractedParams, update => {
|
|
561
579
|
const parsedData = (0, parseEntities_js_1.parseObjectEntities)(update, shapeDef, this.queryClient);
|
|
562
580
|
// Update the relay state
|
|
563
581
|
if (this.def.type === "stream" /* QueryType.Stream */) {
|
|
564
582
|
this.relayState.value = parsedData;
|
|
565
583
|
this.updatedAt = Date.now();
|
|
566
584
|
// Cache the data
|
|
567
|
-
|
|
585
|
+
// Use storage key for cache operations
|
|
586
|
+
this.queryClient.saveQueryData(this.def, this.storageKey, parsedData, this.updatedAt);
|
|
568
587
|
}
|
|
569
588
|
else {
|
|
570
589
|
const allRefIds = this.getAllEntityRefs();
|
|
@@ -591,8 +610,6 @@ class QueryResultImpl {
|
|
|
591
610
|
try {
|
|
592
611
|
const queryDef = this.def;
|
|
593
612
|
const freshData = await queryDef.fetchFn(this.queryClient.getContext(), params);
|
|
594
|
-
// Success! Reset attempt count
|
|
595
|
-
this.attemptCount = 0;
|
|
596
613
|
// Parse and cache the fresh data
|
|
597
614
|
let entityRefs;
|
|
598
615
|
const isInfinite = this.def.type === "infiniteQuery" /* QueryType.InfiniteQuery */;
|
|
@@ -623,14 +640,14 @@ class QueryResultImpl {
|
|
|
623
640
|
}
|
|
624
641
|
this._nextPageParams = undefined;
|
|
625
642
|
// Cache the data (synchronous, fire-and-forget)
|
|
626
|
-
|
|
643
|
+
// Use storage key for cache operations
|
|
644
|
+
this.queryClient.saveQueryData(this.def, this.storageKey, queryData, updatedAt, entityRefs, this.getExtraForPersistence());
|
|
627
645
|
// Update the timestamp
|
|
628
646
|
this.updatedAt = Date.now();
|
|
629
647
|
return queryData;
|
|
630
648
|
}
|
|
631
649
|
catch (error) {
|
|
632
650
|
lastError = error;
|
|
633
|
-
this.attemptCount = attempt + 1;
|
|
634
651
|
// If we've exhausted retries, throw the error
|
|
635
652
|
if (attempt >= retries) {
|
|
636
653
|
throw error;
|
|
@@ -648,6 +665,28 @@ class QueryResultImpl {
|
|
|
648
665
|
throw lastError;
|
|
649
666
|
}
|
|
650
667
|
// ======================================================
|
|
668
|
+
// Private debounce methods
|
|
669
|
+
// ======================================================
|
|
670
|
+
/**
|
|
671
|
+
* Triggers a debounced refetch. If debounce is configured, delays the fetch.
|
|
672
|
+
* Otherwise, calls refetch immediately.
|
|
673
|
+
*/
|
|
674
|
+
debouncedRefetch() {
|
|
675
|
+
// We know this is a non-stream query because we're calling refetch, which is only available on non-stream queries
|
|
676
|
+
const debounce = this.def.debounce;
|
|
677
|
+
if (debounce === undefined) {
|
|
678
|
+
this.refetch();
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
// Clear existing timer
|
|
682
|
+
clearTimeout(this.debounceTimer);
|
|
683
|
+
// Set new timer
|
|
684
|
+
this.debounceTimer = setTimeout(() => {
|
|
685
|
+
this.debounceTimer = undefined;
|
|
686
|
+
this.refetch();
|
|
687
|
+
}, debounce);
|
|
688
|
+
}
|
|
689
|
+
// ======================================================
|
|
651
690
|
// Public methods
|
|
652
691
|
// ======================================================
|
|
653
692
|
refetch = () => {
|
|
@@ -660,13 +699,16 @@ class QueryResultImpl {
|
|
|
660
699
|
if (this.refetchPromise) {
|
|
661
700
|
return this.refetchPromise;
|
|
662
701
|
}
|
|
702
|
+
// Clear debounce timer if active (manual refetch should bypass debounce)
|
|
703
|
+
clearTimeout(this.debounceTimer);
|
|
704
|
+
this.debounceTimer = undefined;
|
|
663
705
|
// Clear memoized nextPageParams so it's recalculated after refetch
|
|
664
706
|
this._nextPageParams = undefined;
|
|
665
707
|
// Set the signal before any async operations so it's immediately visible
|
|
666
708
|
// Use untrack to avoid reactive violations when called from reactive context
|
|
667
709
|
this.isRefetchingSignal.value = true;
|
|
668
710
|
this._version.update(v => v + 1);
|
|
669
|
-
const promise = this.runQuery(this.
|
|
711
|
+
const promise = this.runQuery(this.currentParams, true)
|
|
670
712
|
.then(result => {
|
|
671
713
|
this.relayState.value = result;
|
|
672
714
|
// Clear stream orphans and optimistic inserts on refetch
|
|
@@ -750,7 +792,8 @@ class QueryResultImpl {
|
|
|
750
792
|
return; // Query not initialized yet
|
|
751
793
|
}
|
|
752
794
|
const extra = this._extra?.getForPersistence();
|
|
753
|
-
|
|
795
|
+
// Use storage key for cache operations
|
|
796
|
+
this.queryClient.saveQueryData(this.def, this.storageKey, this.relayState.value, this.updatedAt, this.refIds, extra);
|
|
754
797
|
}
|
|
755
798
|
/**
|
|
756
799
|
* Get extra data for persistence (converts Sets to arrays of entity ref IDs)
|