@oimdb/core 1.0.6 → 1.2.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/README.md +40 -16
- package/dist/index.cjs +234 -169
- package/dist/index.d.cts +79 -54
- package/dist/index.d.ts +79 -54
- package/dist/index.js +232 -169
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -127,18 +127,66 @@ var EOIMIndexEventType = /* @__PURE__ */ ((EOIMIndexEventType2) => {
|
|
|
127
127
|
return EOIMIndexEventType2;
|
|
128
128
|
})(EOIMIndexEventType || {});
|
|
129
129
|
|
|
130
|
+
// src/abstract/OIMIndexStore.ts
|
|
131
|
+
var OIMIndexStore = class {
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// src/core/OIMIndexStoreMapDriven.ts
|
|
135
|
+
var OIMIndexStoreMapDriven = class extends OIMIndexStore {
|
|
136
|
+
constructor() {
|
|
137
|
+
super(...arguments);
|
|
138
|
+
this.pks = /* @__PURE__ */ new Map();
|
|
139
|
+
}
|
|
140
|
+
setOneByKey(key, pks) {
|
|
141
|
+
this.pks.set(key, pks);
|
|
142
|
+
}
|
|
143
|
+
removeOneByKey(key) {
|
|
144
|
+
this.pks.delete(key);
|
|
145
|
+
}
|
|
146
|
+
removeManyByKeys(keys) {
|
|
147
|
+
for (const key of keys) {
|
|
148
|
+
this.pks.delete(key);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
getOneByKey(key) {
|
|
152
|
+
return this.pks.get(key);
|
|
153
|
+
}
|
|
154
|
+
getManyByKeys(keys) {
|
|
155
|
+
const result = /* @__PURE__ */ new Map();
|
|
156
|
+
for (const key of keys) {
|
|
157
|
+
const pks = this.getOneByKey(key);
|
|
158
|
+
if (pks !== void 0) {
|
|
159
|
+
result.set(key, pks);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
getAllKeys() {
|
|
165
|
+
return Array.from(this.pks.keys());
|
|
166
|
+
}
|
|
167
|
+
getAll() {
|
|
168
|
+
return new Map(this.pks);
|
|
169
|
+
}
|
|
170
|
+
countAll() {
|
|
171
|
+
return this.pks.size;
|
|
172
|
+
}
|
|
173
|
+
clear() {
|
|
174
|
+
this.pks.clear();
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
130
178
|
// src/abstract/OIMIndex.ts
|
|
131
179
|
var OIMIndex = class {
|
|
132
180
|
constructor(options = {}) {
|
|
133
|
-
this.pks = /* @__PURE__ */ new Map();
|
|
134
181
|
this.emitter = new OIMEventEmitter();
|
|
135
182
|
this.comparePks = options.comparePks;
|
|
183
|
+
this.store = options.store ?? new OIMIndexStoreMapDriven();
|
|
136
184
|
}
|
|
137
185
|
/**
|
|
138
186
|
* Get primary keys for multiple index keys
|
|
139
187
|
*/
|
|
140
188
|
getPksByKeys(keys) {
|
|
141
|
-
return
|
|
189
|
+
return this.store.getManyByKeys(keys);
|
|
142
190
|
}
|
|
143
191
|
/**
|
|
144
192
|
* @deprecated Use getPksByKey instead
|
|
@@ -151,39 +199,39 @@ var OIMIndex = class {
|
|
|
151
199
|
* Get primary keys for a specific index key
|
|
152
200
|
*/
|
|
153
201
|
getPksByKey(key) {
|
|
154
|
-
const pksSet = this.
|
|
202
|
+
const pksSet = this.store.getOneByKey(key);
|
|
155
203
|
return pksSet ? pksSet : /* @__PURE__ */ new Set();
|
|
156
204
|
}
|
|
157
205
|
/**
|
|
158
206
|
* Check if an index key exists
|
|
159
207
|
*/
|
|
160
208
|
hasKey(key) {
|
|
161
|
-
return this.
|
|
209
|
+
return this.store.getOneByKey(key) !== void 0;
|
|
162
210
|
}
|
|
163
211
|
/**
|
|
164
212
|
* Get all index keys
|
|
165
213
|
*/
|
|
166
214
|
getKeys() {
|
|
167
|
-
return
|
|
215
|
+
return this.store.getAllKeys();
|
|
168
216
|
}
|
|
169
217
|
/**
|
|
170
218
|
* Get the number of primary keys for a specific index key
|
|
171
219
|
*/
|
|
172
220
|
getKeySize(key) {
|
|
173
|
-
const pksSet = this.
|
|
221
|
+
const pksSet = this.store.getOneByKey(key);
|
|
174
222
|
return pksSet ? pksSet.size : 0;
|
|
175
223
|
}
|
|
176
224
|
/**
|
|
177
225
|
* Get total number of index keys
|
|
178
226
|
*/
|
|
179
227
|
get size() {
|
|
180
|
-
return this.
|
|
228
|
+
return this.store.countAll();
|
|
181
229
|
}
|
|
182
230
|
/**
|
|
183
231
|
* Check if the index is empty
|
|
184
232
|
*/
|
|
185
233
|
get isEmpty() {
|
|
186
|
-
return this.
|
|
234
|
+
return this.store.countAll() === 0;
|
|
187
235
|
}
|
|
188
236
|
/**
|
|
189
237
|
* Get performance metrics for monitoring and debugging
|
|
@@ -192,15 +240,16 @@ var OIMIndex = class {
|
|
|
192
240
|
let totalPks = 0;
|
|
193
241
|
let maxBucketSize = 0;
|
|
194
242
|
let minBucketSize = Infinity;
|
|
195
|
-
|
|
243
|
+
const allPks = this.store.getAll();
|
|
244
|
+
for (const pksSet of allPks.values()) {
|
|
196
245
|
totalPks += pksSet.size;
|
|
197
246
|
maxBucketSize = Math.max(maxBucketSize, pksSet.size);
|
|
198
247
|
minBucketSize = Math.min(minBucketSize, pksSet.size);
|
|
199
248
|
}
|
|
200
249
|
return {
|
|
201
|
-
totalKeys:
|
|
250
|
+
totalKeys: allPks.size,
|
|
202
251
|
totalPks,
|
|
203
|
-
averagePksPerKey:
|
|
252
|
+
averagePksPerKey: allPks.size > 0 ? totalPks / allPks.size : 0,
|
|
204
253
|
maxBucketSize: maxBucketSize === -Infinity ? 0 : maxBucketSize,
|
|
205
254
|
minBucketSize: minBucketSize === Infinity ? 0 : minBucketSize
|
|
206
255
|
};
|
|
@@ -210,21 +259,26 @@ var OIMIndex = class {
|
|
|
210
259
|
*/
|
|
211
260
|
destroy() {
|
|
212
261
|
this.emitter.offAll();
|
|
213
|
-
this.
|
|
262
|
+
this.store.clear();
|
|
214
263
|
}
|
|
215
264
|
/**
|
|
216
265
|
* Set primary keys for a specific index key with optional comparison.
|
|
217
266
|
* If comparator is provided and returns true (no changes), skip the update.
|
|
218
267
|
*/
|
|
219
268
|
setPksWithComparison(key, newPks) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
269
|
+
if (this.comparePks) {
|
|
270
|
+
const existingPksSet = this.store.getOneByKey(key);
|
|
271
|
+
if (existingPksSet && existingPksSet.size === newPks.size) {
|
|
272
|
+
const existingPksArray = existingPksSet.size > 0 ? [...existingPksSet] : [];
|
|
273
|
+
const newPksArray = newPks.size > 0 ? [...newPks] : [];
|
|
274
|
+
if (this.comparePks(existingPksArray, newPksArray)) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
} else if (!existingPksSet && newPks.size === 0) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
226
280
|
}
|
|
227
|
-
this.
|
|
281
|
+
this.store.setOneByKey(key, newPks);
|
|
228
282
|
return true;
|
|
229
283
|
}
|
|
230
284
|
/**
|
|
@@ -238,6 +292,8 @@ var OIMIndex = class {
|
|
|
238
292
|
// src/enum/EOIMUpdateEventCoalescerEventType.ts
|
|
239
293
|
var EOIMUpdateEventCoalescerEventType = /* @__PURE__ */ ((EOIMUpdateEventCoalescerEventType2) => {
|
|
240
294
|
EOIMUpdateEventCoalescerEventType2[EOIMUpdateEventCoalescerEventType2["HAS_CHANGES"] = 0] = "HAS_CHANGES";
|
|
295
|
+
EOIMUpdateEventCoalescerEventType2[EOIMUpdateEventCoalescerEventType2["BEFORE_FLUSH"] = 1] = "BEFORE_FLUSH";
|
|
296
|
+
EOIMUpdateEventCoalescerEventType2[EOIMUpdateEventCoalescerEventType2["AFTER_FLUSH"] = 2] = "AFTER_FLUSH";
|
|
241
297
|
return EOIMUpdateEventCoalescerEventType2;
|
|
242
298
|
})(EOIMUpdateEventCoalescerEventType || {});
|
|
243
299
|
|
|
@@ -359,35 +415,141 @@ var OIMUpdateEventEmitter = class {
|
|
|
359
415
|
}
|
|
360
416
|
};
|
|
361
417
|
|
|
418
|
+
// src/core/OIMIndexManual.ts
|
|
419
|
+
var OIMIndexManual = class extends OIMIndex {
|
|
420
|
+
constructor(options = {}) {
|
|
421
|
+
super(options);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Set primary keys for a specific index key, replacing any existing values.
|
|
425
|
+
* Uses optional comparator to skip updates if PKs haven't actually changed.
|
|
426
|
+
*/
|
|
427
|
+
setPks(key, pks) {
|
|
428
|
+
const hasChanges = this.setPksWithComparison(key, new Set(pks));
|
|
429
|
+
if (hasChanges) {
|
|
430
|
+
this.emitUpdate([key]);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Add primary keys to a specific index key
|
|
435
|
+
*/
|
|
436
|
+
addPks(key, pks) {
|
|
437
|
+
if (pks.length === 0) return;
|
|
438
|
+
let pksSet = this.store.getOneByKey(key);
|
|
439
|
+
if (!pksSet) {
|
|
440
|
+
pksSet = /* @__PURE__ */ new Set();
|
|
441
|
+
this.store.setOneByKey(key, pksSet);
|
|
442
|
+
}
|
|
443
|
+
let hasChanges = false;
|
|
444
|
+
for (const pk of pks) {
|
|
445
|
+
if (!pksSet.has(pk)) {
|
|
446
|
+
pksSet.add(pk);
|
|
447
|
+
hasChanges = true;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (hasChanges) {
|
|
451
|
+
this.store.setOneByKey(key, pksSet);
|
|
452
|
+
this.emitUpdate([key]);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Remove primary keys from a specific index key
|
|
457
|
+
*/
|
|
458
|
+
removePks(key, pks) {
|
|
459
|
+
if (pks.length === 0) return;
|
|
460
|
+
const pksSet = this.store.getOneByKey(key);
|
|
461
|
+
if (!pksSet) return;
|
|
462
|
+
let hasChanges = false;
|
|
463
|
+
for (const pk of pks) {
|
|
464
|
+
if (pksSet.delete(pk)) {
|
|
465
|
+
hasChanges = true;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (pksSet.size === 0) {
|
|
469
|
+
this.store.removeOneByKey(key);
|
|
470
|
+
hasChanges = true;
|
|
471
|
+
} else if (hasChanges) {
|
|
472
|
+
this.store.setOneByKey(key, pksSet);
|
|
473
|
+
}
|
|
474
|
+
if (hasChanges) {
|
|
475
|
+
this.emitUpdate([key]);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
480
|
+
*/
|
|
481
|
+
clear(key) {
|
|
482
|
+
if (key === void 0) {
|
|
483
|
+
const allKeys = this.store.getAllKeys();
|
|
484
|
+
if (allKeys.length > 0) {
|
|
485
|
+
this.store.clear();
|
|
486
|
+
this.emitUpdate(allKeys);
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
if (this.store.getOneByKey(key) !== void 0) {
|
|
490
|
+
this.store.removeOneByKey(key);
|
|
491
|
+
this.emitUpdate([key]);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
// src/const/OIMDBSettings.ts
|
|
498
|
+
var OIMDBSettings = class {
|
|
499
|
+
};
|
|
500
|
+
/**
|
|
501
|
+
* Fixed key used in the manual index to store updated keys set in coalescers.
|
|
502
|
+
* This constant is exported so users can create their own indexes and pass them to coalescers.
|
|
503
|
+
*/
|
|
504
|
+
OIMDBSettings.UPDATED_KEYS_INDEX_KEY = "__updatedKeys__";
|
|
505
|
+
|
|
362
506
|
// src/core/OIMUpdateEventCoalescer.ts
|
|
363
507
|
var OIMUpdateEventCoalescer = class {
|
|
364
|
-
constructor() {
|
|
508
|
+
constructor(index) {
|
|
365
509
|
this.emitter = new OIMEventEmitter();
|
|
366
|
-
this.updatedKeys = /* @__PURE__ */ new Set();
|
|
367
510
|
this.hasEmittedChanges = false;
|
|
511
|
+
this.updatedKeysIndex = index ?? new OIMIndexManual({
|
|
512
|
+
store: new OIMIndexStoreMapDriven()
|
|
513
|
+
});
|
|
514
|
+
if (!this.updatedKeysIndex.hasKey(OIMDBSettings.UPDATED_KEYS_INDEX_KEY)) {
|
|
515
|
+
this.updatedKeysIndex.setPks(
|
|
516
|
+
OIMDBSettings.UPDATED_KEYS_INDEX_KEY,
|
|
517
|
+
[]
|
|
518
|
+
);
|
|
519
|
+
}
|
|
368
520
|
}
|
|
369
521
|
/**
|
|
370
522
|
* Get the set of keys that have been updated since last clear
|
|
371
523
|
*/
|
|
372
524
|
getUpdatedKeys() {
|
|
373
|
-
return this.
|
|
525
|
+
return this.updatedKeysIndex.getPksByKey(
|
|
526
|
+
OIMDBSettings.UPDATED_KEYS_INDEX_KEY
|
|
527
|
+
);
|
|
374
528
|
}
|
|
375
529
|
/**
|
|
376
530
|
* Clear all updated keys and reset the changed state
|
|
377
531
|
*/
|
|
378
532
|
clearUpdatedKeys() {
|
|
379
|
-
this.
|
|
533
|
+
this.emitter.emit(
|
|
534
|
+
1 /* BEFORE_FLUSH */,
|
|
535
|
+
void 0
|
|
536
|
+
);
|
|
537
|
+
this.updatedKeysIndex.setPks(OIMDBSettings.UPDATED_KEYS_INDEX_KEY, []);
|
|
380
538
|
this.hasEmittedChanges = false;
|
|
539
|
+
this.emitter.emit(
|
|
540
|
+
2 /* AFTER_FLUSH */,
|
|
541
|
+
void 0
|
|
542
|
+
);
|
|
381
543
|
}
|
|
382
544
|
/**
|
|
383
545
|
* Add keys to the updated set and emit HAS_CHANGES event if needed
|
|
384
546
|
*/
|
|
385
547
|
addUpdatedKeys(keys) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
if (!
|
|
548
|
+
this.updatedKeysIndex.addPks(
|
|
549
|
+
OIMDBSettings.UPDATED_KEYS_INDEX_KEY,
|
|
550
|
+
keys
|
|
551
|
+
);
|
|
552
|
+
if (!this.hasEmittedChanges) {
|
|
391
553
|
this.hasEmittedChanges = true;
|
|
392
554
|
this.emitter.emit(
|
|
393
555
|
0 /* HAS_CHANGES */,
|
|
@@ -406,23 +568,14 @@ var OIMUpdateEventCoalescerIndex = class extends OIMUpdateEventCoalescer {
|
|
|
406
568
|
* When the index is updated, we keep track of the updated keys.
|
|
407
569
|
*/
|
|
408
570
|
this.handleUpdate = (payload) => {
|
|
409
|
-
|
|
410
|
-
for (const key of payload.keys) {
|
|
411
|
-
this.updatedKeys.add(key);
|
|
412
|
-
}
|
|
413
|
-
if (!hadChanges && this.updatedKeys.size > 0) {
|
|
414
|
-
this.emitter.emit(
|
|
415
|
-
0 /* HAS_CHANGES */,
|
|
416
|
-
void 0
|
|
417
|
-
);
|
|
418
|
-
}
|
|
571
|
+
this.addUpdatedKeys(payload.keys);
|
|
419
572
|
};
|
|
420
573
|
this.indexEmitter.on(0 /* UPDATE */, this.handleUpdate);
|
|
421
574
|
}
|
|
422
575
|
destroy() {
|
|
423
576
|
this.indexEmitter.off(0 /* UPDATE */, this.handleUpdate);
|
|
424
577
|
this.emitter.offAll();
|
|
425
|
-
this.
|
|
578
|
+
this.clearUpdatedKeys();
|
|
426
579
|
}
|
|
427
580
|
};
|
|
428
581
|
|
|
@@ -493,14 +646,24 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
493
646
|
}
|
|
494
647
|
removeManyByPks(pks) {
|
|
495
648
|
for (const pk of pks) {
|
|
496
|
-
this.
|
|
649
|
+
this.entities.delete(pk);
|
|
497
650
|
}
|
|
498
651
|
}
|
|
499
652
|
getOneByPk(pk) {
|
|
500
653
|
return this.entities.get(pk);
|
|
501
654
|
}
|
|
502
655
|
getManyByPks(pks) {
|
|
503
|
-
|
|
656
|
+
const result = [];
|
|
657
|
+
result.length = pks.length;
|
|
658
|
+
let writeIndex = 0;
|
|
659
|
+
for (let i = 0; i < pks.length; i++) {
|
|
660
|
+
const entity = this.getOneByPk(pks[i]);
|
|
661
|
+
if (entity !== void 0) {
|
|
662
|
+
result[writeIndex++] = entity;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
result.length = writeIndex;
|
|
666
|
+
return result;
|
|
504
667
|
}
|
|
505
668
|
getAll() {
|
|
506
669
|
return Array.from(this.entities.values());
|
|
@@ -565,6 +728,14 @@ var OIMCollection = class {
|
|
|
565
728
|
this.store.removeManyByPks(pks);
|
|
566
729
|
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
567
730
|
}
|
|
731
|
+
removeOneByPk(pk) {
|
|
732
|
+
this.store.removeOneByPk(pk);
|
|
733
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
734
|
+
}
|
|
735
|
+
removeManyByPks(pks) {
|
|
736
|
+
this.store.removeManyByPks(pks);
|
|
737
|
+
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
738
|
+
}
|
|
568
739
|
clear() {
|
|
569
740
|
this.store.clear();
|
|
570
741
|
this.emitter.emit(0 /* UPDATE */, { pks: [] });
|
|
@@ -602,16 +773,7 @@ var OIMUpdateEventCoalescerCollection = class extends OIMUpdateEventCoalescer {
|
|
|
602
773
|
* When the collection is updated, we keep track of the updated pks.
|
|
603
774
|
*/
|
|
604
775
|
this.handleUpdate = (payload) => {
|
|
605
|
-
|
|
606
|
-
for (const pk of payload.pks) {
|
|
607
|
-
this.updatedKeys.add(pk);
|
|
608
|
-
}
|
|
609
|
-
if (!hadChanges && this.updatedKeys.size > 0) {
|
|
610
|
-
this.emitter.emit(
|
|
611
|
-
0 /* HAS_CHANGES */,
|
|
612
|
-
void 0
|
|
613
|
-
);
|
|
614
|
-
}
|
|
776
|
+
this.addUpdatedKeys(payload.pks);
|
|
615
777
|
};
|
|
616
778
|
this.collectionEmitter.on(
|
|
617
779
|
0 /* UPDATE */,
|
|
@@ -624,129 +786,22 @@ var OIMUpdateEventCoalescerCollection = class extends OIMUpdateEventCoalescer {
|
|
|
624
786
|
this.handleUpdate
|
|
625
787
|
);
|
|
626
788
|
this.emitter.offAll();
|
|
627
|
-
this.
|
|
789
|
+
this.clearUpdatedKeys();
|
|
628
790
|
}
|
|
629
791
|
};
|
|
630
792
|
|
|
631
793
|
// src/core/OIMReactiveCollection.ts
|
|
632
|
-
var OIMReactiveCollection = class {
|
|
794
|
+
var OIMReactiveCollection = class extends OIMCollection {
|
|
633
795
|
constructor(queue, opts) {
|
|
634
|
-
|
|
796
|
+
super(opts);
|
|
635
797
|
this.coalescer = new OIMUpdateEventCoalescerCollection(
|
|
636
|
-
this.
|
|
798
|
+
this.emitter
|
|
637
799
|
);
|
|
638
800
|
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
639
801
|
coalescer: this.coalescer,
|
|
640
802
|
queue
|
|
641
803
|
});
|
|
642
804
|
}
|
|
643
|
-
upsertMany(entities) {
|
|
644
|
-
this.collection.upsertMany(entities);
|
|
645
|
-
}
|
|
646
|
-
upsertOne(entity) {
|
|
647
|
-
this.collection.upsertOne(entity);
|
|
648
|
-
}
|
|
649
|
-
removeMany(entities) {
|
|
650
|
-
this.collection.removeMany(entities);
|
|
651
|
-
}
|
|
652
|
-
removeOne(entity) {
|
|
653
|
-
this.collection.removeOne(entity);
|
|
654
|
-
}
|
|
655
|
-
getOneByPk(pk) {
|
|
656
|
-
return this.collection.getOneByPk(pk);
|
|
657
|
-
}
|
|
658
|
-
getManyByPks(pks) {
|
|
659
|
-
return this.collection.getManyByPks(pks);
|
|
660
|
-
}
|
|
661
|
-
clear() {
|
|
662
|
-
this.collection.clear();
|
|
663
|
-
}
|
|
664
|
-
countAll() {
|
|
665
|
-
return this.collection.countAll();
|
|
666
|
-
}
|
|
667
|
-
getAll() {
|
|
668
|
-
return this.collection.getAll();
|
|
669
|
-
}
|
|
670
|
-
getAllPks() {
|
|
671
|
-
return this.collection.getAllPks();
|
|
672
|
-
}
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
// src/core/OIMIndexManual.ts
|
|
676
|
-
var OIMIndexManual = class extends OIMIndex {
|
|
677
|
-
constructor(options = {}) {
|
|
678
|
-
super(options);
|
|
679
|
-
}
|
|
680
|
-
/**
|
|
681
|
-
* Set primary keys for a specific index key, replacing any existing values.
|
|
682
|
-
* Uses optional comparator to skip updates if PKs haven't actually changed.
|
|
683
|
-
*/
|
|
684
|
-
setPks(key, pks) {
|
|
685
|
-
const hasChanges = this.setPksWithComparison(key, new Set(pks));
|
|
686
|
-
if (hasChanges) {
|
|
687
|
-
this.emitUpdate([key]);
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
/**
|
|
691
|
-
* Add primary keys to a specific index key
|
|
692
|
-
*/
|
|
693
|
-
addPks(key, pks) {
|
|
694
|
-
if (pks.length === 0) return;
|
|
695
|
-
let pksSet = this.pks.get(key);
|
|
696
|
-
if (!pksSet) {
|
|
697
|
-
pksSet = /* @__PURE__ */ new Set();
|
|
698
|
-
this.pks.set(key, pksSet);
|
|
699
|
-
}
|
|
700
|
-
let hasChanges = false;
|
|
701
|
-
for (const pk of pks) {
|
|
702
|
-
const sizeBefore = pksSet.size;
|
|
703
|
-
pksSet.add(pk);
|
|
704
|
-
if (pksSet.size > sizeBefore) {
|
|
705
|
-
hasChanges = true;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
if (hasChanges) {
|
|
709
|
-
this.emitUpdate([key]);
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
/**
|
|
713
|
-
* Remove primary keys from a specific index key
|
|
714
|
-
*/
|
|
715
|
-
removePks(key, pks) {
|
|
716
|
-
if (pks.length === 0) return;
|
|
717
|
-
const pksSet = this.pks.get(key);
|
|
718
|
-
if (!pksSet) return;
|
|
719
|
-
let hasChanges = false;
|
|
720
|
-
for (const pk of pks) {
|
|
721
|
-
if (pksSet.delete(pk)) {
|
|
722
|
-
hasChanges = true;
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
if (pksSet.size === 0) {
|
|
726
|
-
this.pks.delete(key);
|
|
727
|
-
hasChanges = true;
|
|
728
|
-
}
|
|
729
|
-
if (hasChanges) {
|
|
730
|
-
this.emitUpdate([key]);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
/**
|
|
734
|
-
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
735
|
-
*/
|
|
736
|
-
clear(key) {
|
|
737
|
-
if (key === void 0) {
|
|
738
|
-
if (this.pks.size > 0) {
|
|
739
|
-
const allKeys = Array.from(this.pks.keys());
|
|
740
|
-
this.pks.clear();
|
|
741
|
-
this.emitUpdate(allKeys);
|
|
742
|
-
}
|
|
743
|
-
} else {
|
|
744
|
-
if (this.pks.has(key)) {
|
|
745
|
-
this.pks.delete(key);
|
|
746
|
-
this.emitUpdate([key]);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
805
|
};
|
|
751
806
|
|
|
752
807
|
// src/core/OIMReactiveIndexManual.ts
|
|
@@ -774,10 +829,8 @@ var OIMReactiveIndexManual = class extends OIMReactiveIndex {
|
|
|
774
829
|
// src/core/OIMRICollection.ts
|
|
775
830
|
var OIMRICollection = class extends OIMReactiveCollection {
|
|
776
831
|
constructor(queue, opts) {
|
|
777
|
-
super(queue,
|
|
778
|
-
|
|
779
|
-
});
|
|
780
|
-
this.indexes = opts.indexes || {};
|
|
832
|
+
super(queue, opts.collectionOpts);
|
|
833
|
+
this.indexes = opts.indexes;
|
|
781
834
|
}
|
|
782
835
|
};
|
|
783
836
|
|
|
@@ -799,9 +852,17 @@ var OIMComparatorFactory = class {
|
|
|
799
852
|
}
|
|
800
853
|
};
|
|
801
854
|
|
|
855
|
+
// src/enum/EOIMEventQueueEventType.ts
|
|
856
|
+
var EOIMEventQueueEventType = /* @__PURE__ */ ((EOIMEventQueueEventType2) => {
|
|
857
|
+
EOIMEventQueueEventType2[EOIMEventQueueEventType2["AFTER_FLUSH"] = 0] = "AFTER_FLUSH";
|
|
858
|
+
EOIMEventQueueEventType2[EOIMEventQueueEventType2["BEFORE_FLUSH"] = 1] = "BEFORE_FLUSH";
|
|
859
|
+
return EOIMEventQueueEventType2;
|
|
860
|
+
})(EOIMEventQueueEventType || {});
|
|
861
|
+
|
|
802
862
|
// src/core/OIMEventQueue.ts
|
|
803
863
|
var OIMEventQueue = class {
|
|
804
864
|
constructor(options = {}) {
|
|
865
|
+
this.emitter = new OIMEventEmitter();
|
|
805
866
|
this.queue = [];
|
|
806
867
|
this.scheduler = options.scheduler;
|
|
807
868
|
if (this.scheduler) {
|
|
@@ -828,11 +889,13 @@ var OIMEventQueue = class {
|
|
|
828
889
|
*/
|
|
829
890
|
flush() {
|
|
830
891
|
if (this.queue.length === 0) return;
|
|
892
|
+
this.emitter.emit(1 /* BEFORE_FLUSH */, void 0);
|
|
831
893
|
const currentQueue = this.queue.slice();
|
|
832
894
|
this.queue.length = 0;
|
|
833
895
|
for (let i = 0; i < currentQueue.length; i++) {
|
|
834
896
|
currentQueue[i]();
|
|
835
897
|
}
|
|
898
|
+
this.emitter.emit(0 /* AFTER_FLUSH */, void 0);
|
|
836
899
|
}
|
|
837
900
|
/**
|
|
838
901
|
* Get the current number of queued functions.
|
|
@@ -900,9 +963,7 @@ var OIMIndexComparatorFactory = class {
|
|
|
900
963
|
if (existingSet.size !== newSet.size || existingSet.size !== existingPks.length) {
|
|
901
964
|
return false;
|
|
902
965
|
}
|
|
903
|
-
const
|
|
904
|
-
for (let i = 0; i < setValues.length; i++) {
|
|
905
|
-
const pk = setValues[i];
|
|
966
|
+
for (const pk of existingSet) {
|
|
906
967
|
if (!newSet.has(pk)) {
|
|
907
968
|
return false;
|
|
908
969
|
}
|
|
@@ -1138,6 +1199,7 @@ var OIMEventQueueSchedulerFactory = class {
|
|
|
1138
1199
|
};
|
|
1139
1200
|
export {
|
|
1140
1201
|
EOIMCollectionEventType,
|
|
1202
|
+
EOIMEventQueueEventType,
|
|
1141
1203
|
EOIMEventQueueSchedulerEventType,
|
|
1142
1204
|
EOIMIndexEventType,
|
|
1143
1205
|
EOIMUpdateEventCoalescerEventType,
|
|
@@ -1145,6 +1207,7 @@ export {
|
|
|
1145
1207
|
OIMCollectionStore,
|
|
1146
1208
|
OIMCollectionStoreMapDriven,
|
|
1147
1209
|
OIMComparatorFactory,
|
|
1210
|
+
OIMDBSettings,
|
|
1148
1211
|
OIMEntityUpdaterFactory,
|
|
1149
1212
|
OIMEventEmitter,
|
|
1150
1213
|
OIMEventQueue,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oimdb/core",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Core in-memory data library with type-safe indices, reactive subscriptions, and event processing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -24,8 +24,10 @@
|
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsup src/index.ts --dts --format esm,cjs",
|
|
27
|
+
"test": "jest",
|
|
28
|
+
"type-check": "tsc --noEmit",
|
|
27
29
|
"clean": "rimraf dist",
|
|
28
|
-
"prepublishOnly": "npm run build"
|
|
30
|
+
"prepublishOnly": "npm run type-check && npm test && npm run build"
|
|
29
31
|
},
|
|
30
32
|
"files": [
|
|
31
33
|
"dist"
|
|
@@ -33,6 +35,9 @@
|
|
|
33
35
|
"author": "Andrei Baikov",
|
|
34
36
|
"license": "MIT",
|
|
35
37
|
"devDependencies": {
|
|
38
|
+
"@types/jest": "^29.5.8",
|
|
39
|
+
"jest": "^29.7.0",
|
|
40
|
+
"ts-jest": "^29.1.1",
|
|
36
41
|
"tsup": "^8.5.0",
|
|
37
42
|
"typescript": "^5.2.2",
|
|
38
43
|
"rimraf": "^5.0.5"
|