@oimdb/core 1.2.2 → 1.3.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 +116 -27
- package/dist/index.cjs +334 -26
- package/dist/index.d.cts +222 -36
- package/dist/index.d.ts +222 -36
- package/dist/index.js +322 -22
- package/package.json +13 -1
package/dist/index.js
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
var OIMCollectionStore = class {
|
|
3
3
|
};
|
|
4
4
|
|
|
5
|
+
// src/abstract/OIMIndexStoreSetBased.ts
|
|
6
|
+
var OIMIndexStoreSetBased = class {
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// src/abstract/OIMIndexStoreArrayBased.ts
|
|
10
|
+
var OIMIndexStoreArrayBased = class {
|
|
11
|
+
};
|
|
12
|
+
|
|
5
13
|
// src/core/OIMEventEmitter.ts
|
|
6
14
|
var OIMEventEmitter = class {
|
|
7
15
|
constructor() {
|
|
@@ -127,12 +135,8 @@ var EOIMIndexEventType = /* @__PURE__ */ ((EOIMIndexEventType2) => {
|
|
|
127
135
|
return EOIMIndexEventType2;
|
|
128
136
|
})(EOIMIndexEventType || {});
|
|
129
137
|
|
|
130
|
-
// src/
|
|
131
|
-
var
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// src/core/OIMIndexStoreMapDriven.ts
|
|
135
|
-
var OIMIndexStoreMapDriven = class extends OIMIndexStore {
|
|
138
|
+
// src/core/OIMIndexStoreMapDrivenSetBased.ts
|
|
139
|
+
var OIMIndexStoreMapDrivenSetBased = class extends OIMIndexStoreSetBased {
|
|
136
140
|
constructor() {
|
|
137
141
|
super(...arguments);
|
|
138
142
|
this.pks = /* @__PURE__ */ new Map();
|
|
@@ -175,12 +179,12 @@ var OIMIndexStoreMapDriven = class extends OIMIndexStore {
|
|
|
175
179
|
}
|
|
176
180
|
};
|
|
177
181
|
|
|
178
|
-
// src/abstract/
|
|
179
|
-
var
|
|
182
|
+
// src/abstract/OIMIndexSetBased.ts
|
|
183
|
+
var OIMIndexSetBased = class {
|
|
180
184
|
constructor(options = {}) {
|
|
181
185
|
this.emitter = new OIMEventEmitter();
|
|
182
186
|
this.comparePks = options.comparePks;
|
|
183
|
-
this.store = options.store ?? new
|
|
187
|
+
this.store = options.store ?? new OIMIndexStoreMapDrivenSetBased();
|
|
184
188
|
}
|
|
185
189
|
/**
|
|
186
190
|
* Get primary keys for multiple index keys
|
|
@@ -289,6 +293,155 @@ var OIMIndex = class {
|
|
|
289
293
|
}
|
|
290
294
|
};
|
|
291
295
|
|
|
296
|
+
// src/core/OIMIndexStoreMapDrivenArrayBased.ts
|
|
297
|
+
var OIMIndexStoreMapDrivenArrayBased = class extends OIMIndexStoreArrayBased {
|
|
298
|
+
constructor() {
|
|
299
|
+
super(...arguments);
|
|
300
|
+
this.pks = /* @__PURE__ */ new Map();
|
|
301
|
+
}
|
|
302
|
+
setOneByKey(key, pks) {
|
|
303
|
+
this.pks.set(key, pks);
|
|
304
|
+
}
|
|
305
|
+
removeOneByKey(key) {
|
|
306
|
+
this.pks.delete(key);
|
|
307
|
+
}
|
|
308
|
+
removeManyByKeys(keys) {
|
|
309
|
+
for (const key of keys) {
|
|
310
|
+
this.pks.delete(key);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
getOneByKey(key) {
|
|
314
|
+
return this.pks.get(key);
|
|
315
|
+
}
|
|
316
|
+
getManyByKeys(keys) {
|
|
317
|
+
const result = /* @__PURE__ */ new Map();
|
|
318
|
+
for (const key of keys) {
|
|
319
|
+
const pks = this.getOneByKey(key);
|
|
320
|
+
if (pks !== void 0) {
|
|
321
|
+
result.set(key, pks);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
getAllKeys() {
|
|
327
|
+
return Array.from(this.pks.keys());
|
|
328
|
+
}
|
|
329
|
+
getAll() {
|
|
330
|
+
return new Map(this.pks);
|
|
331
|
+
}
|
|
332
|
+
countAll() {
|
|
333
|
+
return this.pks.size;
|
|
334
|
+
}
|
|
335
|
+
clear() {
|
|
336
|
+
this.pks.clear();
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// src/abstract/OIMIndexArrayBased.ts
|
|
341
|
+
var OIMIndexArrayBased = class {
|
|
342
|
+
constructor(options = {}) {
|
|
343
|
+
this.emitter = new OIMEventEmitter();
|
|
344
|
+
this.comparePks = options.comparePks;
|
|
345
|
+
this.store = options.store ?? new OIMIndexStoreMapDrivenArrayBased();
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Get primary keys for multiple index keys
|
|
349
|
+
*/
|
|
350
|
+
getPksByKeys(keys) {
|
|
351
|
+
return this.store.getManyByKeys(keys);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Get primary keys for a specific index key
|
|
355
|
+
*/
|
|
356
|
+
getPksByKey(key) {
|
|
357
|
+
const pksArray = this.store.getOneByKey(key);
|
|
358
|
+
return pksArray ? pksArray : [];
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Check if an index key exists
|
|
362
|
+
*/
|
|
363
|
+
hasKey(key) {
|
|
364
|
+
return this.store.getOneByKey(key) !== void 0;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Get all index keys
|
|
368
|
+
*/
|
|
369
|
+
getKeys() {
|
|
370
|
+
return this.store.getAllKeys();
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Get the number of primary keys for a specific index key
|
|
374
|
+
*/
|
|
375
|
+
getKeySize(key) {
|
|
376
|
+
const pksArray = this.store.getOneByKey(key);
|
|
377
|
+
return pksArray ? pksArray.length : 0;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Get total number of index keys
|
|
381
|
+
*/
|
|
382
|
+
get size() {
|
|
383
|
+
return this.store.countAll();
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Check if the index is empty
|
|
387
|
+
*/
|
|
388
|
+
get isEmpty() {
|
|
389
|
+
return this.store.countAll() === 0;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Get performance metrics for monitoring and debugging
|
|
393
|
+
*/
|
|
394
|
+
getMetrics() {
|
|
395
|
+
let totalPks = 0;
|
|
396
|
+
let maxBucketSize = 0;
|
|
397
|
+
let minBucketSize = Infinity;
|
|
398
|
+
const allPks = this.store.getAll();
|
|
399
|
+
for (const pksArray of allPks.values()) {
|
|
400
|
+
totalPks += pksArray.length;
|
|
401
|
+
maxBucketSize = Math.max(maxBucketSize, pksArray.length);
|
|
402
|
+
minBucketSize = Math.min(minBucketSize, pksArray.length);
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
totalKeys: allPks.size,
|
|
406
|
+
totalPks,
|
|
407
|
+
averagePksPerKey: allPks.size > 0 ? totalPks / allPks.size : 0,
|
|
408
|
+
maxBucketSize: maxBucketSize === -Infinity ? 0 : maxBucketSize,
|
|
409
|
+
minBucketSize: minBucketSize === Infinity ? 0 : minBucketSize
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Clean up event listeners when index is no longer needed
|
|
414
|
+
*/
|
|
415
|
+
destroy() {
|
|
416
|
+
this.emitter.offAll();
|
|
417
|
+
this.store.clear();
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Set primary keys for a specific index key with optional comparison.
|
|
421
|
+
* If comparator is provided and returns true (no changes), skip the update.
|
|
422
|
+
*/
|
|
423
|
+
setPksWithComparison(key, newPks) {
|
|
424
|
+
if (this.comparePks) {
|
|
425
|
+
const existingPksArray = this.store.getOneByKey(key);
|
|
426
|
+
if (existingPksArray && existingPksArray.length === newPks.length) {
|
|
427
|
+
if (this.comparePks(existingPksArray, newPks)) {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
} else if (!existingPksArray && newPks.length === 0) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
this.store.setOneByKey(key, newPks);
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Emit update event with changed keys
|
|
439
|
+
*/
|
|
440
|
+
emitUpdate(keys) {
|
|
441
|
+
this.emitter.emit(0 /* UPDATE */, { keys });
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
292
445
|
// src/enum/EOIMUpdateEventCoalescerEventType.ts
|
|
293
446
|
var EOIMUpdateEventCoalescerEventType = /* @__PURE__ */ ((EOIMUpdateEventCoalescerEventType2) => {
|
|
294
447
|
EOIMUpdateEventCoalescerEventType2[EOIMUpdateEventCoalescerEventType2["HAS_CHANGES"] = 0] = "HAS_CHANGES";
|
|
@@ -415,8 +568,8 @@ var OIMUpdateEventEmitter = class {
|
|
|
415
568
|
}
|
|
416
569
|
};
|
|
417
570
|
|
|
418
|
-
// src/core/
|
|
419
|
-
var
|
|
571
|
+
// src/core/OIMIndexManualSetBased.ts
|
|
572
|
+
var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
420
573
|
constructor(options = {}) {
|
|
421
574
|
super(options);
|
|
422
575
|
}
|
|
@@ -508,8 +661,8 @@ var OIMUpdateEventCoalescer = class {
|
|
|
508
661
|
constructor(index) {
|
|
509
662
|
this.emitter = new OIMEventEmitter();
|
|
510
663
|
this.hasEmittedChanges = false;
|
|
511
|
-
this.updatedKeysIndex = index ?? new
|
|
512
|
-
store: new
|
|
664
|
+
this.updatedKeysIndex = index ?? new OIMIndexManualSetBased({
|
|
665
|
+
store: new OIMIndexStoreMapDrivenSetBased()
|
|
513
666
|
});
|
|
514
667
|
if (!this.updatedKeysIndex.hasKey(OIMDBSettings.UPDATED_KEYS_INDEX_KEY)) {
|
|
515
668
|
this.updatedKeysIndex.setPks(
|
|
@@ -579,8 +732,49 @@ var OIMUpdateEventCoalescerIndex = class extends OIMUpdateEventCoalescer {
|
|
|
579
732
|
}
|
|
580
733
|
};
|
|
581
734
|
|
|
582
|
-
// src/abstract/
|
|
583
|
-
var
|
|
735
|
+
// src/abstract/OIMReactiveIndexSetBased.ts
|
|
736
|
+
var OIMReactiveIndexSetBased = class {
|
|
737
|
+
constructor(queue, opts) {
|
|
738
|
+
this.index = opts?.index ?? this.createDefaultIndex();
|
|
739
|
+
this.coalescer = new OIMUpdateEventCoalescerIndex(
|
|
740
|
+
this.index.emitter
|
|
741
|
+
);
|
|
742
|
+
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
743
|
+
coalescer: this.coalescer,
|
|
744
|
+
queue
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
getPksByKey(key) {
|
|
748
|
+
return this.index.getPksByKey(key);
|
|
749
|
+
}
|
|
750
|
+
getPksByKeys(keys) {
|
|
751
|
+
return this.index.getPksByKeys(keys);
|
|
752
|
+
}
|
|
753
|
+
hasKey(key) {
|
|
754
|
+
return this.index.hasKey(key);
|
|
755
|
+
}
|
|
756
|
+
getKeys() {
|
|
757
|
+
return this.index.getKeys();
|
|
758
|
+
}
|
|
759
|
+
getKeySize(key) {
|
|
760
|
+
return this.index.getKeySize(key);
|
|
761
|
+
}
|
|
762
|
+
get size() {
|
|
763
|
+
return this.index.size;
|
|
764
|
+
}
|
|
765
|
+
get isEmpty() {
|
|
766
|
+
return this.index.isEmpty;
|
|
767
|
+
}
|
|
768
|
+
getMetrics() {
|
|
769
|
+
return this.index.getMetrics();
|
|
770
|
+
}
|
|
771
|
+
destroy() {
|
|
772
|
+
this.index.destroy();
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
// src/abstract/OIMReactiveIndexArrayBased.ts
|
|
777
|
+
var OIMReactiveIndexArrayBased = class {
|
|
584
778
|
constructor(queue, opts) {
|
|
585
779
|
this.index = opts?.index ?? this.createDefaultIndex();
|
|
586
780
|
this.coalescer = new OIMUpdateEventCoalescerIndex(
|
|
@@ -816,13 +1010,111 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
816
1010
|
}
|
|
817
1011
|
};
|
|
818
1012
|
|
|
819
|
-
// src/core/
|
|
820
|
-
var
|
|
1013
|
+
// src/core/OIMReactiveIndexManualSetBased.ts
|
|
1014
|
+
var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
1015
|
+
constructor(queue, opts) {
|
|
1016
|
+
super(queue, opts);
|
|
1017
|
+
}
|
|
1018
|
+
createDefaultIndex() {
|
|
1019
|
+
return new OIMIndexManualSetBased();
|
|
1020
|
+
}
|
|
1021
|
+
setPks(key, pks) {
|
|
1022
|
+
this.index.setPks(key, pks);
|
|
1023
|
+
}
|
|
1024
|
+
addPks(key, pks) {
|
|
1025
|
+
this.index.addPks(key, pks);
|
|
1026
|
+
}
|
|
1027
|
+
removePks(key, pks) {
|
|
1028
|
+
this.index.removePks(key, pks);
|
|
1029
|
+
}
|
|
1030
|
+
clear(key) {
|
|
1031
|
+
this.index.clear(key);
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1034
|
+
|
|
1035
|
+
// src/core/OIMIndexManualArrayBased.ts
|
|
1036
|
+
var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
1037
|
+
constructor(options = {}) {
|
|
1038
|
+
super(options);
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* Set primary keys for a specific index key, replacing any existing values.
|
|
1042
|
+
* Uses optional comparator to skip updates if PKs haven't actually changed.
|
|
1043
|
+
*/
|
|
1044
|
+
setPks(key, pks) {
|
|
1045
|
+
const hasChanges = this.setPksWithComparison(key, pks);
|
|
1046
|
+
if (hasChanges) {
|
|
1047
|
+
this.emitUpdate([key]);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Add primary keys to a specific index key
|
|
1052
|
+
*/
|
|
1053
|
+
addPks(key, pks) {
|
|
1054
|
+
if (pks.length === 0) return;
|
|
1055
|
+
let pksArray = this.store.getOneByKey(key);
|
|
1056
|
+
if (!pksArray) {
|
|
1057
|
+
pksArray = [];
|
|
1058
|
+
this.store.setOneByKey(key, pksArray);
|
|
1059
|
+
}
|
|
1060
|
+
const pksSet = new Set(pksArray);
|
|
1061
|
+
let hasChanges = false;
|
|
1062
|
+
for (const pk of pks) {
|
|
1063
|
+
if (!pksSet.has(pk)) {
|
|
1064
|
+
pksSet.add(pk);
|
|
1065
|
+
hasChanges = true;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
if (hasChanges) {
|
|
1069
|
+
this.store.setOneByKey(key, Array.from(pksSet));
|
|
1070
|
+
this.emitUpdate([key]);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Remove primary keys from a specific index key
|
|
1075
|
+
*/
|
|
1076
|
+
removePks(key, pks) {
|
|
1077
|
+
if (pks.length === 0) return;
|
|
1078
|
+
const pksArray = this.store.getOneByKey(key);
|
|
1079
|
+
if (!pksArray) return;
|
|
1080
|
+
const pksSet = new Set(pks);
|
|
1081
|
+
const filtered = pksArray.filter((pk) => !pksSet.has(pk));
|
|
1082
|
+
const hasChanges = filtered.length !== pksArray.length;
|
|
1083
|
+
if (hasChanges) {
|
|
1084
|
+
if (filtered.length === 0) {
|
|
1085
|
+
this.store.removeOneByKey(key);
|
|
1086
|
+
} else {
|
|
1087
|
+
this.store.setOneByKey(key, filtered);
|
|
1088
|
+
}
|
|
1089
|
+
this.emitUpdate([key]);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
1094
|
+
*/
|
|
1095
|
+
clear(key) {
|
|
1096
|
+
if (key === void 0) {
|
|
1097
|
+
const allKeys = this.store.getAllKeys();
|
|
1098
|
+
if (allKeys.length > 0) {
|
|
1099
|
+
this.store.clear();
|
|
1100
|
+
this.emitUpdate(allKeys);
|
|
1101
|
+
}
|
|
1102
|
+
} else {
|
|
1103
|
+
if (this.store.getOneByKey(key) !== void 0) {
|
|
1104
|
+
this.store.removeOneByKey(key);
|
|
1105
|
+
this.emitUpdate([key]);
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
|
|
1111
|
+
// src/core/OIMReactiveIndexManualArrayBased.ts
|
|
1112
|
+
var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased {
|
|
821
1113
|
constructor(queue, opts) {
|
|
822
1114
|
super(queue, opts);
|
|
823
1115
|
}
|
|
824
1116
|
createDefaultIndex() {
|
|
825
|
-
return new
|
|
1117
|
+
return new OIMIndexManualArrayBased();
|
|
826
1118
|
}
|
|
827
1119
|
setPks(key, pks) {
|
|
828
1120
|
this.index.setPks(key, pks);
|
|
@@ -1229,15 +1521,23 @@ export {
|
|
|
1229
1521
|
OIMEventQueueSchedulerImmediate,
|
|
1230
1522
|
OIMEventQueueSchedulerMicrotask,
|
|
1231
1523
|
OIMEventQueueSchedulerTimeout,
|
|
1232
|
-
|
|
1524
|
+
OIMIndexArrayBased,
|
|
1233
1525
|
OIMIndexComparatorFactory,
|
|
1234
|
-
|
|
1526
|
+
OIMIndexManualArrayBased,
|
|
1527
|
+
OIMIndexManualSetBased,
|
|
1528
|
+
OIMIndexSetBased,
|
|
1529
|
+
OIMIndexStoreArrayBased,
|
|
1530
|
+
OIMIndexStoreMapDrivenArrayBased,
|
|
1531
|
+
OIMIndexStoreMapDrivenSetBased,
|
|
1532
|
+
OIMIndexStoreSetBased,
|
|
1235
1533
|
OIMMap2Keys,
|
|
1236
1534
|
OIMPkSelectorFactory,
|
|
1237
1535
|
OIMRICollection,
|
|
1238
1536
|
OIMReactiveCollection,
|
|
1239
|
-
|
|
1240
|
-
|
|
1537
|
+
OIMReactiveIndexArrayBased,
|
|
1538
|
+
OIMReactiveIndexManualArrayBased,
|
|
1539
|
+
OIMReactiveIndexManualSetBased,
|
|
1540
|
+
OIMReactiveIndexSetBased,
|
|
1241
1541
|
OIMUpdateEventCoalescer,
|
|
1242
1542
|
OIMUpdateEventCoalescerCollection,
|
|
1243
1543
|
OIMUpdateEventCoalescerIndex,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oimdb/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.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",
|
|
@@ -32,6 +32,18 @@
|
|
|
32
32
|
"files": [
|
|
33
33
|
"dist"
|
|
34
34
|
],
|
|
35
|
+
"keywords": [
|
|
36
|
+
"oimdb",
|
|
37
|
+
"in-memory",
|
|
38
|
+
"database",
|
|
39
|
+
"reactive",
|
|
40
|
+
"typescript",
|
|
41
|
+
"type-safe",
|
|
42
|
+
"indices",
|
|
43
|
+
"subscriptions",
|
|
44
|
+
"event-processing",
|
|
45
|
+
"state-management"
|
|
46
|
+
],
|
|
35
47
|
"author": "Andrei Baikov",
|
|
36
48
|
"license": "MIT",
|
|
37
49
|
"devDependencies": {
|