@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
@@ -0,0 +1,214 @@
1
+ type ReconciliationResult = 'applied' | 'conflict';
2
+ /**
3
+ * Removal type for has-many items
4
+ */
5
+ export type HasManyRemovalType = 'disconnect' | 'delete';
6
+ /**
7
+ * Kind of a planned has-many addition:
8
+ * - 'created': a newly created entity (via add())
9
+ * - 'connected': an existing persisted entity being connected (via connect())
10
+ */
11
+ export type HasManyAdditionKind = 'created' | 'connected';
12
+ export interface SentHasManyAddition {
13
+ itemId: string;
14
+ kind: HasManyAdditionKind;
15
+ }
16
+ export interface SentHasManyRemoval {
17
+ itemId: string;
18
+ type: HasManyRemovalType;
19
+ }
20
+ export interface SentHasManyDelta {
21
+ additions: readonly SentHasManyAddition[];
22
+ removals: readonly SentHasManyRemoval[];
23
+ }
24
+ /**
25
+ * Has-many list state stored in SnapshotStore
26
+ */
27
+ export interface StoredHasManyState {
28
+ /** IDs of items from server */
29
+ serverIds: Set<string>;
30
+ /** Explicit ordered list of item IDs, null means use default order (serverIds + plannedAdditions) */
31
+ orderedIds: string[] | null;
32
+ /** Planned removals (disconnect or delete) keyed by entity ID */
33
+ plannedRemovals: Map<string, HasManyRemovalType>;
34
+ /**
35
+ * Planned additions (IDs to add to the list) keyed by entity ID, with the
36
+ * value distinguishing newly CREATED entities (add()) from existing PERSISTED
37
+ * entities being CONNECTED (connect()). The keys are exactly the connections;
38
+ * the keys whose value is 'created' are exactly the created entities, so the
39
+ * "created ⊆ connections" invariant is structural.
40
+ */
41
+ plannedAdditions: Map<string, HasManyAdditionKind>;
42
+ version: number;
43
+ }
44
+ /**
45
+ * Computes the default ordered IDs for a has-many relation.
46
+ * Order is: serverIds (minus removals) + plannedAdditions
47
+ */
48
+ export declare function computeDefaultOrderedIds(state: StoredHasManyState): string[];
49
+ /**
50
+ * Owns has-many list state ("parentType:parentId:fieldName" → {@link StoredHasManyState}).
51
+ *
52
+ * Has its own monotonic {@link mutationVersion} bumped on every actual write
53
+ * (funnelled through {@link writeHasMany} plus the delete/clear paths); the
54
+ * facade sums this with the has-one counter for {@link ReachabilityAnalyzer}.
55
+ */
56
+ export declare class HasManyStore {
57
+ /** Has-many list states keyed by "parentType:parentId:fieldName" */
58
+ private readonly hasManyStates;
59
+ /**
60
+ * Bidirectional live-edge index, maintained by {@link writeHasMany} /
61
+ * {@link deleteHasMany} so the parent↔child queries are O(degree) and the two
62
+ * directions stay consistent by construction.
63
+ */
64
+ private readonly edges;
65
+ private mutationVersion;
66
+ /**
67
+ * Monotonic counter bumped on EDITABLE-layer has-many writes (plan add/remove,
68
+ * add, connectExisting, remove, move, reset) — the writes an undo gesture must
69
+ * first record. Server- id ingestion (setHasManyServerIds), materialization
70
+ * (getOrCreateHasMany), post-persist commit, import, replaceEntityId, rekey and
71
+ * delete deliberately do NOT bump it. Read by the undo write-guard (see UndoJournal).
72
+ */
73
+ private editableWriteVersion;
74
+ getMutationVersion(): number;
75
+ getEditableWriteVersion(): number;
76
+ /**
77
+ * The single write chokepoint. Reconciles the edge index by diffing the live
78
+ * members of the previous state against the next, so every state-changing path
79
+ * (server ids / planned add/remove / move / import / replaceEntityId / ...)
80
+ * keeps the index correct without tracking the reverse direction itself.
81
+ */
82
+ private writeHasMany;
83
+ /**
84
+ * The single delete chokepoint — removes an entry and its live edges. Used by
85
+ * the bulk remove and rekey-owner paths so they don't leak edges.
86
+ */
87
+ private deleteHasMany;
88
+ /**
89
+ * Gets or creates has-many list state.
90
+ */
91
+ getOrCreateHasMany(key: string, serverIds?: string[]): StoredHasManyState;
92
+ /**
93
+ * Gets has-many list state.
94
+ */
95
+ getHasMany(key: string): StoredHasManyState | undefined;
96
+ /**
97
+ * Sets server IDs for a has-many relation.
98
+ */
99
+ setHasManyServerIds(key: string, serverIds: string[]): void;
100
+ /**
101
+ * Plans a removal for a has-many item.
102
+ */
103
+ planHasManyRemoval(key: string, itemId: string, type: HasManyRemovalType): void;
104
+ /**
105
+ * Plans a connection for a has-many item.
106
+ */
107
+ planHasManyConnection(key: string, itemId: string): void;
108
+ /**
109
+ * Commits has-many state after successful persist.
110
+ */
111
+ commitHasMany(key: string, newServerIds: string[]): void;
112
+ /**
113
+ * Advances the server baseline by the confirmed sent delta and rebases local
114
+ * edits made after the request started onto that new baseline.
115
+ */
116
+ reconcileSentDelta(key: string, delta: SentHasManyDelta): ReconciliationResult;
117
+ /**
118
+ * Resets has-many state to server state (clears planned operations).
119
+ */
120
+ resetHasMany(key: string): void;
121
+ /**
122
+ * Adds a newly created entity to a has-many relation.
123
+ * Used by HasManyListHandle.add() for inline entity creation.
124
+ */
125
+ addToHasMany(key: string, itemId: string): void;
126
+ /**
127
+ * Connects an existing (persisted) entity to a has-many relation.
128
+ * Unlike addToHasMany, records the addition as 'connected' (not 'created') —
129
+ * used for materializing embedded connect references to existing entities.
130
+ */
131
+ connectExistingToHasMany(key: string, itemId: string): void;
132
+ /**
133
+ * Removes an entity from a has-many relation.
134
+ * For newly created entities (via add()), cancels the connection.
135
+ * For existing server entities, plans the specified removal type.
136
+ * Returns true if the state changed (caller should notify), false if it was a no-op.
137
+ */
138
+ removeFromHasMany(key: string, itemId: string, removalType: HasManyRemovalType): boolean;
139
+ /**
140
+ * Moves an item within a has-many relation from one index to another.
141
+ */
142
+ moveInHasMany(key: string, fromIndex: number, toIndex: number): void;
143
+ /**
144
+ * Gets the ordered list of item IDs for a has-many relation.
145
+ */
146
+ getHasManyOrderedIds(key: string): string[];
147
+ /**
148
+ * Collects the ids of child entities reachable through LIVE has-many edges
149
+ * (key prefix "parentType:parentId:") — an O(degree) read of the edge index.
150
+ */
151
+ collectLiveChildIds(keyPrefix: string, ids: Set<string>): void;
152
+ /**
153
+ * Adds the composite parent keys of every LIVE has-many edge containing
154
+ * {@link childId} — an O(degree) read of the edge index, the exact reverse of
155
+ * {@link collectLiveChildIds}.
156
+ */
157
+ collectParentKeysForChild(childId: string, parents: Set<string>): void;
158
+ /**
159
+ * Collects the keys of every has-many list owned by an entity (keys under the
160
+ * given owner prefix). Mirrors {@link removeOwnedRelations} but only enumerates.
161
+ */
162
+ collectOwnedKeys(keyPrefix: string, keys: string[]): void;
163
+ /**
164
+ * Removes a single has-many list state (and its live edges). Used by undo
165
+ * restore to drop a list that did not exist before the gesture.
166
+ */
167
+ removeHasMany(key: string): void;
168
+ /**
169
+ * Removes all has-many state owned by an entity (keys under the given owner
170
+ * prefix), dropping each entry's edges through {@link deleteHasMany}.
171
+ */
172
+ removeOwnedRelations(keyPrefix: string): void;
173
+ /**
174
+ * Commits all has-many relations for an entity.
175
+ *
176
+ * `pendingItems` (by relation key) names planned additions/removals that were NOT
177
+ * sent — they stay planned instead of being folded into the server baseline.
178
+ */
179
+ commitAllRelations(keyPrefix: string, pendingItems?: ReadonlyMap<string, ReadonlySet<string>>): void;
180
+ /**
181
+ * Resets all has-many relations for an entity to server state.
182
+ */
183
+ resetAllRelations(keyPrefix: string): void;
184
+ /**
185
+ * Collects the field names of dirty has-many relations for an entity.
186
+ */
187
+ collectDirtyRelations(keyPrefix: string, dirtyRelations: string[]): void;
188
+ /**
189
+ * Exports has-many states for given keys.
190
+ */
191
+ exportHasManyStates(keys: string[]): Map<string, StoredHasManyState>;
192
+ /**
193
+ * Imports has-many states from a snapshot.
194
+ * Returns the keys that were imported for notification.
195
+ */
196
+ importHasManyStates(states: Map<string, StoredHasManyState>): string[];
197
+ /**
198
+ * Replaces all occurrences of oldId with newId across has-many states
199
+ * (serverIds, orderedIds, plannedAdditions, plannedRemovals).
200
+ */
201
+ replaceEntityId(oldId: string, newId: string): void;
202
+ /**
203
+ * Rekeys has-many entries owned by an entity (changes the parent ID in the key).
204
+ * Routing through {@link deleteHasMany} + {@link writeHasMany} migrates the edge
205
+ * index from the old parent key to the new one for free.
206
+ */
207
+ rekeyOwner(oldKeyPrefix: string, newKeyPrefix: string): void;
208
+ /**
209
+ * Clears all has-many relation data.
210
+ */
211
+ clear(): void;
212
+ }
213
+ export {};
214
+ //# sourceMappingURL=HasManyStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HasManyStore.d.ts","sourceRoot":"","sources":["../../src/store/HasManyStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ import type { HasOneRelationState } from '../handles/types.js';
2
+ import type { EntitySnapshot } from './snapshots.js';
3
+ /**
4
+ * Relation state stored in SnapshotStore
5
+ */
6
+ export interface StoredRelationState {
7
+ currentId: string | null;
8
+ serverId: string | null;
9
+ state: HasOneRelationState;
10
+ serverState: HasOneRelationState;
11
+ placeholderData: Record<string, unknown>;
12
+ version: number;
13
+ }
14
+ type ReconciliationResult = 'applied' | 'conflict';
15
+ export type SentHasOneTransition = {
16
+ operation: 'connect';
17
+ targetId: string;
18
+ } | {
19
+ operation: 'create';
20
+ targetId: string;
21
+ } | {
22
+ operation: 'disconnect';
23
+ targetId: string;
24
+ } | {
25
+ operation: 'delete';
26
+ targetId: string;
27
+ };
28
+ /**
29
+ * Owns has-one relation state ("parentType:parentId:fieldName" → {@link StoredRelationState}).
30
+ *
31
+ * Has its own monotonic {@link mutationVersion} bumped on every actual write
32
+ * (funnelled through {@link writeRelation} plus the delete/clear paths); the
33
+ * facade sums this with the has-many counter for {@link ReachabilityAnalyzer}.
34
+ */
35
+ export declare class HasOneStore {
36
+ /** Relation states keyed by "parentType:parentId:fieldName" */
37
+ private readonly relationStates;
38
+ /**
39
+ * Bidirectional live-edge index, maintained by {@link writeRelation} /
40
+ * {@link deleteRelation} so the parent↔child queries are O(degree) and the two
41
+ * directions stay consistent by construction.
42
+ */
43
+ private readonly edges;
44
+ private mutationVersion;
45
+ /**
46
+ * Monotonic counter bumped on EDITABLE-layer has-one writes (setRelation /
47
+ * resetRelation) — the writes an undo gesture must first record. Materialization
48
+ * (getOrCreateRelation), post-persist commit, import, replaceEntityId, rekey and
49
+ * delete deliberately do NOT bump it. Read by the undo write-guard (see UndoJournal).
50
+ */
51
+ private editableWriteVersion;
52
+ getMutationVersion(): number;
53
+ getEditableWriteVersion(): number;
54
+ /**
55
+ * The single write chokepoint. Reconciles the edge index by diffing the live
56
+ * child of the previous state against the next, so every state-changing path
57
+ * (set/commit/reset/import/replaceEntityId/...) keeps the index correct without
58
+ * tracking the reverse direction itself.
59
+ */
60
+ private writeRelation;
61
+ /**
62
+ * The single delete chokepoint — removes an entry and its live edge. Used by
63
+ * the bulk remove and rekey-owner paths so they don't leak edges.
64
+ */
65
+ private deleteRelation;
66
+ /**
67
+ * Gets or creates relation state.
68
+ */
69
+ getOrCreateRelation(key: string, initial: Omit<StoredRelationState, 'version'>): StoredRelationState;
70
+ /**
71
+ * Gets relation state.
72
+ */
73
+ getRelation(key: string): StoredRelationState | undefined;
74
+ /**
75
+ * Updates relation state.
76
+ * If the relation state doesn't exist, creates it using entity snapshot for server data.
77
+ */
78
+ setRelation(key: string, updates: Partial<Omit<StoredRelationState, 'version'>>, entitySnapshot: EntitySnapshot | undefined, fieldName: string): void;
79
+ /**
80
+ * Commits relation state (server = current).
81
+ */
82
+ commitRelation(key: string): void;
83
+ /**
84
+ * Advances the server baseline by one confirmed sent transition while keeping
85
+ * edits made after the request started as pending local state.
86
+ */
87
+ reconcileSentTransition(key: string, transition: SentHasOneTransition): ReconciliationResult;
88
+ /**
89
+ * Resets relation to server state.
90
+ */
91
+ resetRelation(key: string): void;
92
+ /**
93
+ * Collects the ids of child entities reachable through LIVE has-one edges
94
+ * (key prefix "parentType:parentId:") — an O(degree) read of the edge index.
95
+ */
96
+ collectLiveChildIds(keyPrefix: string, ids: Set<string>): void;
97
+ /**
98
+ * Adds the composite parent keys of every LIVE has-one edge pointing at
99
+ * {@link childId} — an O(degree) read of the edge index, the exact reverse of
100
+ * {@link collectLiveChildIds}.
101
+ */
102
+ collectParentKeysForChild(childId: string, parents: Set<string>): void;
103
+ /**
104
+ * Collects the keys of every has-one relation owned by an entity (keys under the
105
+ * given owner prefix). Mirrors {@link removeOwnedRelations} but only enumerates.
106
+ */
107
+ collectOwnedKeys(keyPrefix: string, keys: string[]): void;
108
+ /**
109
+ * Removes a single has-one relation state (and its live edge). Used by undo
110
+ * restore to drop a relation that did not exist before the gesture.
111
+ */
112
+ removeRelation(key: string): void;
113
+ /**
114
+ * Removes all has-one state owned by an entity (keys under the given owner
115
+ * prefix), dropping each entry's edge through {@link deleteRelation}.
116
+ */
117
+ removeOwnedRelations(keyPrefix: string): void;
118
+ /**
119
+ * Commits all has-one relations for an entity.
120
+ *
121
+ * A relation whose planned op targets an item in `pendingItems` (by relation key)
122
+ * was not sent and is left uncommitted, so the op is retried on the next persist.
123
+ */
124
+ commitAllRelations(keyPrefix: string, pendingItems?: ReadonlyMap<string, ReadonlySet<string>>): void;
125
+ /**
126
+ * Resets all has-one relations for an entity to server state.
127
+ */
128
+ resetAllRelations(keyPrefix: string): void;
129
+ /**
130
+ * Collects the field names of dirty has-one relations for an entity.
131
+ */
132
+ collectDirtyRelations(keyPrefix: string, dirtyRelations: string[]): void;
133
+ /**
134
+ * Exports relation states for given keys.
135
+ */
136
+ exportRelationStates(keys: string[]): Map<string, StoredRelationState>;
137
+ /**
138
+ * Imports relation states from a snapshot.
139
+ * Returns the keys that were imported for notification.
140
+ */
141
+ importRelationStates(states: Map<string, StoredRelationState>): string[];
142
+ /**
143
+ * Replaces all occurrences of oldId with newId across has-one relation states
144
+ * (currentId, serverId).
145
+ */
146
+ replaceEntityId(oldId: string, newId: string): void;
147
+ /**
148
+ * Rekeys has-one entries owned by an entity (changes the parent ID in the key).
149
+ * Routing through {@link deleteRelation} + {@link writeRelation} migrates the
150
+ * edge index from the old parent key to the new one for free.
151
+ */
152
+ rekeyOwner(oldKeyPrefix: string, newKeyPrefix: string): void;
153
+ /**
154
+ * Clears all has-one relation data.
155
+ */
156
+ clear(): void;
157
+ }
158
+ export {};
159
+ //# sourceMappingURL=HasOneStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HasOneStore.d.ts","sourceRoot":"","sources":["../../src/store/HasOneStore.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,14 @@ import type { RootRegistry } from './RootRegistry.js';
17
17
  * The graph is read from {@link RelationStore} (the source of truth for live
18
18
  * relation membership), never from the subscription parent-child registry,
19
19
  * which is append-mostly for notifications and does not reflect disconnects.
20
+ *
21
+ * The walk is O(E+R) and runs on every dirty check and post-persist sweep, so
22
+ * its result is memoized. Each sub-store the walk reads exposes a monotonic
23
+ * `getMutationVersion()` that bumps only when graph-relevant state changes
24
+ * (entity key set, `existsOnServer`/`isPersisting`, roots, relation edges).
25
+ * Their sum is a cache key: it is strictly increasing, so an unchanged sum
26
+ * proves nothing relevant changed and the cached set can be returned. Pure
27
+ * field edits do not bump any counter, keeping the cache warm on the hot path.
20
28
  */
21
29
  export declare class ReachabilityAnalyzer {
22
30
  private readonly entitySnapshots;
@@ -24,10 +32,21 @@ export declare class ReachabilityAnalyzer {
24
32
  private readonly relations;
25
33
  private readonly roots;
26
34
  constructor(entitySnapshots: EntitySnapshotStore, meta: EntityMetaStore, relations: RelationStore, roots: RootRegistry);
35
+ private cache;
27
36
  /**
28
37
  * Returns the set of entity keys ("entityType:id") for created
29
38
  * (never-persisted) entities reachable from a root through live relations.
39
+ *
40
+ * The returned set is the cached instance and is owned by the analyzer —
41
+ * callers must treat it as read-only (the current consumers only call
42
+ * `.has(...)` on it).
30
43
  */
31
44
  computeReachableCreated(): Set<string>;
45
+ /**
46
+ * Sum of the graph-relevant mutation counters across the sub-stores the walk
47
+ * reads. Monotonic, so an unchanged value means no relevant mutation happened.
48
+ */
49
+ private graphVersion;
50
+ private walk;
32
51
  }
33
52
  //# sourceMappingURL=ReachabilityAnalyzer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReachabilityAnalyzer.d.ts","sourceRoot":"","sources":["../../src/store/ReachabilityAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,oBAAoB;IAE/B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAHL,eAAe,EAAE,mBAAmB,EACpC,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,YAAY;IAGrC;;;OAGG;IACH,uBAAuB,IAAI,GAAG,CAAC,MAAM,CAAC;CA0DtC"}
1
+ {"version":3,"file":"ReachabilityAnalyzer.d.ts","sourceRoot":"","sources":["../../src/store/ReachabilityAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,oBAAoB;IAE/B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAHL,eAAe,EAAE,mBAAmB,EACpC,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,YAAY;IAGrC,OAAO,CAAC,KAAK,CAAwD;IAErE;;;;;;;OAOG;IACH,uBAAuB,IAAI,GAAG,CAAC,MAAM,CAAC;IAYtC;;;OAGG;IACH,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,IAAI;CA0DZ"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Describes a single temp→persisted rekey in every shape the participating
3
+ * sub-stores need (full key, owner prefix, bare id).
4
+ */
5
+ export interface RekeyContext {
6
+ /** Old composite key, "entityType:tempId". */
7
+ readonly oldKey: string;
8
+ /** New composite key, "entityType:persistedId". */
9
+ readonly newKey: string;
10
+ /** Old owner prefix, "entityType:tempId:". */
11
+ readonly oldKeyPrefix: string;
12
+ /** New owner prefix, "entityType:persistedId:". */
13
+ readonly newKeyPrefix: string;
14
+ /** The temp id being replaced. */
15
+ readonly oldId: string;
16
+ /** The server-assigned id. */
17
+ readonly newId: string;
18
+ }
19
+ /**
20
+ * A store that owns per-entity state keyed (directly or by prefix) on an entity
21
+ * id and can migrate it from a temp id to its persisted id.
22
+ */
23
+ export interface Rekeyable {
24
+ rekey(ctx: RekeyContext): void;
25
+ }
26
+ /**
27
+ * Single source of temp→persisted identity, and the one place the rekey fan-out
28
+ * is sequenced.
29
+ *
30
+ * Owns the only id-redirect map: "entityType:tempId" → persistedId. Both key
31
+ * resolution ({@link resolveKey}/{@link resolveId}) and persisted-id queries
32
+ * ({@link getPersistedId}/{@link isNewEntity}) derive from it, so there is no
33
+ * second copy to keep in sync — the former `SnapshotStore.rekeyedEntities` and
34
+ * `EntityMetaStore.tempToPersistedId` are both gone. `SubscriptionManager` keeps
35
+ * its own closure-redirect chain, which tracks relation-key prefixes and stale
36
+ * unsubscribe closures rather than entity identity, so it stays internal there.
37
+ */
38
+ export declare class RekeyOrchestrator {
39
+ /** "entityType:tempId" → persistedId. The single identity-redirect map. */
40
+ private readonly tempToPersisted;
41
+ private readonly participants;
42
+ private readonly participantSet;
43
+ /**
44
+ * @param participants the sub-stores to migrate, in the exact order
45
+ * {@link rekey} must visit them (the order is load-bearing — see rekey()).
46
+ */
47
+ constructor(participants: readonly Rekeyable[]);
48
+ /** Adds a participant once, preserving registration order. */
49
+ registerParticipant(participant: Rekeyable): void;
50
+ /** Resolves an entity key, following a temp→persisted redirect if present. */
51
+ resolveKey(entityType: string, id: string): string;
52
+ /** Resolves an entity id to its persisted id if it has been rekeyed. */
53
+ resolveId(entityType: string, id: string): string;
54
+ /** The persisted id for an entity, or null if it has none yet. */
55
+ getPersistedId(entityType: string, id: string): string | null;
56
+ /** Whether an entity has never been persisted (no server-assigned id yet). */
57
+ isNewEntity(entityType: string, id: string): boolean;
58
+ /**
59
+ * Migrates an entity from its temp id to its server-assigned id across every
60
+ * participating store.
61
+ *
62
+ * Ordering contract (do not reorder — each step relies on the previous):
63
+ * 0. register the redirect, so any resolveKey/resolveId during the fan-out
64
+ * already sees the persisted key;
65
+ * 1. roots — keep the root registry aligned;
66
+ * 2. entity snapshot — move data, rewrite the id field and id index;
67
+ * 3. meta — move metadata/load/persisting, then mark exists-on-server;
68
+ * 4. subscriptions — move entity + relation subscribers and parent links;
69
+ * 5. relations — rekey owned relation keys, then replace value references;
70
+ * 6. errors / touched / propagation — move the remaining per-entity state.
71
+ * The caller performs the final notification on the new key.
72
+ */
73
+ rekey(entityType: string, tempId: string, persistedId: string): void;
74
+ clear(): void;
75
+ }
76
+ //# sourceMappingURL=RekeyOrchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RekeyOrchestrator.d.ts","sourceRoot":"","sources":["../../src/store/RekeyOrchestrator.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,mDAAmD;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,8CAA8C;IAC9C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACzB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAAA;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAiB;IAC7B,2EAA2E;IAC3E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4B;IAC5D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;IAEtD;;;OAGG;gBACS,YAAY,EAAE,SAAS,SAAS,EAAE;IAI9C,8DAA8D;IAC9D,mBAAmB,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI;IAMjD,8EAA8E;IAC9E,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM;IAKlD,wEAAwE;IACxE,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM;IAIjD,kEAAkE;IAClE,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAM7D,8EAA8E;IAC9E,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO;IAMpD;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAiBpE,KAAK,IAAI,IAAI;CAGb"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Bidirectional index of LIVE relation edges between a parent entity
3
+ * ("parentType:parentId") and a child entity id (a bare id).
4
+ *
5
+ * Both directions are updated together by {@link addEdge}/{@link removeEdge}, so
6
+ * the forward query ({@link collectChildren}) and the reverse query
7
+ * ({@link collectParents}) can never disagree — that was the failure mode of the
8
+ * old append-only `childToParents` map, which was updated on connect but not on
9
+ * disconnect. Both queries are O(degree), not O(total edges).
10
+ *
11
+ * Edges are reference-counted: one parent entity may reach the same child through
12
+ * more than one relation field (e.g. `author` and `coauthor`, or two has-many
13
+ * fields), so an edge survives until the last field that contributes it drops it.
14
+ *
15
+ * The index stores only the LIVE edge set; turning relation state (server ids,
16
+ * planned additions/removals, has-one state) into that set is the owning
17
+ * sub-store's job, done once per write by diffing the previous against the next
18
+ * live set (see {@link HasOneStore}/{@link HasManyStore}). The index itself knows
19
+ * nothing about liveness rules.
20
+ */
21
+ export declare class RelationEdgeIndex {
22
+ /** parentKey ("parentType:parentId") → childId → refcount */
23
+ private readonly forward;
24
+ /** childId → parentKey → refcount */
25
+ private readonly reverse;
26
+ addEdge(parentKey: string, childId: string): void;
27
+ removeEdge(parentKey: string, childId: string): void;
28
+ /** Adds the live child ids of {@link parentKey} to {@link out}. */
29
+ collectChildren(parentKey: string, out: Set<string>): void;
30
+ /** Adds the parent keys that hold a live edge to {@link childId} to {@link out}. */
31
+ collectParents(childId: string, out: Set<string>): void;
32
+ clear(): void;
33
+ }
34
+ //# sourceMappingURL=RelationEdgeIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RelationEdgeIndex.d.ts","sourceRoot":"","sources":["../../src/store/RelationEdgeIndex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,iBAAiB;IAC7B,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IACjE,qCAAqC;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IAEjE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAKjD,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAKpD,mEAAmE;IACnE,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI;IAO1D,oFAAoF;IACpF,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI;IAOvD,KAAK,IAAI,IAAI;CAIb"}