@contember/bindx 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/ContemberAdapter.d.ts +40 -0
- package/dist/adapter/ContemberAdapter.d.ts.map +1 -0
- package/dist/adapter/MockAdapter.d.ts +81 -0
- package/dist/adapter/MockAdapter.d.ts.map +1 -0
- package/dist/adapter/MockQueryEngine.d.ts +43 -0
- package/dist/adapter/MockQueryEngine.d.ts.map +1 -0
- package/dist/adapter/index.d.ts +5 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/types.d.ts +184 -0
- package/dist/adapter/types.d.ts.map +1 -0
- package/dist/brand/ComponentBrand.d.ts +25 -0
- package/dist/brand/ComponentBrand.d.ts.map +1 -0
- package/dist/contember/index.d.ts +10 -0
- package/dist/contember/index.d.ts.map +1 -0
- package/dist/core/ActionDispatcher.d.ts +64 -0
- package/dist/core/ActionDispatcher.d.ts.map +1 -0
- package/dist/core/Disposable.d.ts +57 -0
- package/dist/core/Disposable.d.ts.map +1 -0
- package/dist/core/EntityLoader.d.ts +80 -0
- package/dist/core/EntityLoader.d.ts.map +1 -0
- package/dist/core/PersistenceManager.d.ts +126 -0
- package/dist/core/PersistenceManager.d.ts.map +1 -0
- package/dist/core/SelectionResolver.d.ts +21 -0
- package/dist/core/SelectionResolver.d.ts.map +1 -0
- package/dist/core/actionClassification.d.ts +48 -0
- package/dist/core/actionClassification.d.ts.map +1 -0
- package/dist/core/actions.d.ts +301 -0
- package/dist/core/actions.d.ts.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/dataview/filterHandlers.d.ts +18 -0
- package/dist/dataview/filterHandlers.d.ts.map +1 -0
- package/dist/dataview/index.d.ts +3 -0
- package/dist/dataview/index.d.ts.map +1 -0
- package/dist/dataview/types.d.ts +164 -0
- package/dist/dataview/types.d.ts.map +1 -0
- package/dist/errors/UnfetchedFieldError.d.ts +11 -0
- package/dist/errors/UnfetchedFieldError.d.ts.map +1 -0
- package/dist/errors/errorPathResolver.d.ts +52 -0
- package/dist/errors/errorPathResolver.d.ts.map +1 -0
- package/dist/errors/index.d.ts +5 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/pathMapper.d.ts +42 -0
- package/dist/errors/pathMapper.d.ts.map +1 -0
- package/dist/errors/types.d.ts +131 -0
- package/dist/errors/types.d.ts.map +1 -0
- package/dist/events/EventEmitter.d.ts +97 -0
- package/dist/events/EventEmitter.d.ts.map +1 -0
- package/dist/events/eventFactory.d.ts +40 -0
- package/dist/events/eventFactory.d.ts.map +1 -0
- package/dist/events/index.d.ts +15 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/types.d.ts +264 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/handles/BaseHandle.d.ts +64 -0
- package/dist/handles/BaseHandle.d.ts.map +1 -0
- package/dist/handles/EntityHandle.d.ts +208 -0
- package/dist/handles/EntityHandle.d.ts.map +1 -0
- package/dist/handles/FieldHandle.d.ts +111 -0
- package/dist/handles/FieldHandle.d.ts.map +1 -0
- package/dist/handles/HasManyListHandle.d.ts +166 -0
- package/dist/handles/HasManyListHandle.d.ts.map +1 -0
- package/dist/handles/HasOneHandle.d.ts +168 -0
- package/dist/handles/HasOneHandle.d.ts.map +1 -0
- package/dist/handles/PlaceholderHandle.d.ts +117 -0
- package/dist/handles/PlaceholderHandle.d.ts.map +1 -0
- package/dist/handles/index.d.ts +8 -0
- package/dist/handles/index.d.ts.map +1 -0
- package/dist/handles/proxyFactory.d.ts +66 -0
- package/dist/handles/proxyFactory.d.ts.map +1 -0
- package/dist/handles/types.d.ts +430 -0
- package/dist/handles/types.d.ts.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/internal.d.ts +11 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/persistence/BatchPersister.d.ts +142 -0
- package/dist/persistence/BatchPersister.d.ts.map +1 -0
- package/dist/persistence/ChangeRegistry.d.ts +87 -0
- package/dist/persistence/ChangeRegistry.d.ts.map +1 -0
- package/dist/persistence/ContemberSchemaMutationAdapter.d.ts +16 -0
- package/dist/persistence/ContemberSchemaMutationAdapter.d.ts.map +1 -0
- package/dist/persistence/MutationCollector.d.ts +96 -0
- package/dist/persistence/MutationCollector.d.ts.map +1 -0
- package/dist/persistence/MutationSchemaProvider.d.ts +30 -0
- package/dist/persistence/MutationSchemaProvider.d.ts.map +1 -0
- package/dist/persistence/index.d.ts +7 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/types.d.ts +189 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/roles/RoleSchemaRegistry.d.ts +77 -0
- package/dist/roles/RoleSchemaRegistry.d.ts.map +1 -0
- package/dist/roles/index.d.ts +11 -0
- package/dist/roles/index.d.ts.map +1 -0
- package/dist/roles/types.d.ts +242 -0
- package/dist/roles/types.d.ts.map +1 -0
- package/dist/schema/ContemberSchema.d.ts +98 -0
- package/dist/schema/ContemberSchema.d.ts.map +1 -0
- package/dist/schema/SchemaLoader.d.ts +28 -0
- package/dist/schema/SchemaLoader.d.ts.map +1 -0
- package/dist/schema/SchemaRegistry.d.ts +95 -0
- package/dist/schema/SchemaRegistry.d.ts.map +1 -0
- package/dist/schema/index.d.ts +6 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/roles.d.ts +62 -0
- package/dist/schema/roles.d.ts.map +1 -0
- package/dist/schema/types.d.ts +179 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/selection/SelectionMetaCollector.d.ts +32 -0
- package/dist/selection/SelectionMetaCollector.d.ts.map +1 -0
- package/dist/selection/SelectionScope.d.ts +77 -0
- package/dist/selection/SelectionScope.d.ts.map +1 -0
- package/dist/selection/buildQuery.d.ts +45 -0
- package/dist/selection/buildQuery.d.ts.map +1 -0
- package/dist/selection/createFragment.d.ts +29 -0
- package/dist/selection/createFragment.d.ts.map +1 -0
- package/dist/selection/createSelectionBuilder.d.ts +18 -0
- package/dist/selection/createSelectionBuilder.d.ts.map +1 -0
- package/dist/selection/index.d.ts +8 -0
- package/dist/selection/index.d.ts.map +1 -0
- package/dist/selection/queryTypes.d.ts +84 -0
- package/dist/selection/queryTypes.d.ts.map +1 -0
- package/dist/selection/types.d.ts +238 -0
- package/dist/selection/types.d.ts.map +1 -0
- package/dist/store/DirtyTracker.d.ts +26 -0
- package/dist/store/DirtyTracker.d.ts.map +1 -0
- package/dist/store/EntityMetaStore.d.ts +52 -0
- package/dist/store/EntityMetaStore.d.ts.map +1 -0
- package/dist/store/EntitySnapshotStore.d.ts +63 -0
- package/dist/store/EntitySnapshotStore.d.ts.map +1 -0
- package/dist/store/ErrorStore.d.ts +82 -0
- package/dist/store/ErrorStore.d.ts.map +1 -0
- package/dist/store/RelationStore.d.ts +175 -0
- package/dist/store/RelationStore.d.ts.map +1 -0
- package/dist/store/SnapshotStore.d.ts +143 -0
- package/dist/store/SnapshotStore.d.ts.map +1 -0
- package/dist/store/SubscriptionManager.d.ts +90 -0
- package/dist/store/SubscriptionManager.d.ts.map +1 -0
- package/dist/store/TouchedStore.d.ts +24 -0
- package/dist/store/TouchedStore.d.ts.map +1 -0
- package/dist/store/entityId.d.ts +29 -0
- package/dist/store/entityId.d.ts.map +1 -0
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/snapshots.d.ts +144 -0
- package/dist/store/snapshots.d.ts.map +1 -0
- package/dist/undo/UndoManager.d.ts +120 -0
- package/dist/undo/UndoManager.d.ts.map +1 -0
- package/dist/undo/index.d.ts +3 -0
- package/dist/undo/index.d.ts.map +1 -0
- package/dist/undo/types.d.ts +74 -0
- package/dist/undo/types.d.ts.map +1 -0
- package/dist/utils/aliasGenerator.d.ts +25 -0
- package/dist/utils/aliasGenerator.d.ts.map +1 -0
- package/dist/utils/deepEqual.d.ts +6 -0
- package/dist/utils/deepEqual.d.ts.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/package.json +29 -0
- package/src/adapter/ContemberAdapter.ts +239 -0
- package/src/adapter/MockAdapter.ts +394 -0
- package/src/adapter/MockQueryEngine.ts +236 -0
- package/src/adapter/index.ts +21 -0
- package/src/adapter/types.ts +199 -0
- package/src/brand/ComponentBrand.ts +28 -0
- package/src/contember/index.ts +17 -0
- package/src/core/ActionDispatcher.ts +450 -0
- package/src/core/Disposable.ts +126 -0
- package/src/core/EntityLoader.ts +169 -0
- package/src/core/SelectionResolver.ts +78 -0
- package/src/core/actionClassification.ts +196 -0
- package/src/core/actions.ts +491 -0
- package/src/core/index.ts +20 -0
- package/src/dataview/filterHandlers.ts +443 -0
- package/src/dataview/index.ts +36 -0
- package/src/dataview/types.ts +220 -0
- package/src/errors/UnfetchedFieldError.ts +18 -0
- package/src/errors/errorPathResolver.ts +239 -0
- package/src/errors/index.ts +40 -0
- package/src/errors/pathMapper.ts +40 -0
- package/src/errors/types.ts +223 -0
- package/src/events/EventEmitter.ts +447 -0
- package/src/events/eventFactory.ts +430 -0
- package/src/events/index.ts +89 -0
- package/src/events/types.ts +374 -0
- package/src/handles/BaseHandle.ts +100 -0
- package/src/handles/EntityHandle.ts +538 -0
- package/src/handles/FieldHandle.ts +268 -0
- package/src/handles/HasManyListHandle.ts +500 -0
- package/src/handles/HasOneHandle.ts +500 -0
- package/src/handles/PlaceholderHandle.ts +321 -0
- package/src/handles/index.ts +37 -0
- package/src/handles/proxyFactory.ts +218 -0
- package/src/handles/types.ts +743 -0
- package/src/index.ts +384 -0
- package/src/internal.ts +19 -0
- package/src/persistence/BatchPersister.ts +911 -0
- package/src/persistence/ChangeRegistry.ts +150 -0
- package/src/persistence/ContemberSchemaMutationAdapter.ts +57 -0
- package/src/persistence/MutationCollector.ts +567 -0
- package/src/persistence/MutationSchemaProvider.ts +33 -0
- package/src/persistence/index.ts +23 -0
- package/src/persistence/types.ts +220 -0
- package/src/schema/ContemberSchema.ts +132 -0
- package/src/schema/SchemaLoader.ts +93 -0
- package/src/schema/SchemaRegistry.ts +286 -0
- package/src/schema/index.ts +51 -0
- package/src/schema/roles.ts +83 -0
- package/src/schema/types.ts +238 -0
- package/src/selection/SelectionMetaCollector.ts +122 -0
- package/src/selection/SelectionScope.ts +208 -0
- package/src/selection/buildQuery.ts +134 -0
- package/src/selection/createFragment.ts +50 -0
- package/src/selection/createSelectionBuilder.ts +283 -0
- package/src/selection/index.ts +31 -0
- package/src/selection/queryTypes.ts +135 -0
- package/src/selection/types.ts +320 -0
- package/src/store/DirtyTracker.ts +117 -0
- package/src/store/EntityMetaStore.ts +143 -0
- package/src/store/EntitySnapshotStore.ts +260 -0
- package/src/store/ErrorStore.ts +251 -0
- package/src/store/RelationStore.ts +696 -0
- package/src/store/SnapshotStore.ts +765 -0
- package/src/store/SubscriptionManager.ts +241 -0
- package/src/store/TouchedStore.ts +42 -0
- package/src/store/entityId.ts +43 -0
- package/src/store/index.ts +2 -0
- package/src/store/snapshots.ts +203 -0
- package/src/undo/UndoManager.ts +418 -0
- package/src/undo/index.ts +9 -0
- package/src/undo/types.ts +84 -0
- package/src/utils/aliasGenerator.ts +56 -0
- package/src/utils/deepEqual.ts +33 -0
- package/src/utils/index.ts +2 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { SnapshotStore } from '../store/SnapshotStore.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Information about a dirty entity
|
|
5
|
+
*/
|
|
6
|
+
export interface DirtyEntity {
|
|
7
|
+
readonly entityType: string
|
|
8
|
+
readonly entityId: string
|
|
9
|
+
readonly changeType: 'create' | 'update' | 'delete'
|
|
10
|
+
readonly dirtyFields: readonly string[]
|
|
11
|
+
readonly dirtyRelations: readonly string[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* ChangeRegistry tracks all dirty entities and in-flight persistence operations.
|
|
16
|
+
* It wraps SnapshotStore's dirty tracking methods and adds deduplication and
|
|
17
|
+
* in-flight tracking for batch persistence operations.
|
|
18
|
+
*/
|
|
19
|
+
export class ChangeRegistry {
|
|
20
|
+
/** Set of entity keys currently being persisted (for batch operations) */
|
|
21
|
+
private readonly inFlight = new Set<string>()
|
|
22
|
+
|
|
23
|
+
/** Subscribers to in-flight state changes */
|
|
24
|
+
private readonly subscribers = new Set<() => void>()
|
|
25
|
+
|
|
26
|
+
constructor(private readonly store: SnapshotStore) {}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Gets the entity key for internal tracking.
|
|
30
|
+
*/
|
|
31
|
+
private getKey(entityType: string, entityId: string): string {
|
|
32
|
+
return `${entityType}:${entityId}`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Gets all dirty entities with their change types and dirty fields/relations.
|
|
37
|
+
*/
|
|
38
|
+
getDirtyEntities(): readonly DirtyEntity[] {
|
|
39
|
+
const rawDirty = this.store.getAllDirtyEntities()
|
|
40
|
+
|
|
41
|
+
return rawDirty.map(entity => ({
|
|
42
|
+
entityType: entity.entityType,
|
|
43
|
+
entityId: entity.entityId,
|
|
44
|
+
changeType: entity.changeType,
|
|
45
|
+
dirtyFields: this.store.getDirtyFields(entity.entityType, entity.entityId),
|
|
46
|
+
dirtyRelations: this.store.getDirtyRelations(entity.entityType, entity.entityId),
|
|
47
|
+
}))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Gets dirty entities that are not currently in-flight.
|
|
52
|
+
*/
|
|
53
|
+
getDirtyEntitiesNotInFlight(): readonly DirtyEntity[] {
|
|
54
|
+
return this.getDirtyEntities().filter(
|
|
55
|
+
entity => !this.isInFlight(entity.entityType, entity.entityId),
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gets dirty fields for a specific entity.
|
|
61
|
+
*/
|
|
62
|
+
getDirtyFields(entityType: string, entityId: string): readonly string[] {
|
|
63
|
+
return this.store.getDirtyFields(entityType, entityId)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Gets dirty relations for a specific entity.
|
|
68
|
+
*/
|
|
69
|
+
getDirtyRelations(entityType: string, entityId: string): readonly string[] {
|
|
70
|
+
return this.store.getDirtyRelations(entityType, entityId)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Checks if an entity is currently being persisted (in a batch operation).
|
|
75
|
+
*/
|
|
76
|
+
isInFlight(entityType: string, entityId: string): boolean {
|
|
77
|
+
const key = this.getKey(entityType, entityId)
|
|
78
|
+
return this.inFlight.has(key) || this.store.isPersisting(entityType, entityId)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Marks entities as in-flight (being persisted).
|
|
83
|
+
*/
|
|
84
|
+
markInFlight(entities: ReadonlyArray<{ entityType: string; entityId: string }>): void {
|
|
85
|
+
for (const entity of entities) {
|
|
86
|
+
const key = this.getKey(entity.entityType, entity.entityId)
|
|
87
|
+
this.inFlight.add(key)
|
|
88
|
+
}
|
|
89
|
+
this.notifySubscribers()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Clears in-flight status for entities.
|
|
94
|
+
*/
|
|
95
|
+
clearInFlight(entities: ReadonlyArray<{ entityType: string; entityId: string }>): void {
|
|
96
|
+
for (const entity of entities) {
|
|
97
|
+
const key = this.getKey(entity.entityType, entity.entityId)
|
|
98
|
+
this.inFlight.delete(key)
|
|
99
|
+
}
|
|
100
|
+
this.notifySubscribers()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Clears all in-flight status.
|
|
105
|
+
*/
|
|
106
|
+
clearAllInFlight(): void {
|
|
107
|
+
this.inFlight.clear()
|
|
108
|
+
this.notifySubscribers()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Gets the set of all in-flight entity keys.
|
|
113
|
+
*/
|
|
114
|
+
getInFlightEntities(): ReadonlySet<string> {
|
|
115
|
+
return this.inFlight
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Checks if any entity is currently in-flight.
|
|
120
|
+
*/
|
|
121
|
+
hasInFlight(): boolean {
|
|
122
|
+
return this.inFlight.size > 0
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Checks if there are any dirty entities.
|
|
127
|
+
*/
|
|
128
|
+
hasDirtyEntities(): boolean {
|
|
129
|
+
return this.store.getAllDirtyEntities().length > 0
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Subscribe to in-flight state changes.
|
|
134
|
+
*/
|
|
135
|
+
subscribe(callback: () => void): () => void {
|
|
136
|
+
this.subscribers.add(callback)
|
|
137
|
+
return () => {
|
|
138
|
+
this.subscribers.delete(callback)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Notifies all subscribers of in-flight state changes.
|
|
144
|
+
*/
|
|
145
|
+
private notifySubscribers(): void {
|
|
146
|
+
for (const subscriber of this.subscribers) {
|
|
147
|
+
subscriber()
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { SchemaNames } from '@contember/client-content'
|
|
2
|
+
import type { MutationSchemaProvider } from './MutationSchemaProvider.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Adapter that wraps Contember SchemaNames to implement MutationSchemaProvider.
|
|
6
|
+
* Translates Contember's schema format (column/one/many) to the unified format (scalar/hasOne/hasMany).
|
|
7
|
+
*/
|
|
8
|
+
export class ContemberSchemaMutationAdapter implements MutationSchemaProvider {
|
|
9
|
+
constructor(private readonly schema: SchemaNames) {}
|
|
10
|
+
|
|
11
|
+
getScalarFields(entityType: string): readonly string[] {
|
|
12
|
+
const entitySchema = this.schema.entities[entityType]
|
|
13
|
+
if (!entitySchema) return []
|
|
14
|
+
|
|
15
|
+
return Object.entries(entitySchema.fields)
|
|
16
|
+
.filter(([_, fieldDef]) => fieldDef.type === 'column')
|
|
17
|
+
.map(([name]) => name)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getRelationFields(entityType: string): readonly string[] {
|
|
21
|
+
const entitySchema = this.schema.entities[entityType]
|
|
22
|
+
if (!entitySchema) return []
|
|
23
|
+
|
|
24
|
+
return Object.entries(entitySchema.fields)
|
|
25
|
+
.filter(([_, fieldDef]) => fieldDef.type === 'one' || fieldDef.type === 'many')
|
|
26
|
+
.map(([name]) => name)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getRelationType(entityType: string, fieldName: string): 'hasOne' | 'hasMany' | undefined {
|
|
30
|
+
const entitySchema = this.schema.entities[entityType]
|
|
31
|
+
if (!entitySchema) return undefined
|
|
32
|
+
|
|
33
|
+
const fieldDef = entitySchema.fields[fieldName]
|
|
34
|
+
if (!fieldDef) return undefined
|
|
35
|
+
|
|
36
|
+
if (fieldDef.type === 'one') return 'hasOne'
|
|
37
|
+
if (fieldDef.type === 'many') return 'hasMany'
|
|
38
|
+
return undefined
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getRelationTarget(entityType: string, fieldName: string): string | undefined {
|
|
42
|
+
const entitySchema = this.schema.entities[entityType]
|
|
43
|
+
if (!entitySchema) return undefined
|
|
44
|
+
|
|
45
|
+
const fieldDef = entitySchema.fields[fieldName]
|
|
46
|
+
if (!fieldDef) return undefined
|
|
47
|
+
|
|
48
|
+
if (fieldDef.type === 'one' || fieldDef.type === 'many') {
|
|
49
|
+
return fieldDef.entity
|
|
50
|
+
}
|
|
51
|
+
return undefined
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
hasEntity(entityType: string): boolean {
|
|
55
|
+
return entityType in this.schema.entities
|
|
56
|
+
}
|
|
57
|
+
}
|