@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.
Files changed (72) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/EntityMap.js +45 -7
  3. package/dist/cjs/EntityMap.js.map +1 -1
  4. package/dist/cjs/QueryClient.js +48 -4
  5. package/dist/cjs/QueryClient.js.map +1 -1
  6. package/dist/cjs/QueryResult.js +132 -80
  7. package/dist/cjs/QueryResult.js.map +1 -1
  8. package/dist/cjs/errors.js +17 -0
  9. package/dist/cjs/errors.js.map +1 -1
  10. package/dist/cjs/proxy.js +54 -14
  11. package/dist/cjs/proxy.js.map +1 -1
  12. package/dist/cjs/query.js +2 -1
  13. package/dist/cjs/query.js.map +1 -1
  14. package/dist/cjs/stores/async.js +56 -6
  15. package/dist/cjs/stores/async.js.map +1 -1
  16. package/dist/cjs/stores/shared.js +5 -1
  17. package/dist/cjs/stores/shared.js.map +1 -1
  18. package/dist/cjs/stores/sync.js +49 -13
  19. package/dist/cjs/stores/sync.js.map +1 -1
  20. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  21. package/dist/cjs/typeDefs.js +141 -8
  22. package/dist/cjs/typeDefs.js.map +1 -1
  23. package/dist/esm/EntityMap.d.ts +9 -3
  24. package/dist/esm/EntityMap.d.ts.map +1 -1
  25. package/dist/esm/EntityMap.js +46 -8
  26. package/dist/esm/EntityMap.js.map +1 -1
  27. package/dist/esm/QueryClient.d.ts +31 -2
  28. package/dist/esm/QueryClient.d.ts.map +1 -1
  29. package/dist/esm/QueryClient.js +47 -4
  30. package/dist/esm/QueryClient.js.map +1 -1
  31. package/dist/esm/QueryResult.d.ts +9 -3
  32. package/dist/esm/QueryResult.d.ts.map +1 -1
  33. package/dist/esm/QueryResult.js +132 -80
  34. package/dist/esm/QueryResult.js.map +1 -1
  35. package/dist/esm/errors.d.ts.map +1 -1
  36. package/dist/esm/errors.js +18 -1
  37. package/dist/esm/errors.js.map +1 -1
  38. package/dist/esm/proxy.d.ts +1 -1
  39. package/dist/esm/proxy.d.ts.map +1 -1
  40. package/dist/esm/proxy.js +54 -14
  41. package/dist/esm/proxy.js.map +1 -1
  42. package/dist/esm/query.d.ts +2 -0
  43. package/dist/esm/query.d.ts.map +1 -1
  44. package/dist/esm/query.js +2 -1
  45. package/dist/esm/query.js.map +1 -1
  46. package/dist/esm/stores/async.d.ts +8 -3
  47. package/dist/esm/stores/async.d.ts.map +1 -1
  48. package/dist/esm/stores/async.js +57 -7
  49. package/dist/esm/stores/async.js.map +1 -1
  50. package/dist/esm/stores/shared.d.ts +2 -0
  51. package/dist/esm/stores/shared.d.ts.map +1 -1
  52. package/dist/esm/stores/shared.js +2 -0
  53. package/dist/esm/stores/shared.js.map +1 -1
  54. package/dist/esm/stores/sync.d.ts +4 -3
  55. package/dist/esm/stores/sync.d.ts.map +1 -1
  56. package/dist/esm/stores/sync.js +43 -8
  57. package/dist/esm/stores/sync.js.map +1 -1
  58. package/dist/esm/type-utils.d.ts +4 -0
  59. package/dist/esm/type-utils.d.ts.map +1 -1
  60. package/dist/esm/typeDefs.d.ts +53 -5
  61. package/dist/esm/typeDefs.d.ts.map +1 -1
  62. package/dist/esm/typeDefs.js +139 -8
  63. package/dist/esm/typeDefs.js.map +1 -1
  64. package/dist/esm/types.d.ts +38 -12
  65. package/dist/esm/types.d.ts.map +1 -1
  66. package/package.json +3 -3
  67. package/dist/cjs/QueryStore.js +0 -583
  68. package/dist/cjs/QueryStore.js.map +0 -1
  69. package/dist/esm/QueryStore.d.ts +0 -147
  70. package/dist/esm/QueryStore.d.ts.map +0 -1
  71. package/dist/esm/QueryStore.js +0 -570
  72. 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
@@ -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
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
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 = (0, proxy_js_1.createEntityProxy)(key, record, shape);
39
+ record.proxy = this.createEntityProxy(record, shape);
37
40
  return record;
38
41
  }
39
- setPreloadedEntity(key, obj) {
42
+ setPreloadedEntity(key, data) {
40
43
  const record = {
41
44
  key,
42
- signal: (0, signalium_1.signal)(obj, { equals: false }),
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 = (0, proxy_js_1.createEntityProxy)(key, record, shape);
59
+ record.proxy = this.createEntityProxy(record, shape);
55
60
  }
56
61
  else {
57
- record.signal.update(value => (0, proxy_js_1.mergeValues)(value, obj));
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,yCAA2C;AAE3C,yCAA4D;AAY5D,MAAa,WAAW;IACd,GAAG,GAAG,IAAI,GAAG,EAAgD,CAAC;IAEtE,SAAS,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,SAAS,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,qBAAqB,CAAC,GAAW,EAAE,MAAmB;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAEnC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,+CAA+C,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEhB,0EAA0E;QAC1E,wDAAwD;QACxD,oEAAoE;QACpE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QAEpB,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpC,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,sBAAsB,CAAC,GAAW,EAAE,KAAgB;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,YAAY,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,CAAC,KAAK,GAAG,IAAA,4BAAiB,EAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAErD,OAAO,MAAsB,CAAC;IAChC,CAAC;IAED,kBAAkB,CAAC,GAAW,EAAE,GAA4B;QAC1D,MAAM,MAAM,GAA0B;YACpC,GAAG;YACH,MAAM,EAAE,IAAA,kBAAM,EAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;YACtC,KAAK,EAAE,IAAI,GAAG,EAAE;YAChB,KAAK,EAAE,SAAS;YAChB,UAAU,EAAE,SAAS;SACtB,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAE1B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,SAAS,CAAC,GAAW,EAAE,GAA4B,EAAE,KAAgB,EAAE,UAAwB;QAC7F,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE/B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAE3C,MAAM,CAAC,KAAK,GAAG,IAAA,4BAAiB,EAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAA,sBAAW,EAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YACvD,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAE/B,OAAO,MAAsB,CAAC;IAChC,CAAC;CACF;AA3ED,kCA2EC"}
1
+ {"version":3,"file":"EntityMap.js","sourceRoot":"","sources":["../../src/EntityMap.ts"],"names":[],"mappings":";;;AAAA,yCAAoF;AAEpF,yCAA4D;AAgB5D,MAAa,WAAW;IACd,GAAG,GAAG,IAAI,GAAG,EAAgD,CAAC;IAC9D,WAAW,CAAc;IAEjC,YAAY,WAAwB;QAClC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED,SAAS,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,SAAS,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,qBAAqB,CAAC,GAAW,EAAE,MAAmB;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAEnC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,+CAA+C,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEhB,0EAA0E;QAC1E,wDAAwD;QACxD,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAE1B,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpC,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,sBAAsB,CAAC,GAAW,EAAE,KAAgB;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,YAAY,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAErD,OAAO,MAAsB,CAAC;IAChC,CAAC;IAED,kBAAkB,CAAC,GAAW,EAAE,IAA6B;QAC3D,MAAM,MAAM,GAA0B;YACpC,GAAG;YACH,IAAI;YACJ,QAAQ,EAAE,IAAA,oBAAQ,GAAE;YACpB,KAAK,EAAE,IAAI,GAAG,EAAE;YAChB,EAAE,EAAE,SAAS;YACb,KAAK,EAAE,SAAS;YAChB,UAAU,EAAE,SAAS;SACtB,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAE1B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,SAAS,CAAC,GAAW,EAAE,GAA4B,EAAE,KAAgB,EAAE,UAAwB;QAC7F,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE/B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAE3C,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,GAAG,IAAA,sBAAW,EAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5C,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACzB,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAE/B,OAAO,MAAsB,CAAC;IAChC,CAAC;IAEO,iBAAiB,CAAC,MAA6B,EAAE,KAAgB;QACvE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEhC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC;QAEf,IAAI,WAA8E,CAAC;QACnF,MAAM,YAAY,GAAI,KAA0C,CAAC,aAAa,CAAC;QAE/E,IAAI,YAAY,EAAE,MAAM,EAAE,CAAC;YACzB,WAAW,GAAG,IAAA,iBAAK,EAAC,KAAK,CAAC,EAAE;gBAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;gBAC9C,MAAM,QAAQ,GAAG,CAAC,MAAwC,EAAE,EAAE;oBAC5D,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;oBACjC,MAAM,MAAM,GAAG,IAAA,sBAAW,EAAC,YAAY,EAAE,MAAM,CAAC,CAAC;oBACjD,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC;oBACrB,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;oBACzB,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACvB,CAAC,CAAC;gBAEF,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,EAAqB,EAAE,QAAe,CAAC,CAAC;gBAEnG,mEAAmE;gBACnE,iFAAiF;gBACjF,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,KAAM,CAAC;gBAE5B,OAAO,WAAW,CAAC;YACrB,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,IAAA,4BAAiB,EAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACrF,CAAC;CACF;AA5HD,kCA4HC"}
@@ -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 = new EntityMap_js_1.EntityStore();
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
- this.store.activateQuery(def, queryKey);
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":"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"}
1
+ {"version":3,"file":"QueryClient.js","sourceRoot":"","sources":["../../src/QueryClient.ts"],"names":[],"mappings":"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"}
@@ -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
- wasOffline = false;
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.params };
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
- this.wasOffline = !isOnline;
339
+ const isPaused = this.isPaused;
340
+ this.wasPaused = isPaused;
338
341
  if (this.initialized) {
339
- // For any query with streams, resubscribe on reactivation
340
- if (this.def.type === "stream" /* QueryType.Stream */ ||
341
- this.def.stream) {
342
- this.setupSubscription();
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
- else if (this.isStale && !this.isPaused) {
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
- // For any query with streams, unsubscribe and resubscribe to re-establish connection
369
- if (this.def.type === "stream" /* QueryType.Stream */ ||
370
- this.def.stream) {
371
- this.setupSubscription();
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
- // Network status changed - check if we should react
378
- const currentlyOnline = networkManager.getOnlineSignal().value;
379
- // If we just came back online
380
- if (this.wasOffline && currentlyOnline) {
381
- const refreshStaleOnReconnect = this.def.cache?.refreshStaleOnReconnect ?? true;
382
- if (refreshStaleOnReconnect && this.isStale) {
383
- state.setPromise(this.runQuery(this.params, true));
384
- }
385
- // Reset attempt count on reconnect
386
- this.attemptCount = 0;
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 (this.streamUnsubscribe) {
399
- this.streamUnsubscribe();
400
- this.streamUnsubscribe = undefined;
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
- // Remove from refetch manager if configured
403
- if (this.def.type !== "stream" /* QueryType.Stream */ && this.def.cache?.refetchInterval) {
404
- this.queryClient.refetchManager.removeQuery(this);
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
- this.initialized = true;
494
- // Load from cache first
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.refetch();
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
- state.setPromise(this.runQuery(this.params, true));
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
- this.unsubscribe = subscribeFn(this.queryClient.getContext(), this.params, update => {
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
- this.queryClient.saveQueryData(this.def, this.queryKey, parsedData, this.updatedAt);
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
- this.queryClient.saveQueryData(this.def, this.queryKey, queryData, updatedAt, entityRefs, this.getExtraForPersistence());
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.params, true)
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
- this.queryClient.saveQueryData(this.def, this.queryKey, this.relayState.value, this.updatedAt, this.refIds, extra);
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)