@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/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/abstract/OIMIndexStore.ts
131
- var OIMIndexStore = class {
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/OIMIndex.ts
179
- var OIMIndex = class {
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 OIMIndexStoreMapDriven();
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/OIMIndexManual.ts
419
- var OIMIndexManual = class extends OIMIndex {
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 OIMIndexManual({
512
- store: new OIMIndexStoreMapDriven()
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/OIMReactiveIndex.ts
583
- var OIMReactiveIndex = class {
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/OIMReactiveIndexManual.ts
820
- var OIMReactiveIndexManual = class extends OIMReactiveIndex {
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 OIMIndexManual();
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
- OIMIndex,
1524
+ OIMIndexArrayBased,
1233
1525
  OIMIndexComparatorFactory,
1234
- OIMIndexManual,
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
- OIMReactiveIndex,
1240
- OIMReactiveIndexManual,
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.2.2",
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": {