@oimdb/core 3.6.0 → 3.8.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
@@ -634,6 +634,24 @@ users.upsertOne({ id: 'user1', role: 'admin' });
634
634
  // This prevents unnecessary re-renders and improves performance
635
635
  ```
636
636
 
637
+ ### Disposing everything at once — `OIMDisposeScope`
638
+
639
+ Teardown is LIFO: dispose dependents before what they depend on (indexes / streams / selectors → collection → queue). Instead of tracking that order by hand, register into an `OIMDisposeScope` as you build and tear it all down in one call:
640
+
641
+ ```typescript
642
+ import { OIMDisposeScope, OIMEventQueue, OIMReactiveCollection } from '@oimdb/core';
643
+
644
+ const scope = new OIMDisposeScope();
645
+ const queue = scope.add(new OIMEventQueue());
646
+ const users = scope.add(new OIMReactiveCollection(queue, { selectPk: u => u.id }));
647
+ const byTeam = scope.add(usersIndexFactory.setBasedIndex());
648
+ scope.add(selector.watch(render)); // bare unsubscribe fn works too
649
+
650
+ scope.destroy(); // disposes byTeam → users → queue (reverse order), no bookkeeping
651
+ ```
652
+
653
+ `add(x)` returns `x` for inline capture. Accepts both `{ destroy(): void }` objects and bare `() => void` unsubscribe functions (selectors, per-key subscriptions and scheduler tasks expose only the latter). Idempotent; every item is disposed even if one throws (first error rethrown after); `child()` nests a sub-scope. Factory: `createOIMDisposeScope()`. Related exports: `IOIMDisposable`, `TOIMDisposable`.
654
+
637
655
  ### Effects, Computed, and the Event Lifecycle
638
656
 
639
657
  OIMDB uses a single-pass flush boundary: `queue.flush()` executes the current batch of pending work.
@@ -1361,6 +1379,8 @@ createOIMCollectionIndexFactory(queue, collection)
1361
1379
 
1362
1380
  **Methods:**
1363
1381
  - `setBasedIndex<TKey>()` - Create `OIMReactiveCollectionIndexManualSetBased<TKey, TPk, TEntity>`
1382
+ - `compositeSetIndex()` - Create `OIMReactiveCollectionIndexCompositeTrieSetBased<TPk, TEntity>` — set-based index keyed by a composite **key path** (`TOIMKeyPath`, an arbitrary-length tuple of primitive segments, e.g. `setPks([projectId, role], pks)`). Matched by content in O(arity), no string concatenation. Primitive-keyed indexes keep their native-`Map` fast path.
1383
+ - `compositeArrayIndex()` - Create `OIMReactiveCollectionIndexCompositeTrieArrayBased<TPk, TEntity>` — ordered counterpart of `compositeSetIndex`, buckets are ordered slot arrays per key path.
1364
1384
  - `derivedSetIndex<TKey>(selectIndexKeys)` - Create `OIMDerivedCollectionIndexSetBased<TKey, TPk, TEntity>`
1365
1385
  - `arrayBasedIndex<TKey>()` - Create `OIMReactiveCollectionIndexManualArrayBased<TKey, TPk, TEntity>`
1366
1386
  - `derivedArrayIndex<TKey>(selectIndexKeys, { orderBy?, compareEntities? })` - Create `OIMDerivedCollectionIndexArrayBased<TKey, TPk, TEntity>`