@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,374 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe event system for bindx.
|
|
3
|
+
*
|
|
4
|
+
* Events are categorized into:
|
|
5
|
+
* - Before events (interceptable): Can be cancelled or modified
|
|
6
|
+
* - After events (notifications): Fired after state changes
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { FieldError } from '../errors/types.js'
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Base Event Types
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Base interface for all bindx events.
|
|
17
|
+
*/
|
|
18
|
+
export interface BindxEvent<TType extends string = string> {
|
|
19
|
+
readonly type: TType
|
|
20
|
+
readonly timestamp: number
|
|
21
|
+
readonly entityType: string
|
|
22
|
+
readonly entityId: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Base interface for field-scoped events.
|
|
27
|
+
*/
|
|
28
|
+
export interface FieldScopedEvent<TType extends string> extends BindxEvent<TType> {
|
|
29
|
+
readonly fieldName: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Field Events
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Fired before a field value changes. Can be intercepted to cancel or modify.
|
|
38
|
+
*/
|
|
39
|
+
export interface FieldChangingEvent extends FieldScopedEvent<'field:changing'> {
|
|
40
|
+
readonly fieldPath: readonly string[]
|
|
41
|
+
readonly oldValue: unknown
|
|
42
|
+
readonly newValue: unknown
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Fired after a field value has changed.
|
|
47
|
+
*/
|
|
48
|
+
export interface FieldChangedEvent extends FieldScopedEvent<'field:changed'> {
|
|
49
|
+
readonly fieldPath: readonly string[]
|
|
50
|
+
readonly oldValue: unknown
|
|
51
|
+
readonly newValue: unknown
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// HasOne Relation Events
|
|
56
|
+
// ============================================================================
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Fired before a has-one relation is connected.
|
|
60
|
+
*/
|
|
61
|
+
export interface RelationConnectingEvent extends FieldScopedEvent<'relation:connecting'> {
|
|
62
|
+
readonly targetId: string
|
|
63
|
+
readonly previousId: string | null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Fired after a has-one relation has been connected.
|
|
68
|
+
*/
|
|
69
|
+
export interface RelationConnectedEvent extends FieldScopedEvent<'relation:connected'> {
|
|
70
|
+
readonly targetId: string
|
|
71
|
+
readonly previousId: string | null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Fired before a has-one relation is disconnected.
|
|
76
|
+
*/
|
|
77
|
+
export interface RelationDisconnectingEvent extends FieldScopedEvent<'relation:disconnecting'> {
|
|
78
|
+
readonly currentId: string | null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Fired after a has-one relation has been disconnected.
|
|
83
|
+
*/
|
|
84
|
+
export interface RelationDisconnectedEvent extends FieldScopedEvent<'relation:disconnected'> {
|
|
85
|
+
readonly previousId: string | null
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Fired before a has-one relation is deleted.
|
|
90
|
+
*/
|
|
91
|
+
export interface RelationDeletingEvent extends FieldScopedEvent<'relation:deleting'> {
|
|
92
|
+
readonly currentId: string | null
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Fired after a has-one relation has been deleted.
|
|
97
|
+
*/
|
|
98
|
+
export interface RelationDeletedEvent extends FieldScopedEvent<'relation:deleted'> {
|
|
99
|
+
readonly previousId: string | null
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// HasMany Relation Events
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Fired before an item is connected to a has-many relation.
|
|
108
|
+
*/
|
|
109
|
+
export interface HasManyConnectingEvent extends FieldScopedEvent<'hasMany:connecting'> {
|
|
110
|
+
readonly itemId: string
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Fired after an item has been connected to a has-many relation.
|
|
115
|
+
*/
|
|
116
|
+
export interface HasManyConnectedEvent extends FieldScopedEvent<'hasMany:connected'> {
|
|
117
|
+
readonly itemId: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Fired before an item is disconnected from a has-many relation.
|
|
122
|
+
*/
|
|
123
|
+
export interface HasManyDisconnectingEvent extends FieldScopedEvent<'hasMany:disconnecting'> {
|
|
124
|
+
readonly itemId: string
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Fired after an item has been disconnected from a has-many relation.
|
|
129
|
+
*/
|
|
130
|
+
export interface HasManyDisconnectedEvent extends FieldScopedEvent<'hasMany:disconnected'> {
|
|
131
|
+
readonly itemId: string
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ============================================================================
|
|
135
|
+
// Entity Lifecycle Events
|
|
136
|
+
// ============================================================================
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Fired before an entity is persisted (create or update).
|
|
140
|
+
*/
|
|
141
|
+
export interface EntityPersistingEvent extends BindxEvent<'entity:persisting'> {
|
|
142
|
+
readonly isNew: boolean
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Fired after an entity has been successfully persisted.
|
|
147
|
+
*/
|
|
148
|
+
export interface EntityPersistedEvent extends BindxEvent<'entity:persisted'> {
|
|
149
|
+
readonly isNew: boolean
|
|
150
|
+
readonly persistedId: string
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Fired when entity persistence fails.
|
|
155
|
+
*/
|
|
156
|
+
export interface EntityPersistFailedEvent extends BindxEvent<'entity:persistFailed'> {
|
|
157
|
+
readonly isNew: boolean
|
|
158
|
+
readonly error: Error
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Fired before an entity is reset to server state.
|
|
163
|
+
*/
|
|
164
|
+
export interface EntityResettingEvent extends BindxEvent<'entity:resetting'> {}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Fired after an entity has been reset to server state.
|
|
168
|
+
*/
|
|
169
|
+
export interface EntityResetEvent extends BindxEvent<'entity:reset'> {}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Fired before an entity is deleted.
|
|
173
|
+
*/
|
|
174
|
+
export interface EntityDeletingEvent extends BindxEvent<'entity:deleting'> {}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Fired after an entity has been deleted.
|
|
178
|
+
*/
|
|
179
|
+
export interface EntityDeletedEvent extends BindxEvent<'entity:deleted'> {}
|
|
180
|
+
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// Error Events
|
|
183
|
+
// ============================================================================
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Fired when an error is added to a field, entity, or relation.
|
|
187
|
+
*/
|
|
188
|
+
export interface ErrorAddedEvent extends BindxEvent<'error:added'> {
|
|
189
|
+
readonly target: 'entity' | 'field' | 'relation'
|
|
190
|
+
readonly targetName: string | null
|
|
191
|
+
readonly error: FieldError
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Fired when errors are cleared.
|
|
196
|
+
*/
|
|
197
|
+
export interface ErrorsClearedEvent extends BindxEvent<'errors:cleared'> {
|
|
198
|
+
readonly target: 'entity' | 'field' | 'relation' | 'all'
|
|
199
|
+
readonly targetName: string | null
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// Load State Events
|
|
204
|
+
// ============================================================================
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Fired when entity load state changes.
|
|
208
|
+
*/
|
|
209
|
+
export interface LoadStateChangedEvent extends BindxEvent<'load:stateChanged'> {
|
|
210
|
+
readonly previousStatus: string | undefined
|
|
211
|
+
readonly newStatus: string
|
|
212
|
+
readonly error?: FieldError
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ============================================================================
|
|
216
|
+
// Union Types
|
|
217
|
+
// ============================================================================
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* All "before" events that can be intercepted and cancelled.
|
|
221
|
+
*/
|
|
222
|
+
export type BeforeEvent =
|
|
223
|
+
| FieldChangingEvent
|
|
224
|
+
| RelationConnectingEvent
|
|
225
|
+
| RelationDisconnectingEvent
|
|
226
|
+
| RelationDeletingEvent
|
|
227
|
+
| HasManyConnectingEvent
|
|
228
|
+
| HasManyDisconnectingEvent
|
|
229
|
+
| EntityPersistingEvent
|
|
230
|
+
| EntityResettingEvent
|
|
231
|
+
| EntityDeletingEvent
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* All "after" events (notifications).
|
|
235
|
+
*/
|
|
236
|
+
export type AfterEvent =
|
|
237
|
+
| FieldChangedEvent
|
|
238
|
+
| RelationConnectedEvent
|
|
239
|
+
| RelationDisconnectedEvent
|
|
240
|
+
| RelationDeletedEvent
|
|
241
|
+
| HasManyConnectedEvent
|
|
242
|
+
| HasManyDisconnectedEvent
|
|
243
|
+
| EntityPersistedEvent
|
|
244
|
+
| EntityPersistFailedEvent
|
|
245
|
+
| EntityResetEvent
|
|
246
|
+
| EntityDeletedEvent
|
|
247
|
+
| ErrorAddedEvent
|
|
248
|
+
| ErrorsClearedEvent
|
|
249
|
+
| LoadStateChangedEvent
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* All bindx events.
|
|
253
|
+
*/
|
|
254
|
+
export type AnyBindxEvent = BeforeEvent | AfterEvent
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* All before event type strings.
|
|
258
|
+
*/
|
|
259
|
+
export type BeforeEventType = BeforeEvent['type']
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* All after event type strings.
|
|
263
|
+
*/
|
|
264
|
+
export type AfterEventType = AfterEvent['type']
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* All event type strings.
|
|
268
|
+
*/
|
|
269
|
+
export type AnyEventType = AnyBindxEvent['type']
|
|
270
|
+
|
|
271
|
+
// ============================================================================
|
|
272
|
+
// Event Type Map
|
|
273
|
+
// ============================================================================
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Map of event types to their event objects.
|
|
277
|
+
* Enables type-safe subscriptions.
|
|
278
|
+
*/
|
|
279
|
+
export interface EventTypeMap {
|
|
280
|
+
// Field events
|
|
281
|
+
'field:changing': FieldChangingEvent
|
|
282
|
+
'field:changed': FieldChangedEvent
|
|
283
|
+
|
|
284
|
+
// HasOne relation events
|
|
285
|
+
'relation:connecting': RelationConnectingEvent
|
|
286
|
+
'relation:connected': RelationConnectedEvent
|
|
287
|
+
'relation:disconnecting': RelationDisconnectingEvent
|
|
288
|
+
'relation:disconnected': RelationDisconnectedEvent
|
|
289
|
+
'relation:deleting': RelationDeletingEvent
|
|
290
|
+
'relation:deleted': RelationDeletedEvent
|
|
291
|
+
|
|
292
|
+
// HasMany relation events
|
|
293
|
+
'hasMany:connecting': HasManyConnectingEvent
|
|
294
|
+
'hasMany:connected': HasManyConnectedEvent
|
|
295
|
+
'hasMany:disconnecting': HasManyDisconnectingEvent
|
|
296
|
+
'hasMany:disconnected': HasManyDisconnectedEvent
|
|
297
|
+
|
|
298
|
+
// Entity lifecycle events
|
|
299
|
+
'entity:persisting': EntityPersistingEvent
|
|
300
|
+
'entity:persisted': EntityPersistedEvent
|
|
301
|
+
'entity:persistFailed': EntityPersistFailedEvent
|
|
302
|
+
'entity:resetting': EntityResettingEvent
|
|
303
|
+
'entity:reset': EntityResetEvent
|
|
304
|
+
'entity:deleting': EntityDeletingEvent
|
|
305
|
+
'entity:deleted': EntityDeletedEvent
|
|
306
|
+
|
|
307
|
+
// Error events
|
|
308
|
+
'error:added': ErrorAddedEvent
|
|
309
|
+
'errors:cleared': ErrorsClearedEvent
|
|
310
|
+
|
|
311
|
+
// Load state events
|
|
312
|
+
'load:stateChanged': LoadStateChangedEvent
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Extract event type from event name.
|
|
317
|
+
*/
|
|
318
|
+
export type EventByType<T extends keyof EventTypeMap> = EventTypeMap[T]
|
|
319
|
+
|
|
320
|
+
// ============================================================================
|
|
321
|
+
// Interceptor Types
|
|
322
|
+
// ============================================================================
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Result of an interceptor execution.
|
|
326
|
+
*/
|
|
327
|
+
export type InterceptorResult<T extends BeforeEvent = BeforeEvent> =
|
|
328
|
+
| { readonly action: 'cancel' }
|
|
329
|
+
| { readonly action: 'continue' }
|
|
330
|
+
| { readonly action: 'modify'; readonly event: T }
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Interceptor function type.
|
|
334
|
+
* Can be sync or async.
|
|
335
|
+
* Return undefined/void to continue without changes.
|
|
336
|
+
*/
|
|
337
|
+
export type Interceptor<T extends BeforeEvent> = (
|
|
338
|
+
event: T,
|
|
339
|
+
) => InterceptorResult<T> | Promise<InterceptorResult<T>> | void | Promise<void>
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Event listener function type.
|
|
343
|
+
*/
|
|
344
|
+
export type EventListener<T extends AfterEvent> = (event: T) => void
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Unsubscribe function returned by subscription methods.
|
|
348
|
+
*/
|
|
349
|
+
export type Unsubscribe = () => void
|
|
350
|
+
|
|
351
|
+
// ============================================================================
|
|
352
|
+
// Helper Types
|
|
353
|
+
// ============================================================================
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Extract before events from EventTypeMap.
|
|
357
|
+
*/
|
|
358
|
+
export type BeforeEventTypes = {
|
|
359
|
+
[K in keyof EventTypeMap]: EventTypeMap[K] extends BeforeEvent ? K : never
|
|
360
|
+
}[keyof EventTypeMap]
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Extract after events from EventTypeMap.
|
|
364
|
+
*/
|
|
365
|
+
export type AfterEventTypes = {
|
|
366
|
+
[K in keyof EventTypeMap]: EventTypeMap[K] extends AfterEvent ? K : never
|
|
367
|
+
}[keyof EventTypeMap]
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Extract field-scoped events.
|
|
371
|
+
*/
|
|
372
|
+
export type FieldScopedEventTypes = {
|
|
373
|
+
[K in keyof EventTypeMap]: EventTypeMap[K] extends FieldScopedEvent<string> ? K : never
|
|
374
|
+
}[keyof EventTypeMap]
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { Disposable, DisposableGroup } from '../core/Disposable.js'
|
|
2
|
+
import type { ActionDispatcher } from '../core/ActionDispatcher.js'
|
|
3
|
+
import type { SnapshotStore } from '../store/SnapshotStore.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base class for all handles.
|
|
7
|
+
* Provides common functionality for subscription and disposal.
|
|
8
|
+
*
|
|
9
|
+
* Handles are stable objects that:
|
|
10
|
+
* - Have stable identity (same instance across renders)
|
|
11
|
+
* - Provide subscribe/getSnapshot for useSyncExternalStore
|
|
12
|
+
* - Dispatch actions for mutations
|
|
13
|
+
*/
|
|
14
|
+
export abstract class BaseHandle implements Disposable {
|
|
15
|
+
protected _disposed = false
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
protected readonly store: SnapshotStore,
|
|
19
|
+
protected readonly dispatcher: ActionDispatcher,
|
|
20
|
+
) {}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Subscribe to changes. Used by useSyncExternalStore.
|
|
24
|
+
*/
|
|
25
|
+
abstract subscribe(callback: () => void): () => void
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get current version for change detection.
|
|
29
|
+
*/
|
|
30
|
+
abstract getVersion(): number
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Dispose resources (unsubscribe, cleanup).
|
|
34
|
+
*/
|
|
35
|
+
dispose(): void {
|
|
36
|
+
this._disposed = true
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if the handle has been disposed.
|
|
41
|
+
*/
|
|
42
|
+
get isDisposed(): boolean {
|
|
43
|
+
return this._disposed
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Throws if the handle has been disposed.
|
|
48
|
+
*/
|
|
49
|
+
protected assertNotDisposed(): void {
|
|
50
|
+
if (this._disposed) {
|
|
51
|
+
throw new Error('Handle has been disposed')
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Base class for entity-related handles.
|
|
58
|
+
* Provides common entity subscription logic.
|
|
59
|
+
*/
|
|
60
|
+
export abstract class EntityRelatedHandle extends BaseHandle {
|
|
61
|
+
constructor(
|
|
62
|
+
protected readonly entityType: string,
|
|
63
|
+
protected readonly entityId: string,
|
|
64
|
+
store: SnapshotStore,
|
|
65
|
+
dispatcher: ActionDispatcher,
|
|
66
|
+
) {
|
|
67
|
+
super(store, dispatcher)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Subscribe to entity changes.
|
|
72
|
+
*/
|
|
73
|
+
subscribe(callback: () => void): () => void {
|
|
74
|
+
return this.store.subscribeToEntity(this.entityType, this.entityId, callback)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get entity snapshot version.
|
|
79
|
+
*/
|
|
80
|
+
getVersion(): number {
|
|
81
|
+
const snapshot = this.store.getEntitySnapshot(this.entityType, this.entityId)
|
|
82
|
+
return snapshot?.version ?? 0
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get entity data.
|
|
87
|
+
*/
|
|
88
|
+
protected getEntityData(): Record<string, unknown> | undefined {
|
|
89
|
+
const snapshot = this.store.getEntitySnapshot(this.entityType, this.entityId)
|
|
90
|
+
return snapshot?.data as Record<string, unknown> | undefined
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get entity server data.
|
|
95
|
+
*/
|
|
96
|
+
protected getServerData(): Record<string, unknown> | undefined {
|
|
97
|
+
const snapshot = this.store.getEntitySnapshot(this.entityType, this.entityId)
|
|
98
|
+
return snapshot?.serverData as Record<string, unknown> | undefined
|
|
99
|
+
}
|
|
100
|
+
}
|