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