@tanstack/db 0.5.32 → 0.6.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/dist/cjs/collection/change-events.cjs.map +1 -1
- package/dist/cjs/collection/change-events.d.cts +3 -2
- package/dist/cjs/collection/changes.cjs +13 -4
- package/dist/cjs/collection/changes.cjs.map +1 -1
- package/dist/cjs/collection/changes.d.cts +10 -1
- package/dist/cjs/collection/cleanup-queue.cjs +89 -0
- package/dist/cjs/collection/cleanup-queue.cjs.map +1 -0
- package/dist/cjs/collection/cleanup-queue.d.cts +30 -0
- package/dist/cjs/collection/events.cjs +14 -0
- package/dist/cjs/collection/events.cjs.map +1 -1
- package/dist/cjs/collection/events.d.cts +39 -1
- package/dist/cjs/collection/index.cjs +66 -28
- package/dist/cjs/collection/index.cjs.map +1 -1
- package/dist/cjs/collection/index.d.cts +49 -36
- package/dist/cjs/collection/indexes.cjs +211 -62
- package/dist/cjs/collection/indexes.cjs.map +1 -1
- package/dist/cjs/collection/indexes.d.cts +27 -17
- package/dist/cjs/collection/lifecycle.cjs +5 -22
- package/dist/cjs/collection/lifecycle.cjs.map +1 -1
- package/dist/cjs/collection/lifecycle.d.cts +0 -1
- package/dist/cjs/collection/mutations.cjs +18 -0
- package/dist/cjs/collection/mutations.cjs.map +1 -1
- package/dist/cjs/collection/mutations.d.cts +1 -0
- package/dist/cjs/collection/state.cjs +381 -53
- package/dist/cjs/collection/state.cjs.map +1 -1
- package/dist/cjs/collection/state.d.cts +65 -1
- package/dist/cjs/collection/subscription.cjs +6 -0
- package/dist/cjs/collection/subscription.cjs.map +1 -1
- package/dist/cjs/collection/subscription.d.cts +4 -0
- package/dist/cjs/collection/sync.cjs +108 -1
- package/dist/cjs/collection/sync.cjs.map +1 -1
- package/dist/cjs/collection/sync.d.cts +2 -0
- package/dist/cjs/collection/transaction-metadata.cjs +5 -0
- package/dist/cjs/collection/transaction-metadata.cjs.map +1 -0
- package/dist/cjs/collection/transaction-metadata.d.cts +1 -0
- package/dist/cjs/errors.cjs +8 -0
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/errors.d.cts +3 -0
- package/dist/cjs/index.cjs +24 -4
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +12 -3
- package/dist/cjs/indexes/auto-index.cjs +13 -6
- package/dist/cjs/indexes/auto-index.cjs.map +1 -1
- package/dist/cjs/indexes/base-index.cjs +0 -3
- package/dist/cjs/indexes/base-index.cjs.map +1 -1
- package/dist/cjs/indexes/base-index.d.cts +2 -6
- package/dist/cjs/indexes/basic-index.cjs +361 -0
- package/dist/cjs/indexes/basic-index.cjs.map +1 -0
- package/dist/cjs/indexes/basic-index.d.cts +102 -0
- package/dist/cjs/indexes/btree-index.cjs.map +1 -1
- package/dist/cjs/indexes/btree-index.d.cts +1 -1
- package/dist/cjs/indexes/index-options.d.cts +8 -9
- package/dist/cjs/indexes/index-registry.cjs +89 -0
- package/dist/cjs/indexes/index-registry.cjs.map +1 -0
- package/dist/cjs/indexes/index-registry.d.cts +61 -0
- package/dist/cjs/local-only.cjs +5 -0
- package/dist/cjs/local-only.cjs.map +1 -1
- package/dist/cjs/query/builder/functions.cjs +27 -11
- package/dist/cjs/query/builder/functions.cjs.map +1 -1
- package/dist/cjs/query/builder/functions.d.cts +25 -3
- package/dist/cjs/query/builder/index.cjs +200 -39
- package/dist/cjs/query/builder/index.cjs.map +1 -1
- package/dist/cjs/query/builder/index.d.cts +4 -3
- package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -1
- package/dist/cjs/query/builder/ref-proxy.d.cts +14 -3
- package/dist/cjs/query/builder/types.d.cts +84 -19
- package/dist/cjs/query/compiler/evaluators.cjs +51 -0
- package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
- package/dist/cjs/query/compiler/group-by.cjs +100 -28
- package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/group-by.d.cts +4 -2
- package/dist/cjs/query/compiler/index.cjs +283 -11
- package/dist/cjs/query/compiler/index.cjs.map +1 -1
- package/dist/cjs/query/compiler/index.d.cts +30 -2
- package/dist/cjs/query/compiler/order-by.cjs +29 -10
- package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.d.cts +1 -1
- package/dist/cjs/query/compiler/select.cjs +8 -0
- package/dist/cjs/query/compiler/select.cjs.map +1 -1
- package/dist/cjs/query/effect.cjs +602 -0
- package/dist/cjs/query/effect.cjs.map +1 -0
- package/dist/cjs/query/effect.d.cts +94 -0
- package/dist/cjs/query/index.d.cts +2 -1
- package/dist/cjs/query/ir.cjs +18 -1
- package/dist/cjs/query/ir.cjs.map +1 -1
- package/dist/cjs/query/ir.d.cts +21 -1
- package/dist/cjs/query/live/collection-config-builder.cjs +493 -66
- package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
- package/dist/cjs/query/live/collection-config-builder.d.cts +7 -0
- package/dist/cjs/query/live/collection-subscriber.cjs +33 -100
- package/dist/cjs/query/live/collection-subscriber.cjs.map +1 -1
- package/dist/cjs/query/live/collection-subscriber.d.cts +0 -1
- package/dist/cjs/query/live/types.d.cts +3 -3
- package/dist/cjs/query/live/utils.cjs +219 -0
- package/dist/cjs/query/live/utils.cjs.map +1 -0
- package/dist/cjs/query/live/utils.d.cts +110 -0
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/query/live-query-collection.d.cts +9 -6
- package/dist/cjs/query/query-once.cjs.map +1 -1
- package/dist/cjs/query/query-once.d.cts +7 -5
- package/dist/cjs/query/subset-dedupe.cjs +9 -3
- package/dist/cjs/query/subset-dedupe.cjs.map +1 -1
- package/dist/cjs/types.d.cts +42 -8
- package/dist/cjs/utils/array-utils.cjs +27 -0
- package/dist/cjs/utils/array-utils.cjs.map +1 -0
- package/dist/cjs/utils/array-utils.d.cts +16 -0
- package/dist/cjs/utils/comparison.cjs +11 -0
- package/dist/cjs/utils/comparison.cjs.map +1 -1
- package/dist/cjs/utils/index-optimization.cjs +4 -0
- package/dist/cjs/utils/index-optimization.cjs.map +1 -1
- package/dist/cjs/utils.cjs +7 -9
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +6 -1
- package/dist/cjs/virtual-props.cjs +33 -0
- package/dist/cjs/virtual-props.cjs.map +1 -0
- package/dist/cjs/virtual-props.d.cts +196 -0
- package/dist/esm/collection/change-events.d.ts +3 -2
- package/dist/esm/collection/change-events.js.map +1 -1
- package/dist/esm/collection/changes.d.ts +10 -1
- package/dist/esm/collection/changes.js +13 -4
- package/dist/esm/collection/changes.js.map +1 -1
- package/dist/esm/collection/cleanup-queue.d.ts +30 -0
- package/dist/esm/collection/cleanup-queue.js +89 -0
- package/dist/esm/collection/cleanup-queue.js.map +1 -0
- package/dist/esm/collection/events.d.ts +39 -1
- package/dist/esm/collection/events.js +14 -0
- package/dist/esm/collection/events.js.map +1 -1
- package/dist/esm/collection/index.d.ts +49 -36
- package/dist/esm/collection/index.js +67 -29
- package/dist/esm/collection/index.js.map +1 -1
- package/dist/esm/collection/indexes.d.ts +27 -17
- package/dist/esm/collection/indexes.js +211 -62
- package/dist/esm/collection/indexes.js.map +1 -1
- package/dist/esm/collection/lifecycle.d.ts +0 -1
- package/dist/esm/collection/lifecycle.js +5 -22
- package/dist/esm/collection/lifecycle.js.map +1 -1
- package/dist/esm/collection/mutations.d.ts +1 -0
- package/dist/esm/collection/mutations.js +18 -0
- package/dist/esm/collection/mutations.js.map +1 -1
- package/dist/esm/collection/state.d.ts +65 -1
- package/dist/esm/collection/state.js +381 -53
- package/dist/esm/collection/state.js.map +1 -1
- package/dist/esm/collection/subscription.d.ts +4 -0
- package/dist/esm/collection/subscription.js +6 -0
- package/dist/esm/collection/subscription.js.map +1 -1
- package/dist/esm/collection/sync.d.ts +2 -0
- package/dist/esm/collection/sync.js +108 -1
- package/dist/esm/collection/sync.js.map +1 -1
- package/dist/esm/collection/transaction-metadata.d.ts +1 -0
- package/dist/esm/collection/transaction-metadata.js +5 -0
- package/dist/esm/collection/transaction-metadata.js.map +1 -0
- package/dist/esm/errors.d.ts +3 -0
- package/dist/esm/errors.js +8 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +12 -3
- package/dist/esm/index.js +27 -7
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/indexes/auto-index.js +13 -6
- package/dist/esm/indexes/auto-index.js.map +1 -1
- package/dist/esm/indexes/base-index.d.ts +2 -6
- package/dist/esm/indexes/base-index.js +1 -4
- package/dist/esm/indexes/base-index.js.map +1 -1
- package/dist/esm/indexes/basic-index.d.ts +102 -0
- package/dist/esm/indexes/basic-index.js +361 -0
- package/dist/esm/indexes/basic-index.js.map +1 -0
- package/dist/esm/indexes/btree-index.d.ts +1 -1
- package/dist/esm/indexes/btree-index.js.map +1 -1
- package/dist/esm/indexes/index-options.d.ts +8 -9
- package/dist/esm/indexes/index-registry.d.ts +61 -0
- package/dist/esm/indexes/index-registry.js +89 -0
- package/dist/esm/indexes/index-registry.js.map +1 -0
- package/dist/esm/local-only.js +5 -0
- package/dist/esm/local-only.js.map +1 -1
- package/dist/esm/query/builder/functions.d.ts +25 -3
- package/dist/esm/query/builder/functions.js +27 -11
- package/dist/esm/query/builder/functions.js.map +1 -1
- package/dist/esm/query/builder/index.d.ts +4 -3
- package/dist/esm/query/builder/index.js +201 -40
- package/dist/esm/query/builder/index.js.map +1 -1
- package/dist/esm/query/builder/ref-proxy.d.ts +14 -3
- package/dist/esm/query/builder/ref-proxy.js.map +1 -1
- package/dist/esm/query/builder/types.d.ts +84 -19
- package/dist/esm/query/compiler/evaluators.js +51 -0
- package/dist/esm/query/compiler/evaluators.js.map +1 -1
- package/dist/esm/query/compiler/group-by.d.ts +4 -2
- package/dist/esm/query/compiler/group-by.js +101 -29
- package/dist/esm/query/compiler/group-by.js.map +1 -1
- package/dist/esm/query/compiler/index.d.ts +30 -2
- package/dist/esm/query/compiler/index.js +285 -13
- package/dist/esm/query/compiler/index.js.map +1 -1
- package/dist/esm/query/compiler/order-by.d.ts +1 -1
- package/dist/esm/query/compiler/order-by.js +30 -11
- package/dist/esm/query/compiler/order-by.js.map +1 -1
- package/dist/esm/query/compiler/select.js +8 -0
- package/dist/esm/query/compiler/select.js.map +1 -1
- package/dist/esm/query/effect.d.ts +94 -0
- package/dist/esm/query/effect.js +602 -0
- package/dist/esm/query/effect.js.map +1 -0
- package/dist/esm/query/index.d.ts +2 -1
- package/dist/esm/query/ir.d.ts +21 -1
- package/dist/esm/query/ir.js +18 -1
- package/dist/esm/query/ir.js.map +1 -1
- package/dist/esm/query/live/collection-config-builder.d.ts +7 -0
- package/dist/esm/query/live/collection-config-builder.js +492 -65
- package/dist/esm/query/live/collection-config-builder.js.map +1 -1
- package/dist/esm/query/live/collection-subscriber.d.ts +0 -1
- package/dist/esm/query/live/collection-subscriber.js +31 -98
- package/dist/esm/query/live/collection-subscriber.js.map +1 -1
- package/dist/esm/query/live/types.d.ts +3 -3
- package/dist/esm/query/live/utils.d.ts +110 -0
- package/dist/esm/query/live/utils.js +219 -0
- package/dist/esm/query/live/utils.js.map +1 -0
- package/dist/esm/query/live-query-collection.d.ts +9 -6
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/query/query-once.d.ts +7 -5
- package/dist/esm/query/query-once.js.map +1 -1
- package/dist/esm/query/subset-dedupe.js +9 -3
- package/dist/esm/query/subset-dedupe.js.map +1 -1
- package/dist/esm/types.d.ts +42 -8
- package/dist/esm/utils/array-utils.d.ts +16 -0
- package/dist/esm/utils/array-utils.js +27 -0
- package/dist/esm/utils/array-utils.js.map +1 -0
- package/dist/esm/utils/comparison.js +11 -0
- package/dist/esm/utils/comparison.js.map +1 -1
- package/dist/esm/utils/index-optimization.js +4 -0
- package/dist/esm/utils/index-optimization.js.map +1 -1
- package/dist/esm/utils.d.ts +6 -1
- package/dist/esm/utils.js +7 -9
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/virtual-props.d.ts +196 -0
- package/dist/esm/virtual-props.js +33 -0
- package/dist/esm/virtual-props.js.map +1 -0
- package/package.json +2 -2
- package/skills/db-core/collection-setup/references/electric-adapter.md +1 -1
- package/src/collection/change-events.ts +13 -9
- package/src/collection/changes.ts +30 -7
- package/src/collection/cleanup-queue.ts +105 -0
- package/src/collection/events.ts +65 -0
- package/src/collection/index.ts +110 -45
- package/src/collection/indexes.ts +283 -76
- package/src/collection/lifecycle.ts +5 -26
- package/src/collection/mutations.ts +21 -0
- package/src/collection/state.ts +545 -71
- package/src/collection/subscription.ts +7 -0
- package/src/collection/sync.ts +137 -0
- package/src/collection/transaction-metadata.ts +1 -0
- package/src/errors.ts +9 -0
- package/src/index.ts +57 -3
- package/src/indexes/auto-index.ts +18 -8
- package/src/indexes/base-index.ts +2 -10
- package/src/indexes/basic-index.ts +507 -0
- package/src/indexes/btree-index.ts +1 -1
- package/src/indexes/index-options.ts +17 -37
- package/src/indexes/index-registry.ts +174 -0
- package/src/local-only.ts +7 -0
- package/src/query/builder/functions.ts +84 -7
- package/src/query/builder/index.ts +329 -9
- package/src/query/builder/ref-proxy.ts +22 -4
- package/src/query/builder/types.ts +257 -62
- package/src/query/compiler/evaluators.ts +57 -0
- package/src/query/compiler/group-by.ts +156 -35
- package/src/query/compiler/index.ts +445 -15
- package/src/query/compiler/order-by.ts +51 -12
- package/src/query/compiler/select.ts +9 -0
- package/src/query/effect.ts +1119 -0
- package/src/query/index.ts +7 -0
- package/src/query/ir.ts +23 -2
- package/src/query/live/collection-config-builder.ts +778 -104
- package/src/query/live/collection-subscriber.ts +40 -156
- package/src/query/live/types.ts +10 -4
- package/src/query/live/utils.ts +417 -0
- package/src/query/live-query-collection.ts +43 -18
- package/src/query/query-once.ts +31 -12
- package/src/query/subset-dedupe.ts +11 -7
- package/src/types.ts +49 -9
- package/src/utils/array-utils.ts +49 -0
- package/src/utils/comparison.ts +14 -0
- package/src/utils/index-optimization.ts +4 -0
- package/src/utils.ts +12 -9
- package/src/virtual-props.ts +282 -0
- package/dist/cjs/indexes/lazy-index.cjs +0 -190
- package/dist/cjs/indexes/lazy-index.cjs.map +0 -1
- package/dist/cjs/indexes/lazy-index.d.cts +0 -96
- package/dist/esm/indexes/lazy-index.d.ts +0 -96
- package/dist/esm/indexes/lazy-index.js +0 -190
- package/dist/esm/indexes/lazy-index.js.map +0 -1
- package/src/indexes/lazy-index.ts +0 -251
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const _CleanupQueue = class _CleanupQueue {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.tasks = /* @__PURE__ */ new Map();
|
|
4
|
+
this.timeoutId = null;
|
|
5
|
+
this.microtaskScheduled = false;
|
|
6
|
+
}
|
|
7
|
+
static getInstance() {
|
|
8
|
+
if (!_CleanupQueue.instance) {
|
|
9
|
+
_CleanupQueue.instance = new _CleanupQueue();
|
|
10
|
+
}
|
|
11
|
+
return _CleanupQueue.instance;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Queues a cleanup task and defers timeout selection to a microtask so
|
|
15
|
+
* multiple synchronous registrations can share one root timer.
|
|
16
|
+
*/
|
|
17
|
+
schedule(key, gcTime, callback) {
|
|
18
|
+
const executeAt = Date.now() + gcTime;
|
|
19
|
+
this.tasks.set(key, { executeAt, callback });
|
|
20
|
+
if (!this.microtaskScheduled) {
|
|
21
|
+
this.microtaskScheduled = true;
|
|
22
|
+
Promise.resolve().then(() => {
|
|
23
|
+
this.microtaskScheduled = false;
|
|
24
|
+
this.updateTimeout();
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
cancel(key) {
|
|
29
|
+
this.tasks.delete(key);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Keeps only one active timeout: whichever task is due next.
|
|
33
|
+
*/
|
|
34
|
+
updateTimeout() {
|
|
35
|
+
if (this.timeoutId !== null) {
|
|
36
|
+
clearTimeout(this.timeoutId);
|
|
37
|
+
this.timeoutId = null;
|
|
38
|
+
}
|
|
39
|
+
if (this.tasks.size === 0) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
let earliestTime = Infinity;
|
|
43
|
+
for (const task of this.tasks.values()) {
|
|
44
|
+
if (task.executeAt < earliestTime) {
|
|
45
|
+
earliestTime = task.executeAt;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const delay = Math.max(0, earliestTime - Date.now());
|
|
49
|
+
this.timeoutId = setTimeout(() => this.process(), delay);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Runs every task whose deadline has passed, then schedules the next wakeup
|
|
53
|
+
* if there is still pending work.
|
|
54
|
+
*/
|
|
55
|
+
process() {
|
|
56
|
+
this.timeoutId = null;
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
for (const [key, task] of this.tasks.entries()) {
|
|
59
|
+
if (now >= task.executeAt) {
|
|
60
|
+
this.tasks.delete(key);
|
|
61
|
+
try {
|
|
62
|
+
task.callback();
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error("Error in CleanupQueue task:", error);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (this.tasks.size > 0) {
|
|
69
|
+
this.updateTimeout();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resets the singleton instance for tests.
|
|
74
|
+
*/
|
|
75
|
+
static resetInstance() {
|
|
76
|
+
if (_CleanupQueue.instance) {
|
|
77
|
+
if (_CleanupQueue.instance.timeoutId !== null) {
|
|
78
|
+
clearTimeout(_CleanupQueue.instance.timeoutId);
|
|
79
|
+
}
|
|
80
|
+
_CleanupQueue.instance = null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
_CleanupQueue.instance = null;
|
|
85
|
+
let CleanupQueue = _CleanupQueue;
|
|
86
|
+
export {
|
|
87
|
+
CleanupQueue
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=cleanup-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup-queue.js","sources":["../../../src/collection/cleanup-queue.ts"],"sourcesContent":["type CleanupTask = {\n executeAt: number\n callback: () => void\n}\n\n/**\n * Batches many GC registrations behind a single shared timeout.\n */\nexport class CleanupQueue {\n private static instance: CleanupQueue | null = null\n\n private tasks: Map<unknown, CleanupTask> = new Map()\n\n private timeoutId: ReturnType<typeof setTimeout> | null = null\n private microtaskScheduled = false\n\n private constructor() {}\n\n public static getInstance(): CleanupQueue {\n if (!CleanupQueue.instance) {\n CleanupQueue.instance = new CleanupQueue()\n }\n return CleanupQueue.instance\n }\n\n /**\n * Queues a cleanup task and defers timeout selection to a microtask so\n * multiple synchronous registrations can share one root timer.\n */\n public schedule(key: unknown, gcTime: number, callback: () => void): void {\n const executeAt = Date.now() + gcTime\n this.tasks.set(key, { executeAt, callback })\n\n if (!this.microtaskScheduled) {\n this.microtaskScheduled = true\n Promise.resolve().then(() => {\n this.microtaskScheduled = false\n this.updateTimeout()\n })\n }\n }\n\n public cancel(key: unknown): void {\n this.tasks.delete(key)\n }\n\n /**\n * Keeps only one active timeout: whichever task is due next.\n */\n private updateTimeout(): void {\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n\n if (this.tasks.size === 0) {\n return\n }\n\n let earliestTime = Infinity\n for (const task of this.tasks.values()) {\n if (task.executeAt < earliestTime) {\n earliestTime = task.executeAt\n }\n }\n\n const delay = Math.max(0, earliestTime - Date.now())\n this.timeoutId = setTimeout(() => this.process(), delay)\n }\n\n /**\n * Runs every task whose deadline has passed, then schedules the next wakeup\n * if there is still pending work.\n */\n private process(): void {\n this.timeoutId = null\n const now = Date.now()\n for (const [key, task] of this.tasks.entries()) {\n if (now >= task.executeAt) {\n this.tasks.delete(key)\n try {\n task.callback()\n } catch (error) {\n console.error('Error in CleanupQueue task:', error)\n }\n }\n }\n\n if (this.tasks.size > 0) {\n this.updateTimeout()\n }\n }\n\n /**\n * Resets the singleton instance for tests.\n */\n public static resetInstance(): void {\n if (CleanupQueue.instance) {\n if (CleanupQueue.instance.timeoutId !== null) {\n clearTimeout(CleanupQueue.instance.timeoutId)\n }\n CleanupQueue.instance = null\n }\n }\n}\n"],"names":[],"mappings":"AAQO,MAAM,gBAAN,MAAM,cAAa;AAAA,EAQhB,cAAc;AALtB,SAAQ,4BAAuC,IAAA;AAE/C,SAAQ,YAAkD;AAC1D,SAAQ,qBAAqB;AAAA,EAEN;AAAA,EAEvB,OAAc,cAA4B;AACxC,QAAI,CAAC,cAAa,UAAU;AAC1B,oBAAa,WAAW,IAAI,cAAA;AAAA,IAC9B;AACA,WAAO,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,SAAS,KAAc,QAAgB,UAA4B;AACxE,UAAM,YAAY,KAAK,IAAA,IAAQ;AAC/B,SAAK,MAAM,IAAI,KAAK,EAAE,WAAW,UAAU;AAE3C,QAAI,CAAC,KAAK,oBAAoB;AAC5B,WAAK,qBAAqB;AAC1B,cAAQ,UAAU,KAAK,MAAM;AAC3B,aAAK,qBAAqB;AAC1B,aAAK,cAAA;AAAA,MACP,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEO,OAAO,KAAoB;AAChC,SAAK,MAAM,OAAO,GAAG;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAsB;AAC5B,QAAI,KAAK,cAAc,MAAM;AAC3B,mBAAa,KAAK,SAAS;AAC3B,WAAK,YAAY;AAAA,IACnB;AAEA,QAAI,KAAK,MAAM,SAAS,GAAG;AACzB;AAAA,IACF;AAEA,QAAI,eAAe;AACnB,eAAW,QAAQ,KAAK,MAAM,OAAA,GAAU;AACtC,UAAI,KAAK,YAAY,cAAc;AACjC,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,IAAI,GAAG,eAAe,KAAK,KAAK;AACnD,SAAK,YAAY,WAAW,MAAM,KAAK,QAAA,GAAW,KAAK;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAgB;AACtB,SAAK,YAAY;AACjB,UAAM,MAAM,KAAK,IAAA;AACjB,eAAW,CAAC,KAAK,IAAI,KAAK,KAAK,MAAM,WAAW;AAC9C,UAAI,OAAO,KAAK,WAAW;AACzB,aAAK,MAAM,OAAO,GAAG;AACrB,YAAI;AACF,eAAK,SAAA;AAAA,QACP,SAAS,OAAO;AACd,kBAAQ,MAAM,+BAA+B,KAAK;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,MAAM,OAAO,GAAG;AACvB,WAAK,cAAA;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,gBAAsB;AAClC,QAAI,cAAa,UAAU;AACzB,UAAI,cAAa,SAAS,cAAc,MAAM;AAC5C,qBAAa,cAAa,SAAS,SAAS;AAAA,MAC9C;AACA,oBAAa,WAAW;AAAA,IAC1B;AAAA,EACF;AACF;AA/FE,cAAe,WAAgC;AAD1C,IAAM,eAAN;"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from '../event-emitter.js';
|
|
2
2
|
import { Collection } from './index.js';
|
|
3
3
|
import { CollectionStatus } from '../types.js';
|
|
4
|
+
import { BasicExpression } from '../query/ir.js';
|
|
4
5
|
/**
|
|
5
6
|
* Event emitted when the collection status changes
|
|
6
7
|
*/
|
|
@@ -45,15 +46,50 @@ export interface CollectionTruncateEvent {
|
|
|
45
46
|
type: `truncate`;
|
|
46
47
|
collection: Collection<any, any, any, any, any>;
|
|
47
48
|
}
|
|
49
|
+
export type CollectionIndexSerializableValue = string | number | boolean | null | Array<CollectionIndexSerializableValue> | {
|
|
50
|
+
[key: string]: CollectionIndexSerializableValue;
|
|
51
|
+
};
|
|
52
|
+
export interface CollectionIndexResolverMetadata {
|
|
53
|
+
kind: `constructor` | `async`;
|
|
54
|
+
name?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface CollectionIndexMetadata {
|
|
57
|
+
/**
|
|
58
|
+
* Version for the signature serialization contract.
|
|
59
|
+
*/
|
|
60
|
+
signatureVersion: 1;
|
|
61
|
+
/**
|
|
62
|
+
* Stable signature derived from expression + serializable options.
|
|
63
|
+
* Non-serializable option fields are intentionally omitted.
|
|
64
|
+
*/
|
|
65
|
+
signature: string;
|
|
66
|
+
indexId: number;
|
|
67
|
+
name?: string;
|
|
68
|
+
expression: BasicExpression;
|
|
69
|
+
resolver: CollectionIndexResolverMetadata;
|
|
70
|
+
options?: CollectionIndexSerializableValue;
|
|
71
|
+
}
|
|
72
|
+
export interface CollectionIndexAddedEvent {
|
|
73
|
+
type: `index:added`;
|
|
74
|
+
collection: Collection<any, any, any, any, any>;
|
|
75
|
+
index: CollectionIndexMetadata;
|
|
76
|
+
}
|
|
77
|
+
export interface CollectionIndexRemovedEvent {
|
|
78
|
+
type: `index:removed`;
|
|
79
|
+
collection: Collection<any, any, any, any, any>;
|
|
80
|
+
index: CollectionIndexMetadata;
|
|
81
|
+
}
|
|
48
82
|
export type AllCollectionEvents = {
|
|
49
83
|
'status:change': CollectionStatusChangeEvent;
|
|
50
84
|
'subscribers:change': CollectionSubscribersChangeEvent;
|
|
51
85
|
'loadingSubset:change': CollectionLoadingSubsetChangeEvent;
|
|
52
86
|
truncate: CollectionTruncateEvent;
|
|
87
|
+
'index:added': CollectionIndexAddedEvent;
|
|
88
|
+
'index:removed': CollectionIndexRemovedEvent;
|
|
53
89
|
} & {
|
|
54
90
|
[K in CollectionStatus as `status:${K}`]: CollectionStatusEvent<K>;
|
|
55
91
|
};
|
|
56
|
-
export type CollectionEvent = AllCollectionEvents[keyof AllCollectionEvents] | CollectionStatusChangeEvent | CollectionSubscribersChangeEvent | CollectionLoadingSubsetChangeEvent | CollectionTruncateEvent;
|
|
92
|
+
export type CollectionEvent = AllCollectionEvents[keyof AllCollectionEvents] | CollectionStatusChangeEvent | CollectionSubscribersChangeEvent | CollectionLoadingSubsetChangeEvent | CollectionTruncateEvent | CollectionIndexAddedEvent | CollectionIndexRemovedEvent;
|
|
57
93
|
export type CollectionEventHandler<T extends keyof AllCollectionEvents> = (event: AllCollectionEvents[T]) => void;
|
|
58
94
|
export declare class CollectionEventsManager extends EventEmitter<AllCollectionEvents> {
|
|
59
95
|
private collection;
|
|
@@ -68,5 +104,7 @@ export declare class CollectionEventsManager extends EventEmitter<AllCollectionE
|
|
|
68
104
|
emit<T extends keyof AllCollectionEvents>(event: T, eventPayload: AllCollectionEvents[T]): void;
|
|
69
105
|
emitStatusChange<T extends CollectionStatus>(status: T, previousStatus: CollectionStatus): void;
|
|
70
106
|
emitSubscribersChange(subscriberCount: number, previousSubscriberCount: number): void;
|
|
107
|
+
emitIndexAdded(index: CollectionIndexMetadata): void;
|
|
108
|
+
emitIndexRemoved(index: CollectionIndexMetadata): void;
|
|
71
109
|
cleanup(): void;
|
|
72
110
|
}
|
|
@@ -36,6 +36,20 @@ class CollectionEventsManager extends EventEmitter {
|
|
|
36
36
|
subscriberCount
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
|
+
emitIndexAdded(index) {
|
|
40
|
+
this.emit(`index:added`, {
|
|
41
|
+
type: `index:added`,
|
|
42
|
+
collection: this.collection,
|
|
43
|
+
index
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
emitIndexRemoved(index) {
|
|
47
|
+
this.emit(`index:removed`, {
|
|
48
|
+
type: `index:removed`,
|
|
49
|
+
collection: this.collection,
|
|
50
|
+
index
|
|
51
|
+
});
|
|
52
|
+
}
|
|
39
53
|
cleanup() {
|
|
40
54
|
this.clearListeners();
|
|
41
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sources":["../../../src/collection/events.ts"],"sourcesContent":["import { EventEmitter } from '../event-emitter.js'\nimport type { Collection } from './index.js'\nimport type { CollectionStatus } from '../types.js'\n\n/**\n * Event emitted when the collection status changes\n */\nexport interface CollectionStatusChangeEvent {\n type: `status:change`\n collection: Collection\n previousStatus: CollectionStatus\n status: CollectionStatus\n}\n\n/**\n * Event emitted when the collection status changes to a specific status\n */\nexport interface CollectionStatusEvent<T extends CollectionStatus> {\n type: `status:${T}`\n collection: Collection\n previousStatus: CollectionStatus\n status: T\n}\n\n/**\n * Event emitted when the number of subscribers to the collection changes\n */\nexport interface CollectionSubscribersChangeEvent {\n type: `subscribers:change`\n collection: Collection\n previousSubscriberCount: number\n subscriberCount: number\n}\n\n/**\n * Event emitted when the collection's loading more state changes\n */\nexport interface CollectionLoadingSubsetChangeEvent {\n type: `loadingSubset:change`\n collection: Collection<any, any, any, any, any>\n isLoadingSubset: boolean\n previousIsLoadingSubset: boolean\n loadingSubsetTransition: `start` | `end`\n}\n\n/**\n * Event emitted when the collection is truncated (all data cleared)\n */\nexport interface CollectionTruncateEvent {\n type: `truncate`\n collection: Collection<any, any, any, any, any>\n}\n\nexport type AllCollectionEvents = {\n 'status:change': CollectionStatusChangeEvent\n 'subscribers:change': CollectionSubscribersChangeEvent\n 'loadingSubset:change': CollectionLoadingSubsetChangeEvent\n truncate: CollectionTruncateEvent\n} & {\n [K in CollectionStatus as `status:${K}`]: CollectionStatusEvent<K>\n}\n\nexport type CollectionEvent =\n | AllCollectionEvents[keyof AllCollectionEvents]\n | CollectionStatusChangeEvent\n | CollectionSubscribersChangeEvent\n | CollectionLoadingSubsetChangeEvent\n | CollectionTruncateEvent\n\nexport type CollectionEventHandler<T extends keyof AllCollectionEvents> = (\n event: AllCollectionEvents[T],\n) => void\n\nexport class CollectionEventsManager extends EventEmitter<AllCollectionEvents> {\n private collection!: Collection<any, any, any, any, any>\n\n constructor() {\n super()\n }\n\n setDeps(deps: { collection: Collection<any, any, any, any, any> }) {\n this.collection = deps.collection\n }\n\n /**\n * Emit an event to all listeners\n * Public API for emitting collection events\n */\n emit<T extends keyof AllCollectionEvents>(\n event: T,\n eventPayload: AllCollectionEvents[T],\n ): void {\n this.emitInner(event, eventPayload)\n }\n\n emitStatusChange<T extends CollectionStatus>(\n status: T,\n previousStatus: CollectionStatus,\n ) {\n this.emit(`status:change`, {\n type: `status:change`,\n collection: this.collection,\n previousStatus,\n status,\n })\n\n // Emit specific status event using type assertion\n const eventKey: `status:${T}` = `status:${status}`\n this.emit(eventKey, {\n type: eventKey,\n collection: this.collection,\n previousStatus,\n status,\n } as AllCollectionEvents[`status:${T}`])\n }\n\n emitSubscribersChange(\n subscriberCount: number,\n previousSubscriberCount: number,\n ) {\n this.emit(`subscribers:change`, {\n type: `subscribers:change`,\n collection: this.collection,\n previousSubscriberCount,\n subscriberCount,\n })\n }\n\n cleanup() {\n this.clearListeners()\n }\n}\n"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"events.js","sources":["../../../src/collection/events.ts"],"sourcesContent":["import { EventEmitter } from '../event-emitter.js'\nimport type { Collection } from './index.js'\nimport type { CollectionStatus } from '../types.js'\nimport type { BasicExpression } from '../query/ir.js'\n\n/**\n * Event emitted when the collection status changes\n */\nexport interface CollectionStatusChangeEvent {\n type: `status:change`\n collection: Collection\n previousStatus: CollectionStatus\n status: CollectionStatus\n}\n\n/**\n * Event emitted when the collection status changes to a specific status\n */\nexport interface CollectionStatusEvent<T extends CollectionStatus> {\n type: `status:${T}`\n collection: Collection\n previousStatus: CollectionStatus\n status: T\n}\n\n/**\n * Event emitted when the number of subscribers to the collection changes\n */\nexport interface CollectionSubscribersChangeEvent {\n type: `subscribers:change`\n collection: Collection\n previousSubscriberCount: number\n subscriberCount: number\n}\n\n/**\n * Event emitted when the collection's loading more state changes\n */\nexport interface CollectionLoadingSubsetChangeEvent {\n type: `loadingSubset:change`\n collection: Collection<any, any, any, any, any>\n isLoadingSubset: boolean\n previousIsLoadingSubset: boolean\n loadingSubsetTransition: `start` | `end`\n}\n\n/**\n * Event emitted when the collection is truncated (all data cleared)\n */\nexport interface CollectionTruncateEvent {\n type: `truncate`\n collection: Collection<any, any, any, any, any>\n}\n\nexport type CollectionIndexSerializableValue =\n | string\n | number\n | boolean\n | null\n | Array<CollectionIndexSerializableValue>\n | {\n [key: string]: CollectionIndexSerializableValue\n }\n\nexport interface CollectionIndexResolverMetadata {\n kind: `constructor` | `async`\n name?: string\n}\n\nexport interface CollectionIndexMetadata {\n /**\n * Version for the signature serialization contract.\n */\n signatureVersion: 1\n /**\n * Stable signature derived from expression + serializable options.\n * Non-serializable option fields are intentionally omitted.\n */\n signature: string\n indexId: number\n name?: string\n expression: BasicExpression\n resolver: CollectionIndexResolverMetadata\n options?: CollectionIndexSerializableValue\n}\n\nexport interface CollectionIndexAddedEvent {\n type: `index:added`\n collection: Collection<any, any, any, any, any>\n index: CollectionIndexMetadata\n}\n\nexport interface CollectionIndexRemovedEvent {\n type: `index:removed`\n collection: Collection<any, any, any, any, any>\n index: CollectionIndexMetadata\n}\n\nexport type AllCollectionEvents = {\n 'status:change': CollectionStatusChangeEvent\n 'subscribers:change': CollectionSubscribersChangeEvent\n 'loadingSubset:change': CollectionLoadingSubsetChangeEvent\n truncate: CollectionTruncateEvent\n 'index:added': CollectionIndexAddedEvent\n 'index:removed': CollectionIndexRemovedEvent\n} & {\n [K in CollectionStatus as `status:${K}`]: CollectionStatusEvent<K>\n}\n\nexport type CollectionEvent =\n | AllCollectionEvents[keyof AllCollectionEvents]\n | CollectionStatusChangeEvent\n | CollectionSubscribersChangeEvent\n | CollectionLoadingSubsetChangeEvent\n | CollectionTruncateEvent\n | CollectionIndexAddedEvent\n | CollectionIndexRemovedEvent\n\nexport type CollectionEventHandler<T extends keyof AllCollectionEvents> = (\n event: AllCollectionEvents[T],\n) => void\n\nexport class CollectionEventsManager extends EventEmitter<AllCollectionEvents> {\n private collection!: Collection<any, any, any, any, any>\n\n constructor() {\n super()\n }\n\n setDeps(deps: { collection: Collection<any, any, any, any, any> }) {\n this.collection = deps.collection\n }\n\n /**\n * Emit an event to all listeners\n * Public API for emitting collection events\n */\n emit<T extends keyof AllCollectionEvents>(\n event: T,\n eventPayload: AllCollectionEvents[T],\n ): void {\n this.emitInner(event, eventPayload)\n }\n\n emitStatusChange<T extends CollectionStatus>(\n status: T,\n previousStatus: CollectionStatus,\n ) {\n this.emit(`status:change`, {\n type: `status:change`,\n collection: this.collection,\n previousStatus,\n status,\n })\n\n // Emit specific status event using type assertion\n const eventKey: `status:${T}` = `status:${status}`\n this.emit(eventKey, {\n type: eventKey,\n collection: this.collection,\n previousStatus,\n status,\n } as AllCollectionEvents[`status:${T}`])\n }\n\n emitSubscribersChange(\n subscriberCount: number,\n previousSubscriberCount: number,\n ) {\n this.emit(`subscribers:change`, {\n type: `subscribers:change`,\n collection: this.collection,\n previousSubscriberCount,\n subscriberCount,\n })\n }\n\n emitIndexAdded(index: CollectionIndexMetadata) {\n this.emit(`index:added`, {\n type: `index:added`,\n collection: this.collection,\n index,\n })\n }\n\n emitIndexRemoved(index: CollectionIndexMetadata) {\n this.emit(`index:removed`, {\n type: `index:removed`,\n collection: this.collection,\n index,\n })\n }\n\n cleanup() {\n this.clearListeners()\n }\n}\n"],"names":[],"mappings":";AA0HO,MAAM,gCAAgC,aAAkC;AAAA,EAG7E,cAAc;AACZ,UAAA;AAAA,EACF;AAAA,EAEA,QAAQ,MAA2D;AACjE,SAAK,aAAa,KAAK;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KACE,OACA,cACM;AACN,SAAK,UAAU,OAAO,YAAY;AAAA,EACpC;AAAA,EAEA,iBACE,QACA,gBACA;AACA,SAAK,KAAK,iBAAiB;AAAA,MACzB,MAAM;AAAA,MACN,YAAY,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,CACD;AAGD,UAAM,WAA0B,UAAU,MAAM;AAChD,SAAK,KAAK,UAAU;AAAA,MAClB,MAAM;AAAA,MACN,YAAY,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,CACqC;AAAA,EACzC;AAAA,EAEA,sBACE,iBACA,yBACA;AACA,SAAK,KAAK,sBAAsB;AAAA,MAC9B,MAAM;AAAA,MACN,YAAY,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EAEA,eAAe,OAAgC;AAC7C,SAAK,KAAK,eAAe;AAAA,MACvB,MAAM;AAAA,MACN,YAAY,KAAK;AAAA,MACjB;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EAEA,iBAAiB,OAAgC;AAC/C,SAAK,KAAK,iBAAiB;AAAA,MACzB,MAAM;AAAA,MACN,YAAY,KAAK;AAAA,MACjB;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EAEA,UAAU;AACR,SAAK,eAAA;AAAA,EACP;AACF;"}
|
|
@@ -2,14 +2,14 @@ import { CollectionStateManager } from './state.js';
|
|
|
2
2
|
import { CollectionLifecycleManager } from './lifecycle.js';
|
|
3
3
|
import { CollectionSyncManager } from './sync.js';
|
|
4
4
|
import { CollectionSubscription } from './subscription.js';
|
|
5
|
-
import { AllCollectionEvents, CollectionEventHandler } from './events.js';
|
|
6
|
-
import { BaseIndex,
|
|
5
|
+
import { AllCollectionEvents, CollectionEventHandler, CollectionIndexMetadata } from './events.js';
|
|
6
|
+
import { BaseIndex, IndexConstructor } from '../indexes/base-index.js';
|
|
7
7
|
import { IndexOptions } from '../indexes/index-options.js';
|
|
8
8
|
import { ChangeMessage, CollectionConfig, CollectionStatus, CurrentStateAsChangesOptions, Fn, InferSchemaInput, InferSchemaOutput, InsertConfig, NonSingleResult, OperationConfig, SingleResult, StringCollationConfig, SubscribeChangesOptions, Transaction as TransactionType, UtilsRecord, WritableDeep } from '../types.js';
|
|
9
9
|
import { SingleRowRefProxy } from '../query/builder/ref-proxy.js';
|
|
10
10
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
11
|
-
import {
|
|
12
|
-
|
|
11
|
+
import { WithVirtualProps } from '../virtual-props.js';
|
|
12
|
+
export type { CollectionIndexMetadata } from './events.js';
|
|
13
13
|
/**
|
|
14
14
|
* Enhanced Collection interface that includes both data type T and utilities TUtils
|
|
15
15
|
* @template T - The type of items in the collection
|
|
@@ -130,6 +130,12 @@ export declare class CollectionImpl<TOutput extends object = Record<string, unkn
|
|
|
130
130
|
private _indexes;
|
|
131
131
|
private _mutations;
|
|
132
132
|
_state: CollectionStateManager<TOutput, TKey, TSchema, TInput>;
|
|
133
|
+
/**
|
|
134
|
+
* When set, collection consumers should defer processing incoming data
|
|
135
|
+
* refreshes until this promise resolves. This prevents stale data from
|
|
136
|
+
* overwriting optimistic state while pending writes are being applied.
|
|
137
|
+
*/
|
|
138
|
+
deferDataRefresh: Promise<void> | null;
|
|
133
139
|
private comparisonOpts;
|
|
134
140
|
/**
|
|
135
141
|
* Creates a new Collection instance
|
|
@@ -188,7 +194,7 @@ export declare class CollectionImpl<TOutput extends object = Record<string, unkn
|
|
|
188
194
|
/**
|
|
189
195
|
* Get the current value for a key (virtual derived state)
|
|
190
196
|
*/
|
|
191
|
-
get(key: TKey): TOutput | undefined;
|
|
197
|
+
get(key: TKey): WithVirtualProps<TOutput, TKey> | undefined;
|
|
192
198
|
/**
|
|
193
199
|
* Check if a key exists in the collection (virtual derived state)
|
|
194
200
|
*/
|
|
@@ -204,58 +210,65 @@ export declare class CollectionImpl<TOutput extends object = Record<string, unkn
|
|
|
204
210
|
/**
|
|
205
211
|
* Get all values (virtual derived state)
|
|
206
212
|
*/
|
|
207
|
-
values(): IterableIterator<TOutput
|
|
213
|
+
values(): IterableIterator<WithVirtualProps<TOutput, TKey>>;
|
|
208
214
|
/**
|
|
209
215
|
* Get all entries (virtual derived state)
|
|
210
216
|
*/
|
|
211
|
-
entries(): IterableIterator<[TKey, TOutput]>;
|
|
217
|
+
entries(): IterableIterator<[TKey, WithVirtualProps<TOutput, TKey>]>;
|
|
212
218
|
/**
|
|
213
219
|
* Get all entries (virtual derived state)
|
|
214
220
|
*/
|
|
215
|
-
[Symbol.iterator](): IterableIterator<[
|
|
221
|
+
[Symbol.iterator](): IterableIterator<[
|
|
222
|
+
TKey,
|
|
223
|
+
WithVirtualProps<TOutput, TKey>
|
|
224
|
+
]>;
|
|
216
225
|
/**
|
|
217
226
|
* Execute a callback for each entry in the collection
|
|
218
227
|
*/
|
|
219
|
-
forEach(callbackfn: (value: TOutput, key: TKey, index: number) => void): void;
|
|
228
|
+
forEach(callbackfn: (value: WithVirtualProps<TOutput, TKey>, key: TKey, index: number) => void): void;
|
|
220
229
|
/**
|
|
221
230
|
* Create a new array with the results of calling a function for each entry in the collection
|
|
222
231
|
*/
|
|
223
|
-
map<U>(callbackfn: (value: TOutput, key: TKey, index: number) => U): Array<U>;
|
|
232
|
+
map<U>(callbackfn: (value: WithVirtualProps<TOutput, TKey>, key: TKey, index: number) => U): Array<U>;
|
|
224
233
|
getKeyFromItem(item: TOutput): TKey;
|
|
225
234
|
/**
|
|
226
235
|
* Creates an index on a collection for faster queries.
|
|
227
236
|
* Indexes significantly improve query performance by allowing constant time lookups
|
|
228
237
|
* and logarithmic time range queries instead of full scans.
|
|
229
238
|
*
|
|
230
|
-
* @template TResolver - The type of the index resolver (constructor or async loader)
|
|
231
239
|
* @param indexCallback - Function that extracts the indexed value from each item
|
|
232
240
|
* @param config - Configuration including index type and type-specific options
|
|
233
|
-
* @returns
|
|
241
|
+
* @returns The created index
|
|
234
242
|
*
|
|
235
243
|
* @example
|
|
236
|
-
*
|
|
237
|
-
*
|
|
244
|
+
* ```ts
|
|
245
|
+
* import { BasicIndex } from '@tanstack/db'
|
|
238
246
|
*
|
|
239
|
-
* // Create
|
|
247
|
+
* // Create an index with explicit type
|
|
240
248
|
* const ageIndex = collection.createIndex((row) => row.age, {
|
|
241
|
-
* indexType:
|
|
242
|
-
* options: {
|
|
243
|
-
* compareFn: customComparator,
|
|
244
|
-
* compareOptions: { direction: 'asc', nulls: 'first', stringSort: 'lexical' }
|
|
245
|
-
* },
|
|
246
|
-
* name: 'age_btree'
|
|
249
|
+
* indexType: BasicIndex
|
|
247
250
|
* })
|
|
248
251
|
*
|
|
249
|
-
* // Create an
|
|
250
|
-
* const
|
|
251
|
-
*
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
*
|
|
256
|
-
*
|
|
252
|
+
* // Create an index with collection's default type
|
|
253
|
+
* const nameIndex = collection.createIndex((row) => row.name)
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
createIndex<TIndexType extends IndexConstructor<TKey>>(indexCallback: (row: SingleRowRefProxy<TOutput>) => any, config?: IndexOptions<TIndexType>): BaseIndex<TKey>;
|
|
257
|
+
/**
|
|
258
|
+
* Removes an index created with createIndex.
|
|
259
|
+
* Returns true when an index existed and was removed.
|
|
260
|
+
*
|
|
261
|
+
* Best-effort semantics: removing an index guarantees it is detached from
|
|
262
|
+
* collection query planning. Existing index proxy references should be treated
|
|
263
|
+
* as invalid after removal.
|
|
264
|
+
*/
|
|
265
|
+
removeIndex(indexOrId: BaseIndex<TKey> | number): boolean;
|
|
266
|
+
/**
|
|
267
|
+
* Returns a snapshot of current index metadata sorted by indexId.
|
|
268
|
+
* Persistence wrappers can use this to bootstrap index state if indexes were
|
|
269
|
+
* created before event listeners were attached.
|
|
257
270
|
*/
|
|
258
|
-
|
|
271
|
+
getIndexMetadata(): Array<CollectionIndexMetadata>;
|
|
259
272
|
/**
|
|
260
273
|
* Get resolved indexes for query optimization
|
|
261
274
|
*/
|
|
@@ -392,27 +405,27 @@ export declare class CollectionImpl<TOutput extends object = Record<string, unkn
|
|
|
392
405
|
* console.log("Todo 1 exists:", itemsMap.get("todo-1"))
|
|
393
406
|
* }
|
|
394
407
|
*/
|
|
395
|
-
get state(): Map<TKey, TOutput
|
|
408
|
+
get state(): Map<TKey, WithVirtualProps<TOutput, TKey>>;
|
|
396
409
|
/**
|
|
397
410
|
* Gets the current state of the collection as a Map, but only resolves when data is available
|
|
398
411
|
* Waits for the first sync commit to complete before resolving
|
|
399
412
|
*
|
|
400
413
|
* @returns Promise that resolves to a Map containing all items in the collection
|
|
401
414
|
*/
|
|
402
|
-
stateWhenReady(): Promise<Map<TKey, TOutput
|
|
415
|
+
stateWhenReady(): Promise<Map<TKey, WithVirtualProps<TOutput, TKey>>>;
|
|
403
416
|
/**
|
|
404
417
|
* Gets the current state of the collection as an Array
|
|
405
418
|
*
|
|
406
419
|
* @returns An Array containing all items in the collection
|
|
407
420
|
*/
|
|
408
|
-
get toArray(): TOutput[];
|
|
421
|
+
get toArray(): WithVirtualProps<TOutput, TKey>[];
|
|
409
422
|
/**
|
|
410
423
|
* Gets the current state of the collection as an Array, but only resolves when data is available
|
|
411
424
|
* Waits for the first sync commit to complete before resolving
|
|
412
425
|
*
|
|
413
426
|
* @returns Promise that resolves to an Array containing all items in the collection
|
|
414
427
|
*/
|
|
415
|
-
toArrayWhenReady(): Promise<Array<TOutput
|
|
428
|
+
toArrayWhenReady(): Promise<Array<WithVirtualProps<TOutput, TKey>>>;
|
|
416
429
|
/**
|
|
417
430
|
* Returns the current state of the collection as an array of changes
|
|
418
431
|
* @param options - Options including optional where filter
|
|
@@ -431,7 +444,7 @@ export declare class CollectionImpl<TOutput extends object = Record<string, unkn
|
|
|
431
444
|
* whereExpression: eq(row.status, 'active')
|
|
432
445
|
* })
|
|
433
446
|
*/
|
|
434
|
-
currentStateAsChanges(options?: CurrentStateAsChangesOptions): Array<ChangeMessage<TOutput
|
|
447
|
+
currentStateAsChanges(options?: CurrentStateAsChangesOptions): Array<ChangeMessage<WithVirtualProps<TOutput, TKey>>> | void;
|
|
435
448
|
/**
|
|
436
449
|
* Subscribe to changes in the collection
|
|
437
450
|
* @param callback - Function called when items change
|
|
@@ -474,7 +487,7 @@ export declare class CollectionImpl<TOutput extends object = Record<string, unkn
|
|
|
474
487
|
* where: (row) => and(eq(row.status, "active"), gt(row.priority, 5))
|
|
475
488
|
* })
|
|
476
489
|
*/
|
|
477
|
-
subscribeChanges(callback: (changes: Array<ChangeMessage<TOutput
|
|
490
|
+
subscribeChanges(callback: (changes: Array<ChangeMessage<WithVirtualProps<TOutput, TKey>>>) => void, options?: SubscribeChangesOptions<TOutput, TKey>): CollectionSubscription;
|
|
478
491
|
/**
|
|
479
492
|
* Subscribe to a collection event
|
|
480
493
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CollectionRequiresConfigError, CollectionRequiresSyncConfigError } from "../errors.js";
|
|
1
|
+
import { CollectionRequiresConfigError, CollectionRequiresSyncConfigError, CollectionConfigurationError } from "../errors.js";
|
|
2
2
|
import { currentStateAsChanges } from "./change-events.js";
|
|
3
3
|
import { CollectionStateManager } from "./state.js";
|
|
4
4
|
import { CollectionChangesManager } from "./changes.js";
|
|
@@ -27,6 +27,7 @@ class CollectionImpl {
|
|
|
27
27
|
*/
|
|
28
28
|
constructor(config) {
|
|
29
29
|
this.utils = {};
|
|
30
|
+
this.deferDataRefresh = null;
|
|
30
31
|
this.insert = (data, config2) => {
|
|
31
32
|
return this._mutations.insert(data, config2);
|
|
32
33
|
};
|
|
@@ -46,8 +47,15 @@ class CollectionImpl {
|
|
|
46
47
|
}
|
|
47
48
|
this.config = {
|
|
48
49
|
...config,
|
|
49
|
-
autoIndex: config.autoIndex ?? `
|
|
50
|
+
autoIndex: config.autoIndex ?? `off`
|
|
50
51
|
};
|
|
52
|
+
if (this.config.autoIndex === `eager` && !config.defaultIndexType) {
|
|
53
|
+
throw new CollectionConfigurationError(
|
|
54
|
+
`autoIndex: 'eager' requires defaultIndexType to be set. Import an index type and set it:
|
|
55
|
+
import { BasicIndex } from '@tanstack/db'
|
|
56
|
+
createCollection({ defaultIndexType: BasicIndex, autoIndex: 'eager', ... })`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
51
59
|
this._changes = new CollectionChangesManager();
|
|
52
60
|
this._events = new CollectionEventsManager();
|
|
53
61
|
this._indexes = new CollectionIndexesManager();
|
|
@@ -61,7 +69,9 @@ class CollectionImpl {
|
|
|
61
69
|
// Required for passing to CollectionSubscription
|
|
62
70
|
lifecycle: this._lifecycle,
|
|
63
71
|
sync: this._sync,
|
|
64
|
-
events: this._events
|
|
72
|
+
events: this._events,
|
|
73
|
+
state: this._state
|
|
74
|
+
// Required for enriching changes with virtual properties
|
|
65
75
|
});
|
|
66
76
|
this._events.setDeps({
|
|
67
77
|
collection: this
|
|
@@ -69,7 +79,9 @@ class CollectionImpl {
|
|
|
69
79
|
});
|
|
70
80
|
this._indexes.setDeps({
|
|
71
81
|
state: this._state,
|
|
72
|
-
lifecycle: this._lifecycle
|
|
82
|
+
lifecycle: this._lifecycle,
|
|
83
|
+
defaultIndexType: config.defaultIndexType,
|
|
84
|
+
events: this._events
|
|
73
85
|
});
|
|
74
86
|
this._lifecycle.setDeps({
|
|
75
87
|
changes: this._changes,
|
|
@@ -168,7 +180,7 @@ class CollectionImpl {
|
|
|
168
180
|
* Get the current value for a key (virtual derived state)
|
|
169
181
|
*/
|
|
170
182
|
get(key) {
|
|
171
|
-
return this._state.
|
|
183
|
+
return this._state.getWithVirtualProps(key);
|
|
172
184
|
}
|
|
173
185
|
/**
|
|
174
186
|
* Check if a key exists in the collection (virtual derived state)
|
|
@@ -192,31 +204,49 @@ class CollectionImpl {
|
|
|
192
204
|
* Get all values (virtual derived state)
|
|
193
205
|
*/
|
|
194
206
|
*values() {
|
|
195
|
-
|
|
207
|
+
for (const key of this._state.keys()) {
|
|
208
|
+
const value = this.get(key);
|
|
209
|
+
if (value !== void 0) {
|
|
210
|
+
yield value;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
196
213
|
}
|
|
197
214
|
/**
|
|
198
215
|
* Get all entries (virtual derived state)
|
|
199
216
|
*/
|
|
200
217
|
*entries() {
|
|
201
|
-
|
|
218
|
+
for (const key of this._state.keys()) {
|
|
219
|
+
const value = this.get(key);
|
|
220
|
+
if (value !== void 0) {
|
|
221
|
+
yield [key, value];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
202
224
|
}
|
|
203
225
|
/**
|
|
204
226
|
* Get all entries (virtual derived state)
|
|
205
227
|
*/
|
|
206
228
|
*[Symbol.iterator]() {
|
|
207
|
-
yield* this.
|
|
229
|
+
yield* this.entries();
|
|
208
230
|
}
|
|
209
231
|
/**
|
|
210
232
|
* Execute a callback for each entry in the collection
|
|
211
233
|
*/
|
|
212
234
|
forEach(callbackfn) {
|
|
213
|
-
|
|
235
|
+
let index = 0;
|
|
236
|
+
for (const [key, value] of this.entries()) {
|
|
237
|
+
callbackfn(value, key, index++);
|
|
238
|
+
}
|
|
214
239
|
}
|
|
215
240
|
/**
|
|
216
241
|
* Create a new array with the results of calling a function for each entry in the collection
|
|
217
242
|
*/
|
|
218
243
|
map(callbackfn) {
|
|
219
|
-
|
|
244
|
+
const result = [];
|
|
245
|
+
let index = 0;
|
|
246
|
+
for (const [key, value] of this.entries()) {
|
|
247
|
+
result.push(callbackfn(value, key, index++));
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
220
250
|
}
|
|
221
251
|
getKeyFromItem(item) {
|
|
222
252
|
return this.config.getKey(item);
|
|
@@ -226,37 +256,45 @@ class CollectionImpl {
|
|
|
226
256
|
* Indexes significantly improve query performance by allowing constant time lookups
|
|
227
257
|
* and logarithmic time range queries instead of full scans.
|
|
228
258
|
*
|
|
229
|
-
* @template TResolver - The type of the index resolver (constructor or async loader)
|
|
230
259
|
* @param indexCallback - Function that extracts the indexed value from each item
|
|
231
260
|
* @param config - Configuration including index type and type-specific options
|
|
232
|
-
* @returns
|
|
261
|
+
* @returns The created index
|
|
233
262
|
*
|
|
234
263
|
* @example
|
|
235
|
-
*
|
|
236
|
-
*
|
|
264
|
+
* ```ts
|
|
265
|
+
* import { BasicIndex } from '@tanstack/db'
|
|
237
266
|
*
|
|
238
|
-
* // Create
|
|
267
|
+
* // Create an index with explicit type
|
|
239
268
|
* const ageIndex = collection.createIndex((row) => row.age, {
|
|
240
|
-
* indexType:
|
|
241
|
-
* options: {
|
|
242
|
-
* compareFn: customComparator,
|
|
243
|
-
* compareOptions: { direction: 'asc', nulls: 'first', stringSort: 'lexical' }
|
|
244
|
-
* },
|
|
245
|
-
* name: 'age_btree'
|
|
269
|
+
* indexType: BasicIndex
|
|
246
270
|
* })
|
|
247
271
|
*
|
|
248
|
-
* // Create an
|
|
249
|
-
* const
|
|
250
|
-
*
|
|
251
|
-
* const { FullTextIndex } = await import('./indexes/fulltext.js')
|
|
252
|
-
* return FullTextIndex
|
|
253
|
-
* },
|
|
254
|
-
* options: { language: 'en' }
|
|
255
|
-
* })
|
|
272
|
+
* // Create an index with collection's default type
|
|
273
|
+
* const nameIndex = collection.createIndex((row) => row.name)
|
|
274
|
+
* ```
|
|
256
275
|
*/
|
|
257
276
|
createIndex(indexCallback, config = {}) {
|
|
258
277
|
return this._indexes.createIndex(indexCallback, config);
|
|
259
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Removes an index created with createIndex.
|
|
281
|
+
* Returns true when an index existed and was removed.
|
|
282
|
+
*
|
|
283
|
+
* Best-effort semantics: removing an index guarantees it is detached from
|
|
284
|
+
* collection query planning. Existing index proxy references should be treated
|
|
285
|
+
* as invalid after removal.
|
|
286
|
+
*/
|
|
287
|
+
removeIndex(indexOrId) {
|
|
288
|
+
return this._indexes.removeIndex(indexOrId);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Returns a snapshot of current index metadata sorted by indexId.
|
|
292
|
+
* Persistence wrappers can use this to bootstrap index state if indexes were
|
|
293
|
+
* created before event listeners were attached.
|
|
294
|
+
*/
|
|
295
|
+
getIndexMetadata() {
|
|
296
|
+
return this._indexes.getIndexMetadataSnapshot();
|
|
297
|
+
}
|
|
260
298
|
/**
|
|
261
299
|
* Get resolved indexes for query optimization
|
|
262
300
|
*/
|