@contember/bindx 0.1.46 → 0.1.48
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/adapter/MockAdapter.d.ts +4 -1
- package/dist/adapter/MockAdapter.d.ts.map +1 -1
- package/dist/core/ActionDispatcher.d.ts +4 -1
- package/dist/core/ActionDispatcher.d.ts.map +1 -1
- package/dist/core/actions.d.ts +7 -1
- package/dist/core/actions.d.ts.map +1 -1
- package/dist/events/EventEmitter.d.ts +13 -1
- package/dist/events/EventEmitter.d.ts.map +1 -1
- package/dist/handles/BaseHandle.d.ts +14 -3
- package/dist/handles/BaseHandle.d.ts.map +1 -1
- package/dist/handles/EntityHandle.d.ts +14 -5
- package/dist/handles/EntityHandle.d.ts.map +1 -1
- package/dist/handles/FieldHandle.d.ts +11 -4
- package/dist/handles/FieldHandle.d.ts.map +1 -1
- package/dist/handles/HasManyListHandle.d.ts +36 -2
- package/dist/handles/HasManyListHandle.d.ts.map +1 -1
- package/dist/handles/HasOneHandle.d.ts +52 -9
- package/dist/handles/HasOneHandle.d.ts.map +1 -1
- package/dist/handles/PlaceholderHandle.d.ts +25 -13
- package/dist/handles/PlaceholderHandle.d.ts.map +1 -1
- package/dist/handles/index.d.ts +1 -1
- package/dist/handles/index.d.ts.map +1 -1
- package/dist/handles/proxyFactory.d.ts +7 -1
- package/dist/handles/proxyFactory.d.ts.map +1 -1
- package/dist/handles/types.d.ts +33 -0
- package/dist/handles/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/persistence/BatchPersister.d.ts +53 -37
- package/dist/persistence/BatchPersister.d.ts.map +1 -1
- package/dist/persistence/ChangeRegistry.d.ts +15 -0
- package/dist/persistence/ChangeRegistry.d.ts.map +1 -1
- package/dist/persistence/MutationCollector.d.ts +106 -3
- package/dist/persistence/MutationCollector.d.ts.map +1 -1
- package/dist/persistence/PersistExecution.d.ts +26 -0
- package/dist/persistence/PersistExecution.d.ts.map +1 -0
- package/dist/persistence/types.d.ts +8 -2
- package/dist/persistence/types.d.ts.map +1 -1
- package/dist/store/EntityMetaStore.d.ts +32 -10
- package/dist/store/EntityMetaStore.d.ts.map +1 -1
- package/dist/store/EntitySnapshotStore.d.ts +50 -3
- package/dist/store/EntitySnapshotStore.d.ts.map +1 -1
- package/dist/store/ErrorStore.d.ts +3 -2
- package/dist/store/ErrorStore.d.ts.map +1 -1
- package/dist/store/HasManyStore.d.ts +214 -0
- package/dist/store/HasManyStore.d.ts.map +1 -0
- package/dist/store/HasOneStore.d.ts +159 -0
- package/dist/store/HasOneStore.d.ts.map +1 -0
- package/dist/store/ReachabilityAnalyzer.d.ts +19 -0
- package/dist/store/ReachabilityAnalyzer.d.ts.map +1 -1
- package/dist/store/RekeyOrchestrator.d.ts +76 -0
- package/dist/store/RekeyOrchestrator.d.ts.map +1 -0
- package/dist/store/RelationEdgeIndex.d.ts +34 -0
- package/dist/store/RelationEdgeIndex.d.ts.map +1 -0
- package/dist/store/RelationStore.d.ts +74 -137
- package/dist/store/RelationStore.d.ts.map +1 -1
- package/dist/store/RootRegistry.d.ts +25 -4
- package/dist/store/RootRegistry.d.ts.map +1 -1
- package/dist/store/SnapshotStore.d.ts +137 -13
- package/dist/store/SnapshotStore.d.ts.map +1 -1
- package/dist/store/SubscriptionManager.d.ts +63 -14
- package/dist/store/SubscriptionManager.d.ts.map +1 -1
- package/dist/store/TouchedStore.d.ts +3 -2
- package/dist/store/TouchedStore.d.ts.map +1 -1
- package/dist/store/relationKey.d.ts +15 -0
- package/dist/store/relationKey.d.ts.map +1 -0
- package/dist/undo/UndoJournal.d.ts +133 -0
- package/dist/undo/UndoJournal.d.ts.map +1 -0
- package/dist/undo/UndoManager.d.ts +25 -82
- package/dist/undo/UndoManager.d.ts.map +1 -1
- package/dist/undo/UnrecordedWriteError.d.ts +16 -0
- package/dist/undo/UnrecordedWriteError.d.ts.map +1 -0
- package/dist/undo/index.d.ts +3 -1
- package/dist/undo/index.d.ts.map +1 -1
- package/dist/undo/rekeyJournalEntry.d.ts +20 -0
- package/dist/undo/rekeyJournalEntry.d.ts.map +1 -0
- package/dist/undo/types.d.ts +0 -48
- package/dist/undo/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/adapter/MockAdapter.ts +15 -5
- package/src/core/ActionDispatcher.ts +56 -36
- package/src/core/actions.ts +8 -1
- package/src/events/EventEmitter.ts +78 -24
- package/src/handles/BaseHandle.ts +19 -2
- package/src/handles/EntityHandle.ts +48 -17
- package/src/handles/FieldHandle.ts +36 -10
- package/src/handles/HasManyListHandle.ts +120 -16
- package/src/handles/HasOneHandle.ts +177 -44
- package/src/handles/PlaceholderHandle.ts +184 -36
- package/src/handles/index.ts +3 -0
- package/src/handles/proxyFactory.ts +27 -0
- package/src/handles/types.ts +39 -0
- package/src/index.ts +4 -4
- package/src/persistence/BatchPersister.ts +810 -446
- package/src/persistence/ChangeRegistry.ts +27 -3
- package/src/persistence/MutationCollector.ts +265 -31
- package/src/persistence/PersistExecution.ts +217 -0
- package/src/persistence/types.ts +8 -2
- package/src/store/EntityMetaStore.ts +89 -45
- package/src/store/EntitySnapshotStore.ts +102 -19
- package/src/store/ErrorStore.ts +6 -5
- package/src/store/HasManyStore.ts +810 -0
- package/src/store/HasOneStore.ts +454 -0
- package/src/store/ReachabilityAnalyzer.ts +37 -0
- package/src/store/RekeyOrchestrator.ts +123 -0
- package/src/store/RelationEdgeIndex.ts +79 -0
- package/src/store/RelationStore.ts +176 -725
- package/src/store/RootRegistry.ts +50 -8
- package/src/store/SnapshotStore.ts +572 -101
- package/src/store/SubscriptionManager.ts +122 -75
- package/src/store/TouchedStore.ts +5 -2
- package/src/store/relationKey.ts +20 -0
- package/src/undo/UndoJournal.ts +258 -0
- package/src/undo/UndoManager.ts +151 -281
- package/src/undo/UnrecordedWriteError.ts +23 -0
- package/src/undo/index.ts +8 -7
- package/src/undo/rekeyJournalEntry.ts +145 -0
- package/src/undo/types.ts +0 -58
- package/dist/core/actionClassification.d.ts +0 -48
- package/dist/core/actionClassification.d.ts.map +0 -1
- package/src/core/actionClassification.ts +0 -199
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RekeyContext, Rekeyable } from './RekeyOrchestrator.js';
|
|
1
2
|
type Subscriber = () => void;
|
|
2
3
|
/**
|
|
3
4
|
* Callback interface for SubscriptionManager to request snapshot version bumps.
|
|
@@ -6,6 +7,15 @@ type Subscriber = () => void;
|
|
|
6
7
|
export interface SnapshotVersionBumper {
|
|
7
8
|
bumpEntitySnapshotVersion(key: string): void;
|
|
8
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolves the parent entity keys that currently have a LIVE relation edge to a
|
|
12
|
+
* child, so a child-field change can propagate up to its parents. Implemented by
|
|
13
|
+
* the relation store (the single source of truth for relation membership); this
|
|
14
|
+
* interface keeps {@link SubscriptionManager} decoupled from its concrete type.
|
|
15
|
+
*/
|
|
16
|
+
export interface ParentKeyLookup {
|
|
17
|
+
getParentKeysForChild(childId: string): Set<string>;
|
|
18
|
+
}
|
|
9
19
|
/**
|
|
10
20
|
* Manages subscriptions for entity and relation changes.
|
|
11
21
|
*
|
|
@@ -13,22 +23,26 @@ export interface SnapshotVersionBumper {
|
|
|
13
23
|
* - Entity-level subscriptions
|
|
14
24
|
* - Relation-level subscriptions
|
|
15
25
|
* - Global subscriptions (any change)
|
|
16
|
-
* - Parent-child change propagation
|
|
26
|
+
* - Parent-child change propagation (derived from live relation edges)
|
|
17
27
|
* - Global version tracking for change detection
|
|
18
28
|
*/
|
|
19
|
-
export declare class SubscriptionManager {
|
|
29
|
+
export declare class SubscriptionManager implements Rekeyable {
|
|
20
30
|
/** Subscribers per entity key */
|
|
21
31
|
private readonly entitySubscribers;
|
|
22
32
|
/** Subscribers per relation key */
|
|
23
33
|
private readonly relationSubscribers;
|
|
24
34
|
/** Global subscribers (notified on any change) */
|
|
25
35
|
private readonly globalSubscribers;
|
|
26
|
-
/** Parent-child relationships: childKey -> Set of parentKeys */
|
|
27
|
-
private readonly childToParents;
|
|
28
36
|
/** Maps old keys → new keys after rekey, so unsubscribe closures can find migrated callbacks */
|
|
29
37
|
private readonly rekeyedKeys;
|
|
30
38
|
/** Global version number for change detection */
|
|
31
39
|
private globalVersion;
|
|
40
|
+
/**
|
|
41
|
+
* Resolves a child's parents from live relation edges. Injected after
|
|
42
|
+
* construction (the relation store and this manager are siblings under
|
|
43
|
+
* SnapshotStore) via {@link setParentKeyLookup}.
|
|
44
|
+
*/
|
|
45
|
+
private parentKeyLookup;
|
|
32
46
|
/**
|
|
33
47
|
* Resolves a key through the rekey redirect chain.
|
|
34
48
|
* The rekey() method collapses chains (A→C instead of A→B→C), so this should
|
|
@@ -61,22 +75,48 @@ export declare class SubscriptionManager {
|
|
|
61
75
|
*/
|
|
62
76
|
notify(): void;
|
|
63
77
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
78
|
+
* Notifies every registered subscriber — entity, relation and global.
|
|
79
|
+
*
|
|
80
|
+
* For store-wide events such as clear(), where every subscription's data is gone at once and
|
|
81
|
+
* there is no per-key change to notify from. Registrations are left intact: the subscribers
|
|
82
|
+
* belong to mounted components that must learn their entity is no longer there.
|
|
66
83
|
*/
|
|
67
|
-
|
|
84
|
+
notifyAll(): void;
|
|
68
85
|
/**
|
|
69
|
-
*
|
|
86
|
+
* Wires the live-edge parent lookup. Parent re-render propagation is derived
|
|
87
|
+
* from the relation store's edges rather than a separate registry, so there is
|
|
88
|
+
* one source of truth for the parent-child graph.
|
|
70
89
|
*/
|
|
71
|
-
|
|
90
|
+
setParentKeyLookup(lookup: ParentKeyLookup): void;
|
|
91
|
+
/**
|
|
92
|
+
* Derives the parent entity keys for a child entity key by reading the live
|
|
93
|
+
* relation edges via the injected lookup. The child's bare id is the part of
|
|
94
|
+
* the key after the first ':' ("entityType:id").
|
|
95
|
+
*
|
|
96
|
+
* The child's TYPE is intentionally dropped — {@link ParentKeyLookup} matches on
|
|
97
|
+
* the bare id, relying on the store-wide global-id-uniqueness invariant (see
|
|
98
|
+
* {@link RelationStore.getParentKeysForChild}).
|
|
99
|
+
*/
|
|
100
|
+
private getParentKeys;
|
|
72
101
|
/**
|
|
73
102
|
* Notifies entity subscribers and propagates changes to parents.
|
|
74
103
|
* The bumper callback is used to bump parent entity snapshot versions.
|
|
75
104
|
*/
|
|
76
|
-
notifyEntitySubscribers(key: string, bumper: SnapshotVersionBumper
|
|
105
|
+
notifyEntitySubscribers(key: string, bumper: SnapshotVersionBumper): void;
|
|
106
|
+
/**
|
|
107
|
+
* Walks the entity and its live ancestors. The global version is bumped once by the
|
|
108
|
+
* caller, before the first subscriber runs — a subscriber reading getVersion() from
|
|
109
|
+
* inside its callback must already see the new value.
|
|
110
|
+
*
|
|
111
|
+
* The walk is a transitive closure over live edges, so an entity many rows point at
|
|
112
|
+
* (a shared lookup entity whose own has-many is loaded) acts as a hub: a write in one
|
|
113
|
+
* row reaches every other row through it. That is the price of not knowing which part
|
|
114
|
+
* of the hub each row presents; a selection-aware edge index would be the fix.
|
|
115
|
+
*/
|
|
116
|
+
private notifyEntityAndParentSubscribers;
|
|
77
117
|
/**
|
|
78
|
-
* Notifies relation subscribers
|
|
79
|
-
* The bumper callback is used to bump
|
|
118
|
+
* Notifies relation subscribers, the owning entity, and its ancestors.
|
|
119
|
+
* The bumper callback is used to bump entity snapshot versions.
|
|
80
120
|
* The entityKey is the parent entity key derived from the relation key.
|
|
81
121
|
*/
|
|
82
122
|
notifyRelationSubscribers(key: string, entityKey: string, bumper: SnapshotVersionBumper): void;
|
|
@@ -95,11 +135,20 @@ export declare class SubscriptionManager {
|
|
|
95
135
|
*/
|
|
96
136
|
notifyGlobal(): void;
|
|
97
137
|
/**
|
|
98
|
-
* Moves
|
|
138
|
+
* Moves entity and relation subscriptions from oldKey to newKey.
|
|
99
139
|
* Also rekeys relation subscribers under oldKeyPrefix to newKeyPrefix.
|
|
100
140
|
* Registers redirects so unsubscribe closures can find migrated callbacks.
|
|
141
|
+
*
|
|
142
|
+
* Parent-child links are NOT migrated here — they are derived from the
|
|
143
|
+
* relation store's live edges, which migrate their own id references on rekey.
|
|
144
|
+
*/
|
|
145
|
+
rekey(ctx: RekeyContext): void;
|
|
146
|
+
/**
|
|
147
|
+
* Re-homes a subscriber set under a new key. The destination may already hold
|
|
148
|
+
* subscribers (a component mounted on the persisted id before the draft was rekeyed
|
|
149
|
+
* onto it); replacing the set would silently orphan them, so the two are merged.
|
|
101
150
|
*/
|
|
102
|
-
|
|
151
|
+
private moveSubscribers;
|
|
103
152
|
}
|
|
104
153
|
export {};
|
|
105
154
|
//# sourceMappingURL=SubscriptionManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionManager.d.ts","sourceRoot":"","sources":["../../src/store/SubscriptionManager.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG,MAAM,IAAI,CAAA;AAE5B;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACrC,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5C;AAED
|
|
1
|
+
{"version":3,"file":"SubscriptionManager.d.ts","sourceRoot":"","sources":["../../src/store/SubscriptionManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAErE,KAAK,UAAU,GAAG,MAAM,IAAI,CAAA;AAE5B;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACrC,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5C;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC/B,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAA;CACnD;AAED;;;;;;;;;GASG;AACH,qBAAa,mBAAoB,YAAW,SAAS;IACpD,iCAAiC;IACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqC;IAEvE,mCAAmC;IACnC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqC;IAEzE,kDAAkD;IAClD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwB;IAE1D,gGAAgG;IAChG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IAExD,iDAAiD;IACjD,OAAO,CAAC,aAAa,CAAI;IAEzB;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAA6B;IAEpD;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAUlB;;;OAGG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,MAAM,IAAI;IAahE;;;OAGG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,MAAM,IAAI;IAalE;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,IAAI;IAO3C;;OAEG;IACH,UAAU,IAAI,MAAM;IAIpB;;;OAGG;IACH,MAAM,IAAI,IAAI;IAOd;;;;;;OAMG;IACH,SAAS,IAAI,IAAI;IAiBjB;;;;OAIG;IACH,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAIjD;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAUrB;;;OAGG;IACH,uBAAuB,CACtB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,qBAAqB,GAC3B,IAAI;IAKP;;;;;;;;;OASG;IACH,OAAO,CAAC,gCAAgC;IA2CxC;;;;OAIG;IACH,yBAAyB,CACxB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,qBAAqB,GAC3B,IAAI;IAiBP;;;OAGG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IASrC;;;OAGG;IACH,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IASvC;;OAEG;IACH,YAAY,IAAI,IAAI;IAOpB;;;;;;;OAOG;IACH,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;IAmC9B;;;;OAIG;IACH,OAAO,CAAC,eAAe;CAYvB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RekeyContext, Rekeyable } from './RekeyOrchestrator.js';
|
|
1
2
|
/**
|
|
2
3
|
* Manages touched state for entity fields.
|
|
3
4
|
*
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
*
|
|
7
8
|
* Keys are pre-computed composite strings (e.g., "entityType:id:fieldName").
|
|
8
9
|
*/
|
|
9
|
-
export declare class TouchedStore {
|
|
10
|
+
export declare class TouchedStore implements Rekeyable {
|
|
10
11
|
/** Touched state keyed by "entityType:id:fieldName" */
|
|
11
12
|
private readonly touchedFields;
|
|
12
13
|
isFieldTouched(key: string): boolean;
|
|
@@ -22,7 +23,7 @@ export declare class TouchedStore {
|
|
|
22
23
|
/**
|
|
23
24
|
* Rekeys all touched fields from oldKeyPrefix to newKeyPrefix.
|
|
24
25
|
*/
|
|
25
|
-
rekey(
|
|
26
|
+
rekey(ctx: RekeyContext): void;
|
|
26
27
|
clear(): void;
|
|
27
28
|
}
|
|
28
29
|
//# sourceMappingURL=TouchedStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TouchedStore.d.ts","sourceRoot":"","sources":["../../src/store/TouchedStore.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,qBAAa,
|
|
1
|
+
{"version":3,"file":"TouchedStore.d.ts","sourceRoot":"","sources":["../../src/store/TouchedStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAErE;;;;;;;GAOG;AACH,qBAAa,YAAa,YAAW,SAAS;IAC7C,uDAAuD;IACvD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAE3D,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIpC;;;OAGG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO;IAOvD;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQvC;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;IAc9B,KAAK,IAAI,IAAI;CAGb"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives the parent composite key ("parentType:parentId") from a relation key
|
|
3
|
+
* ("parentType:parentId:fieldName") by dropping the trailing field segment.
|
|
4
|
+
* Entity ids and field names never contain ':', so the parent key is everything
|
|
5
|
+
* before the last separator.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parentKeyFromRelationKey(relationKey: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Derives the parent composite key ("parentType:parentId") from an owner key
|
|
10
|
+
* prefix ("parentType:parentId:") by dropping the trailing separator. Callers
|
|
11
|
+
* pass the owner prefix used for relation-key lookups; this maps it to the key
|
|
12
|
+
* the {@link RelationEdgeIndex} stores edges under.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parentKeyFromOwnerPrefix(ownerPrefix: string): string;
|
|
15
|
+
//# sourceMappingURL=relationKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relationKey.d.ts","sourceRoot":"","sources":["../../src/store/relationKey.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpE"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { EntitySnapshot } from '../store/snapshots.js';
|
|
2
|
+
import type { StoredRelationState, StoredHasManyState } from '../store/RelationStore.js';
|
|
3
|
+
import type { RekeyContext } from '../store/RekeyOrchestrator.js';
|
|
4
|
+
/**
|
|
5
|
+
* Write-journal for undo/redo.
|
|
6
|
+
*
|
|
7
|
+
* A gesture (one dispatch, or one handle operation) opens a transaction; every
|
|
8
|
+
* primary-store write made inside it records the EDITABLE-LAYER pre-image of the
|
|
9
|
+
* cell it touches (first-writer-wins per cell). On commit, the accumulated cells
|
|
10
|
+
* become one {@link JournalEntry} — exactly the keys the gesture actually wrote,
|
|
11
|
+
* each with the state to restore. Undo restores those pre-images through the
|
|
12
|
+
* store's write paths (so the edge index and reachability cache rebuild
|
|
13
|
+
* themselves); derived state is never journaled.
|
|
14
|
+
*
|
|
15
|
+
* The journal captures only the editable layer (and, for re-creates, the full
|
|
16
|
+
* snapshot). The server baseline (serverData / serverId / serverState / serverIds
|
|
17
|
+
* / existsOnServer) is spliced back from the LIVE state on restore, so undoing an
|
|
18
|
+
* already-persisted edit re-dirties it against the current server view instead of
|
|
19
|
+
* resurrecting a stale baseline.
|
|
20
|
+
*
|
|
21
|
+
* Entry-closure invariant: on commit each entry is closed over the created,
|
|
22
|
+
* currently-unreachable subgraph its relation/has-many pre-images detach, so undo
|
|
23
|
+
* works no matter what memory sweep reclaims that subgraph in between (see
|
|
24
|
+
* {@link JournalTarget.exportUnreachableCreatedSubgraph}).
|
|
25
|
+
*/
|
|
26
|
+
/** A captured cell, keyed by kind + composite store key. */
|
|
27
|
+
export interface EntityCellImage {
|
|
28
|
+
readonly kind: 'entity';
|
|
29
|
+
readonly key: string;
|
|
30
|
+
/** Whether the entity existed at capture time. false ⇒ undo removes it (un-create). */
|
|
31
|
+
readonly present: boolean;
|
|
32
|
+
readonly snapshot?: EntitySnapshot;
|
|
33
|
+
readonly existsOnServer?: boolean;
|
|
34
|
+
readonly isScheduledForDeletion?: boolean;
|
|
35
|
+
readonly isRoot?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface RelationCellImage {
|
|
38
|
+
readonly kind: 'relation';
|
|
39
|
+
readonly key: string;
|
|
40
|
+
readonly present: boolean;
|
|
41
|
+
readonly state?: StoredRelationState;
|
|
42
|
+
}
|
|
43
|
+
export interface HasManyCellImage {
|
|
44
|
+
readonly kind: 'hasMany';
|
|
45
|
+
readonly key: string;
|
|
46
|
+
readonly present: boolean;
|
|
47
|
+
readonly state?: StoredHasManyState;
|
|
48
|
+
}
|
|
49
|
+
export type JournalCellImage = EntityCellImage | RelationCellImage | HasManyCellImage;
|
|
50
|
+
/** The kind axis shared by cell images, editable-write counters, and the guard. */
|
|
51
|
+
export type JournalCellKind = JournalCellImage['kind'];
|
|
52
|
+
/**
|
|
53
|
+
* Monotonic editable-layer write counters, one per journal kind. Provided by the
|
|
54
|
+
* store so the journal can prove — at transaction close — that every editable
|
|
55
|
+
* write was preceded by a record call (see {@link UndoJournal.commit}). Counters
|
|
56
|
+
* only ever increase, so a per-transaction delta is `now - base`.
|
|
57
|
+
*/
|
|
58
|
+
export interface EditableWriteCounters {
|
|
59
|
+
readonly entity: number;
|
|
60
|
+
readonly relation: number;
|
|
61
|
+
readonly hasMany: number;
|
|
62
|
+
}
|
|
63
|
+
/** One undoable unit: the editable-layer pre-images of every cell a gesture touched. */
|
|
64
|
+
export interface JournalEntry {
|
|
65
|
+
readonly cells: JournalCellImage[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The store side of the journal: produces editable-layer pre-images for a cell and
|
|
69
|
+
* applies a set of pre-images back (through the write paths). Implemented by
|
|
70
|
+
* SnapshotStore, which alone knows the sub-stores.
|
|
71
|
+
*/
|
|
72
|
+
export interface JournalTarget {
|
|
73
|
+
exportEntityCell(key: string): EntityCellImage;
|
|
74
|
+
exportRelationCell(key: string): RelationCellImage;
|
|
75
|
+
exportHasManyCell(key: string): HasManyCellImage;
|
|
76
|
+
/**
|
|
77
|
+
* Images of every created, currently-unreachable entity (and its owned relation
|
|
78
|
+
* cells) reachable from the seed ids — the subgraph a memory sweep may reclaim
|
|
79
|
+
* before an undo needs it. Backs the journal's entry-closure invariant.
|
|
80
|
+
*/
|
|
81
|
+
exportUnreachableCreatedSubgraph(seedIds: ReadonlySet<string>): JournalCellImage[];
|
|
82
|
+
applyJournalImages(images: JournalCellImage[]): void;
|
|
83
|
+
/**
|
|
84
|
+
* Current editable-layer write counters across the sub-stores. Read once when a
|
|
85
|
+
* transaction opens and again when it closes to detect writes that skipped their
|
|
86
|
+
* record call. Must be O(1) — it is on the write hot path.
|
|
87
|
+
*/
|
|
88
|
+
getEditableWriteCounters(): EditableWriteCounters;
|
|
89
|
+
}
|
|
90
|
+
declare function cellRefKey(image: JournalCellImage): string;
|
|
91
|
+
export declare class UndoJournal {
|
|
92
|
+
private readonly target;
|
|
93
|
+
private readonly onCommit;
|
|
94
|
+
private readonly onRekey?;
|
|
95
|
+
private readonly onClear?;
|
|
96
|
+
private depth;
|
|
97
|
+
/** Cells recorded in the currently-open transaction, deduped first-writer-wins. */
|
|
98
|
+
private active;
|
|
99
|
+
/** Editable-write counters snapshotted when the outermost transaction opened. */
|
|
100
|
+
private baseCounters;
|
|
101
|
+
constructor(target: JournalTarget, onCommit: (entry: JournalEntry) => void, onRekey?: ((ctx: RekeyContext) => void) | undefined, onClear?: (() => void) | undefined);
|
|
102
|
+
get isRecording(): boolean;
|
|
103
|
+
begin(): void;
|
|
104
|
+
commit(): void;
|
|
105
|
+
/**
|
|
106
|
+
* Coarse per-kind invariant check at transaction close: for each journal kind
|
|
107
|
+
* whose editable-write counter advanced during the transaction, at least one
|
|
108
|
+
* cell of that kind must have been recorded. A positive delta with no recorded
|
|
109
|
+
* cell means a mutating method wrote without recording — undo would restore
|
|
110
|
+
* stale/partial state — so fail loudly naming the offending kind(s).
|
|
111
|
+
*/
|
|
112
|
+
private assertAllWritesRecorded;
|
|
113
|
+
/**
|
|
114
|
+
* Folds the detached created subgraph into the entry (first-writer-wins) so undo
|
|
115
|
+
* survives a later sweep of that subgraph. Runs before onCommit so the manager's
|
|
116
|
+
* debounce/group merge already sees the enriched cells.
|
|
117
|
+
*/
|
|
118
|
+
private closeOverUnreachableCreated;
|
|
119
|
+
/** Records the pre-image of an entity cell (snapshot + meta + root membership). */
|
|
120
|
+
recordEntity(key: string): void;
|
|
121
|
+
recordRelation(key: string): void;
|
|
122
|
+
recordHasMany(key: string): void;
|
|
123
|
+
private record;
|
|
124
|
+
/** Captures the CURRENT image of each given cell — used to build the inverse entry. */
|
|
125
|
+
captureCurrent(cells: JournalCellImage[]): JournalCellImage[];
|
|
126
|
+
apply(cells: JournalCellImage[]): void;
|
|
127
|
+
/** Forwarded from the store when a temp id is rekeyed; lets the owner rewrite stacks. */
|
|
128
|
+
rekey(ctx: RekeyContext): void;
|
|
129
|
+
/** Forwarded from the store on a full clear; drops all owner history and any open gesture. */
|
|
130
|
+
clear(): void;
|
|
131
|
+
}
|
|
132
|
+
export { cellRefKey };
|
|
133
|
+
//# sourceMappingURL=UndoJournal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UndoJournal.d.ts","sourceRoot":"","sources":["../../src/undo/UndoJournal.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,117 +3,60 @@ import type { SnapshotStore } from '../store/SnapshotStore.js';
|
|
|
3
3
|
import type { UndoManagerConfig, UndoState } from './types.js';
|
|
4
4
|
type Subscriber = () => void;
|
|
5
5
|
/**
|
|
6
|
-
* UndoManager
|
|
6
|
+
* UndoManager — the policy layer over the {@link UndoJournal}.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
8
|
+
* The journal records each gesture (one dispatch / one handle transaction) as a
|
|
9
|
+
* {@link JournalEntry} of editable-layer pre-images. UndoManager owns the undo /
|
|
10
|
+
* redo stacks and the grouping policy (debounced auto-grouping + manual
|
|
11
|
+
* begin/endGroup), blocks during persist, and keeps the stacks aligned across a
|
|
12
|
+
* temp→persisted rekey. Restore goes straight through the store's write paths, so
|
|
13
|
+
* the edge index and reachability cache rebuild themselves; the event/interceptor
|
|
14
|
+
* pipeline is NOT replayed.
|
|
14
15
|
*/
|
|
15
16
|
export declare class UndoManager {
|
|
16
17
|
private readonly store;
|
|
18
|
+
private readonly journal;
|
|
17
19
|
private undoStack;
|
|
18
20
|
private redoStack;
|
|
19
|
-
|
|
21
|
+
/** Cells accumulated while a debounce window or manual group is open (first-writer-wins). */
|
|
22
|
+
private pending;
|
|
20
23
|
private debounceTimer;
|
|
21
|
-
private isBlocked;
|
|
22
24
|
private manualGroupId;
|
|
23
|
-
private
|
|
25
|
+
private blockDepth;
|
|
24
26
|
private subscribers;
|
|
25
27
|
private cachedState;
|
|
26
28
|
private readonly maxHistorySize;
|
|
27
29
|
private readonly debounceMs;
|
|
28
30
|
constructor(store: SnapshotStore, config?: UndoManagerConfig);
|
|
29
31
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
+
* Wires the journal into the store so its write paths record gestures. The
|
|
33
|
+
* returned middleware is a backward-compatible pass-through (recording is native
|
|
34
|
+
* to the store transaction, not the middleware).
|
|
32
35
|
*/
|
|
33
36
|
createMiddleware(): ActionMiddleware;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
/**
|
|
39
|
-
* Handles action in manual group mode.
|
|
40
|
-
*/
|
|
41
|
-
private handleManualGroupAction;
|
|
42
|
-
/**
|
|
43
|
-
* Handles action in debounced auto-group mode.
|
|
44
|
-
*/
|
|
45
|
-
private handleDebouncedAction;
|
|
46
|
-
/**
|
|
47
|
-
* Gets keys that are in source but not in target.
|
|
48
|
-
*/
|
|
49
|
-
private getNewKeys;
|
|
50
|
-
/**
|
|
51
|
-
* Checks if keys object is empty.
|
|
52
|
-
*/
|
|
53
|
-
private isEmptyKeys;
|
|
54
|
-
/**
|
|
55
|
-
* Merges additional snapshot into target.
|
|
56
|
-
*/
|
|
57
|
-
private mergeSnapshots;
|
|
58
|
-
/**
|
|
59
|
-
* Starts the debounce timer.
|
|
60
|
-
*/
|
|
61
|
-
private startDebounceTimer;
|
|
62
|
-
/**
|
|
63
|
-
* Resets the debounce timer.
|
|
64
|
-
*/
|
|
37
|
+
private onEntry;
|
|
38
|
+
private mergeIntoPending;
|
|
39
|
+
private flushPending;
|
|
40
|
+
private pushEntry;
|
|
65
41
|
private resetDebounceTimer;
|
|
66
42
|
/**
|
|
67
|
-
*
|
|
68
|
-
|
|
69
|
-
private flushPendingEntry;
|
|
70
|
-
/**
|
|
71
|
-
* Trims history to max size.
|
|
72
|
-
*/
|
|
73
|
-
private trimHistory;
|
|
74
|
-
/**
|
|
75
|
-
* Starts a manual group. All actions until endGroup are grouped as one undo entry.
|
|
76
|
-
* Returns group ID that must be passed to endGroup.
|
|
77
|
-
*/
|
|
78
|
-
beginGroup(label?: string): string;
|
|
79
|
-
/**
|
|
80
|
-
* Ends a manual group and pushes to undo stack.
|
|
43
|
+
* Starts a manual group: every gesture until {@link endGroup} folds into one
|
|
44
|
+
* undo entry. Returns a handle that must be passed back to endGroup.
|
|
81
45
|
*/
|
|
46
|
+
beginGroup(_label?: string): string;
|
|
82
47
|
endGroup(groupId: string): void;
|
|
83
|
-
/**
|
|
84
|
-
* Undoes the last entry.
|
|
85
|
-
*/
|
|
86
48
|
undo(): void;
|
|
87
|
-
/**
|
|
88
|
-
* Redoes the last undone entry.
|
|
89
|
-
*/
|
|
90
49
|
redo(): void;
|
|
91
|
-
/**
|
|
92
|
-
* Blocks undo/redo operations.
|
|
93
|
-
* Use during persist to prevent inconsistent state.
|
|
94
|
-
*/
|
|
95
50
|
block(): void;
|
|
96
|
-
/**
|
|
97
|
-
* Unblocks undo/redo operations.
|
|
98
|
-
*/
|
|
99
51
|
unblock(): void;
|
|
100
52
|
/**
|
|
101
|
-
*
|
|
53
|
+
* Rewrites every stacked entry when a temp id is replaced by its persisted id,
|
|
54
|
+
* so stored cells keep valid keys / id references (and sealed creates drop out).
|
|
102
55
|
*/
|
|
56
|
+
private rekeyStacks;
|
|
103
57
|
clear(): void;
|
|
104
|
-
/**
|
|
105
|
-
* Subscribes to state changes.
|
|
106
|
-
* Returns unsubscribe function.
|
|
107
|
-
*/
|
|
108
58
|
subscribe(callback: Subscriber): () => void;
|
|
109
|
-
/**
|
|
110
|
-
* Gets current state for React integration.
|
|
111
|
-
* Returns a cached object to satisfy useSyncExternalStore's referential equality requirement.
|
|
112
|
-
*/
|
|
113
59
|
getState(): UndoState;
|
|
114
|
-
/**
|
|
115
|
-
* Notifies all subscribers of state change.
|
|
116
|
-
*/
|
|
117
60
|
private notifySubscribers;
|
|
118
61
|
}
|
|
119
62
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UndoManager.d.ts","sourceRoot":"","sources":["../../src/undo/UndoManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"UndoManager.d.ts","sourceRoot":"","sources":["../../src/undo/UndoManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAI9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE9D,KAAK,UAAU,GAAG,MAAM,IAAI,CAAA;AAS5B;;;;;;;;;;GAUG;AACH,qBAAa,WAAW;IAkBtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAjBvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,SAAS,CAAqB;IAEtC,6FAA6F;IAC7F,OAAO,CAAC,OAAO,CAA6C;IAC5D,OAAO,CAAC,aAAa,CAA6C;IAClE,OAAO,CAAC,aAAa,CAAsB;IAE3C,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,WAAW,CAAwB;IAC3C,OAAO,CAAC,WAAW,CAAyB;IAE5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;gBAGjB,KAAK,EAAE,aAAa,EACrC,MAAM,GAAE,iBAAsB;IAY/B;;;;OAIG;IACH,gBAAgB,IAAI,gBAAgB;IAWpC,OAAO,CAAC,OAAO;IAwBf,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,kBAAkB;IAS1B;;;OAGG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;IAOnC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAW/B,IAAI,IAAI,IAAI;IAcZ,IAAI,IAAI,IAAI;IAaZ,KAAK,IAAI,IAAI;IAUb,OAAO,IAAI,IAAI;IAUf;;;OAGG;IACH,OAAO,CAAC,WAAW;IAiCnB,KAAK,IAAI,IAAI;IAYb,SAAS,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,IAAI;IAO3C,QAAQ,IAAI,SAAS;IAcrB,OAAO,CAAC,iBAAiB;CAMzB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { JournalCellKind } from './UndoJournal.js';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when a journal transaction closes after an editable-layer store write
|
|
4
|
+
* that was NOT preceded by a matching `journal.record*` call — i.e. a mutating
|
|
5
|
+
* SnapshotStore method wrote primary state a gesture can no longer undo.
|
|
6
|
+
*
|
|
7
|
+
* This turns the "every mutating method must record before writing" convention
|
|
8
|
+
* into a checked invariant: the sub-store editable-write counters advanced for a
|
|
9
|
+
* kind the transaction never recorded. The named kinds pinpoint which record call
|
|
10
|
+
* is missing (recordEntity / recordRelation / recordHasMany).
|
|
11
|
+
*/
|
|
12
|
+
export declare class UnrecordedWriteError extends Error {
|
|
13
|
+
readonly kinds: ReadonlyArray<JournalCellKind>;
|
|
14
|
+
constructor(kinds: ReadonlyArray<JournalCellKind>);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=UnrecordedWriteError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UnrecordedWriteError.d.ts","sourceRoot":"","sources":["../../src/undo/UnrecordedWriteError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAEvD;;;;;;;;;GASG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;aAClB,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC;gBAArC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC;CASjE"}
|
package/dist/undo/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { UndoManager } from './UndoManager.js';
|
|
2
|
-
export
|
|
2
|
+
export { UnrecordedWriteError } from './UnrecordedWriteError.js';
|
|
3
|
+
export type { UndoManagerConfig, UndoState } from './types.js';
|
|
4
|
+
export type { JournalEntry, JournalCellImage, EntityCellImage, RelationCellImage, HasManyCellImage, } from './UndoJournal.js';
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/undo/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/undo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,YAAY,EACX,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/undo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC9D,YAAY,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RekeyContext } from '../store/RekeyOrchestrator.js';
|
|
2
|
+
import type { JournalEntry } from './UndoJournal.js';
|
|
3
|
+
/**
|
|
4
|
+
* Rewrites a journal entry for a temp→persisted rekey so stored cells stay valid
|
|
5
|
+
* after persist:
|
|
6
|
+
* - owner keys move from the temp prefix to the persisted prefix;
|
|
7
|
+
* - embedded id references (snapshot ids, relation currentId/serverId, has-many
|
|
8
|
+
* members) are remapped oldId→newId;
|
|
9
|
+
* - the create is SEALED: an "absent" pre-image of the now-persisted entity (or
|
|
10
|
+
* its owned relations) is dropped, so undo can no longer delete the
|
|
11
|
+
* server-backed row — only later edits to it remain undoable.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Looks up the live server-member ids of a has-many list by its key. Lets the
|
|
15
|
+
* rekey rebase a pre-image when the just-persisted create has become a permanent
|
|
16
|
+
* member of that list.
|
|
17
|
+
*/
|
|
18
|
+
export type LiveServerIdsLookup = (relationKey: string) => Set<string>;
|
|
19
|
+
export declare function rekeyJournalEntry(entry: JournalEntry, ctx: RekeyContext, liveServerIds: LiveServerIdsLookup): JournalEntry;
|
|
20
|
+
//# sourceMappingURL=rekeyJournalEntry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rekeyJournalEntry.d.ts","sourceRoot":"","sources":["../../src/undo/rekeyJournalEntry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAIjE,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,kBAAkB,CAAA;AAEtE;;;;;;;;;GASG;AACH;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,CAAA;AAEtE,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,YAAY,EACjB,aAAa,EAAE,mBAAmB,GAChC,YAAY,CAOd"}
|
package/dist/undo/types.d.ts
CHANGED
|
@@ -1,50 +1,3 @@
|
|
|
1
|
-
import type { StoreAffectedKeys } from '../core/actionClassification.js';
|
|
2
|
-
import type { EntitySnapshot } from '../store/snapshots.js';
|
|
3
|
-
import type { StoredRelationState, StoredHasManyState, EntityMeta } from '../store/SnapshotStore.js';
|
|
4
|
-
/**
|
|
5
|
-
* Partial snapshot of store state.
|
|
6
|
-
* Contains only the data affected by an action or group of actions.
|
|
7
|
-
*/
|
|
8
|
-
export interface PartialStoreSnapshot {
|
|
9
|
-
/** Entity snapshots (frozen, immutable) */
|
|
10
|
-
entitySnapshots: Map<string, EntitySnapshot>;
|
|
11
|
-
/** Has-one relation states */
|
|
12
|
-
relationStates: Map<string, StoredRelationState>;
|
|
13
|
-
/** Has-many list states */
|
|
14
|
-
hasManyStates: Map<string, StoredHasManyState>;
|
|
15
|
-
/** Entity metadata (existsOnServer, deletion flags) */
|
|
16
|
-
entityMetas: Map<string, EntityMeta>;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* A single undo/redo entry.
|
|
20
|
-
* Contains the snapshot of state BEFORE the action(s) were applied.
|
|
21
|
-
*/
|
|
22
|
-
export interface UndoEntry {
|
|
23
|
-
/** Unique identifier for this entry */
|
|
24
|
-
id: string;
|
|
25
|
-
/** Optional human-readable label */
|
|
26
|
-
label?: string;
|
|
27
|
-
/** Snapshot of state BEFORE the action(s) */
|
|
28
|
-
beforeSnapshot: PartialStoreSnapshot;
|
|
29
|
-
/** Keys that were affected (for redo snapshot capture) */
|
|
30
|
-
affectedKeys: StoreAffectedKeys;
|
|
31
|
-
/** When this entry was created */
|
|
32
|
-
timestamp: number;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Pending entry during debounce window.
|
|
36
|
-
* Accumulates affected keys while waiting for debounce to complete.
|
|
37
|
-
*/
|
|
38
|
-
export interface PendingUndoEntry {
|
|
39
|
-
/** Snapshot captured before the first action in the group */
|
|
40
|
-
beforeSnapshot: PartialStoreSnapshot;
|
|
41
|
-
/** Accumulated affected keys */
|
|
42
|
-
affectedKeys: StoreAffectedKeys;
|
|
43
|
-
/** When the first action occurred */
|
|
44
|
-
timestamp: number;
|
|
45
|
-
/** Optional label for manual grouping */
|
|
46
|
-
label?: string;
|
|
47
|
-
}
|
|
48
1
|
/**
|
|
49
2
|
* Configuration options for UndoManager.
|
|
50
3
|
*/
|
|
@@ -70,5 +23,4 @@ export interface UndoState {
|
|
|
70
23
|
/** Number of entries in redo stack */
|
|
71
24
|
redoCount: number;
|
|
72
25
|
}
|
|
73
|
-
export type { StoreAffectedKeys } from '../core/actionClassification.js';
|
|
74
26
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/undo/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/undo/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/undo/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACzB,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;IAClB,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAA;CACjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/bindx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"description": "Type-safe data binding framework (core)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@contember/bindx-client": "0.1.
|
|
20
|
+
"@contember/bindx-client": "0.1.48",
|
|
21
21
|
"@contember/graphql-client": "^2.1.0-beta.1"
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|