@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.
Files changed (121) hide show
  1. package/dist/adapter/MockAdapter.d.ts +4 -1
  2. package/dist/adapter/MockAdapter.d.ts.map +1 -1
  3. package/dist/core/ActionDispatcher.d.ts +4 -1
  4. package/dist/core/ActionDispatcher.d.ts.map +1 -1
  5. package/dist/core/actions.d.ts +7 -1
  6. package/dist/core/actions.d.ts.map +1 -1
  7. package/dist/events/EventEmitter.d.ts +13 -1
  8. package/dist/events/EventEmitter.d.ts.map +1 -1
  9. package/dist/handles/BaseHandle.d.ts +14 -3
  10. package/dist/handles/BaseHandle.d.ts.map +1 -1
  11. package/dist/handles/EntityHandle.d.ts +14 -5
  12. package/dist/handles/EntityHandle.d.ts.map +1 -1
  13. package/dist/handles/FieldHandle.d.ts +11 -4
  14. package/dist/handles/FieldHandle.d.ts.map +1 -1
  15. package/dist/handles/HasManyListHandle.d.ts +36 -2
  16. package/dist/handles/HasManyListHandle.d.ts.map +1 -1
  17. package/dist/handles/HasOneHandle.d.ts +52 -9
  18. package/dist/handles/HasOneHandle.d.ts.map +1 -1
  19. package/dist/handles/PlaceholderHandle.d.ts +25 -13
  20. package/dist/handles/PlaceholderHandle.d.ts.map +1 -1
  21. package/dist/handles/index.d.ts +1 -1
  22. package/dist/handles/index.d.ts.map +1 -1
  23. package/dist/handles/proxyFactory.d.ts +7 -1
  24. package/dist/handles/proxyFactory.d.ts.map +1 -1
  25. package/dist/handles/types.d.ts +33 -0
  26. package/dist/handles/types.d.ts.map +1 -1
  27. package/dist/index.d.ts +3 -3
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/persistence/BatchPersister.d.ts +53 -37
  30. package/dist/persistence/BatchPersister.d.ts.map +1 -1
  31. package/dist/persistence/ChangeRegistry.d.ts +15 -0
  32. package/dist/persistence/ChangeRegistry.d.ts.map +1 -1
  33. package/dist/persistence/MutationCollector.d.ts +106 -3
  34. package/dist/persistence/MutationCollector.d.ts.map +1 -1
  35. package/dist/persistence/PersistExecution.d.ts +26 -0
  36. package/dist/persistence/PersistExecution.d.ts.map +1 -0
  37. package/dist/persistence/types.d.ts +8 -2
  38. package/dist/persistence/types.d.ts.map +1 -1
  39. package/dist/store/EntityMetaStore.d.ts +32 -10
  40. package/dist/store/EntityMetaStore.d.ts.map +1 -1
  41. package/dist/store/EntitySnapshotStore.d.ts +50 -3
  42. package/dist/store/EntitySnapshotStore.d.ts.map +1 -1
  43. package/dist/store/ErrorStore.d.ts +3 -2
  44. package/dist/store/ErrorStore.d.ts.map +1 -1
  45. package/dist/store/HasManyStore.d.ts +214 -0
  46. package/dist/store/HasManyStore.d.ts.map +1 -0
  47. package/dist/store/HasOneStore.d.ts +159 -0
  48. package/dist/store/HasOneStore.d.ts.map +1 -0
  49. package/dist/store/ReachabilityAnalyzer.d.ts +19 -0
  50. package/dist/store/ReachabilityAnalyzer.d.ts.map +1 -1
  51. package/dist/store/RekeyOrchestrator.d.ts +76 -0
  52. package/dist/store/RekeyOrchestrator.d.ts.map +1 -0
  53. package/dist/store/RelationEdgeIndex.d.ts +34 -0
  54. package/dist/store/RelationEdgeIndex.d.ts.map +1 -0
  55. package/dist/store/RelationStore.d.ts +74 -137
  56. package/dist/store/RelationStore.d.ts.map +1 -1
  57. package/dist/store/RootRegistry.d.ts +25 -4
  58. package/dist/store/RootRegistry.d.ts.map +1 -1
  59. package/dist/store/SnapshotStore.d.ts +137 -13
  60. package/dist/store/SnapshotStore.d.ts.map +1 -1
  61. package/dist/store/SubscriptionManager.d.ts +63 -14
  62. package/dist/store/SubscriptionManager.d.ts.map +1 -1
  63. package/dist/store/TouchedStore.d.ts +3 -2
  64. package/dist/store/TouchedStore.d.ts.map +1 -1
  65. package/dist/store/relationKey.d.ts +15 -0
  66. package/dist/store/relationKey.d.ts.map +1 -0
  67. package/dist/undo/UndoJournal.d.ts +133 -0
  68. package/dist/undo/UndoJournal.d.ts.map +1 -0
  69. package/dist/undo/UndoManager.d.ts +25 -82
  70. package/dist/undo/UndoManager.d.ts.map +1 -1
  71. package/dist/undo/UnrecordedWriteError.d.ts +16 -0
  72. package/dist/undo/UnrecordedWriteError.d.ts.map +1 -0
  73. package/dist/undo/index.d.ts +3 -1
  74. package/dist/undo/index.d.ts.map +1 -1
  75. package/dist/undo/rekeyJournalEntry.d.ts +20 -0
  76. package/dist/undo/rekeyJournalEntry.d.ts.map +1 -0
  77. package/dist/undo/types.d.ts +0 -48
  78. package/dist/undo/types.d.ts.map +1 -1
  79. package/package.json +2 -2
  80. package/src/adapter/MockAdapter.ts +15 -5
  81. package/src/core/ActionDispatcher.ts +56 -36
  82. package/src/core/actions.ts +8 -1
  83. package/src/events/EventEmitter.ts +78 -24
  84. package/src/handles/BaseHandle.ts +19 -2
  85. package/src/handles/EntityHandle.ts +48 -17
  86. package/src/handles/FieldHandle.ts +36 -10
  87. package/src/handles/HasManyListHandle.ts +120 -16
  88. package/src/handles/HasOneHandle.ts +177 -44
  89. package/src/handles/PlaceholderHandle.ts +184 -36
  90. package/src/handles/index.ts +3 -0
  91. package/src/handles/proxyFactory.ts +27 -0
  92. package/src/handles/types.ts +39 -0
  93. package/src/index.ts +4 -4
  94. package/src/persistence/BatchPersister.ts +810 -446
  95. package/src/persistence/ChangeRegistry.ts +27 -3
  96. package/src/persistence/MutationCollector.ts +265 -31
  97. package/src/persistence/PersistExecution.ts +217 -0
  98. package/src/persistence/types.ts +8 -2
  99. package/src/store/EntityMetaStore.ts +89 -45
  100. package/src/store/EntitySnapshotStore.ts +102 -19
  101. package/src/store/ErrorStore.ts +6 -5
  102. package/src/store/HasManyStore.ts +810 -0
  103. package/src/store/HasOneStore.ts +454 -0
  104. package/src/store/ReachabilityAnalyzer.ts +37 -0
  105. package/src/store/RekeyOrchestrator.ts +123 -0
  106. package/src/store/RelationEdgeIndex.ts +79 -0
  107. package/src/store/RelationStore.ts +176 -725
  108. package/src/store/RootRegistry.ts +50 -8
  109. package/src/store/SnapshotStore.ts +572 -101
  110. package/src/store/SubscriptionManager.ts +122 -75
  111. package/src/store/TouchedStore.ts +5 -2
  112. package/src/store/relationKey.ts +20 -0
  113. package/src/undo/UndoJournal.ts +258 -0
  114. package/src/undo/UndoManager.ts +151 -281
  115. package/src/undo/UnrecordedWriteError.ts +23 -0
  116. package/src/undo/index.ts +8 -7
  117. package/src/undo/rekeyJournalEntry.ts +145 -0
  118. package/src/undo/types.ts +0 -58
  119. package/dist/core/actionClassification.d.ts +0 -48
  120. package/dist/core/actionClassification.d.ts.map +0 -1
  121. 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
- * Registers a parent-child relationship for change propagation.
65
- * When the child entity changes, parent entity subscribers will be notified.
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
- registerParentChild(parentKey: string, childKey: string): void;
84
+ notifyAll(): void;
68
85
  /**
69
- * Unregisters a parent-child relationship.
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
- unregisterParentChild(parentKey: string, childKey: string): void;
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, notifiedKeys?: Set<string>): void;
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 and the parent entity's subscribers.
79
- * The bumper callback is used to bump the parent entity snapshot version.
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 subscriptions and parent-child relationships from oldKey to newKey.
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
- rekey(oldKey: string, newKey: string, oldKeyPrefix: string, newKeyPrefix: string): void;
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;;;;;;;;;GASG;AACH,qBAAa,mBAAmB;IAC/B,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,gEAAgE;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiC;IAEhE,gGAAgG;IAChG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IAExD,iDAAiD;IACjD,OAAO,CAAC,aAAa,CAAI;IAEzB;;;;;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;IASd;;;OAGG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAS9D;;OAEG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYhE;;;OAGG;IACH,uBAAuB,CACtB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,qBAAqB,EAC7B,YAAY,GAAE,GAAG,CAAC,MAAM,CAAa,GACnC,IAAI;IAuCP;;;;OAIG;IACH,yBAAyB,CACxB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,qBAAqB,GAC3B,IAAI;IA4BP;;;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;;;;OAIG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;CAqDvF"}
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(oldKeyPrefix: string, newKeyPrefix: string): void;
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,YAAY;IACxB,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,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAavD,KAAK,IAAI,IAAI;CAGb"}
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 provides undo/redo functionality for the Bindx store.
6
+ * UndoManager — the policy layer over the {@link UndoJournal}.
7
7
  *
8
- * Features:
9
- * - Automatic debounced grouping of rapid changes
10
- * - Manual grouping via beginGroup/endGroup
11
- * - Configurable history size
12
- * - Block/unblock during persist operations
13
- * - React integration via subscribe/getState
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
- private pendingEntry;
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 manualGroupLabel;
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
- * Creates middleware for ActionDispatcher.
31
- * Must be added to dispatcher to enable undo tracking.
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
- * Handles an action, capturing state for undo if trackable.
36
- */
37
- private handleAction;
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
- * Flushes pending entry to undo stack.
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
- * Clears all undo/redo history.
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;AASnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,KAAK,EAIX,iBAAiB,EACjB,SAAS,EACT,MAAM,YAAY,CAAA;AAEnB,KAAK,UAAU,GAAG,MAAM,IAAI,CAAA;AAS5B;;;;;;;;;GASG;AACH,qBAAa,WAAW;IAetB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAdvB,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,aAAa,CAA6C;IAClE,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,gBAAgB,CAAgC;IACxD,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;IAM/B;;;OAGG;IACH,gBAAgB,IAAI,gBAAgB;IAQpC;;OAEG;IACH,OAAO,CAAC,YAAY;IAuBpB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAsB/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAqC7B;;OAEG;IACH,OAAO,CAAC,UAAU;IAQlB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,cAAc;IAuBtB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqBzB;;OAEG;IACH,OAAO,CAAC,WAAW;IAMnB;;;OAGG;IACH,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAUlC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAW/B;;OAEG;IACH,IAAI,IAAI,IAAI;IA4BZ;;OAEG;IACH,IAAI,IAAI,IAAI;IAyBZ;;;OAGG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,OAAO,IAAI,IAAI;IAKf;;OAEG;IACH,KAAK,IAAI,IAAI;IAab;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,IAAI;IAO3C;;;OAGG;IACH,QAAQ,IAAI,SAAS;IAarB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAMzB"}
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"}
@@ -1,3 +1,5 @@
1
1
  export { UndoManager } from './UndoManager.js';
2
- export type { PartialStoreSnapshot, PendingUndoEntry, UndoEntry, UndoManagerConfig, UndoState, StoreAffectedKeys, } from './types.js';
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
@@ -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,oBAAoB,EACpB,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,SAAS,EACT,iBAAiB,GACjB,MAAM,YAAY,CAAA"}
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"}
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/undo/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,KAAK,EACX,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EACV,MAAM,2BAA2B,CAAA;AAElC;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,2CAA2C;IAC3C,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC5C,8BAA8B;IAC9B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAChD,2BAA2B;IAC3B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;IAC9C,uDAAuD;IACvD,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACzB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAA;IACV,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,cAAc,EAAE,oBAAoB,CAAA;IACpC,0DAA0D;IAC1D,YAAY,EAAE,iBAAiB,CAAA;IAC/B,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,6DAA6D;IAC7D,cAAc,EAAE,oBAAoB,CAAA;IACpC,gCAAgC;IAChC,YAAY,EAAE,iBAAiB,CAAA;IAC/B,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;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;AAGD,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA"}
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.46",
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.46",
20
+ "@contember/bindx-client": "0.1.48",
21
21
  "@contember/graphql-client": "^2.1.0-beta.1"
22
22
  },
23
23
  "repository": {