@signaldb/core 2.0.0-beta.0 → 2.0.0-beta.1

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 (52) hide show
  1. package/dist/.vite/manifest.json +25 -12
  2. package/dist/AutoFetchDataAdapter.d.ts +0 -1
  3. package/dist/Collection/index.d.ts +2 -0
  4. package/dist/DataAdapter.d.ts +7 -6
  5. package/dist/DefaultDataAdapter.d.ts +1 -0
  6. package/dist/WorkerDataAdapter.d.ts +4 -1
  7. package/dist/WorkerDataAdapterHost.d.ts +9 -6
  8. package/dist/index.cjs12.js +32 -21
  9. package/dist/index.cjs13.js +25 -13
  10. package/dist/index.cjs14.js +31 -37
  11. package/dist/index.cjs15.js +120 -75
  12. package/dist/index.cjs16.js +45 -36
  13. package/dist/index.cjs17.js +1 -1
  14. package/dist/index.cjs2.js +5 -2
  15. package/dist/index.cjs20.js +5 -102
  16. package/dist/index.cjs21.js +93 -118
  17. package/dist/index.cjs22.js +127 -5
  18. package/dist/index.cjs23.js +5 -25
  19. package/dist/index.cjs24.js +25 -5
  20. package/dist/index.cjs26.js +1 -1
  21. package/dist/index.cjs27.js +44 -3
  22. package/dist/index.cjs28.js +6 -5
  23. package/dist/index.cjs29.js +7 -27
  24. package/dist/index.cjs3.js +25 -21
  25. package/dist/index.cjs30.js +3 -40
  26. package/dist/index.cjs31.js +5 -7
  27. package/dist/index.cjs32.js +29 -0
  28. package/dist/index.cjs33.js +42 -0
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index12.mjs +32 -21
  31. package/dist/index13.mjs +25 -13
  32. package/dist/index14.mjs +31 -37
  33. package/dist/index15.mjs +120 -75
  34. package/dist/index16.mjs +45 -36
  35. package/dist/index17.mjs +1 -1
  36. package/dist/index2.mjs +5 -2
  37. package/dist/index20.mjs +5 -102
  38. package/dist/index21.mjs +93 -117
  39. package/dist/index22.mjs +126 -5
  40. package/dist/index23.mjs +5 -25
  41. package/dist/index24.mjs +25 -5
  42. package/dist/index26.mjs +1 -1
  43. package/dist/index27.mjs +44 -3
  44. package/dist/index28.mjs +6 -5
  45. package/dist/index29.mjs +7 -27
  46. package/dist/index3.mjs +25 -21
  47. package/dist/index30.mjs +3 -40
  48. package/dist/index31.mjs +5 -7
  49. package/dist/index32.mjs +30 -0
  50. package/dist/index33.mjs +43 -0
  51. package/dist/utils/batchOnNextTick.d.ts +16 -0
  52. package/package.json +1 -1
@@ -1,17 +1,20 @@
1
1
  "use strict";
2
2
  const deepClone = require("./index.cjs19.js");
3
- const match = require("./index.cjs22.js");
3
+ const match = require("./index.cjs23.js");
4
4
  const modify = require("./index.cjs7.js");
5
- const queryId = require("./index.cjs24.js");
5
+ const queryId = require("./index.cjs20.js");
6
6
  const isEqual = require("./index.cjs6.js");
7
- const getIndexInfo = require("./index.cjs21.js");
7
+ const getIndexInfo = require("./index.cjs22.js");
8
8
  const getMatchingKeys = require("./index.cjs26.js");
9
9
  const sortItems = require("./index.cjs25.js");
10
- const project = require("./index.cjs23.js");
10
+ const project = require("./index.cjs24.js");
11
+ const compact = require("./index.cjs28.js");
11
12
  class WorkerDataAdapterHost {
12
13
  workerContext;
13
14
  options;
14
15
  id;
16
+ log = () => {
17
+ };
15
18
  storageAdapters = /* @__PURE__ */ new Map();
16
19
  storageAdapterReady = /* @__PURE__ */ new Map();
17
20
  collectionIndices = /* @__PURE__ */ new Map();
@@ -26,6 +29,8 @@ class WorkerDataAdapterHost {
26
29
  if (this.options.onError) {
27
30
  this.onError = this.options.onError;
28
31
  }
32
+ if (this.options.log)
33
+ this.log = this.options.log;
29
34
  if (typeof addEventListener === "undefined" || typeof postMessage === "undefined") {
30
35
  throw new TypeError("WorkerDataAdapterHost can only be used in a Web Worker context");
31
36
  }
@@ -50,6 +55,8 @@ class WorkerDataAdapterHost {
50
55
  this.respond(id, null, new Error(`Method ${method} not found`));
51
56
  return;
52
57
  }
58
+ this.log(method, ...args);
59
+ await this.isReady(args[0]);
53
60
  try {
54
61
  const result = await fn.apply(this, args);
55
62
  this.respond(id, result);
@@ -64,7 +71,7 @@ class WorkerDataAdapterHost {
64
71
  if (selector != null && Object.keys(selector).length === 1 && "id" in selector && typeof selector.id !== "object") {
65
72
  return {
66
73
  matched: true,
67
- ids: [selector.id],
74
+ ids: compact([selector.id]),
68
75
  optimizedSelector: {}
69
76
  };
70
77
  }
@@ -214,10 +221,7 @@ class WorkerDataAdapterHost {
214
221
  if (!storageAdapter)
215
222
  throw new Error(`No persistence adapter for collection ${collectionName}`);
216
223
  const setupPromise = (async () => {
217
- await Promise.all([
218
- storageAdapter.createIndex("id"),
219
- ...indices.map((index) => storageAdapter.createIndex(index))
220
- ]);
224
+ await Promise.all(indices.map((index) => storageAdapter.createIndex(index)));
221
225
  await storageAdapter.setup();
222
226
  })();
223
227
  this.storageAdapterReady.set(collectionName, setupPromise);
@@ -238,101 +242,142 @@ class WorkerDataAdapterHost {
238
242
  throw new Error(`Collection ${collectionName} not initialized!`);
239
243
  this.queries.get(collectionName)?.delete(id);
240
244
  };
241
- insert = async (collectionName, newItem) => {
242
- const storageAdapter = this.storageAdapters.get(collectionName);
243
- if (!storageAdapter)
244
- throw new Error(`No persistence adapter for collection ${collectionName}`);
245
- const existingItems = await this.executeQuery(collectionName, { id: newItem.id }, { limit: 1 });
246
- if (existingItems.length > 0) {
247
- throw new Error(`Item with id ${newItem.id} already exists`);
248
- }
249
- await storageAdapter.insert([newItem]);
250
- await this.checkQueryUpdates(collectionName, [newItem]);
251
- return newItem;
252
- };
253
- updateOne = async (collectionName, selector, modifier) => {
245
+ insert = async (collectionName, input) => {
254
246
  const storageAdapter = this.storageAdapters.get(collectionName);
255
247
  if (!storageAdapter)
256
248
  throw new Error(`No persistence adapter for collection ${collectionName}`);
257
- const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items) => items[0] ?? null);
258
- const { $setOnInsert, ...restModifier } = modifier;
259
- if (item == null)
260
- return [];
261
- const modifiedItem = modify(deepClone.default(item), restModifier);
262
- if (item.id !== modifiedItem.id) {
263
- const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
264
- if (existingItems.length > 0) {
265
- throw new Error(`Item with id ${modifiedItem.id} already exists`);
249
+ const existingItems = await this.executeQuery(collectionName, { id: { $in: input.map((i) => i[0].id) } });
250
+ const result = input.map(([item]) => {
251
+ if (item.id == null)
252
+ throw new Error("Item must have an id");
253
+ if (existingItems.some((existing) => existing.id === item.id)) {
254
+ return new Error(`Item with id ${item.id} already exists`);
266
255
  }
267
- }
268
- await storageAdapter.replace([modifiedItem]);
269
- await this.checkQueryUpdates(collectionName, [modifiedItem]);
270
- return [modifiedItem];
256
+ return item;
257
+ });
258
+ const newItems = result.filter((item) => !(item instanceof Error));
259
+ await storageAdapter.insert(newItems);
260
+ await this.checkQueryUpdates(collectionName, newItems);
261
+ return result;
271
262
  };
272
- updateMany = async (collectionName, selector, modifier) => {
263
+ updateOne = async (collectionName, parameters) => {
273
264
  const storageAdapter = this.storageAdapters.get(collectionName);
274
265
  if (!storageAdapter)
275
266
  throw new Error(`No persistence adapter for collection ${collectionName}`);
276
- const items = await this.executeQuery(collectionName, selector);
277
- if (items.length === 0)
278
- return [];
279
- const { $setOnInsert, ...restModifier } = modifier;
280
- const changedItems = await Promise.all(items.map(async (item) => {
267
+ const previousItems = [];
268
+ const result = await Promise.all(parameters.map(async ([selector, modifier]) => {
269
+ const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items) => items[0] ?? null);
270
+ const { $setOnInsert, ...restModifier } = modifier;
271
+ if (item == null)
272
+ return [];
273
+ previousItems.push(item);
281
274
  const modifiedItem = modify(deepClone.default(item), restModifier);
282
275
  if (item.id !== modifiedItem.id) {
283
276
  const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
284
277
  if (existingItems.length > 0) {
285
- throw new Error(`Item with id ${modifiedItem.id} already exists`);
278
+ return new Error(`Item with id ${modifiedItem.id} already exists`);
286
279
  }
287
280
  }
288
- return modifiedItem;
281
+ return [modifiedItem];
289
282
  }));
290
- await storageAdapter.replace(changedItems);
291
- await this.checkQueryUpdates(collectionName, changedItems);
292
- return changedItems;
283
+ const modifiedItems = compact(result.filter((item) => !(item instanceof Error)).flat());
284
+ if (modifiedItems.length > 0) {
285
+ await storageAdapter.replace(modifiedItems);
286
+ await this.checkQueryUpdates(collectionName, [...modifiedItems, ...previousItems]);
287
+ }
288
+ return result;
293
289
  };
294
- replaceOne = async (collectionName, selector, replacement) => {
290
+ updateMany = async (collectionName, parameters) => {
295
291
  const storageAdapter = this.storageAdapters.get(collectionName);
296
292
  if (!storageAdapter)
297
293
  throw new Error(`No persistence adapter for collection ${collectionName}`);
298
- const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items) => items[0] ?? null);
299
- if (item == null)
300
- return [];
301
- const modifiedItem = {
302
- ...replacement,
303
- id: replacement.id ?? item.id
304
- };
305
- if (item.id !== modifiedItem.id) {
306
- const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
307
- if (existingItems.length > 0) {
308
- throw new Error(`Item with id ${modifiedItem.id} already exists`);
294
+ const previousItems = [];
295
+ const result = await Promise.all(parameters.map(async ([selector, modifier]) => {
296
+ const items = await this.executeQuery(collectionName, selector);
297
+ if (items.length === 0)
298
+ return [];
299
+ const { $setOnInsert, ...restModifier } = modifier;
300
+ try {
301
+ const changedItems = await Promise.all(items.map(async (item) => {
302
+ const modifiedItem = modify(deepClone.default(item), restModifier);
303
+ if (item.id !== modifiedItem.id) {
304
+ const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
305
+ if (existingItems.length > 0) {
306
+ throw new Error(`Item with id ${modifiedItem.id} already exists`);
307
+ }
308
+ }
309
+ previousItems.push(item);
310
+ return modifiedItem;
311
+ }));
312
+ return changedItems;
313
+ } catch (error) {
314
+ return error;
315
+ }
316
+ }));
317
+ const modifiedItems = compact(result.filter((item) => !(item instanceof Error)).flat());
318
+ if (modifiedItems.length > 0) {
319
+ await storageAdapter.replace(modifiedItems);
320
+ await this.checkQueryUpdates(collectionName, [...modifiedItems, ...previousItems]);
321
+ }
322
+ return result;
323
+ };
324
+ replaceOne = async (collectionName, parameters) => {
325
+ const storageAdapter = this.storageAdapters.get(collectionName);
326
+ if (!storageAdapter)
327
+ throw new Error(`No persistence adapter for collection ${collectionName}`);
328
+ const previousItems = [];
329
+ const result = await Promise.all(parameters.map(async ([selector, replacement]) => {
330
+ const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items) => items[0] ?? null);
331
+ if (item == null)
332
+ return [];
333
+ previousItems.push(item);
334
+ const modifiedItem = {
335
+ ...replacement,
336
+ id: replacement.id ?? item.id
337
+ };
338
+ if (item.id !== modifiedItem.id) {
339
+ const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
340
+ if (existingItems.length > 0) {
341
+ return new Error(`Item with id ${modifiedItem.id} already exists`);
342
+ }
309
343
  }
344
+ return [modifiedItem];
345
+ }));
346
+ const modifiedItems = compact(result.filter((item) => !(item instanceof Error)).flat());
347
+ if (modifiedItems.length > 0) {
348
+ await storageAdapter.replace(modifiedItems);
349
+ await this.checkQueryUpdates(collectionName, [...modifiedItems, ...previousItems]);
310
350
  }
311
- await storageAdapter.replace([modifiedItem]);
312
- await this.checkQueryUpdates(collectionName, [modifiedItem]);
313
- return [modifiedItem];
351
+ return result;
314
352
  };
315
- removeOne = async (collectionName, selector) => {
353
+ removeOne = async (collectionName, selectors) => {
316
354
  const storageAdapter = this.storageAdapters.get(collectionName);
317
355
  if (!storageAdapter)
318
356
  throw new Error(`No persistence adapter for collection ${collectionName}`);
319
- const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items) => items[0] ?? null);
320
- if (item == null)
321
- return [];
322
- await storageAdapter.remove([item]);
323
- await this.checkQueryUpdates(collectionName, [item]);
324
- return [item];
357
+ const result = await Promise.all(selectors.map(async ([selector]) => {
358
+ const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items2) => items2[0] ?? null);
359
+ if (item == null)
360
+ return [];
361
+ return [item];
362
+ }));
363
+ const items = result.flat();
364
+ if (items.length > 0) {
365
+ await storageAdapter.remove(items);
366
+ await this.checkQueryUpdates(collectionName, items);
367
+ }
368
+ return result;
325
369
  };
326
- removeMany = async (collectionName, selector) => {
370
+ removeMany = async (collectionName, selectors) => {
327
371
  const storageAdapter = this.storageAdapters.get(collectionName);
328
372
  if (!storageAdapter)
329
373
  throw new Error(`No persistence adapter for collection ${collectionName}`);
330
- const items = await this.executeQuery(collectionName, selector);
331
- if (items.length === 0)
332
- return [];
333
- await storageAdapter.remove(items);
334
- await this.checkQueryUpdates(collectionName, items);
335
- return items;
374
+ const result = await Promise.all(selectors.map(async ([selector]) => this.executeQuery(collectionName, selector)));
375
+ const items = result.flat();
376
+ if (items.length > 0) {
377
+ await storageAdapter.remove(items);
378
+ await this.checkQueryUpdates(collectionName, items);
379
+ }
380
+ return result;
336
381
  };
337
382
  isReady = async (collectionName) => {
338
383
  return this.storageAdapterReady.get(collectionName);
@@ -1,16 +1,19 @@
1
1
  "use strict";
2
2
  const deepClone = require("./index.cjs19.js");
3
- const match = require("./index.cjs22.js");
3
+ const match = require("./index.cjs23.js");
4
4
  const modify = require("./index.cjs7.js");
5
- const queryId = require("./index.cjs24.js");
5
+ const queryId = require("./index.cjs20.js");
6
6
  const isEqual = require("./index.cjs6.js");
7
- const getIndexInfo = require("./index.cjs21.js");
7
+ const getIndexInfo = require("./index.cjs22.js");
8
8
  const getMatchingKeys = require("./index.cjs26.js");
9
9
  const sortItems = require("./index.cjs25.js");
10
- const project = require("./index.cjs23.js");
10
+ const project = require("./index.cjs24.js");
11
11
  function defaultMergeItems(a, b) {
12
12
  return { ...a, ...b };
13
13
  }
14
+ function selectorId(selector) {
15
+ return JSON.stringify(selector ?? {});
16
+ }
14
17
  class AutoFetchDataAdapter {
15
18
  options;
16
19
  id;
@@ -74,7 +77,7 @@ class AutoFetchDataAdapter {
74
77
  state: "active",
75
78
  error: null
76
79
  });
77
- const key = this.selectorKey(selector);
80
+ const key = selectorId(selector);
78
81
  const perColObservers = this.activeObservers.get(collection.name);
79
82
  const current = perColObservers?.get(key)?.count ?? 0;
80
83
  perColObservers?.set(key, { selector, count: current + 1 });
@@ -91,7 +94,7 @@ class AutoFetchDataAdapter {
91
94
  const qid = queryId(selector, options);
92
95
  const registry = this.queries.get(collection.name);
93
96
  registry?.delete(qid);
94
- const key = this.selectorKey(selector);
97
+ const key = selectorId(selector);
95
98
  const perColObservers = this.activeObservers.get(collection.name);
96
99
  const current = perColObservers?.get(key)?.count ?? 0;
97
100
  const remaining = Math.max(0, current - 1);
@@ -141,7 +144,9 @@ class AutoFetchDataAdapter {
141
144
  });
142
145
  }
143
146
  registry.get(qid)?.listeners.add(callback);
144
- return () => registry.get(qid)?.listeners.delete(callback);
147
+ return () => {
148
+ registry.get(qid)?.listeners.delete(callback);
149
+ };
145
150
  };
146
151
  return {
147
152
  insert: async (item) => {
@@ -175,6 +180,23 @@ class AutoFetchDataAdapter {
175
180
  getQueryError,
176
181
  getQueryResult,
177
182
  onQueryStateChange,
183
+ executeQuery: async (selector, options) => {
184
+ await ready;
185
+ registerQuery(selector, options);
186
+ await new Promise((resolve) => {
187
+ let stop = () => {
188
+ };
189
+ stop = onQueryStateChange(selector, options, (state) => {
190
+ if (state === "active")
191
+ return;
192
+ resolve();
193
+ stop();
194
+ });
195
+ });
196
+ const result = getQueryResult(selector, options);
197
+ unregisterQuery(selector, options);
198
+ return result;
199
+ },
178
200
  dispose: async () => {
179
201
  this.storageAdapters.delete(collection.name);
180
202
  this.queries.delete(collection.name);
@@ -192,9 +214,6 @@ class AutoFetchDataAdapter {
192
214
  };
193
215
  }
194
216
  // ===== Auto-fetch mechanics =====
195
- selectorKey(selector) {
196
- return JSON.stringify(selector ?? {});
197
- }
198
217
  async forceRefetchAll() {
199
218
  const tasks = [];
200
219
  for (const [collectionName, observers] of this.activeObservers.entries()) {
@@ -213,7 +232,7 @@ class AutoFetchDataAdapter {
213
232
  throw new Error("AutoFetchDataAdapter: fetchQueryItems must resolve to { items: T[] }");
214
233
  }
215
234
  const ids = items.map((i) => i.id);
216
- const selectorKey = this.selectorKey(selector);
235
+ const selectorKey = selectorId(selector);
217
236
  const selMap = this.selectorIds.get(collectionName);
218
237
  const previous = selMap?.get(selectorKey) ?? /* @__PURE__ */ new Set();
219
238
  ids.forEach((id) => previous.add(id));
@@ -226,7 +245,7 @@ class AutoFetchDataAdapter {
226
245
  }
227
246
  }
228
247
  async purgeSelector(collectionName, selector) {
229
- const selectorKey = this.selectorKey(selector);
248
+ const selectorKey = selectorId(selector);
230
249
  const selMap = this.selectorIds.get(collectionName);
231
250
  const ids = selMap?.get(selectorKey);
232
251
  selMap?.delete(selectorKey);
@@ -263,10 +282,7 @@ class AutoFetchDataAdapter {
263
282
  const storage = this.storageAdapters.get(collectionName);
264
283
  if (!storage)
265
284
  throw new Error(`No persistence adapter for collection ${collectionName}`);
266
- await Promise.all([
267
- storage.createIndex("id"),
268
- ...indices.map((field) => storage.createIndex(field))
269
- ]);
285
+ await Promise.all(indices.map((field) => storage.createIndex(field)));
270
286
  await storage.setup();
271
287
  }
272
288
  ensureStorageAdapter(name) {
@@ -284,24 +300,16 @@ class AutoFetchDataAdapter {
284
300
  for (const query of registry.values()) {
285
301
  if (!isEqual(query.selector, selector))
286
302
  continue;
287
- query.state = state;
288
- query.error = error;
289
- for (const callback of query.listeners) {
290
- try {
291
- callback(state);
292
- } catch (error_) {
293
- this.onError(error_);
294
- }
295
- }
303
+ this.publishState(collectionName, queryId(query.selector, query.options), state, error);
296
304
  }
297
305
  }
298
306
  publishState(collectionName, qid, state, error) {
299
- const rec = this.queries.get(collectionName)?.get(qid);
300
- if (!rec)
307
+ const query = this.queries.get(collectionName)?.get(qid);
308
+ if (!query)
301
309
  return;
302
- rec.state = state;
303
- rec.error = error;
304
- for (const callback of rec.listeners) {
310
+ query.state = state;
311
+ query.error = error;
312
+ for (const callback of query.listeners) {
305
313
  try {
306
314
  callback(state);
307
315
  } catch (error_) {
@@ -310,10 +318,11 @@ class AutoFetchDataAdapter {
310
318
  }
311
319
  }
312
320
  publishResult(collectionName, qid, items) {
313
- const rec = this.queries.get(collectionName)?.get(qid);
314
- if (!rec)
321
+ const query = this.queries.get(collectionName)?.get(qid);
322
+ if (!query)
315
323
  return;
316
- rec.items = items;
324
+ query.items = items;
325
+ this.queries.get(collectionName)?.set(qid, query);
317
326
  }
318
327
  async fulfillQuery(collectionName, selector, options) {
319
328
  const qid = queryId(selector, options);
@@ -472,7 +481,7 @@ class AutoFetchDataAdapter {
472
481
  throw new Error(`Item with id ${String(modified.id)} already exists`);
473
482
  }
474
483
  await storage.replace([modified]);
475
- await this.checkQueryUpdates(collectionName, [modified]);
484
+ await this.checkQueryUpdates(collectionName, [item, modified]);
476
485
  return [modified];
477
486
  }
478
487
  async updateMany(collectionName, selector, modifier) {
@@ -493,7 +502,7 @@ class AutoFetchDataAdapter {
493
502
  return modified;
494
503
  }));
495
504
  await storage.replace(changed);
496
- await this.checkQueryUpdates(collectionName, changed);
505
+ await this.checkQueryUpdates(collectionName, [...items, ...changed]);
497
506
  return changed;
498
507
  }
499
508
  async replaceOne(collectionName, selector, replacement) {
@@ -511,7 +520,7 @@ class AutoFetchDataAdapter {
511
520
  throw new Error(`Item with id ${String(modified.id)} already exists`);
512
521
  }
513
522
  await storage.replace([modified]);
514
- await this.checkQueryUpdates(collectionName, [modified]);
523
+ await this.checkQueryUpdates(collectionName, [item, modified]);
515
524
  return [modified];
516
525
  }
517
526
  async removeOne(collectionName, selector) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  const isEqual = require("./index.cjs6.js");
3
- const uniqueBy = require("./index.cjs31.js");
3
+ const uniqueBy = require("./index.cjs29.js");
4
4
  class Observer {
5
5
  previousItems = [];
6
6
  callbacks;
@@ -62,9 +62,12 @@ class Cursor {
62
62
  return this.options.transform(item);
63
63
  }
64
64
  depend(changeEvents) {
65
- if (!this.options.reactive)
65
+ if (this.options?.async)
66
66
  return;
67
- if (!isInReactiveScope(this.options.reactive))
67
+ if (!isInReactiveScope(this.options.reactive)) {
68
+ console.warn("Cursor.depend() called outside of a reactive scope without async option; consider using { async: true } or wrapping in a reactive scope");
69
+ }
70
+ if (!this.options.reactive)
68
71
  return;
69
72
  const signal = this.options.reactive.create();
70
73
  signal.depend();
@@ -1,104 +1,7 @@
1
1
  "use strict";
2
- const createIndexProvider = require("./index.cjs27.js");
3
- const get = require("./index.cjs10.js");
4
- const getMatchingKeys = require("./index.cjs26.js");
5
- const serializeValue = require("./index.cjs11.js");
6
- function createIndex(field) {
7
- const index = /* @__PURE__ */ new Map();
8
- const ensureSet = (key) => {
9
- let set = index.get(key);
10
- if (!set) {
11
- set = /* @__PURE__ */ new Set();
12
- index.set(key, set);
13
- }
14
- return set;
15
- };
16
- return createIndexProvider({
17
- query(selector) {
18
- if (!Object.hasOwnProperty.call(selector, field)) {
19
- return { matched: false };
20
- }
21
- const fieldSelector = selector[field];
22
- const filteresForNull = fieldSelector == null || fieldSelector.$exists === false;
23
- const keys = filteresForNull ? { include: null, exclude: [...index.keys()].filter((key) => key != null) } : getMatchingKeys(field, selector);
24
- if (keys.include == null && keys.exclude == null)
25
- return { matched: false };
26
- let includedIds = [];
27
- if (keys.include == null) {
28
- for (const set of index.values()) {
29
- for (const pos of set) {
30
- includedIds.push(pos);
31
- }
32
- }
33
- } else {
34
- for (const key of keys.include) {
35
- const posSet = index.get(key);
36
- if (posSet) {
37
- for (const pos of posSet) {
38
- includedIds.push(pos);
39
- }
40
- }
41
- }
42
- }
43
- if (keys.exclude != null) {
44
- const excludeIds = /* @__PURE__ */ new Set();
45
- for (const key of keys.exclude) {
46
- const posSet = index.get(key);
47
- if (posSet) {
48
- for (const pos of posSet) {
49
- excludeIds.add(pos);
50
- }
51
- }
52
- }
53
- includedIds = includedIds.filter((pos) => !excludeIds.has(pos));
54
- }
55
- return {
56
- matched: true,
57
- ids: includedIds,
58
- fields: [field],
59
- keepSelector: filteresForNull
60
- };
61
- },
62
- rebuild(items) {
63
- index.clear();
64
- items.forEach((item) => {
65
- const value = serializeValue(get(item, field));
66
- ensureSet(value).add(item.id);
67
- });
68
- },
69
- // NEW: delta methods
70
- insert(items) {
71
- for (const item of items) {
72
- const value = serializeValue(get(item, field));
73
- ensureSet(value).add(item.id);
74
- }
75
- },
76
- remove(items) {
77
- for (const item of items) {
78
- const value = serializeValue(get(item, field));
79
- const set = index.get(value);
80
- if (!set)
81
- continue;
82
- set.delete(item.id);
83
- if (set.size === 0)
84
- index.delete(value);
85
- }
86
- },
87
- update(pairs) {
88
- for (const { oldItem, newItem } of pairs) {
89
- const oldValue = serializeValue(get(oldItem, field));
90
- const newValue = serializeValue(get(newItem, field));
91
- if (oldValue === newValue)
92
- continue;
93
- const oldSet = index.get(oldValue);
94
- if (oldSet) {
95
- oldSet.delete(oldItem.id);
96
- if (oldSet.size === 0)
97
- index.delete(oldValue);
98
- }
99
- ensureSet(newValue).add(newItem.id);
100
- }
101
- }
102
- });
2
+ function queryId(selector, options) {
3
+ const selectorId = JSON.stringify(selector);
4
+ const optionsId = options == null ? -1 : JSON.stringify(options);
5
+ return `${selectorId}:${optionsId}`;
103
6
  }
104
- module.exports = createIndex;
7
+ module.exports = queryId;