@signalium/query 1.0.10 → 1.0.12
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 +21 -0
- package/dist/cjs/EntityMap.js +45 -7
- package/dist/cjs/EntityMap.js.map +1 -1
- package/dist/cjs/QueryClient.js +48 -4
- package/dist/cjs/QueryClient.js.map +1 -1
- package/dist/cjs/QueryResult.js +132 -80
- package/dist/cjs/QueryResult.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 +56 -6
- 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 +49 -13
- package/dist/cjs/stores/sync.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/cjs/typeDefs.js +141 -8
- 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 +31 -2
- package/dist/esm/QueryClient.d.ts.map +1 -1
- package/dist/esm/QueryClient.js +47 -4
- 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 +132 -80
- package/dist/esm/QueryResult.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 +8 -3
- package/dist/esm/stores/async.d.ts.map +1 -1
- package/dist/esm/stores/async.js +57 -7
- 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 -3
- package/dist/esm/stores/sync.d.ts.map +1 -1
- package/dist/esm/stores/sync.js +43 -8
- 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 +139 -8
- package/dist/esm/typeDefs.js.map +1 -1
- package/dist/esm/types.d.ts +38 -12
- package/dist/esm/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/cjs/QueryStore.js +0 -583
- package/dist/cjs/QueryStore.js.map +0 -1
- package/dist/esm/QueryStore.d.ts +0 -147
- package/dist/esm/QueryStore.d.ts.map +0 -1
- package/dist/esm/QueryStore.js +0 -570
- package/dist/esm/QueryStore.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @signalium/query
|
|
2
2
|
|
|
3
|
+
## 1.0.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f3e1ef0: Fix case-insensitive enum type inference
|
|
8
|
+
- 11116da: Add more tests for shapeKey and fix some small issues
|
|
9
|
+
- 0219742: Fix initialization error handling
|
|
10
|
+
- Updated dependencies [985abb0]
|
|
11
|
+
- signalium@2.1.5
|
|
12
|
+
|
|
13
|
+
## 1.0.11
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 7f94377: Fixup format registry and add global format type registry
|
|
18
|
+
- d1f9def: Add ability to defined cached methods to entities
|
|
19
|
+
- e0a4844: Add ability for Entities to subscribe to streams when in use
|
|
20
|
+
- 6b961f0: Add support for Signal query parameters and debounced updates
|
|
21
|
+
- Updated dependencies [2cf6766]
|
|
22
|
+
- signalium@2.1.4
|
|
23
|
+
|
|
3
24
|
## 1.0.10
|
|
4
25
|
|
|
5
26
|
### 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,13 +65,13 @@ 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;
|
|
36
72
|
networkManager;
|
|
37
73
|
isServer;
|
|
38
|
-
constructor(store, context = { fetch }, networkManager, memoryEvictionManager, refetchManager) {
|
|
74
|
+
constructor(store, context = { fetch, log: console }, networkManager, memoryEvictionManager, refetchManager) {
|
|
39
75
|
this.store = store;
|
|
40
76
|
this.context = context;
|
|
41
77
|
this.memoryEvictionManager =
|
|
@@ -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,17 +91,22 @@ 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) {
|
|
66
105
|
return this.store.loadQuery(queryDef, queryKey, this.entityMap);
|
|
67
106
|
}
|
|
107
|
+
deleteCachedQuery(queryKey) {
|
|
108
|
+
this.store.deleteQuery(queryKey);
|
|
109
|
+
}
|
|
68
110
|
/**
|
|
69
111
|
* Loads a query from the document store and returns a QueryResult
|
|
70
112
|
* that triggers fetches and prepopulates with cached data
|
|
@@ -84,7 +126,9 @@ class QueryClient {
|
|
|
84
126
|
return this.entityMap.hydratePreloadedEntity(key, shape);
|
|
85
127
|
}
|
|
86
128
|
saveEntity(key, obj, shape, entityRefs) {
|
|
129
|
+
// console.log('saveEntity', key, JSON.stringify(obj, null, 2), shape, entityRefs, new Error().stack);
|
|
87
130
|
const record = this.entityMap.setEntity(key, obj, shape, entityRefs);
|
|
131
|
+
// console.log('saveEntity record', JSON.stringify(obj, null, 2), new Error().stack);
|
|
88
132
|
this.store.saveEntity(key, obj, entityRefs);
|
|
89
133
|
return record;
|
|
90
134
|
}
|
|
@@ -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
|
}
|
|
@@ -489,10 +496,11 @@ class QueryResultImpl {
|
|
|
489
496
|
*/
|
|
490
497
|
async initialize() {
|
|
491
498
|
const state = this.relayState;
|
|
499
|
+
this.initialized = true;
|
|
500
|
+
let cached;
|
|
492
501
|
try {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
const cached = await this.queryClient.loadCachedQuery(this.def, this.queryKey);
|
|
502
|
+
// Load from cache first (use storage key for cache operations)
|
|
503
|
+
cached = await this.queryClient.loadCachedQuery(this.def, this.storageKey);
|
|
496
504
|
if (cached !== undefined) {
|
|
497
505
|
// Set the cached timestamp
|
|
498
506
|
this.updatedAt = cached.updatedAt;
|
|
@@ -511,6 +519,17 @@ class QueryResultImpl {
|
|
|
511
519
|
? (0, parseEntities_js_1.parseEntities)(cached.value, shape, this.queryClient, new Set())
|
|
512
520
|
: (0, proxy_js_1.parseValue)(cached.value, shape, this.def.id);
|
|
513
521
|
}
|
|
522
|
+
}
|
|
523
|
+
catch (error) {
|
|
524
|
+
this.queryClient.deleteCachedQuery(this.storageKey);
|
|
525
|
+
this.queryClient
|
|
526
|
+
.getContext()
|
|
527
|
+
.log?.warn?.('Failed to initialize query, the query cache may be corrupted or invalid', error);
|
|
528
|
+
}
|
|
529
|
+
if (this.isPaused) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
try {
|
|
514
533
|
// Setup subscriptions (handles both StreamQuery and Query/InfiniteQuery with stream)
|
|
515
534
|
if (this.def.type === "stream" /* QueryType.Stream */ ||
|
|
516
535
|
this.def.stream) {
|
|
@@ -521,13 +540,19 @@ class QueryResultImpl {
|
|
|
521
540
|
if (cached !== undefined) {
|
|
522
541
|
// Check if data is stale
|
|
523
542
|
if (this.isStale) {
|
|
524
|
-
// Data is stale, trigger background refetch
|
|
525
|
-
this.
|
|
543
|
+
// Data is stale, trigger background refetch (with debounce if configured)
|
|
544
|
+
if (this.def.debounce !== undefined && this.def.debounce > 0) {
|
|
545
|
+
this.debouncedRefetch();
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
this.refetch();
|
|
549
|
+
}
|
|
526
550
|
}
|
|
527
551
|
}
|
|
528
552
|
else {
|
|
529
|
-
// No cached data, fetch fresh
|
|
530
|
-
|
|
553
|
+
// No cached data, fetch fresh immediately (don't debounce initial fetch)
|
|
554
|
+
// Debounce only applies to refetches triggered by parameter changes
|
|
555
|
+
state.setPromise(this.runQuery(this.currentParams, true));
|
|
531
556
|
}
|
|
532
557
|
}
|
|
533
558
|
}
|
|
@@ -557,14 +582,17 @@ class QueryResultImpl {
|
|
|
557
582
|
shapeDef = stream.shape;
|
|
558
583
|
subscribeFn = stream.subscribeFn;
|
|
559
584
|
}
|
|
560
|
-
|
|
585
|
+
// Extract params (reading Signal values establishes tracking)
|
|
586
|
+
const extractedParams = this.currentParams;
|
|
587
|
+
this.unsubscribe = subscribeFn(this.queryClient.getContext(), extractedParams, update => {
|
|
561
588
|
const parsedData = (0, parseEntities_js_1.parseObjectEntities)(update, shapeDef, this.queryClient);
|
|
562
589
|
// Update the relay state
|
|
563
590
|
if (this.def.type === "stream" /* QueryType.Stream */) {
|
|
564
591
|
this.relayState.value = parsedData;
|
|
565
592
|
this.updatedAt = Date.now();
|
|
566
593
|
// Cache the data
|
|
567
|
-
|
|
594
|
+
// Use storage key for cache operations
|
|
595
|
+
this.queryClient.saveQueryData(this.def, this.storageKey, parsedData, this.updatedAt);
|
|
568
596
|
}
|
|
569
597
|
else {
|
|
570
598
|
const allRefIds = this.getAllEntityRefs();
|
|
@@ -591,8 +619,6 @@ class QueryResultImpl {
|
|
|
591
619
|
try {
|
|
592
620
|
const queryDef = this.def;
|
|
593
621
|
const freshData = await queryDef.fetchFn(this.queryClient.getContext(), params);
|
|
594
|
-
// Success! Reset attempt count
|
|
595
|
-
this.attemptCount = 0;
|
|
596
622
|
// Parse and cache the fresh data
|
|
597
623
|
let entityRefs;
|
|
598
624
|
const isInfinite = this.def.type === "infiniteQuery" /* QueryType.InfiniteQuery */;
|
|
@@ -623,14 +649,14 @@ class QueryResultImpl {
|
|
|
623
649
|
}
|
|
624
650
|
this._nextPageParams = undefined;
|
|
625
651
|
// Cache the data (synchronous, fire-and-forget)
|
|
626
|
-
|
|
652
|
+
// Use storage key for cache operations
|
|
653
|
+
this.queryClient.saveQueryData(this.def, this.storageKey, queryData, updatedAt, entityRefs, this.getExtraForPersistence());
|
|
627
654
|
// Update the timestamp
|
|
628
655
|
this.updatedAt = Date.now();
|
|
629
656
|
return queryData;
|
|
630
657
|
}
|
|
631
658
|
catch (error) {
|
|
632
659
|
lastError = error;
|
|
633
|
-
this.attemptCount = attempt + 1;
|
|
634
660
|
// If we've exhausted retries, throw the error
|
|
635
661
|
if (attempt >= retries) {
|
|
636
662
|
throw error;
|
|
@@ -648,6 +674,28 @@ class QueryResultImpl {
|
|
|
648
674
|
throw lastError;
|
|
649
675
|
}
|
|
650
676
|
// ======================================================
|
|
677
|
+
// Private debounce methods
|
|
678
|
+
// ======================================================
|
|
679
|
+
/**
|
|
680
|
+
* Triggers a debounced refetch. If debounce is configured, delays the fetch.
|
|
681
|
+
* Otherwise, calls refetch immediately.
|
|
682
|
+
*/
|
|
683
|
+
debouncedRefetch() {
|
|
684
|
+
// We know this is a non-stream query because we're calling refetch, which is only available on non-stream queries
|
|
685
|
+
const debounce = this.def.debounce;
|
|
686
|
+
if (debounce === undefined) {
|
|
687
|
+
this.refetch();
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
// Clear existing timer
|
|
691
|
+
clearTimeout(this.debounceTimer);
|
|
692
|
+
// Set new timer
|
|
693
|
+
this.debounceTimer = setTimeout(() => {
|
|
694
|
+
this.debounceTimer = undefined;
|
|
695
|
+
this.refetch();
|
|
696
|
+
}, debounce);
|
|
697
|
+
}
|
|
698
|
+
// ======================================================
|
|
651
699
|
// Public methods
|
|
652
700
|
// ======================================================
|
|
653
701
|
refetch = () => {
|
|
@@ -660,13 +708,16 @@ class QueryResultImpl {
|
|
|
660
708
|
if (this.refetchPromise) {
|
|
661
709
|
return this.refetchPromise;
|
|
662
710
|
}
|
|
711
|
+
// Clear debounce timer if active (manual refetch should bypass debounce)
|
|
712
|
+
clearTimeout(this.debounceTimer);
|
|
713
|
+
this.debounceTimer = undefined;
|
|
663
714
|
// Clear memoized nextPageParams so it's recalculated after refetch
|
|
664
715
|
this._nextPageParams = undefined;
|
|
665
716
|
// Set the signal before any async operations so it's immediately visible
|
|
666
717
|
// Use untrack to avoid reactive violations when called from reactive context
|
|
667
718
|
this.isRefetchingSignal.value = true;
|
|
668
719
|
this._version.update(v => v + 1);
|
|
669
|
-
const promise = this.runQuery(this.
|
|
720
|
+
const promise = this.runQuery(this.currentParams, true)
|
|
670
721
|
.then(result => {
|
|
671
722
|
this.relayState.value = result;
|
|
672
723
|
// Clear stream orphans and optimistic inserts on refetch
|
|
@@ -750,7 +801,8 @@ class QueryResultImpl {
|
|
|
750
801
|
return; // Query not initialized yet
|
|
751
802
|
}
|
|
752
803
|
const extra = this._extra?.getForPersistence();
|
|
753
|
-
|
|
804
|
+
// Use storage key for cache operations
|
|
805
|
+
this.queryClient.saveQueryData(this.def, this.storageKey, this.relayState.value, this.updatedAt, this.refIds, extra);
|
|
754
806
|
}
|
|
755
807
|
/**
|
|
756
808
|
* Get extra data for persistence (converts Sets to arrays of entity ref IDs)
|