@signaldb/core 2.0.0-beta.6 → 2.0.0-beta.8
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/.vite/manifest.json +118 -84
- package/dist/AsyncDataAdapter.d.ts +4 -6
- package/dist/AutoFetchDataAdapter.d.ts +4 -6
- package/dist/Collection/Cursor.d.ts +3 -3
- package/dist/Collection/index.d.ts +8 -9
- package/dist/Collection/types.d.ts +2 -2
- package/dist/DataAdapter.d.ts +3 -4
- package/dist/DefaultDataAdapter.d.ts +3 -5
- package/dist/WorkerDataAdapter.d.ts +2 -4
- package/dist/WorkerDataAdapterHost.d.ts +5 -5
- package/dist/createIndex.d.ts +2 -2
- package/dist/createIndexProvider.d.ts +2 -2
- package/dist/createReactivityAdapter.d.ts +2 -2
- package/dist/createStorageAdapter.d.ts +1 -1
- package/dist/getIndexInfo.d.ts +3 -4
- package/dist/index.cjs.js +33 -34
- package/dist/index.mjs +17 -35
- package/dist/index10.cjs.js +23 -0
- package/dist/index10.mjs +21 -17
- package/dist/index11.cjs.js +45 -0
- package/dist/index11.mjs +44 -15
- package/dist/index12.cjs.js +22 -0
- package/dist/index12.mjs +21 -47
- package/dist/index13.cjs.js +45 -0
- package/dist/index13.mjs +44 -365
- package/dist/index14.cjs.js +86 -0
- package/dist/index14.mjs +85 -416
- package/dist/index15.cjs.js +15 -0
- package/dist/index15.mjs +14 -206
- package/dist/index16.cjs.js +136 -0
- package/dist/index16.mjs +135 -388
- package/dist/index17.cjs.js +47 -0
- package/dist/index17.mjs +45 -578
- package/dist/index18.cjs.js +15 -0
- package/dist/index18.mjs +14 -157
- package/dist/index19.cjs.js +23 -0
- package/dist/index19.mjs +22 -26
- package/dist/index2.cjs.js +33 -0
- package/dist/index2.mjs +32 -258
- package/dist/index20.cjs.js +37 -0
- package/dist/index20.mjs +36 -41
- package/dist/index21.cjs.js +35 -0
- package/dist/index21.mjs +34 -16
- package/dist/index22.cjs.js +25 -0
- package/dist/index22.mjs +24 -104
- package/dist/index23.cjs.js +19 -0
- package/dist/index23.mjs +18 -128
- package/dist/index24.cjs.js +342 -0
- package/dist/index24.mjs +340 -6
- package/dist/index25.cjs.js +519 -0
- package/dist/index25.mjs +518 -27
- package/dist/index26.cjs.js +11 -0
- package/dist/index26.mjs +10 -10
- package/dist/index27.cjs.js +11 -0
- package/dist/index27.mjs +10 -29
- package/dist/index28.cjs.js +90 -0
- package/dist/index28.mjs +88 -46
- package/dist/index29.cjs.js +370 -0
- package/dist/index29.mjs +369 -8
- package/dist/index3.cjs.js +19 -0
- package/dist/index3.mjs +18 -539
- package/dist/index30.cjs.js +72 -0
- package/dist/index30.mjs +71 -9
- package/dist/index31.cjs.js +191 -0
- package/dist/index31.mjs +190 -7
- package/dist/index32.cjs.js +21 -0
- package/dist/index32.mjs +20 -42
- package/dist/index33.cjs.js +336 -0
- package/dist/index33.mjs +335 -29
- package/dist/index34.cjs.js +539 -0
- package/dist/index34.mjs +537 -4
- package/dist/index4.cjs.js +150 -0
- package/dist/index4.mjs +149 -5
- package/dist/index5.cjs.js +254 -0
- package/dist/index5.mjs +252 -4
- package/dist/index6.cjs.js +125 -0
- package/dist/index6.mjs +124 -29
- package/dist/index7.cjs.js +33 -0
- package/dist/index7.mjs +32 -12
- package/dist/index8.cjs.js +12 -0
- package/dist/index8.mjs +10 -4
- package/dist/index9.cjs.js +11 -0
- package/dist/index9.mjs +10 -133
- package/dist/types/IndexProvider.d.ts +2 -2
- package/dist/types/Modifier.d.ts +1 -1
- package/dist/types/ReactivityAdapter.d.ts +1 -1
- package/dist/utils/createSignal.d.ts +2 -2
- package/dist/utils/getMatchingKeys.d.ts +2 -2
- package/dist/utils/isFieldExpression.d.ts +1 -1
- package/dist/utils/match.d.ts +1 -1
- package/dist/utils/modify.d.ts +1 -1
- package/dist/utils/queryId.d.ts +2 -2
- package/package.json +1 -1
- package/dist/index.cjs10.js +0 -18
- package/dist/index.cjs11.js +0 -15
- package/dist/index.cjs12.js +0 -48
- package/dist/index.cjs13.js +0 -365
- package/dist/index.cjs14.js +0 -416
- package/dist/index.cjs15.js +0 -206
- package/dist/index.cjs16.js +0 -388
- package/dist/index.cjs17.js +0 -579
- package/dist/index.cjs18.js +0 -157
- package/dist/index.cjs19.js +0 -26
- package/dist/index.cjs2.js +0 -259
- package/dist/index.cjs20.js +0 -42
- package/dist/index.cjs21.js +0 -16
- package/dist/index.cjs22.js +0 -104
- package/dist/index.cjs23.js +0 -129
- package/dist/index.cjs24.js +0 -7
- package/dist/index.cjs25.js +0 -27
- package/dist/index.cjs26.js +0 -10
- package/dist/index.cjs27.js +0 -29
- package/dist/index.cjs28.js +0 -46
- package/dist/index.cjs29.js +0 -8
- package/dist/index.cjs3.js +0 -540
- package/dist/index.cjs30.js +0 -9
- package/dist/index.cjs31.js +0 -7
- package/dist/index.cjs32.js +0 -42
- package/dist/index.cjs33.js +0 -29
- package/dist/index.cjs34.js +0 -5
- package/dist/index.cjs4.js +0 -5
- package/dist/index.cjs5.js +0 -5
- package/dist/index.cjs6.js +0 -29
- package/dist/index.cjs7.js +0 -12
- package/dist/index.cjs8.js +0 -5
- package/dist/index.cjs9.js +0 -133
package/dist/index30.mjs
CHANGED
|
@@ -1,10 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
//#region src/utils/batchOnNextTick.ts
|
|
2
|
+
/**
|
|
3
|
+
* Groups multiple calls by key and flushes them on the next tick (macrotask).
|
|
4
|
+
* @param onFlush - Function that will be called with the key and all queued items when flushing.
|
|
5
|
+
* @returns An object with `enqueue` and `flush` methods.
|
|
6
|
+
* @example
|
|
7
|
+
* const batcher = batchOnNextTick<string>(async (key, items) => {
|
|
8
|
+
* // items is an array of { args, resolve, reject }
|
|
9
|
+
* // do something once with all args...
|
|
10
|
+
* })
|
|
11
|
+
*
|
|
12
|
+
* batcher.enqueue("my-key", [arg1, arg2])
|
|
13
|
+
*/
|
|
14
|
+
function batchOnNextTick(onFlush) {
|
|
15
|
+
const queues = /* @__PURE__ */ new Map();
|
|
16
|
+
/**
|
|
17
|
+
* Enqueue a call with the given key and arguments.
|
|
18
|
+
* @param key key to group calls
|
|
19
|
+
* @param args arguments for the call
|
|
20
|
+
* @returns A promise that resolves or rejects when the call is flushed.
|
|
21
|
+
*/
|
|
22
|
+
function enqueue(key, args) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
let q = queues.get(key);
|
|
25
|
+
if (!q) {
|
|
26
|
+
q = {
|
|
27
|
+
timer: null,
|
|
28
|
+
items: [],
|
|
29
|
+
flush: () => flush(key)
|
|
30
|
+
};
|
|
31
|
+
queues.set(key, q);
|
|
32
|
+
}
|
|
33
|
+
q.items.push({
|
|
34
|
+
args,
|
|
35
|
+
resolve,
|
|
36
|
+
reject
|
|
37
|
+
});
|
|
38
|
+
if (q.timer == null) q.timer = setTimeout(() => {
|
|
39
|
+
q.timer = null;
|
|
40
|
+
q.flush();
|
|
41
|
+
}, 0);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Flush the queue for the given key immediately.
|
|
46
|
+
* @param key key to flush
|
|
47
|
+
* @returns A promise that resolves when the flush is complete.
|
|
48
|
+
*/
|
|
49
|
+
async function flush(key) {
|
|
50
|
+
const q = queues.get(key);
|
|
51
|
+
if (!q || q.items.length === 0) return;
|
|
52
|
+
if (q.timer != null) {
|
|
53
|
+
clearTimeout(q.timer);
|
|
54
|
+
q.timer = null;
|
|
55
|
+
}
|
|
56
|
+
const items = q.items.splice(0);
|
|
57
|
+
onFlush(key, items.map((i) => i.args)).then((results) => {
|
|
58
|
+
for (const [index, result] of results.entries()) {
|
|
59
|
+
const { resolve } = items[index];
|
|
60
|
+
resolve(result);
|
|
61
|
+
}
|
|
62
|
+
}).catch((error) => {
|
|
63
|
+
for (const { reject } of items) reject(error);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
enqueue,
|
|
68
|
+
flush
|
|
69
|
+
};
|
|
7
70
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
71
|
+
//#endregion
|
|
72
|
+
export { batchOnNextTick as default };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
const require_randomId = require("./index8.cjs.js");
|
|
2
|
+
const require_queryId = require("./index22.cjs.js");
|
|
3
|
+
const require_batchOnNextTick = require("./index30.cjs.js");
|
|
4
|
+
//#region src/WorkerDataAdapter.ts
|
|
5
|
+
var WorkerDataAdapter = class {
|
|
6
|
+
worker;
|
|
7
|
+
options;
|
|
8
|
+
id;
|
|
9
|
+
isDisposed = false;
|
|
10
|
+
workerReady;
|
|
11
|
+
log = () => {};
|
|
12
|
+
collectionReady = /* @__PURE__ */ new Map();
|
|
13
|
+
batchExecutionHelpers = /* @__PURE__ */ new Map();
|
|
14
|
+
queries = {};
|
|
15
|
+
constructor(worker, options) {
|
|
16
|
+
this.worker = worker;
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.id = this.options.id || "default-worker-data-adapter";
|
|
19
|
+
if (this.options.log) this.log = this.options.log;
|
|
20
|
+
this.workerReady = new Promise((resolve, reject) => {
|
|
21
|
+
const timeoutId = setTimeout(() => {
|
|
22
|
+
reject(/* @__PURE__ */ new Error("WorkerDataAdapter initialization timed out"));
|
|
23
|
+
}, 5e3);
|
|
24
|
+
const handleMessage = (event) => {
|
|
25
|
+
const { type, workerId } = event.data;
|
|
26
|
+
if (workerId !== this.id) return;
|
|
27
|
+
if (type === "ready") {
|
|
28
|
+
resolve();
|
|
29
|
+
clearTimeout(timeoutId);
|
|
30
|
+
this.worker.removeEventListener("message", handleMessage);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
this.worker.addEventListener("message", handleMessage);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async exec(method, collectionName, ...args) {
|
|
37
|
+
await this.workerReady;
|
|
38
|
+
if (method !== "isReady") {
|
|
39
|
+
const collectionReady = this.collectionReady.get(collectionName);
|
|
40
|
+
if (!collectionReady) throw new Error(`Collection "${collectionName}" is not registered in WorkerDataAdapter`);
|
|
41
|
+
await collectionReady;
|
|
42
|
+
}
|
|
43
|
+
if (this.isDisposed) throw new Error("WorkerDataAdapter is disposed");
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
const messageId = require_randomId.default();
|
|
46
|
+
const handleMessage = (event) => {
|
|
47
|
+
const { id, workerId, type, data, error } = event.data;
|
|
48
|
+
if (workerId !== this.id) return;
|
|
49
|
+
if (type !== "response") return;
|
|
50
|
+
if (id !== messageId) return;
|
|
51
|
+
this.log(method, "result", data ?? error);
|
|
52
|
+
if (error) reject(error);
|
|
53
|
+
else resolve(data);
|
|
54
|
+
this.worker.removeEventListener("message", handleMessage);
|
|
55
|
+
};
|
|
56
|
+
this.worker.addEventListener("message", handleMessage);
|
|
57
|
+
this.worker.postMessage({
|
|
58
|
+
id: messageId,
|
|
59
|
+
workerId: this.id,
|
|
60
|
+
method,
|
|
61
|
+
args: [collectionName, ...args]
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
enqueueBatched(collectionName, method, args) {
|
|
66
|
+
const helper = this.batchExecutionHelpers.get(collectionName);
|
|
67
|
+
if (!helper) throw new Error(`Collection "${collectionName}" is not registered in WorkerDataAdapter`);
|
|
68
|
+
return helper.enqueue(method, args);
|
|
69
|
+
}
|
|
70
|
+
updateQuery(collectionName, query, update) {
|
|
71
|
+
const id = require_queryId.default(query.selector, query.options);
|
|
72
|
+
const collectionQueries = this.queries[collectionName];
|
|
73
|
+
if (!collectionQueries) return;
|
|
74
|
+
const existing = collectionQueries.get(id);
|
|
75
|
+
const newState = {
|
|
76
|
+
state: "active",
|
|
77
|
+
error: null,
|
|
78
|
+
items: [],
|
|
79
|
+
stateChangeCallbacks: [],
|
|
80
|
+
eventHandler: existing?.eventHandler,
|
|
81
|
+
...existing,
|
|
82
|
+
...update
|
|
83
|
+
};
|
|
84
|
+
collectionQueries.set(id, newState);
|
|
85
|
+
this.queries[collectionName] = collectionQueries;
|
|
86
|
+
}
|
|
87
|
+
createCollectionBackend(collection, indices) {
|
|
88
|
+
this.queries[collection.name] = /* @__PURE__ */ new Map();
|
|
89
|
+
this.exec("registerCollection", collection.name, indices);
|
|
90
|
+
this.collectionReady.set(collection.name, this.exec("isReady", collection.name));
|
|
91
|
+
this.batchExecutionHelpers.set(collection.name, require_batchOnNextTick.default(async (method, args) => this.exec(method, collection.name, args)));
|
|
92
|
+
return {
|
|
93
|
+
insert: async (item) => {
|
|
94
|
+
return this.enqueueBatched(collection.name, "insert", [item]);
|
|
95
|
+
},
|
|
96
|
+
updateOne: async (selector, modifier) => {
|
|
97
|
+
return this.enqueueBatched(collection.name, "updateOne", [selector, modifier]);
|
|
98
|
+
},
|
|
99
|
+
updateMany: async (selector, modifier) => {
|
|
100
|
+
return this.enqueueBatched(collection.name, "updateMany", [selector, modifier]);
|
|
101
|
+
},
|
|
102
|
+
replaceOne: async (selector, replacement) => {
|
|
103
|
+
return this.enqueueBatched(collection.name, "replaceOne", [selector, replacement]);
|
|
104
|
+
},
|
|
105
|
+
removeOne: async (selector) => {
|
|
106
|
+
return this.enqueueBatched(collection.name, "removeOne", [selector]);
|
|
107
|
+
},
|
|
108
|
+
removeMany: async (selector) => {
|
|
109
|
+
return this.enqueueBatched(collection.name, "removeMany", [selector]);
|
|
110
|
+
},
|
|
111
|
+
registerQuery: (selector, options) => {
|
|
112
|
+
this.updateQuery(collection.name, {
|
|
113
|
+
selector,
|
|
114
|
+
options
|
|
115
|
+
}, {
|
|
116
|
+
state: "active",
|
|
117
|
+
error: null,
|
|
118
|
+
items: []
|
|
119
|
+
});
|
|
120
|
+
this.exec("registerQuery", collection.name, selector, options);
|
|
121
|
+
const handler = (event) => {
|
|
122
|
+
const { type, data, workerId, error } = event.data;
|
|
123
|
+
if (type !== "queryUpdate") return;
|
|
124
|
+
if (data == null) return;
|
|
125
|
+
const { collectionName, selector: responseSelector, options: responseOptions, state, items } = data;
|
|
126
|
+
if (workerId !== this.id) return;
|
|
127
|
+
if (collectionName !== collection.name) return;
|
|
128
|
+
if (require_queryId.default(responseSelector, responseOptions) !== require_queryId.default(selector, options)) return;
|
|
129
|
+
this.log("queryUpdate", responseSelector, responseOptions, state, data ?? error);
|
|
130
|
+
this.updateQuery(collection.name, {
|
|
131
|
+
selector: responseSelector,
|
|
132
|
+
options: responseOptions
|
|
133
|
+
}, {
|
|
134
|
+
state,
|
|
135
|
+
error,
|
|
136
|
+
items
|
|
137
|
+
});
|
|
138
|
+
const query = this.queries[collection.name]?.get(require_queryId.default(selector, options));
|
|
139
|
+
if (!query) return;
|
|
140
|
+
query.stateChangeCallbacks.forEach((callback) => callback(state));
|
|
141
|
+
};
|
|
142
|
+
this.worker.addEventListener("message", handler);
|
|
143
|
+
this.updateQuery(collection.name, {
|
|
144
|
+
selector,
|
|
145
|
+
options
|
|
146
|
+
}, { eventHandler: handler });
|
|
147
|
+
},
|
|
148
|
+
unregisterQuery: (selector, options) => {
|
|
149
|
+
const qid = require_queryId.default(selector, options);
|
|
150
|
+
const query = this.queries[collection.name]?.get(qid);
|
|
151
|
+
if (query?.eventHandler) this.worker.removeEventListener("message", query.eventHandler);
|
|
152
|
+
this.queries[collection.name]?.delete(qid);
|
|
153
|
+
this.exec("unregisterQuery", collection.name, selector, options);
|
|
154
|
+
},
|
|
155
|
+
getQueryState: (selector, options) => {
|
|
156
|
+
return (this.queries[collection.name]?.get(require_queryId.default(selector, options)))?.state || "active";
|
|
157
|
+
},
|
|
158
|
+
getQueryError: (selector, options) => {
|
|
159
|
+
return (this.queries[collection.name]?.get(require_queryId.default(selector, options)))?.error || null;
|
|
160
|
+
},
|
|
161
|
+
getQueryResult: (selector, options) => {
|
|
162
|
+
return (this.queries[collection.name]?.get(require_queryId.default(selector, options)))?.items || [];
|
|
163
|
+
},
|
|
164
|
+
onQueryStateChange: (selector, options, callback) => {
|
|
165
|
+
this.updateQuery(collection.name, {
|
|
166
|
+
selector,
|
|
167
|
+
options
|
|
168
|
+
}, { stateChangeCallbacks: [...this.queries[collection.name]?.get(require_queryId.default(selector, options))?.stateChangeCallbacks || [], callback] });
|
|
169
|
+
return () => {
|
|
170
|
+
const currentCallbacks = this.queries[collection.name]?.get(require_queryId.default(selector, options))?.stateChangeCallbacks;
|
|
171
|
+
if (!currentCallbacks) throw new Error("State change callbacks are not defined!");
|
|
172
|
+
this.updateQuery(collection.name, {
|
|
173
|
+
selector,
|
|
174
|
+
options
|
|
175
|
+
}, { stateChangeCallbacks: currentCallbacks.filter((existingCallback) => existingCallback !== callback) });
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
executeQuery: (selector, options) => this.exec("executeQuery", collection.name, selector, options),
|
|
179
|
+
dispose: async () => {
|
|
180
|
+
await this.exec("unregisterCollection", collection.name);
|
|
181
|
+
this.isDisposed = true;
|
|
182
|
+
this.worker.terminate();
|
|
183
|
+
},
|
|
184
|
+
isReady: async () => {
|
|
185
|
+
await this.exec("isReady", collection.name);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
//#endregion
|
|
191
|
+
exports.default = WorkerDataAdapter;
|
package/dist/index31.mjs
CHANGED
|
@@ -1,8 +1,191 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import randomId from "./index8.mjs";
|
|
2
|
+
import queryId from "./index22.mjs";
|
|
3
|
+
import batchOnNextTick from "./index30.mjs";
|
|
4
|
+
//#region src/WorkerDataAdapter.ts
|
|
5
|
+
var WorkerDataAdapter = class {
|
|
6
|
+
worker;
|
|
7
|
+
options;
|
|
8
|
+
id;
|
|
9
|
+
isDisposed = false;
|
|
10
|
+
workerReady;
|
|
11
|
+
log = () => {};
|
|
12
|
+
collectionReady = /* @__PURE__ */ new Map();
|
|
13
|
+
batchExecutionHelpers = /* @__PURE__ */ new Map();
|
|
14
|
+
queries = {};
|
|
15
|
+
constructor(worker, options) {
|
|
16
|
+
this.worker = worker;
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.id = this.options.id || "default-worker-data-adapter";
|
|
19
|
+
if (this.options.log) this.log = this.options.log;
|
|
20
|
+
this.workerReady = new Promise((resolve, reject) => {
|
|
21
|
+
const timeoutId = setTimeout(() => {
|
|
22
|
+
reject(/* @__PURE__ */ new Error("WorkerDataAdapter initialization timed out"));
|
|
23
|
+
}, 5e3);
|
|
24
|
+
const handleMessage = (event) => {
|
|
25
|
+
const { type, workerId } = event.data;
|
|
26
|
+
if (workerId !== this.id) return;
|
|
27
|
+
if (type === "ready") {
|
|
28
|
+
resolve();
|
|
29
|
+
clearTimeout(timeoutId);
|
|
30
|
+
this.worker.removeEventListener("message", handleMessage);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
this.worker.addEventListener("message", handleMessage);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async exec(method, collectionName, ...args) {
|
|
37
|
+
await this.workerReady;
|
|
38
|
+
if (method !== "isReady") {
|
|
39
|
+
const collectionReady = this.collectionReady.get(collectionName);
|
|
40
|
+
if (!collectionReady) throw new Error(`Collection "${collectionName}" is not registered in WorkerDataAdapter`);
|
|
41
|
+
await collectionReady;
|
|
42
|
+
}
|
|
43
|
+
if (this.isDisposed) throw new Error("WorkerDataAdapter is disposed");
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
const messageId = randomId();
|
|
46
|
+
const handleMessage = (event) => {
|
|
47
|
+
const { id, workerId, type, data, error } = event.data;
|
|
48
|
+
if (workerId !== this.id) return;
|
|
49
|
+
if (type !== "response") return;
|
|
50
|
+
if (id !== messageId) return;
|
|
51
|
+
this.log(method, "result", data ?? error);
|
|
52
|
+
if (error) reject(error);
|
|
53
|
+
else resolve(data);
|
|
54
|
+
this.worker.removeEventListener("message", handleMessage);
|
|
55
|
+
};
|
|
56
|
+
this.worker.addEventListener("message", handleMessage);
|
|
57
|
+
this.worker.postMessage({
|
|
58
|
+
id: messageId,
|
|
59
|
+
workerId: this.id,
|
|
60
|
+
method,
|
|
61
|
+
args: [collectionName, ...args]
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
enqueueBatched(collectionName, method, args) {
|
|
66
|
+
const helper = this.batchExecutionHelpers.get(collectionName);
|
|
67
|
+
if (!helper) throw new Error(`Collection "${collectionName}" is not registered in WorkerDataAdapter`);
|
|
68
|
+
return helper.enqueue(method, args);
|
|
69
|
+
}
|
|
70
|
+
updateQuery(collectionName, query, update) {
|
|
71
|
+
const id = queryId(query.selector, query.options);
|
|
72
|
+
const collectionQueries = this.queries[collectionName];
|
|
73
|
+
if (!collectionQueries) return;
|
|
74
|
+
const existing = collectionQueries.get(id);
|
|
75
|
+
const newState = {
|
|
76
|
+
state: "active",
|
|
77
|
+
error: null,
|
|
78
|
+
items: [],
|
|
79
|
+
stateChangeCallbacks: [],
|
|
80
|
+
eventHandler: existing?.eventHandler,
|
|
81
|
+
...existing,
|
|
82
|
+
...update
|
|
83
|
+
};
|
|
84
|
+
collectionQueries.set(id, newState);
|
|
85
|
+
this.queries[collectionName] = collectionQueries;
|
|
86
|
+
}
|
|
87
|
+
createCollectionBackend(collection, indices) {
|
|
88
|
+
this.queries[collection.name] = /* @__PURE__ */ new Map();
|
|
89
|
+
this.exec("registerCollection", collection.name, indices);
|
|
90
|
+
this.collectionReady.set(collection.name, this.exec("isReady", collection.name));
|
|
91
|
+
this.batchExecutionHelpers.set(collection.name, batchOnNextTick(async (method, args) => this.exec(method, collection.name, args)));
|
|
92
|
+
return {
|
|
93
|
+
insert: async (item) => {
|
|
94
|
+
return this.enqueueBatched(collection.name, "insert", [item]);
|
|
95
|
+
},
|
|
96
|
+
updateOne: async (selector, modifier) => {
|
|
97
|
+
return this.enqueueBatched(collection.name, "updateOne", [selector, modifier]);
|
|
98
|
+
},
|
|
99
|
+
updateMany: async (selector, modifier) => {
|
|
100
|
+
return this.enqueueBatched(collection.name, "updateMany", [selector, modifier]);
|
|
101
|
+
},
|
|
102
|
+
replaceOne: async (selector, replacement) => {
|
|
103
|
+
return this.enqueueBatched(collection.name, "replaceOne", [selector, replacement]);
|
|
104
|
+
},
|
|
105
|
+
removeOne: async (selector) => {
|
|
106
|
+
return this.enqueueBatched(collection.name, "removeOne", [selector]);
|
|
107
|
+
},
|
|
108
|
+
removeMany: async (selector) => {
|
|
109
|
+
return this.enqueueBatched(collection.name, "removeMany", [selector]);
|
|
110
|
+
},
|
|
111
|
+
registerQuery: (selector, options) => {
|
|
112
|
+
this.updateQuery(collection.name, {
|
|
113
|
+
selector,
|
|
114
|
+
options
|
|
115
|
+
}, {
|
|
116
|
+
state: "active",
|
|
117
|
+
error: null,
|
|
118
|
+
items: []
|
|
119
|
+
});
|
|
120
|
+
this.exec("registerQuery", collection.name, selector, options);
|
|
121
|
+
const handler = (event) => {
|
|
122
|
+
const { type, data, workerId, error } = event.data;
|
|
123
|
+
if (type !== "queryUpdate") return;
|
|
124
|
+
if (data == null) return;
|
|
125
|
+
const { collectionName, selector: responseSelector, options: responseOptions, state, items } = data;
|
|
126
|
+
if (workerId !== this.id) return;
|
|
127
|
+
if (collectionName !== collection.name) return;
|
|
128
|
+
if (queryId(responseSelector, responseOptions) !== queryId(selector, options)) return;
|
|
129
|
+
this.log("queryUpdate", responseSelector, responseOptions, state, data ?? error);
|
|
130
|
+
this.updateQuery(collection.name, {
|
|
131
|
+
selector: responseSelector,
|
|
132
|
+
options: responseOptions
|
|
133
|
+
}, {
|
|
134
|
+
state,
|
|
135
|
+
error,
|
|
136
|
+
items
|
|
137
|
+
});
|
|
138
|
+
const query = this.queries[collection.name]?.get(queryId(selector, options));
|
|
139
|
+
if (!query) return;
|
|
140
|
+
query.stateChangeCallbacks.forEach((callback) => callback(state));
|
|
141
|
+
};
|
|
142
|
+
this.worker.addEventListener("message", handler);
|
|
143
|
+
this.updateQuery(collection.name, {
|
|
144
|
+
selector,
|
|
145
|
+
options
|
|
146
|
+
}, { eventHandler: handler });
|
|
147
|
+
},
|
|
148
|
+
unregisterQuery: (selector, options) => {
|
|
149
|
+
const qid = queryId(selector, options);
|
|
150
|
+
const query = this.queries[collection.name]?.get(qid);
|
|
151
|
+
if (query?.eventHandler) this.worker.removeEventListener("message", query.eventHandler);
|
|
152
|
+
this.queries[collection.name]?.delete(qid);
|
|
153
|
+
this.exec("unregisterQuery", collection.name, selector, options);
|
|
154
|
+
},
|
|
155
|
+
getQueryState: (selector, options) => {
|
|
156
|
+
return (this.queries[collection.name]?.get(queryId(selector, options)))?.state || "active";
|
|
157
|
+
},
|
|
158
|
+
getQueryError: (selector, options) => {
|
|
159
|
+
return (this.queries[collection.name]?.get(queryId(selector, options)))?.error || null;
|
|
160
|
+
},
|
|
161
|
+
getQueryResult: (selector, options) => {
|
|
162
|
+
return (this.queries[collection.name]?.get(queryId(selector, options)))?.items || [];
|
|
163
|
+
},
|
|
164
|
+
onQueryStateChange: (selector, options, callback) => {
|
|
165
|
+
this.updateQuery(collection.name, {
|
|
166
|
+
selector,
|
|
167
|
+
options
|
|
168
|
+
}, { stateChangeCallbacks: [...this.queries[collection.name]?.get(queryId(selector, options))?.stateChangeCallbacks || [], callback] });
|
|
169
|
+
return () => {
|
|
170
|
+
const currentCallbacks = this.queries[collection.name]?.get(queryId(selector, options))?.stateChangeCallbacks;
|
|
171
|
+
if (!currentCallbacks) throw new Error("State change callbacks are not defined!");
|
|
172
|
+
this.updateQuery(collection.name, {
|
|
173
|
+
selector,
|
|
174
|
+
options
|
|
175
|
+
}, { stateChangeCallbacks: currentCallbacks.filter((existingCallback) => existingCallback !== callback) });
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
executeQuery: (selector, options) => this.exec("executeQuery", collection.name, selector, options),
|
|
179
|
+
dispose: async () => {
|
|
180
|
+
await this.exec("unregisterCollection", collection.name);
|
|
181
|
+
this.isDisposed = true;
|
|
182
|
+
this.worker.terminate();
|
|
183
|
+
},
|
|
184
|
+
isReady: async () => {
|
|
185
|
+
await this.exec("isReady", collection.name);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
8
189
|
};
|
|
190
|
+
//#endregion
|
|
191
|
+
export { WorkerDataAdapter as default };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/utils/compact.ts
|
|
2
|
+
/**
|
|
3
|
+
* Checks if a value is truthy.
|
|
4
|
+
* @template T - The type of the value.
|
|
5
|
+
* @param value - The value to check.
|
|
6
|
+
* @returns A boolean indicating if the value is truthy.
|
|
7
|
+
*/
|
|
8
|
+
function truthy(value) {
|
|
9
|
+
return !!value;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Filters out falsy values (`false`, `''`, `0`, `null`, `undefined`) from an array.
|
|
13
|
+
* @template T - The type of the elements in the array.
|
|
14
|
+
* @param array - The array to filter.
|
|
15
|
+
* @returns A new array containing only the truthy values from the input array.
|
|
16
|
+
*/
|
|
17
|
+
function compact(array) {
|
|
18
|
+
return array.filter(truthy);
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
exports.default = compact;
|
package/dist/index32.mjs
CHANGED
|
@@ -1,43 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"$exists",
|
|
11
|
-
"$not",
|
|
12
|
-
"$expr",
|
|
13
|
-
"$jsonSchema",
|
|
14
|
-
"$mod",
|
|
15
|
-
"$regex",
|
|
16
|
-
"$options",
|
|
17
|
-
"$text",
|
|
18
|
-
"$where",
|
|
19
|
-
"$all",
|
|
20
|
-
"$elemMatch",
|
|
21
|
-
"$size",
|
|
22
|
-
"$bitsAllClear",
|
|
23
|
-
"$bitsAllSet",
|
|
24
|
-
"$bitsAnyClear",
|
|
25
|
-
"$bitsAnySet"
|
|
26
|
-
]);
|
|
27
|
-
function isFieldExpression(expression) {
|
|
28
|
-
if (typeof expression !== "object" || expression == null) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
const keys = Object.keys(expression);
|
|
32
|
-
if (keys.length === 0) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
const hasInvalidKeys = keys.some((key) => !expressionKeys.has(key));
|
|
36
|
-
if (hasInvalidKeys)
|
|
37
|
-
return false;
|
|
38
|
-
const hasValidKeys = keys.every((key) => expressionKeys.has(key));
|
|
39
|
-
return hasValidKeys;
|
|
1
|
+
//#region src/utils/compact.ts
|
|
2
|
+
/**
|
|
3
|
+
* Checks if a value is truthy.
|
|
4
|
+
* @template T - The type of the value.
|
|
5
|
+
* @param value - The value to check.
|
|
6
|
+
* @returns A boolean indicating if the value is truthy.
|
|
7
|
+
*/
|
|
8
|
+
function truthy(value) {
|
|
9
|
+
return !!value;
|
|
40
10
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Filters out falsy values (`false`, `''`, `0`, `null`, `undefined`) from an array.
|
|
13
|
+
* @template T - The type of the elements in the array.
|
|
14
|
+
* @param array - The array to filter.
|
|
15
|
+
* @returns A new array containing only the truthy values from the input array.
|
|
16
|
+
*/
|
|
17
|
+
function compact(array) {
|
|
18
|
+
return array.filter(truthy);
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { compact as default };
|