@oimdb/core 3.4.0 → 3.5.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.cjs +170 -2
- package/dist/index.d.cts +110 -2
- package/dist/index.d.ts +110 -2
- package/dist/index.js +167 -1
- package/llms.txt +33 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -83,6 +83,7 @@ __export(index_exports, {
|
|
|
83
83
|
OIMObjectValueByKeySelector: () => OIMObjectValueByKeySelector,
|
|
84
84
|
OIMObjectValuesByKeysSelector: () => OIMObjectValuesByKeysSelector,
|
|
85
85
|
OIMOrderedListCommandStream: () => OIMOrderedListCommandStream,
|
|
86
|
+
OIMOrderedListMappedCommandStream: () => OIMOrderedListMappedCommandStream,
|
|
86
87
|
OIMPkSelectorFactory: () => OIMPkSelectorFactory,
|
|
87
88
|
OIMReactiveCollection: () => OIMReactiveCollection,
|
|
88
89
|
OIMReactiveCollectionIndexManualArrayBased: () => OIMReactiveCollectionIndexManualArrayBased,
|
|
@@ -97,7 +98,8 @@ __export(index_exports, {
|
|
|
97
98
|
createInPlaceEntityUpdater: () => createInPlaceEntityUpdater,
|
|
98
99
|
createMergeEntityUpdater: () => createMergeEntityUpdater,
|
|
99
100
|
createOIMCollectionIndexFactory: () => createOIMCollectionIndexFactory,
|
|
100
|
-
createOIMCollectionKit: () => createOIMCollectionKit
|
|
101
|
+
createOIMCollectionKit: () => createOIMCollectionKit,
|
|
102
|
+
createOIMOrderedListMappedCommandStream: () => createOIMOrderedListMappedCommandStream
|
|
101
103
|
});
|
|
102
104
|
module.exports = __toCommonJS(index_exports);
|
|
103
105
|
|
|
@@ -1704,6 +1706,14 @@ var OIMOrderedListCommandStream = class {
|
|
|
1704
1706
|
key
|
|
1705
1707
|
);
|
|
1706
1708
|
}
|
|
1709
|
+
/** {@link IOIMOrderedListCommandSource} — alias of {@link getSlotsByKey}. */
|
|
1710
|
+
getItemsByKey(key) {
|
|
1711
|
+
return this.getSlotsByKey(key);
|
|
1712
|
+
}
|
|
1713
|
+
/** {@link IOIMOrderedListCommandSource} — per-key command subscription. */
|
|
1714
|
+
subscribeCommands(key, handler) {
|
|
1715
|
+
return this.commandsEventEmitter.subscribeOnKey(key, handler);
|
|
1716
|
+
}
|
|
1707
1717
|
getEntitiesByKey(key) {
|
|
1708
1718
|
return this.index.getEntitiesByKey(key);
|
|
1709
1719
|
}
|
|
@@ -3650,6 +3660,162 @@ var OIMCollectionChangedFields = class {
|
|
|
3650
3660
|
}
|
|
3651
3661
|
};
|
|
3652
3662
|
|
|
3663
|
+
// src/modules/wrapper/index/OIMOrderedListMappedCommandStream.ts
|
|
3664
|
+
var OIMOrderedListMappedCommandStream = class _OIMOrderedListMappedCommandStream {
|
|
3665
|
+
constructor(source, opts) {
|
|
3666
|
+
/** Per-key positional mirror of the mapped elements. */
|
|
3667
|
+
this.mirror = /* @__PURE__ */ new Map();
|
|
3668
|
+
/** Mapped commands produced for the current delivery, per key. */
|
|
3669
|
+
this.buffer = /* @__PURE__ */ new Map();
|
|
3670
|
+
this.subscribers = /* @__PURE__ */ new Map();
|
|
3671
|
+
this.sourceUnsubscribers = /* @__PURE__ */ new Map();
|
|
3672
|
+
this.source = source;
|
|
3673
|
+
this.create = opts.create;
|
|
3674
|
+
this.destroyItem = opts.destroy;
|
|
3675
|
+
}
|
|
3676
|
+
subscribeCommands(key, handler) {
|
|
3677
|
+
this.ensureWired(key);
|
|
3678
|
+
let subs = this.subscribers.get(key);
|
|
3679
|
+
if (!subs) {
|
|
3680
|
+
subs = /* @__PURE__ */ new Set();
|
|
3681
|
+
this.subscribers.set(key, subs);
|
|
3682
|
+
}
|
|
3683
|
+
subs.add(handler);
|
|
3684
|
+
return () => {
|
|
3685
|
+
const current = this.subscribers.get(key);
|
|
3686
|
+
if (!current) return;
|
|
3687
|
+
current.delete(handler);
|
|
3688
|
+
if (current.size === 0) this.subscribers.delete(key);
|
|
3689
|
+
};
|
|
3690
|
+
}
|
|
3691
|
+
consumeCommands(key) {
|
|
3692
|
+
const cmds = this.buffer.get(key);
|
|
3693
|
+
if (!cmds || cmds.length === 0) return [];
|
|
3694
|
+
return cmds.slice();
|
|
3695
|
+
}
|
|
3696
|
+
getItemsByKey(key) {
|
|
3697
|
+
this.ensureWired(key);
|
|
3698
|
+
return this.mirror.get(key) ?? [];
|
|
3699
|
+
}
|
|
3700
|
+
/** Map this source again, chaining the projection. */
|
|
3701
|
+
map(opts) {
|
|
3702
|
+
return new _OIMOrderedListMappedCommandStream(
|
|
3703
|
+
this,
|
|
3704
|
+
opts
|
|
3705
|
+
);
|
|
3706
|
+
}
|
|
3707
|
+
destroy() {
|
|
3708
|
+
this.sourceUnsubscribers.forEach((unsubscribe) => unsubscribe());
|
|
3709
|
+
this.sourceUnsubscribers.clear();
|
|
3710
|
+
if (this.destroyItem) {
|
|
3711
|
+
this.mirror.forEach(
|
|
3712
|
+
(items) => items.forEach((item) => this.destroyItem(item))
|
|
3713
|
+
);
|
|
3714
|
+
}
|
|
3715
|
+
this.mirror.clear();
|
|
3716
|
+
this.buffer.clear();
|
|
3717
|
+
this.subscribers.clear();
|
|
3718
|
+
}
|
|
3719
|
+
/** Build the initial mirror and subscribe to the source once per key. */
|
|
3720
|
+
ensureWired(key) {
|
|
3721
|
+
if (this.mirror.has(key)) return;
|
|
3722
|
+
const items = this.source.getItemsByKey(key);
|
|
3723
|
+
this.mirror.set(key, items.map((item) => this.create(item)));
|
|
3724
|
+
const unsubscribe = this.source.subscribeCommands(
|
|
3725
|
+
key,
|
|
3726
|
+
() => this.onSourceCommands(key)
|
|
3727
|
+
);
|
|
3728
|
+
this.sourceUnsubscribers.set(key, unsubscribe);
|
|
3729
|
+
}
|
|
3730
|
+
onSourceCommands(key) {
|
|
3731
|
+
const cmds = this.source.consumeCommands(key);
|
|
3732
|
+
if (cmds.length === 0) return;
|
|
3733
|
+
let mirror = this.mirror.get(key);
|
|
3734
|
+
if (!mirror) {
|
|
3735
|
+
mirror = [];
|
|
3736
|
+
this.mirror.set(key, mirror);
|
|
3737
|
+
}
|
|
3738
|
+
const out = [];
|
|
3739
|
+
for (let i = 0; i < cmds.length; i++) {
|
|
3740
|
+
const cmd = cmds[i];
|
|
3741
|
+
switch (cmd.type) {
|
|
3742
|
+
case "insert": {
|
|
3743
|
+
const mapped = this.create(cmd.item);
|
|
3744
|
+
mirror.splice(cmd.index, 0, mapped);
|
|
3745
|
+
out.push({
|
|
3746
|
+
type: "insert",
|
|
3747
|
+
index: cmd.index,
|
|
3748
|
+
item: mapped
|
|
3749
|
+
});
|
|
3750
|
+
break;
|
|
3751
|
+
}
|
|
3752
|
+
case "remove": {
|
|
3753
|
+
const count = cmd.count ?? 1;
|
|
3754
|
+
const removed = mirror.splice(cmd.index, count);
|
|
3755
|
+
if (this.destroyItem) {
|
|
3756
|
+
for (let r = 0; r < removed.length; r++) {
|
|
3757
|
+
this.destroyItem(removed[r]);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
out.push({ type: "remove", index: cmd.index, count });
|
|
3761
|
+
break;
|
|
3762
|
+
}
|
|
3763
|
+
case "move": {
|
|
3764
|
+
const count = cmd.count ?? 1;
|
|
3765
|
+
const segment = mirror.splice(cmd.from, count);
|
|
3766
|
+
mirror.splice(cmd.to, 0, ...segment);
|
|
3767
|
+
out.push({
|
|
3768
|
+
type: "move",
|
|
3769
|
+
from: cmd.from,
|
|
3770
|
+
to: cmd.to,
|
|
3771
|
+
count
|
|
3772
|
+
});
|
|
3773
|
+
break;
|
|
3774
|
+
}
|
|
3775
|
+
case "set": {
|
|
3776
|
+
const mapped = this.create(cmd.item);
|
|
3777
|
+
const replaced = mirror.splice(cmd.index, 1, mapped);
|
|
3778
|
+
if (this.destroyItem && replaced.length > 0) {
|
|
3779
|
+
this.destroyItem(replaced[0]);
|
|
3780
|
+
}
|
|
3781
|
+
out.push({ type: "set", index: cmd.index, item: mapped });
|
|
3782
|
+
break;
|
|
3783
|
+
}
|
|
3784
|
+
case "reset": {
|
|
3785
|
+
if (this.destroyItem) {
|
|
3786
|
+
for (let r = 0; r < mirror.length; r++) {
|
|
3787
|
+
this.destroyItem(mirror[r]);
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
const mapped = cmd.items.map((item) => this.create(item));
|
|
3791
|
+
mirror = mapped;
|
|
3792
|
+
this.mirror.set(key, mapped);
|
|
3793
|
+
out.push({ type: "reset", items: mapped });
|
|
3794
|
+
break;
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
this.buffer.set(key, out);
|
|
3799
|
+
try {
|
|
3800
|
+
const subs = this.subscribers.get(key);
|
|
3801
|
+
if (subs && subs.size > 0) {
|
|
3802
|
+
const snapshot = Array.from(subs);
|
|
3803
|
+
for (let s = 0; s < snapshot.length; s++) {
|
|
3804
|
+
const handler = snapshot[s];
|
|
3805
|
+
if (subs.has(handler)) handler();
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
} finally {
|
|
3809
|
+
this.buffer.delete(key);
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
};
|
|
3813
|
+
|
|
3814
|
+
// src/modules/wrapper/index/createOIMOrderedListMappedCommandStream.ts
|
|
3815
|
+
function createOIMOrderedListMappedCommandStream(source, opts) {
|
|
3816
|
+
return new OIMOrderedListMappedCommandStream(source, opts);
|
|
3817
|
+
}
|
|
3818
|
+
|
|
3653
3819
|
// src/core/event-queue-scheduler/OIMEventQueueSchedulerAnimationFrame.ts
|
|
3654
3820
|
var OIMEventQueueSchedulerAnimationFrame = class extends OIMEventQueueScheduler {
|
|
3655
3821
|
constructor() {
|
|
@@ -4283,6 +4449,7 @@ var OIMIndexPksByKeysArrayBasedSelector = class extends OIMSelector {
|
|
|
4283
4449
|
OIMObjectValueByKeySelector,
|
|
4284
4450
|
OIMObjectValuesByKeysSelector,
|
|
4285
4451
|
OIMOrderedListCommandStream,
|
|
4452
|
+
OIMOrderedListMappedCommandStream,
|
|
4286
4453
|
OIMPkSelectorFactory,
|
|
4287
4454
|
OIMReactiveCollection,
|
|
4288
4455
|
OIMReactiveCollectionIndexManualArrayBased,
|
|
@@ -4297,5 +4464,6 @@ var OIMIndexPksByKeysArrayBasedSelector = class extends OIMSelector {
|
|
|
4297
4464
|
createInPlaceEntityUpdater,
|
|
4298
4465
|
createMergeEntityUpdater,
|
|
4299
4466
|
createOIMCollectionIndexFactory,
|
|
4300
|
-
createOIMCollectionKit
|
|
4467
|
+
createOIMCollectionKit,
|
|
4468
|
+
createOIMOrderedListMappedCommandStream
|
|
4301
4469
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -759,6 +759,32 @@ type TOIMOrderedListCommand<TItem> = {
|
|
|
759
759
|
items: readonly TItem[];
|
|
760
760
|
};
|
|
761
761
|
|
|
762
|
+
/**
|
|
763
|
+
* Read/consume side of an ordered-list command stream, generic over the element
|
|
764
|
+
* type it carries.
|
|
765
|
+
*
|
|
766
|
+
* The concrete stream stores entity slots (`TItem = TOIMEntitySlot<...>`); a
|
|
767
|
+
* mapped source ({@link OIMOrderedListMappedCommandStream}) carries whatever the
|
|
768
|
+
* mapping produces. A consumer that depends on this interface works unchanged
|
|
769
|
+
* against either — raw or mapped.
|
|
770
|
+
*
|
|
771
|
+
* Consumption is pull-based and synchronous: the notification carries no
|
|
772
|
+
* payload, so `consumeCommands(key)` must be called inside the `handler`, before
|
|
773
|
+
* the buffer for that key is cleared.
|
|
774
|
+
*/
|
|
775
|
+
interface IOIMOrderedListCommandSource<TKey extends TOIMPk, TItem> {
|
|
776
|
+
/**
|
|
777
|
+
* Subscribe to per-key command notifications. The handler receives no
|
|
778
|
+
* payload — pull the commands with {@link consumeCommands} synchronously.
|
|
779
|
+
* Returns an unsubscribe function.
|
|
780
|
+
*/
|
|
781
|
+
subscribeCommands(key: TKey, handler: () => void): () => void;
|
|
782
|
+
/** Drain the commands buffered for `key` this delivery (a copy). */
|
|
783
|
+
consumeCommands(key: TKey): TOIMOrderedListCommand<TItem>[];
|
|
784
|
+
/** Current ordered items for `key` — the initial state before any command. */
|
|
785
|
+
getItemsByKey(key: TKey): readonly TItem[];
|
|
786
|
+
}
|
|
787
|
+
|
|
762
788
|
/**
|
|
763
789
|
* Slot-first ordered-list command stream.
|
|
764
790
|
*
|
|
@@ -766,8 +792,12 @@ type TOIMOrderedListCommand<TItem> = {
|
|
|
766
792
|
* entity slot. Use this when you already have slots and want incremental
|
|
767
793
|
* commands for an imperative renderer. For PK writes bound to a collection, use
|
|
768
794
|
* `OIMCollectionOrderedListCommandStream`.
|
|
795
|
+
*
|
|
796
|
+
* Implements {@link IOIMOrderedListCommandSource} (with the slot as the element)
|
|
797
|
+
* so it can be projected element-wise via
|
|
798
|
+
* `createOIMOrderedListMappedCommandStream`.
|
|
769
799
|
*/
|
|
770
|
-
declare class OIMOrderedListCommandStream<TKey extends TOIMPk, TPk extends TOIMPk, TEntity extends object = object> {
|
|
800
|
+
declare class OIMOrderedListCommandStream<TKey extends TOIMPk, TPk extends TOIMPk, TEntity extends object = object> implements IOIMOrderedListCommandSource<TKey, TOIMEntitySlot<TEntity, TPk>> {
|
|
771
801
|
readonly commandsEventEmitter: OIMUpdateEventEmitter<TKey>;
|
|
772
802
|
private readonly unsubscribeAfterFlush;
|
|
773
803
|
private readonly unsubscribeFromIndexEmitter;
|
|
@@ -778,6 +808,10 @@ declare class OIMOrderedListCommandStream<TKey extends TOIMPk, TPk extends TOIMP
|
|
|
778
808
|
constructor(queue: OIMEventQueue, index?: OIMIndexManualOrderedArrayBased<TKey, TPk>);
|
|
779
809
|
getPksByKey(key: TKey): readonly TPk[];
|
|
780
810
|
getSlotsByKey(key: TKey): readonly TOIMEntitySlot<TEntity, TPk>[];
|
|
811
|
+
/** {@link IOIMOrderedListCommandSource} — alias of {@link getSlotsByKey}. */
|
|
812
|
+
getItemsByKey(key: TKey): readonly TOIMEntitySlot<TEntity, TPk>[];
|
|
813
|
+
/** {@link IOIMOrderedListCommandSource} — per-key command subscription. */
|
|
814
|
+
subscribeCommands(key: TKey, handler: () => void): () => void;
|
|
781
815
|
getEntitiesByKey(key: TKey): (TEntity | undefined)[];
|
|
782
816
|
hasKey(key: TKey): boolean;
|
|
783
817
|
getKeys(): readonly TKey[];
|
|
@@ -1398,6 +1432,80 @@ declare class OIMCollectionChangedFields<TEntity extends object, TPk extends TOI
|
|
|
1398
1432
|
private trackPatch;
|
|
1399
1433
|
}
|
|
1400
1434
|
|
|
1435
|
+
/**
|
|
1436
|
+
* Options for {@link OIMOrderedListMappedCommandStream} — how a source element
|
|
1437
|
+
* (`TIn`) is projected to a downstream element (`TOut`) and torn down.
|
|
1438
|
+
*
|
|
1439
|
+
* `create` runs once per element when it enters the list (an `insert`, a `set`
|
|
1440
|
+
* replacement, or list build / `reset`). `destroy` runs when it leaves (a
|
|
1441
|
+
* `remove`, the replaced half of a `set`, every element on `reset`, and on
|
|
1442
|
+
* stream `destroy()`). A `move` reuses the same `TOut` — it is never recreated.
|
|
1443
|
+
*/
|
|
1444
|
+
type TOIMOrderedListMapOptions<TIn, TOut> = {
|
|
1445
|
+
create: (item: TIn) => TOut;
|
|
1446
|
+
destroy?: (mapped: TOut) => void;
|
|
1447
|
+
};
|
|
1448
|
+
|
|
1449
|
+
/**
|
|
1450
|
+
* Projects an ordered-list command source element-wise, re-emitting the same
|
|
1451
|
+
* position-addressed commands with `item` replaced by the mapped value.
|
|
1452
|
+
*
|
|
1453
|
+
* It rides the source's batching: there is no queue and no independent
|
|
1454
|
+
* scheduling. On each source notification it pulls the source commands,
|
|
1455
|
+
* translates them (running `create` / `destroy` and updating a positional
|
|
1456
|
+
* mirror of the mapped elements), and notifies its own subscribers
|
|
1457
|
+
* synchronously — so the source's `after_flush` semantics carry through.
|
|
1458
|
+
*
|
|
1459
|
+
* Identity is positional: a `move` reorders the *same* mapped references in the
|
|
1460
|
+
* mirror, so the mapped element is preserved across moves and never recreated.
|
|
1461
|
+
* `create` runs on `insert` / `set` / `reset` / initial build; `destroy` on
|
|
1462
|
+
* `remove` / the replaced half of `set` / every element on `reset` / `destroy()`.
|
|
1463
|
+
*
|
|
1464
|
+
* Wiring to the source for a key is lazy (on first `subscribeCommands` or
|
|
1465
|
+
* `getItemsByKey`) and lives until `destroy()`; subscriber churn does not
|
|
1466
|
+
* create or tear down mapped elements.
|
|
1467
|
+
*
|
|
1468
|
+
* The output is itself an {@link IOIMOrderedListCommandSource}, so maps chain:
|
|
1469
|
+
* `source.map(...)` → `.map(...)`.
|
|
1470
|
+
*/
|
|
1471
|
+
declare class OIMOrderedListMappedCommandStream<TKey extends TOIMPk, TOut, TIn> implements IOIMOrderedListCommandSource<TKey, TOut> {
|
|
1472
|
+
private readonly source;
|
|
1473
|
+
private readonly create;
|
|
1474
|
+
private readonly destroyItem?;
|
|
1475
|
+
/** Per-key positional mirror of the mapped elements. */
|
|
1476
|
+
private readonly mirror;
|
|
1477
|
+
/** Mapped commands produced for the current delivery, per key. */
|
|
1478
|
+
private readonly buffer;
|
|
1479
|
+
private readonly subscribers;
|
|
1480
|
+
private readonly sourceUnsubscribers;
|
|
1481
|
+
constructor(source: IOIMOrderedListCommandSource<TKey, TIn>, opts: TOIMOrderedListMapOptions<TIn, TOut>);
|
|
1482
|
+
subscribeCommands(key: TKey, handler: () => void): () => void;
|
|
1483
|
+
consumeCommands(key: TKey): TOIMOrderedListCommand<TOut>[];
|
|
1484
|
+
getItemsByKey(key: TKey): readonly TOut[];
|
|
1485
|
+
/** Map this source again, chaining the projection. */
|
|
1486
|
+
map<TNext>(opts: TOIMOrderedListMapOptions<TOut, TNext>): OIMOrderedListMappedCommandStream<TKey, TNext, TOut>;
|
|
1487
|
+
destroy(): void;
|
|
1488
|
+
/** Build the initial mirror and subscribe to the source once per key. */
|
|
1489
|
+
private ensureWired;
|
|
1490
|
+
private onSourceCommands;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
/**
|
|
1494
|
+
* Map an ordered-list command source element-wise. The result is itself a
|
|
1495
|
+
* source, so it can be mapped again (or via its `.map()` method).
|
|
1496
|
+
*
|
|
1497
|
+
* ```ts
|
|
1498
|
+
* const nodes = createOIMOrderedListMappedCommandStream(stream, {
|
|
1499
|
+
* create: (slot) => engine.makeNode(slot.item),
|
|
1500
|
+
* destroy: (node) => engine.dropNode(node),
|
|
1501
|
+
* });
|
|
1502
|
+
* nodes.subscribeCommands(key, () =>
|
|
1503
|
+
* engine.apply(nodes.consumeCommands(key))
|
|
1504
|
+
* );
|
|
1505
|
+
* ```
|
|
1506
|
+
*/
|
|
1507
|
+
declare function createOIMOrderedListMappedCommandStream<TKey extends TOIMPk, TIn, TOut>(source: IOIMOrderedListCommandSource<TKey, TIn>, opts: TOIMOrderedListMapOptions<TIn, TOut>): OIMOrderedListMappedCommandStream<TKey, TOut, TIn>;
|
|
1508
|
+
|
|
1401
1509
|
/**
|
|
1402
1510
|
* Animation frame-based scheduler that executes flushes synchronized with the browser's repaint cycle.
|
|
1403
1511
|
* Ideal for UI-related updates that need to be synchronized with rendering.
|
|
@@ -1750,4 +1858,4 @@ declare class OIMEntitiesByIndexKeyArrayBasedSelector<TEntity extends object, TP
|
|
|
1750
1858
|
protected areEqual(prev: readonly (TEntity | undefined)[], next: readonly (TEntity | undefined)[]): boolean;
|
|
1751
1859
|
}
|
|
1752
1860
|
|
|
1753
|
-
export { EOIMCollectionEventType, EOIMComputedEventType, EOIMEventQueueEventType, EOIMEventQueueSchedulerEventType, EOIMIndexEventType, EOIMObjectEventType, type IOIMCarrierResolver, type IOIMComputedEventSource, type IOIMEffectDependency, type IOIMEventQueueSchedulerEvents, type IOIMIndexStore, type IOIMKeyedUpdateEmitter, type IOIMSubscribable, OIMCarrierKeyedEmitter, OIMCollection, OIMCollectionByPkSelector, OIMCollectionByPksSelector, OIMCollectionChangedFields, OIMCollectionIndexFactory, OIMCollectionIndexManualOrderedArrayBased, OIMCollectionOrderedListCommandStream, OIMCollectionSelectors, OIMCollectionStore, OIMCollectionStoreMapDriven, OIMComparatorFactory, OIMComputeRuntime, OIMComputed, OIMDBSettings, OIMDerivedCollectionIndexArrayBased, OIMDerivedCollectionIndexSetBased, OIMEffect, OIMEffectDependencyComputed, OIMEffectDependencyKeyed, OIMEffectDependencyKeyedCollection, OIMEffectDependencyKeyedIndex, OIMEffectDependencyKeyedObject, OIMEntitiesByIndexKeyArrayBasedSelector, OIMEntitiesByIndexKeySetBasedSelector, OIMEntityUpdaterFactory, OIMEventEmitter, OIMEventQueue, OIMEventQueueScheduler, OIMEventQueueSchedulerAnimationFrame, OIMEventQueueSchedulerFactory, OIMEventQueueSchedulerImmediate, OIMEventQueueSchedulerMicrotask, OIMEventQueueSchedulerTimeout, OIMIndex, OIMIndexArrayBased, OIMIndexComparatorFactory, OIMIndexManualArrayBased, OIMIndexManualOrderedArrayBased, OIMIndexManualSetBased, OIMIndexPksByKeyArrayBasedSelector, OIMIndexPksByKeySetBasedSelector, OIMIndexPksByKeysArrayBasedSelector, OIMIndexPksByKeysSetBasedSelector, OIMIndexSetBased, OIMIndexStoreArrayBased, OIMIndexStoreMapDrivenArrayBased, OIMIndexStoreMapDrivenSetBased, OIMIndexStoreSetBased, OIMMap2Keys, OIMObject, OIMObjectStore, OIMObjectStoreMapDriven, OIMObjectStoreRecordDriven, OIMObjectValueByKeySelector, OIMObjectValuesByKeysSelector, OIMOrderedListCommandStream, OIMPkSelectorFactory, OIMReactiveCollection, OIMReactiveCollectionIndexManualArrayBased, OIMReactiveCollectionIndexManualSetBased, OIMReactiveIndex, OIMReactiveIndexArrayBased, OIMReactiveIndexManualArrayBased, OIMReactiveIndexManualSetBased, OIMReactiveIndexSetBased, OIMReactiveObject, OIMSelector, type TOIMAnyEntitySlot, type TOIMCollectionEntitiesSelector, type TOIMCollectionEntitySelector, type TOIMCollectionIndexArrayBasedOptions, type TOIMCollectionIndexSetBasedOptions, type TOIMCollectionKit, type TOIMCollectionOptions, type TOIMCollectionOrderedIndexOptions, type TOIMCollectionOrderedListCommandStreamOptions, type TOIMCollectionUpdatePayload, type TOIMComparator, type TOIMComputedOptions, type TOIMComputedUpdatePayload, type TOIMDerivedCollectionIndexArrayBasedOptions, type TOIMDerivedCollectionIndexSetBasedOptions, type TOIMDerivedEntityComparator, type TOIMDerivedEntityOrderSelector, type TOIMDerivedEntityOrderValue, type TOIMDerivedIndexKeySelector, type TOIMEffectOptions, type TOIMEntitySlot, type TOIMEntitySlotResolver, type TOIMEntityUpdater, type TOIMEventHandler, type TOIMEventQueueOptions, type TOIMIndexComparator, type TOIMIndexKey, type TOIMIndexOptionsArrayBased, type TOIMIndexOptionsSetBased, type TOIMIndexPksUpdatePayload, type TOIMIndexUpdatePayload, type TOIMObjectOptions, type TOIMOrderedListCommand, type TOIMPk, type TOIMPkSelector, type TOIMReactiveCollectionFactoryOptions, type TOIMRelationsArrayIndexOptions, type TOIMRelationsDerivedArrayIndexOptions, type TOIMRelationsDerivedSetIndexOptions, type TOIMRelationsOrderedListOptions, type TOIMRelationsSetIndexOptions, type TOIMSchedulerOptions, type TOIMSchedulerType, type TOIMUpdatePayload, createInPlaceEntityUpdater, createMergeEntityUpdater, createOIMCollectionIndexFactory, createOIMCollectionKit };
|
|
1861
|
+
export { EOIMCollectionEventType, EOIMComputedEventType, EOIMEventQueueEventType, EOIMEventQueueSchedulerEventType, EOIMIndexEventType, EOIMObjectEventType, type IOIMCarrierResolver, type IOIMComputedEventSource, type IOIMEffectDependency, type IOIMEventQueueSchedulerEvents, type IOIMIndexStore, type IOIMKeyedUpdateEmitter, type IOIMOrderedListCommandSource, type IOIMSubscribable, OIMCarrierKeyedEmitter, OIMCollection, OIMCollectionByPkSelector, OIMCollectionByPksSelector, OIMCollectionChangedFields, OIMCollectionIndexFactory, OIMCollectionIndexManualOrderedArrayBased, OIMCollectionOrderedListCommandStream, OIMCollectionSelectors, OIMCollectionStore, OIMCollectionStoreMapDriven, OIMComparatorFactory, OIMComputeRuntime, OIMComputed, OIMDBSettings, OIMDerivedCollectionIndexArrayBased, OIMDerivedCollectionIndexSetBased, OIMEffect, OIMEffectDependencyComputed, OIMEffectDependencyKeyed, OIMEffectDependencyKeyedCollection, OIMEffectDependencyKeyedIndex, OIMEffectDependencyKeyedObject, OIMEntitiesByIndexKeyArrayBasedSelector, OIMEntitiesByIndexKeySetBasedSelector, OIMEntityUpdaterFactory, OIMEventEmitter, OIMEventQueue, OIMEventQueueScheduler, OIMEventQueueSchedulerAnimationFrame, OIMEventQueueSchedulerFactory, OIMEventQueueSchedulerImmediate, OIMEventQueueSchedulerMicrotask, OIMEventQueueSchedulerTimeout, OIMIndex, OIMIndexArrayBased, OIMIndexComparatorFactory, OIMIndexManualArrayBased, OIMIndexManualOrderedArrayBased, OIMIndexManualSetBased, OIMIndexPksByKeyArrayBasedSelector, OIMIndexPksByKeySetBasedSelector, OIMIndexPksByKeysArrayBasedSelector, OIMIndexPksByKeysSetBasedSelector, OIMIndexSetBased, OIMIndexStoreArrayBased, OIMIndexStoreMapDrivenArrayBased, OIMIndexStoreMapDrivenSetBased, OIMIndexStoreSetBased, OIMMap2Keys, OIMObject, OIMObjectStore, OIMObjectStoreMapDriven, OIMObjectStoreRecordDriven, OIMObjectValueByKeySelector, OIMObjectValuesByKeysSelector, OIMOrderedListCommandStream, OIMOrderedListMappedCommandStream, OIMPkSelectorFactory, OIMReactiveCollection, OIMReactiveCollectionIndexManualArrayBased, OIMReactiveCollectionIndexManualSetBased, OIMReactiveIndex, OIMReactiveIndexArrayBased, OIMReactiveIndexManualArrayBased, OIMReactiveIndexManualSetBased, OIMReactiveIndexSetBased, OIMReactiveObject, OIMSelector, type TOIMAnyEntitySlot, type TOIMCollectionEntitiesSelector, type TOIMCollectionEntitySelector, type TOIMCollectionIndexArrayBasedOptions, type TOIMCollectionIndexSetBasedOptions, type TOIMCollectionKit, type TOIMCollectionOptions, type TOIMCollectionOrderedIndexOptions, type TOIMCollectionOrderedListCommandStreamOptions, type TOIMCollectionUpdatePayload, type TOIMComparator, type TOIMComputedOptions, type TOIMComputedUpdatePayload, type TOIMDerivedCollectionIndexArrayBasedOptions, type TOIMDerivedCollectionIndexSetBasedOptions, type TOIMDerivedEntityComparator, type TOIMDerivedEntityOrderSelector, type TOIMDerivedEntityOrderValue, type TOIMDerivedIndexKeySelector, type TOIMEffectOptions, type TOIMEntitySlot, type TOIMEntitySlotResolver, type TOIMEntityUpdater, type TOIMEventHandler, type TOIMEventQueueOptions, type TOIMIndexComparator, type TOIMIndexKey, type TOIMIndexOptionsArrayBased, type TOIMIndexOptionsSetBased, type TOIMIndexPksUpdatePayload, type TOIMIndexUpdatePayload, type TOIMObjectOptions, type TOIMOrderedListCommand, type TOIMOrderedListMapOptions, type TOIMPk, type TOIMPkSelector, type TOIMReactiveCollectionFactoryOptions, type TOIMRelationsArrayIndexOptions, type TOIMRelationsDerivedArrayIndexOptions, type TOIMRelationsDerivedSetIndexOptions, type TOIMRelationsOrderedListOptions, type TOIMRelationsSetIndexOptions, type TOIMSchedulerOptions, type TOIMSchedulerType, type TOIMUpdatePayload, createInPlaceEntityUpdater, createMergeEntityUpdater, createOIMCollectionIndexFactory, createOIMCollectionKit, createOIMOrderedListMappedCommandStream };
|
package/dist/index.d.ts
CHANGED
|
@@ -759,6 +759,32 @@ type TOIMOrderedListCommand<TItem> = {
|
|
|
759
759
|
items: readonly TItem[];
|
|
760
760
|
};
|
|
761
761
|
|
|
762
|
+
/**
|
|
763
|
+
* Read/consume side of an ordered-list command stream, generic over the element
|
|
764
|
+
* type it carries.
|
|
765
|
+
*
|
|
766
|
+
* The concrete stream stores entity slots (`TItem = TOIMEntitySlot<...>`); a
|
|
767
|
+
* mapped source ({@link OIMOrderedListMappedCommandStream}) carries whatever the
|
|
768
|
+
* mapping produces. A consumer that depends on this interface works unchanged
|
|
769
|
+
* against either — raw or mapped.
|
|
770
|
+
*
|
|
771
|
+
* Consumption is pull-based and synchronous: the notification carries no
|
|
772
|
+
* payload, so `consumeCommands(key)` must be called inside the `handler`, before
|
|
773
|
+
* the buffer for that key is cleared.
|
|
774
|
+
*/
|
|
775
|
+
interface IOIMOrderedListCommandSource<TKey extends TOIMPk, TItem> {
|
|
776
|
+
/**
|
|
777
|
+
* Subscribe to per-key command notifications. The handler receives no
|
|
778
|
+
* payload — pull the commands with {@link consumeCommands} synchronously.
|
|
779
|
+
* Returns an unsubscribe function.
|
|
780
|
+
*/
|
|
781
|
+
subscribeCommands(key: TKey, handler: () => void): () => void;
|
|
782
|
+
/** Drain the commands buffered for `key` this delivery (a copy). */
|
|
783
|
+
consumeCommands(key: TKey): TOIMOrderedListCommand<TItem>[];
|
|
784
|
+
/** Current ordered items for `key` — the initial state before any command. */
|
|
785
|
+
getItemsByKey(key: TKey): readonly TItem[];
|
|
786
|
+
}
|
|
787
|
+
|
|
762
788
|
/**
|
|
763
789
|
* Slot-first ordered-list command stream.
|
|
764
790
|
*
|
|
@@ -766,8 +792,12 @@ type TOIMOrderedListCommand<TItem> = {
|
|
|
766
792
|
* entity slot. Use this when you already have slots and want incremental
|
|
767
793
|
* commands for an imperative renderer. For PK writes bound to a collection, use
|
|
768
794
|
* `OIMCollectionOrderedListCommandStream`.
|
|
795
|
+
*
|
|
796
|
+
* Implements {@link IOIMOrderedListCommandSource} (with the slot as the element)
|
|
797
|
+
* so it can be projected element-wise via
|
|
798
|
+
* `createOIMOrderedListMappedCommandStream`.
|
|
769
799
|
*/
|
|
770
|
-
declare class OIMOrderedListCommandStream<TKey extends TOIMPk, TPk extends TOIMPk, TEntity extends object = object> {
|
|
800
|
+
declare class OIMOrderedListCommandStream<TKey extends TOIMPk, TPk extends TOIMPk, TEntity extends object = object> implements IOIMOrderedListCommandSource<TKey, TOIMEntitySlot<TEntity, TPk>> {
|
|
771
801
|
readonly commandsEventEmitter: OIMUpdateEventEmitter<TKey>;
|
|
772
802
|
private readonly unsubscribeAfterFlush;
|
|
773
803
|
private readonly unsubscribeFromIndexEmitter;
|
|
@@ -778,6 +808,10 @@ declare class OIMOrderedListCommandStream<TKey extends TOIMPk, TPk extends TOIMP
|
|
|
778
808
|
constructor(queue: OIMEventQueue, index?: OIMIndexManualOrderedArrayBased<TKey, TPk>);
|
|
779
809
|
getPksByKey(key: TKey): readonly TPk[];
|
|
780
810
|
getSlotsByKey(key: TKey): readonly TOIMEntitySlot<TEntity, TPk>[];
|
|
811
|
+
/** {@link IOIMOrderedListCommandSource} — alias of {@link getSlotsByKey}. */
|
|
812
|
+
getItemsByKey(key: TKey): readonly TOIMEntitySlot<TEntity, TPk>[];
|
|
813
|
+
/** {@link IOIMOrderedListCommandSource} — per-key command subscription. */
|
|
814
|
+
subscribeCommands(key: TKey, handler: () => void): () => void;
|
|
781
815
|
getEntitiesByKey(key: TKey): (TEntity | undefined)[];
|
|
782
816
|
hasKey(key: TKey): boolean;
|
|
783
817
|
getKeys(): readonly TKey[];
|
|
@@ -1398,6 +1432,80 @@ declare class OIMCollectionChangedFields<TEntity extends object, TPk extends TOI
|
|
|
1398
1432
|
private trackPatch;
|
|
1399
1433
|
}
|
|
1400
1434
|
|
|
1435
|
+
/**
|
|
1436
|
+
* Options for {@link OIMOrderedListMappedCommandStream} — how a source element
|
|
1437
|
+
* (`TIn`) is projected to a downstream element (`TOut`) and torn down.
|
|
1438
|
+
*
|
|
1439
|
+
* `create` runs once per element when it enters the list (an `insert`, a `set`
|
|
1440
|
+
* replacement, or list build / `reset`). `destroy` runs when it leaves (a
|
|
1441
|
+
* `remove`, the replaced half of a `set`, every element on `reset`, and on
|
|
1442
|
+
* stream `destroy()`). A `move` reuses the same `TOut` — it is never recreated.
|
|
1443
|
+
*/
|
|
1444
|
+
type TOIMOrderedListMapOptions<TIn, TOut> = {
|
|
1445
|
+
create: (item: TIn) => TOut;
|
|
1446
|
+
destroy?: (mapped: TOut) => void;
|
|
1447
|
+
};
|
|
1448
|
+
|
|
1449
|
+
/**
|
|
1450
|
+
* Projects an ordered-list command source element-wise, re-emitting the same
|
|
1451
|
+
* position-addressed commands with `item` replaced by the mapped value.
|
|
1452
|
+
*
|
|
1453
|
+
* It rides the source's batching: there is no queue and no independent
|
|
1454
|
+
* scheduling. On each source notification it pulls the source commands,
|
|
1455
|
+
* translates them (running `create` / `destroy` and updating a positional
|
|
1456
|
+
* mirror of the mapped elements), and notifies its own subscribers
|
|
1457
|
+
* synchronously — so the source's `after_flush` semantics carry through.
|
|
1458
|
+
*
|
|
1459
|
+
* Identity is positional: a `move` reorders the *same* mapped references in the
|
|
1460
|
+
* mirror, so the mapped element is preserved across moves and never recreated.
|
|
1461
|
+
* `create` runs on `insert` / `set` / `reset` / initial build; `destroy` on
|
|
1462
|
+
* `remove` / the replaced half of `set` / every element on `reset` / `destroy()`.
|
|
1463
|
+
*
|
|
1464
|
+
* Wiring to the source for a key is lazy (on first `subscribeCommands` or
|
|
1465
|
+
* `getItemsByKey`) and lives until `destroy()`; subscriber churn does not
|
|
1466
|
+
* create or tear down mapped elements.
|
|
1467
|
+
*
|
|
1468
|
+
* The output is itself an {@link IOIMOrderedListCommandSource}, so maps chain:
|
|
1469
|
+
* `source.map(...)` → `.map(...)`.
|
|
1470
|
+
*/
|
|
1471
|
+
declare class OIMOrderedListMappedCommandStream<TKey extends TOIMPk, TOut, TIn> implements IOIMOrderedListCommandSource<TKey, TOut> {
|
|
1472
|
+
private readonly source;
|
|
1473
|
+
private readonly create;
|
|
1474
|
+
private readonly destroyItem?;
|
|
1475
|
+
/** Per-key positional mirror of the mapped elements. */
|
|
1476
|
+
private readonly mirror;
|
|
1477
|
+
/** Mapped commands produced for the current delivery, per key. */
|
|
1478
|
+
private readonly buffer;
|
|
1479
|
+
private readonly subscribers;
|
|
1480
|
+
private readonly sourceUnsubscribers;
|
|
1481
|
+
constructor(source: IOIMOrderedListCommandSource<TKey, TIn>, opts: TOIMOrderedListMapOptions<TIn, TOut>);
|
|
1482
|
+
subscribeCommands(key: TKey, handler: () => void): () => void;
|
|
1483
|
+
consumeCommands(key: TKey): TOIMOrderedListCommand<TOut>[];
|
|
1484
|
+
getItemsByKey(key: TKey): readonly TOut[];
|
|
1485
|
+
/** Map this source again, chaining the projection. */
|
|
1486
|
+
map<TNext>(opts: TOIMOrderedListMapOptions<TOut, TNext>): OIMOrderedListMappedCommandStream<TKey, TNext, TOut>;
|
|
1487
|
+
destroy(): void;
|
|
1488
|
+
/** Build the initial mirror and subscribe to the source once per key. */
|
|
1489
|
+
private ensureWired;
|
|
1490
|
+
private onSourceCommands;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
/**
|
|
1494
|
+
* Map an ordered-list command source element-wise. The result is itself a
|
|
1495
|
+
* source, so it can be mapped again (or via its `.map()` method).
|
|
1496
|
+
*
|
|
1497
|
+
* ```ts
|
|
1498
|
+
* const nodes = createOIMOrderedListMappedCommandStream(stream, {
|
|
1499
|
+
* create: (slot) => engine.makeNode(slot.item),
|
|
1500
|
+
* destroy: (node) => engine.dropNode(node),
|
|
1501
|
+
* });
|
|
1502
|
+
* nodes.subscribeCommands(key, () =>
|
|
1503
|
+
* engine.apply(nodes.consumeCommands(key))
|
|
1504
|
+
* );
|
|
1505
|
+
* ```
|
|
1506
|
+
*/
|
|
1507
|
+
declare function createOIMOrderedListMappedCommandStream<TKey extends TOIMPk, TIn, TOut>(source: IOIMOrderedListCommandSource<TKey, TIn>, opts: TOIMOrderedListMapOptions<TIn, TOut>): OIMOrderedListMappedCommandStream<TKey, TOut, TIn>;
|
|
1508
|
+
|
|
1401
1509
|
/**
|
|
1402
1510
|
* Animation frame-based scheduler that executes flushes synchronized with the browser's repaint cycle.
|
|
1403
1511
|
* Ideal for UI-related updates that need to be synchronized with rendering.
|
|
@@ -1750,4 +1858,4 @@ declare class OIMEntitiesByIndexKeyArrayBasedSelector<TEntity extends object, TP
|
|
|
1750
1858
|
protected areEqual(prev: readonly (TEntity | undefined)[], next: readonly (TEntity | undefined)[]): boolean;
|
|
1751
1859
|
}
|
|
1752
1860
|
|
|
1753
|
-
export { EOIMCollectionEventType, EOIMComputedEventType, EOIMEventQueueEventType, EOIMEventQueueSchedulerEventType, EOIMIndexEventType, EOIMObjectEventType, type IOIMCarrierResolver, type IOIMComputedEventSource, type IOIMEffectDependency, type IOIMEventQueueSchedulerEvents, type IOIMIndexStore, type IOIMKeyedUpdateEmitter, type IOIMSubscribable, OIMCarrierKeyedEmitter, OIMCollection, OIMCollectionByPkSelector, OIMCollectionByPksSelector, OIMCollectionChangedFields, OIMCollectionIndexFactory, OIMCollectionIndexManualOrderedArrayBased, OIMCollectionOrderedListCommandStream, OIMCollectionSelectors, OIMCollectionStore, OIMCollectionStoreMapDriven, OIMComparatorFactory, OIMComputeRuntime, OIMComputed, OIMDBSettings, OIMDerivedCollectionIndexArrayBased, OIMDerivedCollectionIndexSetBased, OIMEffect, OIMEffectDependencyComputed, OIMEffectDependencyKeyed, OIMEffectDependencyKeyedCollection, OIMEffectDependencyKeyedIndex, OIMEffectDependencyKeyedObject, OIMEntitiesByIndexKeyArrayBasedSelector, OIMEntitiesByIndexKeySetBasedSelector, OIMEntityUpdaterFactory, OIMEventEmitter, OIMEventQueue, OIMEventQueueScheduler, OIMEventQueueSchedulerAnimationFrame, OIMEventQueueSchedulerFactory, OIMEventQueueSchedulerImmediate, OIMEventQueueSchedulerMicrotask, OIMEventQueueSchedulerTimeout, OIMIndex, OIMIndexArrayBased, OIMIndexComparatorFactory, OIMIndexManualArrayBased, OIMIndexManualOrderedArrayBased, OIMIndexManualSetBased, OIMIndexPksByKeyArrayBasedSelector, OIMIndexPksByKeySetBasedSelector, OIMIndexPksByKeysArrayBasedSelector, OIMIndexPksByKeysSetBasedSelector, OIMIndexSetBased, OIMIndexStoreArrayBased, OIMIndexStoreMapDrivenArrayBased, OIMIndexStoreMapDrivenSetBased, OIMIndexStoreSetBased, OIMMap2Keys, OIMObject, OIMObjectStore, OIMObjectStoreMapDriven, OIMObjectStoreRecordDriven, OIMObjectValueByKeySelector, OIMObjectValuesByKeysSelector, OIMOrderedListCommandStream, OIMPkSelectorFactory, OIMReactiveCollection, OIMReactiveCollectionIndexManualArrayBased, OIMReactiveCollectionIndexManualSetBased, OIMReactiveIndex, OIMReactiveIndexArrayBased, OIMReactiveIndexManualArrayBased, OIMReactiveIndexManualSetBased, OIMReactiveIndexSetBased, OIMReactiveObject, OIMSelector, type TOIMAnyEntitySlot, type TOIMCollectionEntitiesSelector, type TOIMCollectionEntitySelector, type TOIMCollectionIndexArrayBasedOptions, type TOIMCollectionIndexSetBasedOptions, type TOIMCollectionKit, type TOIMCollectionOptions, type TOIMCollectionOrderedIndexOptions, type TOIMCollectionOrderedListCommandStreamOptions, type TOIMCollectionUpdatePayload, type TOIMComparator, type TOIMComputedOptions, type TOIMComputedUpdatePayload, type TOIMDerivedCollectionIndexArrayBasedOptions, type TOIMDerivedCollectionIndexSetBasedOptions, type TOIMDerivedEntityComparator, type TOIMDerivedEntityOrderSelector, type TOIMDerivedEntityOrderValue, type TOIMDerivedIndexKeySelector, type TOIMEffectOptions, type TOIMEntitySlot, type TOIMEntitySlotResolver, type TOIMEntityUpdater, type TOIMEventHandler, type TOIMEventQueueOptions, type TOIMIndexComparator, type TOIMIndexKey, type TOIMIndexOptionsArrayBased, type TOIMIndexOptionsSetBased, type TOIMIndexPksUpdatePayload, type TOIMIndexUpdatePayload, type TOIMObjectOptions, type TOIMOrderedListCommand, type TOIMPk, type TOIMPkSelector, type TOIMReactiveCollectionFactoryOptions, type TOIMRelationsArrayIndexOptions, type TOIMRelationsDerivedArrayIndexOptions, type TOIMRelationsDerivedSetIndexOptions, type TOIMRelationsOrderedListOptions, type TOIMRelationsSetIndexOptions, type TOIMSchedulerOptions, type TOIMSchedulerType, type TOIMUpdatePayload, createInPlaceEntityUpdater, createMergeEntityUpdater, createOIMCollectionIndexFactory, createOIMCollectionKit };
|
|
1861
|
+
export { EOIMCollectionEventType, EOIMComputedEventType, EOIMEventQueueEventType, EOIMEventQueueSchedulerEventType, EOIMIndexEventType, EOIMObjectEventType, type IOIMCarrierResolver, type IOIMComputedEventSource, type IOIMEffectDependency, type IOIMEventQueueSchedulerEvents, type IOIMIndexStore, type IOIMKeyedUpdateEmitter, type IOIMOrderedListCommandSource, type IOIMSubscribable, OIMCarrierKeyedEmitter, OIMCollection, OIMCollectionByPkSelector, OIMCollectionByPksSelector, OIMCollectionChangedFields, OIMCollectionIndexFactory, OIMCollectionIndexManualOrderedArrayBased, OIMCollectionOrderedListCommandStream, OIMCollectionSelectors, OIMCollectionStore, OIMCollectionStoreMapDriven, OIMComparatorFactory, OIMComputeRuntime, OIMComputed, OIMDBSettings, OIMDerivedCollectionIndexArrayBased, OIMDerivedCollectionIndexSetBased, OIMEffect, OIMEffectDependencyComputed, OIMEffectDependencyKeyed, OIMEffectDependencyKeyedCollection, OIMEffectDependencyKeyedIndex, OIMEffectDependencyKeyedObject, OIMEntitiesByIndexKeyArrayBasedSelector, OIMEntitiesByIndexKeySetBasedSelector, OIMEntityUpdaterFactory, OIMEventEmitter, OIMEventQueue, OIMEventQueueScheduler, OIMEventQueueSchedulerAnimationFrame, OIMEventQueueSchedulerFactory, OIMEventQueueSchedulerImmediate, OIMEventQueueSchedulerMicrotask, OIMEventQueueSchedulerTimeout, OIMIndex, OIMIndexArrayBased, OIMIndexComparatorFactory, OIMIndexManualArrayBased, OIMIndexManualOrderedArrayBased, OIMIndexManualSetBased, OIMIndexPksByKeyArrayBasedSelector, OIMIndexPksByKeySetBasedSelector, OIMIndexPksByKeysArrayBasedSelector, OIMIndexPksByKeysSetBasedSelector, OIMIndexSetBased, OIMIndexStoreArrayBased, OIMIndexStoreMapDrivenArrayBased, OIMIndexStoreMapDrivenSetBased, OIMIndexStoreSetBased, OIMMap2Keys, OIMObject, OIMObjectStore, OIMObjectStoreMapDriven, OIMObjectStoreRecordDriven, OIMObjectValueByKeySelector, OIMObjectValuesByKeysSelector, OIMOrderedListCommandStream, OIMOrderedListMappedCommandStream, OIMPkSelectorFactory, OIMReactiveCollection, OIMReactiveCollectionIndexManualArrayBased, OIMReactiveCollectionIndexManualSetBased, OIMReactiveIndex, OIMReactiveIndexArrayBased, OIMReactiveIndexManualArrayBased, OIMReactiveIndexManualSetBased, OIMReactiveIndexSetBased, OIMReactiveObject, OIMSelector, type TOIMAnyEntitySlot, type TOIMCollectionEntitiesSelector, type TOIMCollectionEntitySelector, type TOIMCollectionIndexArrayBasedOptions, type TOIMCollectionIndexSetBasedOptions, type TOIMCollectionKit, type TOIMCollectionOptions, type TOIMCollectionOrderedIndexOptions, type TOIMCollectionOrderedListCommandStreamOptions, type TOIMCollectionUpdatePayload, type TOIMComparator, type TOIMComputedOptions, type TOIMComputedUpdatePayload, type TOIMDerivedCollectionIndexArrayBasedOptions, type TOIMDerivedCollectionIndexSetBasedOptions, type TOIMDerivedEntityComparator, type TOIMDerivedEntityOrderSelector, type TOIMDerivedEntityOrderValue, type TOIMDerivedIndexKeySelector, type TOIMEffectOptions, type TOIMEntitySlot, type TOIMEntitySlotResolver, type TOIMEntityUpdater, type TOIMEventHandler, type TOIMEventQueueOptions, type TOIMIndexComparator, type TOIMIndexKey, type TOIMIndexOptionsArrayBased, type TOIMIndexOptionsSetBased, type TOIMIndexPksUpdatePayload, type TOIMIndexUpdatePayload, type TOIMObjectOptions, type TOIMOrderedListCommand, type TOIMOrderedListMapOptions, type TOIMPk, type TOIMPkSelector, type TOIMReactiveCollectionFactoryOptions, type TOIMRelationsArrayIndexOptions, type TOIMRelationsDerivedArrayIndexOptions, type TOIMRelationsDerivedSetIndexOptions, type TOIMRelationsOrderedListOptions, type TOIMRelationsSetIndexOptions, type TOIMSchedulerOptions, type TOIMSchedulerType, type TOIMUpdatePayload, createInPlaceEntityUpdater, createMergeEntityUpdater, createOIMCollectionIndexFactory, createOIMCollectionKit, createOIMOrderedListMappedCommandStream };
|
package/dist/index.js
CHANGED
|
@@ -1601,6 +1601,14 @@ var OIMOrderedListCommandStream = class {
|
|
|
1601
1601
|
key
|
|
1602
1602
|
);
|
|
1603
1603
|
}
|
|
1604
|
+
/** {@link IOIMOrderedListCommandSource} — alias of {@link getSlotsByKey}. */
|
|
1605
|
+
getItemsByKey(key) {
|
|
1606
|
+
return this.getSlotsByKey(key);
|
|
1607
|
+
}
|
|
1608
|
+
/** {@link IOIMOrderedListCommandSource} — per-key command subscription. */
|
|
1609
|
+
subscribeCommands(key, handler) {
|
|
1610
|
+
return this.commandsEventEmitter.subscribeOnKey(key, handler);
|
|
1611
|
+
}
|
|
1604
1612
|
getEntitiesByKey(key) {
|
|
1605
1613
|
return this.index.getEntitiesByKey(key);
|
|
1606
1614
|
}
|
|
@@ -3547,6 +3555,162 @@ var OIMCollectionChangedFields = class {
|
|
|
3547
3555
|
}
|
|
3548
3556
|
};
|
|
3549
3557
|
|
|
3558
|
+
// src/modules/wrapper/index/OIMOrderedListMappedCommandStream.ts
|
|
3559
|
+
var OIMOrderedListMappedCommandStream = class _OIMOrderedListMappedCommandStream {
|
|
3560
|
+
constructor(source, opts) {
|
|
3561
|
+
/** Per-key positional mirror of the mapped elements. */
|
|
3562
|
+
this.mirror = /* @__PURE__ */ new Map();
|
|
3563
|
+
/** Mapped commands produced for the current delivery, per key. */
|
|
3564
|
+
this.buffer = /* @__PURE__ */ new Map();
|
|
3565
|
+
this.subscribers = /* @__PURE__ */ new Map();
|
|
3566
|
+
this.sourceUnsubscribers = /* @__PURE__ */ new Map();
|
|
3567
|
+
this.source = source;
|
|
3568
|
+
this.create = opts.create;
|
|
3569
|
+
this.destroyItem = opts.destroy;
|
|
3570
|
+
}
|
|
3571
|
+
subscribeCommands(key, handler) {
|
|
3572
|
+
this.ensureWired(key);
|
|
3573
|
+
let subs = this.subscribers.get(key);
|
|
3574
|
+
if (!subs) {
|
|
3575
|
+
subs = /* @__PURE__ */ new Set();
|
|
3576
|
+
this.subscribers.set(key, subs);
|
|
3577
|
+
}
|
|
3578
|
+
subs.add(handler);
|
|
3579
|
+
return () => {
|
|
3580
|
+
const current = this.subscribers.get(key);
|
|
3581
|
+
if (!current) return;
|
|
3582
|
+
current.delete(handler);
|
|
3583
|
+
if (current.size === 0) this.subscribers.delete(key);
|
|
3584
|
+
};
|
|
3585
|
+
}
|
|
3586
|
+
consumeCommands(key) {
|
|
3587
|
+
const cmds = this.buffer.get(key);
|
|
3588
|
+
if (!cmds || cmds.length === 0) return [];
|
|
3589
|
+
return cmds.slice();
|
|
3590
|
+
}
|
|
3591
|
+
getItemsByKey(key) {
|
|
3592
|
+
this.ensureWired(key);
|
|
3593
|
+
return this.mirror.get(key) ?? [];
|
|
3594
|
+
}
|
|
3595
|
+
/** Map this source again, chaining the projection. */
|
|
3596
|
+
map(opts) {
|
|
3597
|
+
return new _OIMOrderedListMappedCommandStream(
|
|
3598
|
+
this,
|
|
3599
|
+
opts
|
|
3600
|
+
);
|
|
3601
|
+
}
|
|
3602
|
+
destroy() {
|
|
3603
|
+
this.sourceUnsubscribers.forEach((unsubscribe) => unsubscribe());
|
|
3604
|
+
this.sourceUnsubscribers.clear();
|
|
3605
|
+
if (this.destroyItem) {
|
|
3606
|
+
this.mirror.forEach(
|
|
3607
|
+
(items) => items.forEach((item) => this.destroyItem(item))
|
|
3608
|
+
);
|
|
3609
|
+
}
|
|
3610
|
+
this.mirror.clear();
|
|
3611
|
+
this.buffer.clear();
|
|
3612
|
+
this.subscribers.clear();
|
|
3613
|
+
}
|
|
3614
|
+
/** Build the initial mirror and subscribe to the source once per key. */
|
|
3615
|
+
ensureWired(key) {
|
|
3616
|
+
if (this.mirror.has(key)) return;
|
|
3617
|
+
const items = this.source.getItemsByKey(key);
|
|
3618
|
+
this.mirror.set(key, items.map((item) => this.create(item)));
|
|
3619
|
+
const unsubscribe = this.source.subscribeCommands(
|
|
3620
|
+
key,
|
|
3621
|
+
() => this.onSourceCommands(key)
|
|
3622
|
+
);
|
|
3623
|
+
this.sourceUnsubscribers.set(key, unsubscribe);
|
|
3624
|
+
}
|
|
3625
|
+
onSourceCommands(key) {
|
|
3626
|
+
const cmds = this.source.consumeCommands(key);
|
|
3627
|
+
if (cmds.length === 0) return;
|
|
3628
|
+
let mirror = this.mirror.get(key);
|
|
3629
|
+
if (!mirror) {
|
|
3630
|
+
mirror = [];
|
|
3631
|
+
this.mirror.set(key, mirror);
|
|
3632
|
+
}
|
|
3633
|
+
const out = [];
|
|
3634
|
+
for (let i = 0; i < cmds.length; i++) {
|
|
3635
|
+
const cmd = cmds[i];
|
|
3636
|
+
switch (cmd.type) {
|
|
3637
|
+
case "insert": {
|
|
3638
|
+
const mapped = this.create(cmd.item);
|
|
3639
|
+
mirror.splice(cmd.index, 0, mapped);
|
|
3640
|
+
out.push({
|
|
3641
|
+
type: "insert",
|
|
3642
|
+
index: cmd.index,
|
|
3643
|
+
item: mapped
|
|
3644
|
+
});
|
|
3645
|
+
break;
|
|
3646
|
+
}
|
|
3647
|
+
case "remove": {
|
|
3648
|
+
const count = cmd.count ?? 1;
|
|
3649
|
+
const removed = mirror.splice(cmd.index, count);
|
|
3650
|
+
if (this.destroyItem) {
|
|
3651
|
+
for (let r = 0; r < removed.length; r++) {
|
|
3652
|
+
this.destroyItem(removed[r]);
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
out.push({ type: "remove", index: cmd.index, count });
|
|
3656
|
+
break;
|
|
3657
|
+
}
|
|
3658
|
+
case "move": {
|
|
3659
|
+
const count = cmd.count ?? 1;
|
|
3660
|
+
const segment = mirror.splice(cmd.from, count);
|
|
3661
|
+
mirror.splice(cmd.to, 0, ...segment);
|
|
3662
|
+
out.push({
|
|
3663
|
+
type: "move",
|
|
3664
|
+
from: cmd.from,
|
|
3665
|
+
to: cmd.to,
|
|
3666
|
+
count
|
|
3667
|
+
});
|
|
3668
|
+
break;
|
|
3669
|
+
}
|
|
3670
|
+
case "set": {
|
|
3671
|
+
const mapped = this.create(cmd.item);
|
|
3672
|
+
const replaced = mirror.splice(cmd.index, 1, mapped);
|
|
3673
|
+
if (this.destroyItem && replaced.length > 0) {
|
|
3674
|
+
this.destroyItem(replaced[0]);
|
|
3675
|
+
}
|
|
3676
|
+
out.push({ type: "set", index: cmd.index, item: mapped });
|
|
3677
|
+
break;
|
|
3678
|
+
}
|
|
3679
|
+
case "reset": {
|
|
3680
|
+
if (this.destroyItem) {
|
|
3681
|
+
for (let r = 0; r < mirror.length; r++) {
|
|
3682
|
+
this.destroyItem(mirror[r]);
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
const mapped = cmd.items.map((item) => this.create(item));
|
|
3686
|
+
mirror = mapped;
|
|
3687
|
+
this.mirror.set(key, mapped);
|
|
3688
|
+
out.push({ type: "reset", items: mapped });
|
|
3689
|
+
break;
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
this.buffer.set(key, out);
|
|
3694
|
+
try {
|
|
3695
|
+
const subs = this.subscribers.get(key);
|
|
3696
|
+
if (subs && subs.size > 0) {
|
|
3697
|
+
const snapshot = Array.from(subs);
|
|
3698
|
+
for (let s = 0; s < snapshot.length; s++) {
|
|
3699
|
+
const handler = snapshot[s];
|
|
3700
|
+
if (subs.has(handler)) handler();
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
} finally {
|
|
3704
|
+
this.buffer.delete(key);
|
|
3705
|
+
}
|
|
3706
|
+
}
|
|
3707
|
+
};
|
|
3708
|
+
|
|
3709
|
+
// src/modules/wrapper/index/createOIMOrderedListMappedCommandStream.ts
|
|
3710
|
+
function createOIMOrderedListMappedCommandStream(source, opts) {
|
|
3711
|
+
return new OIMOrderedListMappedCommandStream(source, opts);
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3550
3714
|
// src/core/event-queue-scheduler/OIMEventQueueSchedulerAnimationFrame.ts
|
|
3551
3715
|
var OIMEventQueueSchedulerAnimationFrame = class extends OIMEventQueueScheduler {
|
|
3552
3716
|
constructor() {
|
|
@@ -4179,6 +4343,7 @@ export {
|
|
|
4179
4343
|
OIMObjectValueByKeySelector,
|
|
4180
4344
|
OIMObjectValuesByKeysSelector,
|
|
4181
4345
|
OIMOrderedListCommandStream,
|
|
4346
|
+
OIMOrderedListMappedCommandStream,
|
|
4182
4347
|
OIMPkSelectorFactory,
|
|
4183
4348
|
OIMReactiveCollection,
|
|
4184
4349
|
OIMReactiveCollectionIndexManualArrayBased,
|
|
@@ -4193,5 +4358,6 @@ export {
|
|
|
4193
4358
|
createInPlaceEntityUpdater,
|
|
4194
4359
|
createMergeEntityUpdater,
|
|
4195
4360
|
createOIMCollectionIndexFactory,
|
|
4196
|
-
createOIMCollectionKit
|
|
4361
|
+
createOIMCollectionKit,
|
|
4362
|
+
createOIMOrderedListMappedCommandStream
|
|
4197
4363
|
};
|
package/llms.txt
CHANGED
|
@@ -84,6 +84,39 @@ Membership writes are incremental (touch only the changed pks):
|
|
|
84
84
|
- `setPks` / `addPks` resolve each pk → slot (O(1) lookup); if you already hold slots (`collection.upsertMany` returns them) use `setSlots` / `appendSlots` to skip the lookup.
|
|
85
85
|
- `getEntitiesByKey(key)` returns `(TEntity | undefined)[]` — positional holes for not-yet-loaded pks, aligned with `getPksByKey` (not dropped), so you can render a loading state.
|
|
86
86
|
|
|
87
|
+
### Ordered list command stream
|
|
88
|
+
|
|
89
|
+
For an ordered per-key list that emits **position-addressed commands** (insert / remove / move / set / reset) instead of a new array to diff — for imperative renderers that apply edits in place. `OIMCollectionOrderedListCommandStream` (pk writes, via `indexFactory.orderedList()`) or `OIMOrderedListCommandStream` (slot writes). Commands are not in the event payload — subscribe, then pull synchronously.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { createOIMOrderedListMappedCommandStream } from '@oimdb/core';
|
|
93
|
+
|
|
94
|
+
stream.push('main', 'u1'); // append by pk; also insertAt/setAt/removeAt/removeRange/moveRange/set
|
|
95
|
+
stream.subscribeCommands('main', () => {
|
|
96
|
+
for (const cmd of stream.consumeCommands('main')) {
|
|
97
|
+
// { type:'insert', index, item } | { type:'remove', index, count? }
|
|
98
|
+
// | { type:'move', from, to, count? } | { type:'set', index, item }
|
|
99
|
+
// | { type:'reset', items } — item is the entity slot; entity is item.item
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
stream.getEntitiesByKey('main'); // (TEntity | undefined)[] — holes preserved
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`count` defaults to 1 (read `count ?? 1`). A whole-list change collapses to a single `reset`. Reads: `getPksByKey` / `getSlotsByKey` / `getEntitiesByKey`.
|
|
106
|
+
|
|
107
|
+
**Mapping the list to your own elements** — `createOIMOrderedListMappedCommandStream(source, { create, destroy? })` projects element-wise: the same commands with `item` replaced by `create(slot)`'s result (a DOM node, view model, …). Identity is positional — a `move` reuses the **same** mapped instance (never recreated); `create` runs on insert/set/reset/initial build, `destroy` on remove / replaced-set / reset / `destroy()`. It needs no queue (rides the source's batching) and is itself an `IOIMOrderedListCommandSource`, so it consumes like the raw stream and chains via `.map(...)`. New exports: `IOIMOrderedListCommandSource`, `TOIMOrderedListMapOptions`, `OIMOrderedListMappedCommandStream`, `createOIMOrderedListMappedCommandStream`.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
const nodes = createOIMOrderedListMappedCommandStream(stream, {
|
|
111
|
+
create: (slot) => engine.makeNode(slot.item),
|
|
112
|
+
destroy: (node) => engine.dropNode(node),
|
|
113
|
+
});
|
|
114
|
+
nodes.subscribeCommands('main', () => engine.apply(nodes.consumeCommands('main'))); // cmd.item is your node
|
|
115
|
+
nodes.getItemsByKey('main'); // current mapped elements — initial render
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
> Content updates (entity fields changed) are not list commands — they arrive via the collection's per-pk subscription. The stream carries structure only.
|
|
119
|
+
|
|
87
120
|
### DX Layer — Collection Model
|
|
88
121
|
|
|
89
122
|
`createOIMCollectionKit` wires queue + collection + index factory + selectors together.
|