@oimdb/core 1.2.1 → 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 CHANGED
@@ -15,7 +15,8 @@ This package exports all the core classes, interfaces, and types needed to build
15
15
  ### Core Classes
16
16
  - **OIMReactiveCollection**: Reactive entity storage with automatic change notifications
17
17
  - **OIMRICollection**: Reactive collection with integrated indexing capabilities
18
- - **OIMReactiveIndexManual**: Reactive index with manual key-to-entity mapping
18
+ - **OIMReactiveIndexManualSetBased**: Reactive index with Set-based storage (efficient for incremental updates)
19
+ - **OIMReactiveIndexManualArrayBased**: Reactive index with Array-based storage (efficient for full replacements)
19
20
  - **OIMEventQueue**: Configurable event processing queue with scheduler integration
20
21
  - **OIMCollection**: Base collection with CRUD operations and event emission
21
22
 
@@ -27,14 +28,19 @@ This package exports all the core classes, interfaces, and types needed to build
27
28
 
28
29
  ### Storage & Indexing
29
30
  - **OIMCollectionStoreMapDriven**: Map-based storage backend
30
- - **OIMIndexManual**: Manual index management with custom comparison logic
31
+ - **OIMIndexManualSetBased**: Set-based manual index (returns `Set<TPk>`)
32
+ - **OIMIndexManualArrayBased**: Array-based manual index (returns `TPk[]`)
33
+ - **OIMIndexStoreMapDrivenSetBased**: Set-based index storage backend
34
+ - **OIMIndexStoreMapDrivenArrayBased**: Array-based index storage backend
31
35
  - **OIMMap2Keys**: Two-key mapping utilities for complex indexing
32
36
 
33
37
  ### Abstract Classes & Interfaces
34
38
  - **OIMCollectionStore**: Storage backend interface
35
39
  - **OIMEventQueueScheduler**: Event processing scheduler interface
36
- - **OIMIndex**: Base index interface
37
- - **OIMReactiveIndex**: Reactive index interface
40
+ - **OIMIndexSetBased**: Base Set-based index interface (returns `Set<TPk>`)
41
+ - **OIMIndexArrayBased**: Base Array-based index interface (returns `TPk[]`)
42
+ - **OIMReactiveIndexSetBased**: Reactive Set-based index interface
43
+ - **OIMReactiveIndexArrayBased**: Reactive Array-based index interface
38
44
 
39
45
  ### Types & Enums
40
46
  - **TOIM\***: Generic types for collections, indices, events, and schedulers
@@ -92,36 +98,72 @@ const multipleUsers = users.getManyByPks(['user1', 'user2']);
92
98
 
93
99
  ### Creating a Reactive Index
94
100
 
101
+ OIMDB provides two types of indexes optimized for different use cases:
102
+
103
+ #### SetBased Indexes (for incremental updates)
104
+
95
105
  ```typescript
96
- import { OIMReactiveIndexManual, OIMEventQueue } from '@oimdb/core';
106
+ import { OIMReactiveIndexManualSetBased, OIMEventQueue } from '@oimdb/core';
97
107
 
98
- // Create reactive index for user roles
108
+ // Create Set-based reactive index for user roles
99
109
  const queue = new OIMEventQueue({
100
110
  scheduler: OIMEventQueueSchedulerFactory.createMicrotask()
101
111
  });
102
112
 
103
- const userRoleIndex = new OIMReactiveIndexManual<string, string>(queue);
113
+ const userRoleIndex = new OIMReactiveIndexManualSetBased<string, string>(queue);
104
114
 
105
115
  // Subscribe to specific index key changes
106
116
  userRoleIndex.updateEventEmitter.subscribeOnKey('admin', (pks) => {
107
- console.log('Admin users changed:', pks);
117
+ console.log('Admin users changed:', pks); // pks is Set<string>
108
118
  });
109
119
 
110
120
  // Build the index manually
111
121
  userRoleIndex.setPks('admin', ['user1']);
112
122
  userRoleIndex.setPks('user', ['user2', 'user3']);
113
123
 
114
- // Add more users to existing roles
124
+ // Add more users to existing roles (efficient for Set-based)
115
125
  userRoleIndex.addPks('admin', ['user2']);
116
126
 
117
- // Query the index
118
- const adminUsers = userRoleIndex.index.getPksByKey('admin'); // ['user1', 'user2']
119
- const regularUsers = userRoleIndex.index.getPksByKey('user'); // ['user2', 'user3']
127
+ // Query the index - returns Set
128
+ const adminUsers = userRoleIndex.index.getPksByKey('admin'); // Set(['user1', 'user2'])
129
+ const regularUsers = userRoleIndex.index.getPksByKey('user'); // Set(['user2', 'user3'])
120
130
 
121
- // Remove users from roles
131
+ // Remove users from roles (efficient for Set-based)
122
132
  userRoleIndex.removePks('admin', ['user1']);
123
133
  ```
124
134
 
135
+ #### ArrayBased Indexes (for full replacements)
136
+
137
+ ```typescript
138
+ import { OIMReactiveIndexManualArrayBased, OIMEventQueue } from '@oimdb/core';
139
+
140
+ // Create Array-based reactive index for deck cards
141
+ const queue = new OIMEventQueue({
142
+ scheduler: OIMEventQueueSchedulerFactory.createMicrotask()
143
+ });
144
+
145
+ const cardsByDeckIndex = new OIMReactiveIndexManualArrayBased<string, string>(queue);
146
+
147
+ // Subscribe to specific index key changes
148
+ cardsByDeckIndex.updateEventEmitter.subscribeOnKey('deck1', (pks) => {
149
+ console.log('Deck cards changed:', pks); // pks is string[]
150
+ });
151
+
152
+ // Build the index manually - set full array
153
+ cardsByDeckIndex.setPks('deck1', ['card1', 'card2', 'card3']);
154
+
155
+ // Query the index - returns Array
156
+ const deckCards = cardsByDeckIndex.index.getPksByKey('deck1'); // ['card1', 'card2', 'card3']
157
+
158
+ // For Array-based indexes, prefer setPks for updates (addPks/removePks are available but less efficient)
159
+ cardsByDeckIndex.setPks('deck1', ['card1', 'card2', 'card4']); // Full replacement (recommended)
160
+ // cardsByDeckIndex.addPks('deck1', ['card5']); // Works but less efficient than SetBased
161
+ ```
162
+
163
+ **When to use which:**
164
+ - **SetBased**: Use when you frequently add/remove individual items (`addPks`/`removePks` are efficient) and order doesn't matter
165
+ - **ArrayBased**: Use when you typically replace the entire array (`setPks` is more efficient, no diff computation needed) or when you need to preserve element order/sorting
166
+
125
167
  ### Event Queue and Schedulers
126
168
 
127
169
  ```typescript
@@ -187,9 +229,9 @@ const queue = new OIMEventQueue({
187
229
  scheduler: OIMEventQueueSchedulerFactory.createMicrotask()
188
230
  });
189
231
 
190
- // Create indexes
191
- const teamIndex = new OIMReactiveIndexManual<string, string>(queue);
192
- const roleIndex = new OIMReactiveIndexManual<string, string>(queue);
232
+ // Create indexes (choose SetBased or ArrayBased based on your needs)
233
+ const teamIndex = new OIMReactiveIndexManualSetBased<string, string>(queue);
234
+ const roleIndex = new OIMReactiveIndexManualArrayBased<string, string>(queue);
193
235
 
194
236
  // Create collection with indexes
195
237
  const users = new OIMRICollection(queue, {
@@ -334,9 +376,13 @@ OIMCollection (base)
334
376
  ├── OIMReactiveCollection (adds event emitter + coalescing)
335
377
  └── OIMRICollection (reactive collection + indexes)
336
378
 
337
- OIMIndex (base)
338
- ├── OIMIndexManual (manual index management)
339
- └── OIMReactiveIndexManual (reactive index with event emitter)
379
+ OIMIndexSetBased (base for Set-based)
380
+ ├── OIMIndexManualSetBased (manual Set-based index)
381
+ └── OIMReactiveIndexManualSetBased (reactive Set-based index with event emitter)
382
+
383
+ OIMIndexArrayBased (base for Array-based)
384
+ ├── OIMIndexManualArrayBased (manual Array-based index)
385
+ └── OIMReactiveIndexManualArrayBased (reactive Array-based index with event emitter)
340
386
  ```
341
387
 
342
388
  ## ⚡ Performance Characteristics
@@ -352,6 +398,21 @@ OIMIndex (base)
352
398
  - **Timeout**: Custom delay for batching strategies
353
399
  - **AnimationFrame**: 16ms, synced with 60fps rendering
354
400
 
401
+ ### Index Performance
402
+
403
+ **SetBased Indexes** (`OIMReactiveIndexManualSetBased`):
404
+ - **Returns**: `Set<TPk>` for efficient membership checks
405
+ - **Best for**: Frequent incremental updates using `addPks`/`removePks`
406
+ - **Performance**: O(1) add/remove operations, O(n) for `setPks` (requires Set creation)
407
+ - **Use case**: When you need to frequently add/remove individual items
408
+
409
+ **ArrayBased Indexes** (`OIMReactiveIndexManualArrayBased`):
410
+ - **Returns**: `TPk[]` for direct array access
411
+ - **Best for**: Full array replacements using `setPks`
412
+ - **Performance**: O(1) `setPks` operation (direct assignment, no diff computation)
413
+ - **Use case**: When you typically replace the entire array (e.g., deck cards, ordered lists) or when you need to preserve element order/sorting
414
+ - **Note**: While `addPks`/`removePks` are available, they are less efficient (O(n)) than for SetBased indexes. For ArrayBased indexes, prefer `setPks` for better performance.
415
+
355
416
  ## 🔗 Integration Patterns
356
417
 
357
418
  ### With React (@oimdb/react)
@@ -462,26 +523,54 @@ new OIMRICollection(queue: OIMEventQueue, opts: {
462
523
  - `indexes: TReactiveIndexMap` - Named reactive indexes preserving index-to-name mapping
463
524
  - *(inherits all OIMReactiveCollection properties)*
464
525
 
465
- #### `OIMReactiveIndexManual<TKey, TPk>`
466
- Reactive index with manual key-to-entity mapping and change notifications.
526
+ #### `OIMReactiveIndexManualSetBased<TKey, TPk>`
527
+ Reactive Set-based index with manual key-to-entity mapping and change notifications. Returns `Set<TPk>` for efficient membership checks.
528
+
529
+ **Constructor:**
530
+ ```typescript
531
+ new OIMReactiveIndexManualSetBased(queue: OIMEventQueue, opts?: {
532
+ index?: OIMIndexManualSetBased<TKey, TPk>
533
+ })
534
+ ```
535
+
536
+ **Properties:**
537
+ - `index: OIMIndexManualSetBased<TKey, TPk>` - Underlying Set-based index
538
+ - `updateEventEmitter: OIMUpdateEventEmitter<TKey>` - Key-specific subscriptions
539
+
540
+ **Methods:**
541
+ - `setPks(key: TKey, pks: readonly TPk[]): void` - Set primary keys for index key (replaces entire Set)
542
+ - `addPks(key: TKey, pks: readonly TPk[]): void` - Add primary keys to index key (efficient)
543
+ - `removePks(key: TKey, pks: readonly TPk[]): void` - Remove primary keys from index key (efficient)
544
+ - `clear(key?: TKey): void` - Clear all keys or specific key
545
+
546
+ **Query:**
547
+ - `index.getPksByKey(key: TKey): Set<TPk>` - Returns Set of primary keys
548
+
549
+ #### `OIMReactiveIndexManualArrayBased<TKey, TPk>`
550
+ Reactive Array-based index with manual key-to-entity mapping and change notifications. Returns `TPk[]` for direct array access.
467
551
 
468
552
  **Constructor:**
469
553
  ```typescript
470
- new OIMReactiveIndexManual(queue: OIMEventQueue, opts?: {
471
- index?: OIMIndexManual<TKey, TPk>
554
+ new OIMReactiveIndexManualArrayBased(queue: OIMEventQueue, opts?: {
555
+ index?: OIMIndexManualArrayBased<TKey, TPk>
472
556
  })
473
557
  ```
474
558
 
475
559
  **Properties:**
476
- - `index: OIMIndexManual<TKey, TPk>` - Underlying index
560
+ - `index: OIMIndexManualArrayBased<TKey, TPk>` - Underlying Array-based index
477
561
  - `updateEventEmitter: OIMUpdateEventEmitter<TKey>` - Key-specific subscriptions
478
562
 
479
563
  **Methods:**
480
- - `setPks(key: TKey, pks: readonly TPk[]): void` - Set primary keys for index key
481
- - `addPks(key: TKey, pks: readonly TPk[]): void` - Add primary keys to index key
482
- - `removePks(key: TKey, pks: readonly TPk[]): void` - Remove primary keys from index key
564
+ - `setPks(key: TKey, pks: readonly TPk[]): void` - Set primary keys for index key (direct assignment, no diff) - **Recommended for ArrayBased**
565
+ - `addPks(key: TKey, pks: readonly TPk[]): void` - Add primary keys to index key (O(n) operation, less efficient than SetBased)
566
+ - `removePks(key: TKey, pks: readonly TPk[]): void` - Remove primary keys from index key (O(n) operation, less efficient than SetBased)
483
567
  - `clear(key?: TKey): void` - Clear all keys or specific key
484
568
 
569
+ **Query:**
570
+ - `index.getPksByKey(key: TKey): TPk[]` - Returns Array of primary keys
571
+
572
+ **Note**: While `addPks`/`removePks` are available, they require array operations (Set creation, filtering) making them O(n) compared to O(1) for SetBased indexes. For ArrayBased indexes, prefer `setPks` for better performance when replacing the entire array.
573
+
485
574
  #### `OIMEventQueue`
486
575
  Event processing queue with configurable scheduling.
487
576