@contember/bindx 0.1.30 → 0.1.32
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/ContemberAdapter.d.ts.map +1 -1
- package/dist/adapter/types.d.ts +4 -0
- package/dist/adapter/types.d.ts.map +1 -1
- package/dist/core/ActionDispatcher.d.ts.map +1 -1
- package/dist/core/actions.d.ts +4 -2
- package/dist/core/actions.d.ts.map +1 -1
- package/dist/handles/BaseHandle.d.ts +5 -0
- package/dist/handles/BaseHandle.d.ts.map +1 -1
- package/dist/handles/HasManyListHandle.d.ts +1 -0
- package/dist/handles/HasManyListHandle.d.ts.map +1 -1
- package/dist/handles/HasOneHandle.d.ts +6 -0
- package/dist/handles/HasOneHandle.d.ts.map +1 -1
- package/dist/handles/types.d.ts +1 -0
- package/dist/handles/types.d.ts.map +1 -1
- package/dist/persistence/BatchPersister.d.ts +30 -0
- package/dist/persistence/BatchPersister.d.ts.map +1 -1
- package/dist/persistence/MutationCollector.d.ts +28 -0
- package/dist/persistence/MutationCollector.d.ts.map +1 -1
- package/dist/persistence/types.d.ts +6 -0
- package/dist/persistence/types.d.ts.map +1 -1
- package/dist/store/EntityMetaStore.d.ts +4 -0
- package/dist/store/EntityMetaStore.d.ts.map +1 -1
- package/dist/store/EntitySnapshotStore.d.ts +4 -0
- package/dist/store/EntitySnapshotStore.d.ts.map +1 -1
- package/dist/store/ErrorStore.d.ts +6 -0
- package/dist/store/ErrorStore.d.ts.map +1 -1
- package/dist/store/RelationStore.d.ts +15 -0
- package/dist/store/RelationStore.d.ts.map +1 -1
- package/dist/store/SnapshotStore.d.ts +31 -0
- package/dist/store/SnapshotStore.d.ts.map +1 -1
- package/dist/store/SubscriptionManager.d.ts +15 -0
- package/dist/store/SubscriptionManager.d.ts.map +1 -1
- package/dist/store/TouchedStore.d.ts +4 -0
- package/dist/store/TouchedStore.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/adapter/ContemberAdapter.ts +11 -5
- package/src/adapter/types.ts +4 -0
- package/src/core/ActionDispatcher.ts +3 -0
- package/src/core/actions.ts +6 -2
- package/src/handles/BaseHandle.ts +16 -0
- package/src/handles/HasManyListHandle.ts +35 -25
- package/src/handles/HasOneHandle.ts +35 -8
- package/src/handles/types.ts +1 -0
- package/src/persistence/BatchPersister.ts +237 -0
- package/src/persistence/MutationCollector.ts +167 -19
- package/src/persistence/types.ts +6 -0
- package/src/store/EntityMetaStore.ts +29 -0
- package/src/store/EntitySnapshotStore.ts +23 -0
- package/src/store/ErrorStore.ts +30 -0
- package/src/store/RelationStore.ts +157 -1
- package/src/store/SnapshotStore.ts +116 -5
- package/src/store/SubscriptionManager.ts +82 -2
- package/src/store/TouchedStore.ts +16 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapshotStore.d.ts","sourceRoot":"","sources":["../../src/store/SnapshotStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAuB,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAE1F,OAAO,EAEN,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAMvE,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACrG,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAE/F,KAAK,UAAU,GAAG,MAAM,IAAI,CAAA;AAE5B;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAc,YAAW,qBAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4B;IAC5D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAwB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;;
|
|
1
|
+
{"version":3,"file":"SnapshotStore.d.ts","sourceRoot":"","sources":["../../src/store/SnapshotStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,8 +25,17 @@ export declare class SubscriptionManager {
|
|
|
25
25
|
private readonly globalSubscribers;
|
|
26
26
|
/** Parent-child relationships: childKey -> Set of parentKeys */
|
|
27
27
|
private readonly childToParents;
|
|
28
|
+
/** Maps old keys → new keys after rekey, so unsubscribe closures can find migrated callbacks */
|
|
29
|
+
private readonly rekeyedKeys;
|
|
28
30
|
/** Global version number for change detection */
|
|
29
31
|
private globalVersion;
|
|
32
|
+
/**
|
|
33
|
+
* Resolves a key through the rekey redirect chain.
|
|
34
|
+
* The rekey() method collapses chains (A→C instead of A→B→C), so this should
|
|
35
|
+
* always resolve in one hop. The loop with depth limit is a safety net in case
|
|
36
|
+
* chain collapsing has a bug — prevents infinite loops instead of silently hanging.
|
|
37
|
+
*/
|
|
38
|
+
private resolveKey;
|
|
30
39
|
/**
|
|
31
40
|
* Subscribe to changes on a specific entity.
|
|
32
41
|
* Returns unsubscribe function.
|
|
@@ -85,6 +94,12 @@ export declare class SubscriptionManager {
|
|
|
85
94
|
* Bumps global version and notifies global subscribers.
|
|
86
95
|
*/
|
|
87
96
|
notifyGlobal(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Moves subscriptions and parent-child relationships from oldKey to newKey.
|
|
99
|
+
* Also rekeys relation subscribers under oldKeyPrefix to newKeyPrefix.
|
|
100
|
+
* Registers redirects so unsubscribe closures can find migrated callbacks.
|
|
101
|
+
*/
|
|
102
|
+
rekey(oldKey: string, newKey: string, oldKeyPrefix: string, newKeyPrefix: string): void;
|
|
88
103
|
}
|
|
89
104
|
export {};
|
|
90
105
|
//# 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,iDAAiD;IACjD,OAAO,CAAC,aAAa,CAAI;IAEzB;;;OAGG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,MAAM,IAAI;
|
|
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;IAiCP;;;;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"}
|
|
@@ -19,6 +19,10 @@ export declare class TouchedStore {
|
|
|
19
19
|
* Clears all touched state for an entity.
|
|
20
20
|
*/
|
|
21
21
|
clearForEntity(keyPrefix: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Rekeys all touched fields from oldKeyPrefix to newKeyPrefix.
|
|
24
|
+
*/
|
|
25
|
+
rekey(oldKeyPrefix: string, newKeyPrefix: string): void;
|
|
22
26
|
clear(): void;
|
|
23
27
|
}
|
|
24
28
|
//# 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,KAAK,IAAI,IAAI;CAGb"}
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/bindx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
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.32",
|
|
21
21
|
"@contember/graphql-builder": "^2.1.0-beta.1",
|
|
22
22
|
"@contember/graphql-client": "^2.1.0-beta.1"
|
|
23
23
|
},
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
buildUpdateArgs,
|
|
12
12
|
buildDeleteArgs,
|
|
13
13
|
buildMutationSelection,
|
|
14
|
+
buildNodeSelectionFromMutationData,
|
|
14
15
|
mutationFragments,
|
|
15
16
|
unwrapPaginateResult,
|
|
16
17
|
} from '@contember/bindx-client'
|
|
@@ -119,19 +120,24 @@ export class ContemberAdapter implements BackendAdapter {
|
|
|
119
120
|
changes: Record<string, unknown>,
|
|
120
121
|
): Promise<PersistResult> {
|
|
121
122
|
const args = buildUpdateArgs(entityType, { by: { id }, data: changes })
|
|
122
|
-
const
|
|
123
|
+
const nodeSelection = buildNodeSelectionFromMutationData(changes)
|
|
124
|
+
const selectionSet = buildMutationSelection('update', nodeSelection)
|
|
123
125
|
|
|
124
126
|
const mutation = new ContentOperation(
|
|
125
127
|
'mutation',
|
|
126
128
|
`update${entityType}`,
|
|
127
129
|
args,
|
|
128
130
|
selectionSet,
|
|
129
|
-
value => value as { ok: boolean; errorMessage: string | null; errors: unknown[]; validation: unknown },
|
|
131
|
+
value => value as { ok: boolean; errorMessage: string | null; errors: unknown[]; validation: unknown; node: unknown },
|
|
130
132
|
)
|
|
131
133
|
|
|
132
134
|
try {
|
|
133
135
|
const result = await this.contentClient.mutate(mutation)
|
|
134
|
-
|
|
136
|
+
const typedResult = result as { node: Record<string, unknown> | null }
|
|
137
|
+
return {
|
|
138
|
+
ok: true,
|
|
139
|
+
data: typedResult.node as Record<string, unknown> | undefined,
|
|
140
|
+
}
|
|
135
141
|
} catch (e) {
|
|
136
142
|
if (e instanceof Error && 'result' in e) {
|
|
137
143
|
const mutResult = (e as { result: Record<string, unknown> }).result
|
|
@@ -150,8 +156,8 @@ export class ContemberAdapter implements BackendAdapter {
|
|
|
150
156
|
data: Record<string, unknown>,
|
|
151
157
|
): Promise<CreateResult> {
|
|
152
158
|
const args = buildCreateArgs(entityType, { data })
|
|
153
|
-
// Select id on created node
|
|
154
|
-
const nodeSelection =
|
|
159
|
+
// Select id on created node + nested created entity IDs
|
|
160
|
+
const nodeSelection = buildNodeSelectionFromMutationData(data)
|
|
155
161
|
const selectionSet = buildMutationSelection('create', nodeSelection)
|
|
156
162
|
|
|
157
163
|
const mutation = new ContentOperation(
|
package/src/adapter/types.ts
CHANGED
|
@@ -80,6 +80,8 @@ export type QueryResult = GetQueryResult | ListQueryResult
|
|
|
80
80
|
export interface PersistResult {
|
|
81
81
|
readonly ok: boolean
|
|
82
82
|
readonly errorMessage?: string
|
|
83
|
+
/** The entity node data after mutation (when ok is true). Contains nested entity IDs for inline creates. */
|
|
84
|
+
readonly data?: Record<string, unknown>
|
|
83
85
|
/** Detailed mutation result for error mapping (Contember-specific) */
|
|
84
86
|
readonly mutationResult?: ContemberMutationResult
|
|
85
87
|
}
|
|
@@ -128,6 +130,8 @@ export interface TransactionMutationResult {
|
|
|
128
130
|
readonly persistedId?: string
|
|
129
131
|
readonly errorMessage?: string
|
|
130
132
|
readonly mutationResult?: ContemberMutationResult
|
|
133
|
+
/** Results for entities created inline within this mutation's data. */
|
|
134
|
+
readonly nestedResults?: readonly TransactionMutationResult[]
|
|
131
135
|
}
|
|
132
136
|
|
|
133
137
|
/**
|
|
@@ -218,6 +218,7 @@ export class ActionDispatcher {
|
|
|
218
218
|
state: 'connected',
|
|
219
219
|
},
|
|
220
220
|
)
|
|
221
|
+
this.store.registerParentChild(action.entityType, action.entityId, action.targetType, action.targetId)
|
|
221
222
|
break
|
|
222
223
|
|
|
223
224
|
case 'DISCONNECT_RELATION':
|
|
@@ -293,6 +294,7 @@ export class ActionDispatcher {
|
|
|
293
294
|
action.itemId,
|
|
294
295
|
action.alias,
|
|
295
296
|
)
|
|
297
|
+
this.store.registerParentChild(action.entityType, action.entityId, action.targetType, action.itemId)
|
|
296
298
|
break
|
|
297
299
|
|
|
298
300
|
case 'ADD_TO_LIST': {
|
|
@@ -306,6 +308,7 @@ export class ActionDispatcher {
|
|
|
306
308
|
itemId,
|
|
307
309
|
action.alias,
|
|
308
310
|
)
|
|
311
|
+
this.store.registerParentChild(action.entityType, action.entityId, action.targetType, itemId)
|
|
309
312
|
break
|
|
310
313
|
}
|
|
311
314
|
|
package/src/core/actions.ts
CHANGED
|
@@ -61,6 +61,7 @@ export interface ConnectRelationAction {
|
|
|
61
61
|
readonly entityId: string
|
|
62
62
|
readonly fieldName: string
|
|
63
63
|
readonly targetId: string
|
|
64
|
+
readonly targetType: string
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
/**
|
|
@@ -126,6 +127,7 @@ export interface ConnectToListAction {
|
|
|
126
127
|
readonly entityId: string
|
|
127
128
|
readonly fieldName: string
|
|
128
129
|
readonly itemId: string
|
|
130
|
+
readonly targetType: string
|
|
129
131
|
readonly alias?: string
|
|
130
132
|
}
|
|
131
133
|
|
|
@@ -355,8 +357,9 @@ export function connectRelation(
|
|
|
355
357
|
entityId: string,
|
|
356
358
|
fieldName: string,
|
|
357
359
|
targetId: string,
|
|
360
|
+
targetType: string,
|
|
358
361
|
): ConnectRelationAction {
|
|
359
|
-
return { type: 'CONNECT_RELATION', entityType, entityId, fieldName, targetId }
|
|
362
|
+
return { type: 'CONNECT_RELATION', entityType, entityId, fieldName, targetId, targetType }
|
|
360
363
|
}
|
|
361
364
|
|
|
362
365
|
/**
|
|
@@ -517,9 +520,10 @@ export function connectToList(
|
|
|
517
520
|
entityId: string,
|
|
518
521
|
fieldName: string,
|
|
519
522
|
itemId: string,
|
|
523
|
+
targetType: string,
|
|
520
524
|
alias?: string,
|
|
521
525
|
): ConnectToListAction {
|
|
522
|
-
return { type: 'CONNECT_TO_LIST', entityType, entityId, fieldName, itemId, alias }
|
|
526
|
+
return { type: 'CONNECT_TO_LIST', entityType, entityId, fieldName, itemId, targetType, alias }
|
|
523
527
|
}
|
|
524
528
|
|
|
525
529
|
/**
|
|
@@ -98,3 +98,19 @@ export abstract class EntityRelatedHandle extends BaseHandle {
|
|
|
98
98
|
return snapshot?.serverData as Record<string, unknown> | undefined
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Shallow comparison of embedded data keys against existing snapshot data.
|
|
104
|
+
* Returns true if all keys in embedded data match the snapshot.
|
|
105
|
+
*/
|
|
106
|
+
export function embeddedDataMatchesSnapshot(
|
|
107
|
+
embedded: Record<string, unknown>,
|
|
108
|
+
snapshot: Record<string, unknown>,
|
|
109
|
+
): boolean {
|
|
110
|
+
for (const key of Object.keys(embedded)) {
|
|
111
|
+
if (embedded[key] !== snapshot[key]) {
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityRelatedHandle } from './BaseHandle.js'
|
|
1
|
+
import { EntityRelatedHandle, embeddedDataMatchesSnapshot } from './BaseHandle.js'
|
|
2
2
|
import { EntityHandle } from './EntityHandle.js'
|
|
3
3
|
import type { ActionDispatcher } from '../core/ActionDispatcher.js'
|
|
4
4
|
import type { SnapshotStore } from '../store/SnapshotStore.js'
|
|
@@ -124,23 +124,36 @@ export class HasManyListHandle<TEntity extends object = object, TSelected = TEnt
|
|
|
124
124
|
const listData = this.extractItems(rawData)
|
|
125
125
|
if (!listData) return []
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
this.ensureItemSnapshots(listData)
|
|
127
|
+
const fieldKey = this.alias ?? this.fieldName
|
|
129
128
|
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
// Only propagate embedded data when the parent's reference changed (re-fetch).
|
|
130
|
+
// Same reference means the embedded data is stale and must not overwrite
|
|
131
|
+
// child state that may have been updated by a local commit.
|
|
132
|
+
if (this.store.hasEmbeddedDataChanged(this.entityType, this.entityId, fieldKey, rawData)) {
|
|
133
|
+
this.ensureItemSnapshots(listData)
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
this.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
135
|
+
const serverIds = listData
|
|
136
|
+
.map((item) => item['id'] as string | undefined)
|
|
137
|
+
.filter((id): id is string => id !== undefined)
|
|
138
|
+
|
|
139
|
+
this.store.getOrCreateHasMany(
|
|
140
|
+
this.entityType,
|
|
141
|
+
this.entityId,
|
|
142
|
+
this.fieldName,
|
|
143
|
+
serverIds,
|
|
144
|
+
this.alias,
|
|
145
|
+
)
|
|
146
|
+
this.store.markEmbeddedDataPropagated(this.entityType, this.entityId, fieldKey, rawData)
|
|
147
|
+
} else {
|
|
148
|
+
// Ensure has-many state exists (without updating serverIds)
|
|
149
|
+
this.store.getOrCreateHasMany(
|
|
150
|
+
this.entityType,
|
|
151
|
+
this.entityId,
|
|
152
|
+
this.fieldName,
|
|
153
|
+
undefined,
|
|
154
|
+
this.alias,
|
|
155
|
+
)
|
|
156
|
+
}
|
|
144
157
|
|
|
145
158
|
// Use ordered IDs from store (handles removals, connections, and ordering)
|
|
146
159
|
const orderedIds = this.store.getHasManyOrderedIds(
|
|
@@ -155,6 +168,7 @@ export class HasManyListHandle<TEntity extends object = object, TSelected = TEnt
|
|
|
155
168
|
|
|
156
169
|
/**
|
|
157
170
|
* Ensures snapshots exist for embedded has-many items.
|
|
171
|
+
* Only called when parent's embedded data has changed (re-fetch detected).
|
|
158
172
|
*/
|
|
159
173
|
private ensureItemSnapshots(listData: Array<Record<string, unknown>>): void {
|
|
160
174
|
for (const itemData of listData) {
|
|
@@ -165,12 +179,13 @@ export class HasManyListHandle<TEntity extends object = object, TSelected = TEnt
|
|
|
165
179
|
// This needs to happen even if the snapshot already exists
|
|
166
180
|
this.store.registerParentChild(this.entityType, this.entityId, this.itemType, itemId)
|
|
167
181
|
|
|
168
|
-
//
|
|
169
|
-
|
|
182
|
+
// Optimization: skip if item data matches existing snapshot
|
|
183
|
+
const existing = this.store.getEntitySnapshot(this.itemType, itemId)
|
|
184
|
+
if (existing?.serverData && embeddedDataMatchesSnapshot(itemData, existing.serverData as Record<string, unknown>)) {
|
|
170
185
|
continue
|
|
171
186
|
}
|
|
172
187
|
|
|
173
|
-
// Create snapshot from embedded data
|
|
188
|
+
// Create or update snapshot from embedded data
|
|
174
189
|
// Skip notification to avoid triggering React state updates during render
|
|
175
190
|
this.store.setEntityData(
|
|
176
191
|
this.itemType,
|
|
@@ -304,10 +319,8 @@ export class HasManyListHandle<TEntity extends object = object, TSelected = TEnt
|
|
|
304
319
|
connect(itemId: string): void {
|
|
305
320
|
this.assertNotDisposed()
|
|
306
321
|
this.dispatcher.dispatch(
|
|
307
|
-
connectToList(this.entityType, this.entityId, this.fieldName, itemId, this.alias),
|
|
322
|
+
connectToList(this.entityType, this.entityId, this.fieldName, itemId, this.itemType, this.alias),
|
|
308
323
|
)
|
|
309
|
-
// Register parent-child so that changes to the connected entity propagate to the parent
|
|
310
|
-
this.store.registerParentChild(this.entityType, this.entityId, this.itemType, itemId)
|
|
311
324
|
}
|
|
312
325
|
|
|
313
326
|
/**
|
|
@@ -350,9 +363,6 @@ export class HasManyListHandle<TEntity extends object = object, TSelected = TEnt
|
|
|
350
363
|
addToList(this.entityType, this.entityId, this.fieldName, this.itemType, tempId, this.alias),
|
|
351
364
|
)
|
|
352
365
|
|
|
353
|
-
// Register parent-child so that changes to the new entity propagate to the parent
|
|
354
|
-
this.store.registerParentChild(this.entityType, this.entityId, this.itemType, tempId)
|
|
355
|
-
|
|
356
366
|
return tempId
|
|
357
367
|
}
|
|
358
368
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityRelatedHandle } from './BaseHandle.js'
|
|
1
|
+
import { EntityRelatedHandle, embeddedDataMatchesSnapshot } from './BaseHandle.js'
|
|
2
2
|
import type { ActionDispatcher } from '../core/ActionDispatcher.js'
|
|
3
3
|
import type { SnapshotStore } from '../store/SnapshotStore.js'
|
|
4
4
|
import type { SchemaRegistry } from '../schema/SchemaRegistry.js'
|
|
@@ -283,11 +283,6 @@ export class HasOneHandle<TEntity extends object = object, TSelected = TEntity>
|
|
|
283
283
|
// This needs to happen even if the snapshot already exists
|
|
284
284
|
this.store.registerParentChild(this.entityType, this.entityId, this.targetType, id)
|
|
285
285
|
|
|
286
|
-
// Check if snapshot already exists
|
|
287
|
-
if (this.store.hasEntity(this.targetType, id)) {
|
|
288
|
-
return
|
|
289
|
-
}
|
|
290
|
-
|
|
291
286
|
// Get embedded data from parent entity
|
|
292
287
|
const parentSnapshot = this.store.getEntitySnapshot(this.entityType, this.entityId)
|
|
293
288
|
if (!parentSnapshot?.data) {
|
|
@@ -308,7 +303,24 @@ export class HasOneHandle<TEntity extends object = object, TSelected = TEntity>
|
|
|
308
303
|
return
|
|
309
304
|
}
|
|
310
305
|
|
|
311
|
-
//
|
|
306
|
+
// Skip if parent's embedded data reference hasn't changed since last propagation.
|
|
307
|
+
// A new reference means the parent was re-fetched from the server.
|
|
308
|
+
// Same reference means the embedded data is stale and must not overwrite
|
|
309
|
+
// child state that may have been updated by a local commit.
|
|
310
|
+
if (!this.store.hasEmbeddedDataChanged(this.entityType, this.entityId, this.fieldName, embeddedData)) {
|
|
311
|
+
return
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Skip if embedded data values match existing serverData — avoids overwriting
|
|
315
|
+
// unpersisted local mutations when a re-fetch returns the same server data
|
|
316
|
+
// (e.g. polling). A new reference with identical values means no actual change.
|
|
317
|
+
const existing = this.store.getEntitySnapshot(this.targetType, id)
|
|
318
|
+
if (existing?.serverData && embeddedDataMatchesSnapshot(embeddedData as Record<string, unknown>, existing.serverData as Record<string, unknown>)) {
|
|
319
|
+
this.store.markEmbeddedDataPropagated(this.entityType, this.entityId, this.fieldName, embeddedData)
|
|
320
|
+
return
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Create or update snapshot from embedded data
|
|
312
324
|
// Skip notification to avoid triggering React state updates during render
|
|
313
325
|
this.store.setEntityData(
|
|
314
326
|
this.targetType,
|
|
@@ -317,6 +329,7 @@ export class HasOneHandle<TEntity extends object = object, TSelected = TEntity>
|
|
|
317
329
|
true, // isServerData
|
|
318
330
|
true, // skipNotify - called during render, data already exists embedded in parent
|
|
319
331
|
)
|
|
332
|
+
this.store.markEmbeddedDataPropagated(this.entityType, this.entityId, this.fieldName, embeddedData)
|
|
320
333
|
}
|
|
321
334
|
|
|
322
335
|
/**
|
|
@@ -353,13 +366,27 @@ export class HasOneHandle<TEntity extends object = object, TSelected = TEntity>
|
|
|
353
366
|
)
|
|
354
367
|
}
|
|
355
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Creates a new entity of the target type and connects it to this relation.
|
|
371
|
+
* Returns the temp ID of the created entity.
|
|
372
|
+
* Accessible via proxy as `$create()`.
|
|
373
|
+
*/
|
|
374
|
+
create(data?: Partial<TEntity>): string {
|
|
375
|
+
this.assertNotDisposed()
|
|
376
|
+
const tempId = this.store.createEntity(this.targetType, data as Record<string, unknown>)
|
|
377
|
+
this.dispatcher.dispatch(
|
|
378
|
+
connectRelation(this.entityType, this.entityId, this.fieldName, tempId, this.targetType),
|
|
379
|
+
)
|
|
380
|
+
return tempId
|
|
381
|
+
}
|
|
382
|
+
|
|
356
383
|
/**
|
|
357
384
|
* Connects the relation to an entity.
|
|
358
385
|
*/
|
|
359
386
|
connect(targetId: string): void {
|
|
360
387
|
this.assertNotDisposed()
|
|
361
388
|
this.dispatcher.dispatch(
|
|
362
|
-
connectRelation(this.entityType, this.entityId, this.fieldName, targetId),
|
|
389
|
+
connectRelation(this.entityType, this.entityId, this.fieldName, targetId, this.targetType),
|
|
363
390
|
)
|
|
364
391
|
}
|
|
365
392
|
|
package/src/handles/types.ts
CHANGED
|
@@ -228,6 +228,7 @@ export interface HasOneRefInterface<
|
|
|
228
228
|
readonly __entityType: TEntity
|
|
229
229
|
readonly __selected?: TSelected
|
|
230
230
|
readonly __brands?: Set<symbol>
|
|
231
|
+
$create(data?: Partial<TEntity>): string
|
|
231
232
|
$connect(id: string): void
|
|
232
233
|
$disconnect(): void
|
|
233
234
|
$delete(): void
|