doxum 0.1.21 → 0.1.22
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/README.md +21 -2
- package/dist/{access-BeSV5ve-.js → access-CZXv_DIF.js} +179 -37
- package/dist/access-CZXv_DIF.js.map +1 -0
- package/dist/{access-Bienf28h.cjs → access-D64MFRSm.cjs} +228 -38
- package/dist/access-D64MFRSm.cjs.map +1 -0
- package/dist/{advanced-COFJtWMT.js → advanced-BTStm2cW.js} +29 -25
- package/dist/advanced-BTStm2cW.js.map +1 -0
- package/dist/{advanced-FgdTwu5b.d.ts → advanced-CqrR_4dh.d.ts} +3 -3
- package/dist/{advanced-DfKc7TZR.d.cts → advanced-CyR5o3Xr.d.cts} +3 -3
- package/dist/{advanced-BRL5pN0y.cjs → advanced-GKZ-CZ6a.cjs} +29 -25
- package/dist/advanced-GKZ-CZ6a.cjs.map +1 -0
- package/dist/advanced.cjs +1 -1
- package/dist/advanced.d.cts +1 -1
- package/dist/advanced.d.ts +1 -1
- package/dist/advanced.js +1 -1
- package/dist/{contract-KG5XnQZt.d.ts → contract-CRrZ-3sF.d.cts} +64 -34
- package/dist/{contract-CdmDHRUq.d.cts → contract-CxiNcqMn.d.ts} +64 -34
- package/dist/{driver-Djr3BVvo.cjs → driver-BC06FEMF.cjs} +2 -2
- package/dist/{driver-Djr3BVvo.cjs.map → driver-BC06FEMF.cjs.map} +1 -1
- package/dist/{driver-CLYJOGDQ.js → driver-BqRjwFmU.js} +2 -2
- package/dist/{driver-CLYJOGDQ.js.map → driver-BqRjwFmU.js.map} +1 -1
- package/dist/index.cjs +480 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +478 -115
- package/dist/index.js.map +1 -1
- package/dist/{integration-Z6MsfFI7.cjs → integration-BqDw7e2w.cjs} +3 -4
- package/dist/{integration-Z6MsfFI7.cjs.map → integration-BqDw7e2w.cjs.map} +1 -1
- package/dist/{integration-C4Isp8lJ.js → integration-CSXaF8HP.js} +2 -3
- package/dist/{integration-C4Isp8lJ.js.map → integration-CSXaF8HP.js.map} +1 -1
- package/dist/integration.cjs +5 -4
- package/dist/integration.d.cts +1 -1
- package/dist/integration.d.ts +1 -1
- package/dist/integration.js +4 -3
- package/dist/{issue-W0hT8u8D.js → issue-9U6YLYz3.js} +11 -6
- package/dist/issue-9U6YLYz3.js.map +1 -0
- package/dist/{issue-DjK1xp5K.cjs → issue-Bo0FIO3b.cjs} +11 -6
- package/dist/issue-Bo0FIO3b.cjs.map +1 -0
- package/dist/local-sync.cjs +2 -2
- package/dist/local-sync.d.cts +1 -1
- package/dist/local-sync.d.ts +1 -1
- package/dist/local-sync.js +2 -2
- package/dist/{notification-Bkjau6B6.js → notification-CrZHVx3a.js} +3 -59
- package/dist/notification-CrZHVx3a.js.map +1 -0
- package/dist/{notification-DJfouMEb.cjs → notification-DFoA9bQY.cjs} +3 -77
- package/dist/notification-DFoA9bQY.cjs.map +1 -0
- package/dist/react.cjs +4 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +3 -2
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/skills/doxum-runtime/SKILL.md +5 -0
- package/skills/doxum-runtime/references/guide.en.md +9 -0
- package/skills/doxum-runtime/references/guide.zh-CN.md +8 -0
- package/skills/doxum-runtime/references/projections.en.md +5 -0
- package/skills/doxum-runtime/references/projections.zh-CN.md +5 -0
- package/dist/access-BeSV5ve-.js.map +0 -1
- package/dist/access-Bienf28h.cjs.map +0 -1
- package/dist/advanced-BRL5pN0y.cjs.map +0 -1
- package/dist/advanced-COFJtWMT.js.map +0 -1
- package/dist/issue-DjK1xp5K.cjs.map +0 -1
- package/dist/issue-W0hT8u8D.js.map +0 -1
- package/dist/notification-Bkjau6B6.js.map +0 -1
- package/dist/notification-DJfouMEb.cjs.map +0 -1
|
@@ -39,14 +39,17 @@ type ReadonlyValue<T> = T extends ((...args: never[]) => unknown) ? T : T extend
|
|
|
39
39
|
type DocumentListConfig<TItem> = {
|
|
40
40
|
readonly keyOf: (item: ReadonlyValue<TItem>) => string;
|
|
41
41
|
};
|
|
42
|
-
type DocumentTreeNode<TValue> = {
|
|
42
|
+
type DocumentTreeNode<TValue, ValueOptional extends boolean = false> = {
|
|
43
43
|
readonly parentId?: string;
|
|
44
44
|
readonly children: readonly string[];
|
|
45
|
+
} & (ValueOptional extends true ? {
|
|
45
46
|
readonly value?: ReadonlyValue<TValue>;
|
|
46
|
-
}
|
|
47
|
-
|
|
47
|
+
} : {
|
|
48
|
+
readonly value: ReadonlyValue<TValue>;
|
|
49
|
+
});
|
|
50
|
+
type DocumentTreeValue<TValue, ValueOptional extends boolean = false> = {
|
|
48
51
|
readonly rootId?: string;
|
|
49
|
-
readonly nodes: Readonly<Record<string, DocumentTreeNode<TValue>>>;
|
|
52
|
+
readonly nodes: Readonly<Record<string, DocumentTreeNode<TValue, ValueOptional>>>;
|
|
50
53
|
};
|
|
51
54
|
type BaseNode<K extends string> = {
|
|
52
55
|
readonly kind: K;
|
|
@@ -89,10 +92,10 @@ type ListNode<TItem> = BaseNode<'list'> & {
|
|
|
89
92
|
readonly value: FieldNode<TItem, false>;
|
|
90
93
|
keyOf(item: ReadonlyValue<TItem>): string;
|
|
91
94
|
};
|
|
92
|
-
type TreeNode<TValue> = BaseNode<'tree'> & {
|
|
93
|
-
readonly value: FieldNode<TValue,
|
|
95
|
+
type TreeNode<TValue, ValueOptional extends boolean = false> = BaseNode<'tree'> & {
|
|
96
|
+
readonly value: FieldNode<TValue, ValueOptional>;
|
|
94
97
|
};
|
|
95
|
-
type DocumentNode = FieldNode<unknown, false> | FieldNode<unknown, true> | ObjectNode<ObjectShape> | VariantNode<string, VariantShape> | TableNode<ObjectNode<ObjectShape> | VariantNode<string, VariantShape>> | MapNode<ValueSchemaNode> | ListNode<unknown> | TreeNode<unknown>;
|
|
98
|
+
type DocumentNode = FieldNode<unknown, false> | FieldNode<unknown, true> | ObjectNode<ObjectShape> | VariantNode<string, VariantShape> | TableNode<ObjectNode<ObjectShape> | VariantNode<string, VariantShape>> | MapNode<ValueSchemaNode> | ListNode<unknown> | TreeNode<unknown, false> | TreeNode<unknown, true>;
|
|
96
99
|
type SchemaObject<T> = { [K in keyof T]: T[K] } & {};
|
|
97
100
|
/** Infer a document or node value, including optional node presence. */
|
|
98
101
|
type Infer<T extends DocumentNode> = T extends {
|
|
@@ -101,7 +104,7 @@ type Infer<T extends DocumentNode> = T extends {
|
|
|
101
104
|
type NodeValue<N> = N extends FieldNode<infer T, infer O> ? O extends true ? ReadonlyValue<T> | undefined : ReadonlyValue<T> : N extends ObjectNode<infer S> ? ShapeValue<S> : N extends VariantNode<infer T, infer V> ? { [K in keyof V & string]: SchemaObject<{ readonly [P in T]: K } & NodeValue<V[K]>> }[keyof V & string] : N extends TableNode<infer V, infer K> ? {
|
|
102
105
|
readonly ids: readonly K[];
|
|
103
106
|
readonly byId: Readonly<Record<K, NodeValue<V>>>;
|
|
104
|
-
} : N extends MapNode<infer V, infer K> ? Readonly<Record<K, NodeValue<V>>> : N extends ListNode<infer I> ? readonly ReadonlyValue<I>[] : N extends TreeNode<infer T> ? DocumentTreeValue<T> : never;
|
|
107
|
+
} : N extends MapNode<infer V, infer K> ? Readonly<Record<K, NodeValue<V>>> : N extends ListNode<infer I> ? readonly ReadonlyValue<I>[] : N extends TreeNode<infer T, infer O> ? DocumentTreeValue<T, O> : never;
|
|
105
108
|
type OptionalKeys<S extends ObjectShape> = { [K in keyof S]: S[K] extends {
|
|
106
109
|
readonly optional: true;
|
|
107
110
|
} ? K : never }[keyof S];
|
|
@@ -116,29 +119,45 @@ type DocumentAnchor<K extends string = string> = {
|
|
|
116
119
|
} | {
|
|
117
120
|
readonly after: K;
|
|
118
121
|
};
|
|
119
|
-
type
|
|
122
|
+
type TreeTarget = {
|
|
123
|
+
readonly kind: 'root';
|
|
124
|
+
} | {
|
|
125
|
+
readonly kind: 'nodes';
|
|
126
|
+
} | {
|
|
127
|
+
readonly kind: 'node';
|
|
128
|
+
readonly id: string;
|
|
129
|
+
};
|
|
130
|
+
type TreeValueTarget = Exclude<TreeTarget, {
|
|
131
|
+
readonly kind: 'nodes';
|
|
132
|
+
}>;
|
|
133
|
+
type TreeCollectionTarget = Extract<TreeTarget, {
|
|
134
|
+
readonly kind: 'nodes';
|
|
135
|
+
}>;
|
|
136
|
+
type CollectionSelector<TId extends string = string> = {
|
|
120
137
|
readonly kind: 'collection';
|
|
121
138
|
readonly schema: ObjectNode;
|
|
122
139
|
readonly address: DocumentAddress;
|
|
123
|
-
readonly
|
|
124
|
-
readonly
|
|
140
|
+
readonly tree?: TreeCollectionTarget;
|
|
141
|
+
readonly __id?: TId;
|
|
125
142
|
};
|
|
126
143
|
type ValueSelector<TResult = unknown> = {
|
|
127
144
|
readonly kind: 'value';
|
|
128
145
|
readonly schema: ObjectNode;
|
|
129
146
|
readonly address: DocumentAddress;
|
|
147
|
+
readonly tree?: TreeValueTarget;
|
|
130
148
|
readonly __value?: TResult;
|
|
131
149
|
};
|
|
132
150
|
type ImpactTarget<T = unknown> = {
|
|
133
151
|
readonly kind: 'value';
|
|
134
152
|
readonly at: DocumentAddress;
|
|
153
|
+
readonly tree?: TreeValueTarget;
|
|
135
154
|
} | ValueSelector<T> | {
|
|
136
155
|
readonly kind: 'collection';
|
|
137
156
|
readonly at: DocumentAddress;
|
|
138
157
|
readonly id?: string;
|
|
139
158
|
} | CollectionSelector<string>;
|
|
140
159
|
declare const pathValue: unique symbol;
|
|
141
|
-
declare const
|
|
160
|
+
declare const collectionEntry: unique symbol;
|
|
142
161
|
declare const collectionKey: unique symbol;
|
|
143
162
|
type PathMarker<TValue> = {
|
|
144
163
|
readonly [pathValue]: TValue;
|
|
@@ -146,33 +165,44 @@ type PathMarker<TValue> = {
|
|
|
146
165
|
type PathValueOf<T> = T extends {
|
|
147
166
|
readonly [pathValue]: infer TValue;
|
|
148
167
|
} ? TValue : never;
|
|
149
|
-
type
|
|
168
|
+
type Or<A extends boolean, B extends boolean> = A extends true ? true : B;
|
|
169
|
+
type NodeAbsent<N extends DocumentNode, ParentAbsent extends boolean> = Or<ParentAbsent, N extends {
|
|
170
|
+
readonly optional: true;
|
|
171
|
+
} ? true : false>;
|
|
172
|
+
type PathResult<N extends DocumentNode, ParentAbsent extends boolean> = Infer<N> | (ParentAbsent extends true ? undefined : never);
|
|
173
|
+
type SchemaPathFor<S extends ObjectShape = ObjectShape, TValue = unknown, Absent extends boolean = false> = { readonly [K in keyof S]: PathValue<S[K], Absent> } & PathMarker<TValue | (Absent extends true ? undefined : never)>;
|
|
150
174
|
type SchemaPath<S extends ObjectShape = ObjectShape> = SchemaPathFor<S, ShapeValue<S>>;
|
|
151
175
|
type PathPick<S extends ObjectNode = ObjectNode> = (path: SchemaPath<S['shape']>) => PathMarker<unknown>;
|
|
152
176
|
type VariantKeys<V extends VariantShape> = { [K in keyof V & string]: keyof (V[K] extends ObjectNode<infer S> ? S : {}) }[keyof V & string] & string;
|
|
153
|
-
type
|
|
154
|
-
type
|
|
155
|
-
type
|
|
156
|
-
|
|
157
|
-
|
|
177
|
+
type VariantFieldMissing<V extends VariantShape, K extends string> = { [P in keyof V & string]: V[P] extends ObjectNode<infer S> ? (K extends keyof S ? never : P) : P }[keyof V & string] extends never ? false : true;
|
|
178
|
+
type VariantFieldPath<V extends VariantShape, K extends string, Absent extends boolean> = { [P in keyof V & string]: V[P] extends ObjectNode<infer S> ? K extends keyof S ? PathValue<S[K], Or<Absent, VariantFieldMissing<V, K>>> : never : never }[keyof V & string];
|
|
179
|
+
type VariantPath<T extends string, V extends VariantShape, TValue, Absent extends boolean> = { readonly [K in VariantKeys<V>]: VariantFieldPath<V, K, Absent> } & { readonly [K in T]: PathMarker<(keyof V & string) | (Absent extends true ? undefined : never)> } & PathMarker<TValue>;
|
|
180
|
+
type CollectionPath<K extends string = string, TValue = unknown, TEntry = unknown, TItem = PathMarker<TEntry | undefined>> = PathMarker<TValue> & {
|
|
181
|
+
item(id: K): TItem;
|
|
182
|
+
readonly [collectionEntry]: TEntry;
|
|
158
183
|
readonly [collectionKey]: K;
|
|
159
184
|
};
|
|
160
|
-
type
|
|
185
|
+
type TreeNodesPath<TValue, ValueOptional extends boolean> = CollectionPath<string, Readonly<Record<string, DocumentTreeNode<TValue, ValueOptional>>>, DocumentTreeNode<TValue, ValueOptional>, PathMarker<DocumentTreeNode<TValue, ValueOptional> | undefined>>;
|
|
186
|
+
type TreePath<TValue, ValueOptional extends boolean, TValueResult> = PathMarker<TValueResult> & {
|
|
187
|
+
readonly rootId: PathMarker<string | undefined>;
|
|
188
|
+
readonly nodes: TreeNodesPath<TValue, ValueOptional>;
|
|
189
|
+
};
|
|
190
|
+
type PathValue<N extends DocumentNode, ParentAbsent extends boolean = false> = N extends ObjectNode<infer S> ? SchemaPathFor<S, PathResult<N, ParentAbsent>, NodeAbsent<N, ParentAbsent>> : N extends VariantNode<infer TTag, infer V> ? VariantPath<TTag, V, PathResult<N, ParentAbsent>, NodeAbsent<N, ParentAbsent>> : N extends TableNode<infer V, infer K> ? CollectionPath<K, PathResult<N, ParentAbsent>, Infer<V>, PathValue<V, true>> : N extends MapNode<infer V, infer K> ? CollectionPath<K, PathResult<N, ParentAbsent>, Infer<V>, PathValue<V, true>> : N extends ListNode<infer I> ? CollectionPath<string, PathResult<N, ParentAbsent>, ReadonlyValue<I>, PathMarker<ReadonlyValue<I> | undefined>> : N extends TreeNode<infer T, infer O> ? TreePath<T, O, PathResult<N, ParentAbsent>> : PathMarker<PathResult<N, ParentAbsent>>;
|
|
161
191
|
type CollectionInfo<T> = T extends {
|
|
162
|
-
readonly [
|
|
192
|
+
readonly [collectionEntry]: infer TEntry;
|
|
163
193
|
readonly [collectionKey]: infer K extends string;
|
|
164
194
|
} ? {
|
|
165
195
|
readonly id: K;
|
|
166
|
-
readonly
|
|
196
|
+
readonly entry: TEntry;
|
|
167
197
|
} : never;
|
|
168
198
|
type CollectionId<T> = CollectionInfo<T> extends {
|
|
169
199
|
readonly id: infer TId extends string;
|
|
170
200
|
} ? TId : string;
|
|
171
|
-
type
|
|
172
|
-
readonly
|
|
173
|
-
} ?
|
|
201
|
+
type CollectionEntry<T> = CollectionInfo<T> extends {
|
|
202
|
+
readonly entry: infer TEntry;
|
|
203
|
+
} ? TEntry : unknown;
|
|
174
204
|
declare const field: <T>(validator?: Validator<T>) => FieldNode<T>;
|
|
175
|
-
type OptionalLeaf = FieldNode<unknown, boolean> | VariantNode<string, VariantShape> | MapNode<ValueSchemaNode> | ListNode<unknown> | TreeNode<unknown>;
|
|
205
|
+
type OptionalLeaf = FieldNode<unknown, boolean> | VariantNode<string, VariantShape> | MapNode<ValueSchemaNode> | ListNode<unknown> | TreeNode<unknown, false> | TreeNode<unknown, true>;
|
|
176
206
|
declare const optional: <T extends OptionalLeaf>(value: T) => OptionalNode<T>;
|
|
177
207
|
declare const object: <S extends ObjectShape>(shape: S) => ObjectNode<S>;
|
|
178
208
|
declare const variant: <T extends string, V extends VariantShape>(tag: T, variants: V) => VariantNode<T, V>;
|
|
@@ -183,7 +213,7 @@ declare const map: <V extends ValueSchemaNode, K extends string = string>(value:
|
|
|
183
213
|
readonly key: Validator<K>;
|
|
184
214
|
}) => MapNode<V, K>;
|
|
185
215
|
declare const list: <TItem>(value: FieldNode<TItem, false>, config: DocumentListConfig<TItem>) => ListNode<TItem>;
|
|
186
|
-
declare const tree: <TValue>(value: FieldNode<TValue,
|
|
216
|
+
declare const tree: <TValue, ValueOptional extends boolean>(value: FieldNode<TValue, ValueOptional>) => TreeNode<TValue, ValueOptional>;
|
|
187
217
|
//#endregion
|
|
188
218
|
//#region core/src/changes.d.ts
|
|
189
219
|
type ValueTransition<T = unknown> = {
|
|
@@ -213,7 +243,7 @@ type Change = {
|
|
|
213
243
|
readonly at: DocumentAddress;
|
|
214
244
|
readonly before: string | null;
|
|
215
245
|
readonly after: string | null;
|
|
216
|
-
readonly nodes: readonly (ValueTransition<DocumentTreeNode<unknown>> & {
|
|
246
|
+
readonly nodes: readonly (ValueTransition<DocumentTreeNode<unknown, false> | DocumentTreeNode<unknown, true>> & {
|
|
217
247
|
readonly id: string;
|
|
218
248
|
})[];
|
|
219
249
|
} | {
|
|
@@ -290,20 +320,20 @@ type ListAccess<T, W extends boolean> = {
|
|
|
290
320
|
replace(value: readonly ReadonlyValue<T>[]): void;
|
|
291
321
|
replace(key: string, value: ReadonlyValue<T>): void;
|
|
292
322
|
} : {});
|
|
293
|
-
type TreeAccess<T, W extends boolean> = {
|
|
323
|
+
type TreeAccess<T, O extends boolean, W extends boolean> = {
|
|
294
324
|
rootId(): string | undefined;
|
|
295
325
|
get(id: string): ReadonlyValue<T> | undefined;
|
|
296
326
|
has(id: string): boolean;
|
|
297
327
|
parent(id: string): string | undefined;
|
|
298
328
|
children(id: string): readonly string[] | undefined;
|
|
299
329
|
} & (W extends true ? {
|
|
300
|
-
insert(id: string, value: ReadonlyValue<T>, position?: TreePosition): void;
|
|
330
|
+
insert(id: string, value: O extends true ? ReadonlyValue<T> | undefined : ReadonlyValue<T>, position?: TreePosition): void;
|
|
301
331
|
move(id: string, position?: TreePosition): void;
|
|
302
332
|
remove(id: string): void;
|
|
303
|
-
replace(value: DocumentTreeValue<T>): void;
|
|
304
|
-
replace(id: string, value: ReadonlyValue<T>): void;
|
|
333
|
+
replace(value: DocumentTreeValue<T, O>): void;
|
|
334
|
+
replace(id: string, value: O extends true ? ReadonlyValue<T> | undefined : ReadonlyValue<T>): void;
|
|
305
335
|
} : {});
|
|
306
|
-
type NodeAccess<N extends DocumentNode, W extends boolean> = N extends FieldNode<infer T, boolean> ? ReadonlyValue<T> : N extends ObjectNode<infer S> ? ShapeAccess<S, W> & Scoped<N, W> : N extends VariantNode<infer Tag, infer V> ? { [K in keyof V & string]: ShapeAccess<V[K]['shape'], W> & { readonly [P in Tag]: K } & Scoped<N, W, Extract<Infer<N>, Record<Tag, K>>> }[keyof V & string] : N extends MapNode<infer V, infer K> ? MapAccess<K, V, W> & Scoped<N, W> : N extends TableNode<infer V, infer K> ? TableAccess<K, V, W> & Scoped<N, W> : N extends ListNode<infer T> ? ListAccess<T, W> & Scoped<N, W> : N extends TreeNode<infer T> ? TreeAccess<T, W> & Scoped<N, W> : never;
|
|
336
|
+
type NodeAccess<N extends DocumentNode, W extends boolean> = N extends FieldNode<infer T, boolean> ? ReadonlyValue<T> : N extends ObjectNode<infer S> ? ShapeAccess<S, W> & Scoped<N, W> : N extends VariantNode<infer Tag, infer V> ? { [K in keyof V & string]: ShapeAccess<V[K]['shape'], W> & { readonly [P in Tag]: K } & Scoped<N, W, Extract<Infer<N>, Record<Tag, K>>> }[keyof V & string] : N extends MapNode<infer V, infer K> ? MapAccess<K, V, W> & Scoped<N, W> : N extends TableNode<infer V, infer K> ? TableAccess<K, V, W> & Scoped<N, W> : N extends ListNode<infer T> ? ListAccess<T, W> & Scoped<N, W> : N extends TreeNode<infer T, infer O> ? TreeAccess<T, O, W> & Scoped<N, W> : never;
|
|
307
337
|
type Access<N extends DocumentNode, W extends boolean> = N extends {
|
|
308
338
|
readonly optional: true;
|
|
309
339
|
} ? NodeAccess<N, W> | undefined : NodeAccess<N, W>;
|
|
@@ -457,5 +487,5 @@ type DocumentRuntime<S extends ObjectNode> = DocumentReadable<S> & {
|
|
|
457
487
|
dispose(): void;
|
|
458
488
|
};
|
|
459
489
|
//#endregion
|
|
460
|
-
export { OptionalNode as $, overlaps as A, DocumentAddress as B, Draft as C, AddressRef as D, snapshot as E, MemberChange as F, DocumentTreeValue as G, DocumentListConfig as H, ValueTransition as I, Infer as J, FieldNode as K,
|
|
461
|
-
//# sourceMappingURL=contract-
|
|
490
|
+
export { OptionalNode as $, overlaps as A, DocumentAddress as B, Draft as C, AddressRef as D, snapshot as E, MemberChange as F, DocumentTreeValue as G, DocumentListConfig as H, ValueTransition as I, Infer as J, FieldNode as K, CollectionEntry as L, resolveAddress as M, Change as N, contains as O, ChangeSet as P, ObjectShape as Q, CollectionId as R, DocumentImpact as S, replace as T, DocumentNode as U, DocumentAnchor as V, DocumentTreeNode as W, MapNode as X, ListNode as Y, ObjectNode as Z, Unsubscribe as _, Validator as _t, DocumentDisposedError as a, VariantNode as at, MutationIssueCode as b, DocumentReentrancyError as c, list as ct, LocalHistory as d, optional as dt, PathValueOf as et, ObserverError as f, table as ft, TransactionResult as g, ParseIssue as gt, TransactionRejected as h, ParseError as ht, DocumentDiagnostic as i, TreeNode as it, read as j, debugKey as k, DocumentRuntime as l, map as lt, Synchronous as m, variant as mt, CommitSource as n, SchemaPath as nt, DocumentProblem as o, VariantShape as ot, OperationResult as p, tree as pt, ImpactTarget as q, DocumentCommit as r, TableNode as rt, DocumentReadable as s, field as st, CommitListener as t, ReadonlyValue as tt, HistoryState as u, object as ut, Readable as v, parse as vt, Read as w, CollectionImpact as x, MutationIssue as y, CollectionPath as z };
|
|
491
|
+
//# sourceMappingURL=contract-CxiNcqMn.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_issue = require("./issue-
|
|
1
|
+
const require_issue = require("./issue-Bo0FIO3b.cjs");
|
|
2
2
|
//#region core/src/mutation/changes.ts
|
|
3
3
|
const validated = /* @__PURE__ */ new WeakSet();
|
|
4
4
|
const compareChanges = (a, b) => {
|
|
@@ -238,4 +238,4 @@ Object.defineProperty(exports, "sealChanges", {
|
|
|
238
238
|
}
|
|
239
239
|
});
|
|
240
240
|
|
|
241
|
-
//# sourceMappingURL=driver-
|
|
241
|
+
//# sourceMappingURL=driver-BC06FEMF.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver-Djr3BVvo.cjs","names":["isPlainObject","fail","validNode","AddressIndex"],"sources":["../core/src/mutation/changes.ts","../core/src/runtime/driver.ts"],"sourcesContent":["import type { Change, ChangeSet, MemberChange, ValueTransition } from '../changes';\nimport { isPlainObject } from '../value/ownership';\nimport { AddressIndex } from '../address';\nimport { fail } from './issue';\nimport { validNode } from './tree';\n\nconst validated = new WeakSet<ChangeSet>();\n\nconst compareChanges = (a: Change, b: Change): number => {\n if (a.kind === 'reset' || b.kind === 'reset')\n return a.kind === b.kind ? 0 : a.kind === 'reset' ? -1 : 1;\n const length = Math.min(a.at.length, b.at.length);\n for (let i = 0; i < length; i++) if (a.at[i] !== b.at[i]) return lexical(a.at[i], b.at[i]);\n return a.at.length - b.at.length || lexical(a.kind, b.kind);\n};\n\nconst publication = (changes: Change[]): ChangeSet => {\n const result = { changes };\n validated.add(result);\n return result;\n};\n\n/** Register complete recorder groups; unknown input is validated separately. */\nexport const sealChanges = (changes: Change[]): ChangeSet => {\n changes.sort(compareChanges);\n return publication(changes);\n};\n\nconst keys = (value: Record<string, unknown>, expected: readonly string[]) =>\n Object.keys(value).every(key => expected.includes(key));\nconst strings = (value: unknown): value is readonly string[] => {\n if (!Array.isArray(value)) return false;\n for (const item of value) if (typeof item !== 'string') return false;\n return true;\n};\nconst order = (value: unknown): value is readonly string[] =>\n strings(value) && new Set(value).size === value.length;\nconst transition = (\n value: unknown,\n key: 'key' | 'id'\n): value is ValueTransition & Record<string, unknown> => {\n if (!isPlainObject(value) || typeof value[key] !== 'string') return false;\n if (value.kind === 'added')\n return keys(value, ['kind', key, 'after']) && Object.hasOwn(value, 'after');\n if (value.kind === 'removed')\n return keys(value, ['kind', key, 'before']) && Object.hasOwn(value, 'before');\n return (\n value.kind === 'updated' &&\n keys(value, ['kind', key, 'before', 'after']) &&\n Object.hasOwn(value, 'before') &&\n Object.hasOwn(value, 'after')\n );\n};\nconst lexical = (a: string, b: string) => (a < b ? -1 : a === b ? 0 : 1);\n\n/** The sole unknown ChangeSet boundary, including normalized logical-address conflicts. */\nexport const decodeChanges = (input: unknown): ChangeSet => {\n if (typeof input === 'object' && input !== null && validated.has(input as ChangeSet))\n return input as ChangeSet;\n if (!isPlainObject(input) || !keys(input, ['changes']) || !Array.isArray(input.changes))\n return fail([], 'invalid-changes', 'Expected a ChangeSet.');\n const result: Change[] = [];\n for (const entry of input.changes) {\n if (!isPlainObject(entry)) return fail([], 'invalid-changes', 'Expected a change.');\n if (entry.kind === 'reset') {\n if (\n input.changes.length !== 1 ||\n !keys(entry, ['kind', 'before', 'after']) ||\n !Object.hasOwn(entry, 'before') ||\n !Object.hasOwn(entry, 'after')\n )\n return fail(\n [],\n 'invalid-changes',\n 'A reset must be the only change and contain both values.'\n );\n return sealChanges([{ kind: 'reset', before: entry.before, after: entry.after }]);\n }\n if (!strings(entry.at))\n return fail([], 'invalid-changes', 'Change addresses must contain strings.');\n const at = entry.at;\n if (\n entry.kind === 'members' &&\n keys(entry, ['kind', 'at', 'members', 'order']) &&\n Array.isArray(entry.members) &&\n (entry.members.length || Object.hasOwn(entry, 'order'))\n ) {\n const seen = new Set<string>();\n const members: MemberChange[] = [];\n for (const member of entry.members) {\n if (!transition(member, 'key') || typeof member.key !== 'string' || seen.has(member.key))\n return fail(at, 'invalid-changes', 'Malformed or duplicate member transition.');\n seen.add(member.key);\n members.push({ ...member, key: member.key });\n }\n const change: Extract<Change, { kind: 'members' }> = {\n kind: 'members',\n at,\n members: members.sort((a, b) => lexical(a.key, b.key)),\n };\n if (Object.hasOwn(entry, 'order')) {\n if (\n !isPlainObject(entry.order) ||\n !keys(entry.order, ['before', 'after']) ||\n !order(entry.order.before) ||\n !order(entry.order.after)\n )\n return fail(at, 'invalid-changes', 'Malformed container order.');\n result.push({ ...change, order: { before: entry.order.before, after: entry.order.after } });\n } else result.push(change);\n } else if (\n entry.kind === 'tree' &&\n keys(entry, ['kind', 'at', 'before', 'after', 'nodes']) &&\n (entry.before === null || typeof entry.before === 'string') &&\n (entry.after === null || typeof entry.after === 'string') &&\n Array.isArray(entry.nodes)\n ) {\n const seen = new Set<string>();\n for (const node of entry.nodes) {\n if (\n !transition(node, 'id') ||\n typeof node.id !== 'string' ||\n seen.has(node.id) ||\n (node.kind !== 'added' && !validNode(node.before)) ||\n (node.kind !== 'removed' && !validNode(node.after))\n )\n return fail(at, 'invalid-changes', 'Malformed or duplicate tree transition.');\n seen.add(node.id);\n }\n const nodes = entry.nodes as Extract<Change, { kind: 'tree' }>['nodes'];\n result.push({\n kind: 'tree',\n at,\n before: entry.before,\n after: entry.after,\n nodes: [...nodes].sort((a, b) => lexical(a.id, b.id)),\n });\n } else return fail(at, 'invalid-changes', 'Unknown or malformed change.');\n }\n return publication(normalizeChanges(result));\n};\n\nconst normalizeChanges = (changes: Change[]): Change[] => {\n const sorted = changes.sort(compareChanges);\n const groups = new AddressIndex<true>();\n const replacements = new AddressIndex<true>();\n const orders = new AddressIndex<true>();\n for (const change of sorted) {\n if (change.kind === 'reset') continue;\n if (change.kind === 'members') {\n if (groups.exact(change.at)?.size)\n return fail(change.at, 'invalid-changes', 'Duplicate member group.');\n groups.add(change.at, true);\n if (change.order) {\n if (replacements.hasAncestor(change.at))\n return fail(change.at, 'invalid-changes', 'Overlapping container order.');\n orders.add(change.at, true);\n }\n for (const member of change.members) {\n const at = change.at.concat(member.key);\n if (replacements.overlaps(at) || orders.hasDescendant(at))\n return fail(at, 'invalid-changes', 'Overlapping member transitions.');\n replacements.add(at, true);\n }\n } else if (change.kind === 'tree') {\n if (replacements.overlaps(change.at) || orders.hasDescendant(change.at))\n return fail(change.at, 'invalid-changes', 'Overlapping tree transitions.');\n replacements.add(change.at, true);\n }\n }\n return sorted;\n};\n\nexport const changeCount = (changes: ChangeSet): number => {\n let count = 0;\n for (const change of changes.changes)\n count +=\n change.kind === 'members'\n ? change.members.length + (change.order ? 1 : 0)\n : change.kind === 'tree'\n ? 1 + change.nodes.length\n : 1;\n return count;\n};\n","import type { CommitSource, DocumentRuntime } from './contract';\nimport type { ObjectNode } from '../schema';\n\nexport type RuntimeWriteIntent =\n | { readonly kind: 'update'; readonly source: Extract<CommitSource, 'local' | 'system'> }\n | { readonly kind: 'apply'; readonly source: CommitSource }\n | { readonly kind: 'replace'; readonly source: Extract<CommitSource, 'system' | 'remote'> };\n\nexport type RuntimeWriteDriver = {\n readonly assertWritable: (intent: RuntimeWriteIntent) => void;\n};\n\nexport type RuntimeWriteDriverLease = {\n readonly run: <TResult>(run: () => TResult) => TResult;\n readonly dispose: () => void;\n};\n\ntype RuntimeDriverState = {\n driver: RuntimeWriteDriver | undefined;\n bypassDepth: number;\n};\n\nconst states = new WeakMap<object, RuntimeDriverState>();\n\nconst stateOf = (runtime: object): RuntimeDriverState => {\n const state = states.get(runtime);\n if (!state) throw new Error('Unknown Doxum runtime.');\n return state;\n};\n\nexport const bindRuntimeDriver = (runtime: object): void => {\n states.set(runtime, { driver: undefined, bypassDepth: 0 });\n};\n\nexport const assertRuntimeWritable = (runtime: object, intent: RuntimeWriteIntent): void => {\n const state = stateOf(runtime);\n if (state.bypassDepth === 0) state.driver?.assertWritable(intent);\n};\n\nexport const installRuntimeWriteDriver = <TSchema extends ObjectNode>(\n runtime: DocumentRuntime<TSchema>,\n driver: RuntimeWriteDriver\n): RuntimeWriteDriverLease => {\n const state = stateOf(runtime);\n if (state.driver) throw new Error('Doxum runtime already has a write driver.');\n state.driver = driver;\n let active = true;\n return Object.freeze({\n run: <TResult>(run: () => TResult): TResult => {\n if (!active) throw new Error('Doxum runtime write driver is no longer active.');\n state.bypassDepth += 1;\n try {\n return run();\n } finally {\n state.bypassDepth -= 1;\n }\n },\n dispose: (): void => {\n if (!active) return;\n active = false;\n if (state.driver === driver) state.driver = undefined;\n },\n });\n};\n\nexport const disposeRuntimeDriver = (runtime: object): void => {\n states.delete(runtime);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"driver-BC06FEMF.cjs","names":["isPlainObject","fail","validNode","AddressIndex"],"sources":["../core/src/mutation/changes.ts","../core/src/runtime/driver.ts"],"sourcesContent":["import type { Change, ChangeSet, MemberChange, ValueTransition } from '../changes';\nimport { isPlainObject } from '../value/ownership';\nimport { AddressIndex } from '../address';\nimport { fail } from './issue';\nimport { validNode } from './tree';\n\nconst validated = new WeakSet<ChangeSet>();\n\nconst compareChanges = (a: Change, b: Change): number => {\n if (a.kind === 'reset' || b.kind === 'reset')\n return a.kind === b.kind ? 0 : a.kind === 'reset' ? -1 : 1;\n const length = Math.min(a.at.length, b.at.length);\n for (let i = 0; i < length; i++) if (a.at[i] !== b.at[i]) return lexical(a.at[i], b.at[i]);\n return a.at.length - b.at.length || lexical(a.kind, b.kind);\n};\n\nconst publication = (changes: Change[]): ChangeSet => {\n const result = { changes };\n validated.add(result);\n return result;\n};\n\n/** Register complete recorder groups; unknown input is validated separately. */\nexport const sealChanges = (changes: Change[]): ChangeSet => {\n changes.sort(compareChanges);\n return publication(changes);\n};\n\nconst keys = (value: Record<string, unknown>, expected: readonly string[]) =>\n Object.keys(value).every(key => expected.includes(key));\nconst strings = (value: unknown): value is readonly string[] => {\n if (!Array.isArray(value)) return false;\n for (const item of value) if (typeof item !== 'string') return false;\n return true;\n};\nconst order = (value: unknown): value is readonly string[] =>\n strings(value) && new Set(value).size === value.length;\nconst transition = (\n value: unknown,\n key: 'key' | 'id'\n): value is ValueTransition & Record<string, unknown> => {\n if (!isPlainObject(value) || typeof value[key] !== 'string') return false;\n if (value.kind === 'added')\n return keys(value, ['kind', key, 'after']) && Object.hasOwn(value, 'after');\n if (value.kind === 'removed')\n return keys(value, ['kind', key, 'before']) && Object.hasOwn(value, 'before');\n return (\n value.kind === 'updated' &&\n keys(value, ['kind', key, 'before', 'after']) &&\n Object.hasOwn(value, 'before') &&\n Object.hasOwn(value, 'after')\n );\n};\nconst lexical = (a: string, b: string) => (a < b ? -1 : a === b ? 0 : 1);\n\n/** The sole unknown ChangeSet boundary, including normalized logical-address conflicts. */\nexport const decodeChanges = (input: unknown): ChangeSet => {\n if (typeof input === 'object' && input !== null && validated.has(input as ChangeSet))\n return input as ChangeSet;\n if (!isPlainObject(input) || !keys(input, ['changes']) || !Array.isArray(input.changes))\n return fail([], 'invalid-changes', 'Expected a ChangeSet.');\n const result: Change[] = [];\n for (const entry of input.changes) {\n if (!isPlainObject(entry)) return fail([], 'invalid-changes', 'Expected a change.');\n if (entry.kind === 'reset') {\n if (\n input.changes.length !== 1 ||\n !keys(entry, ['kind', 'before', 'after']) ||\n !Object.hasOwn(entry, 'before') ||\n !Object.hasOwn(entry, 'after')\n )\n return fail(\n [],\n 'invalid-changes',\n 'A reset must be the only change and contain both values.'\n );\n return sealChanges([{ kind: 'reset', before: entry.before, after: entry.after }]);\n }\n if (!strings(entry.at))\n return fail([], 'invalid-changes', 'Change addresses must contain strings.');\n const at = entry.at;\n if (\n entry.kind === 'members' &&\n keys(entry, ['kind', 'at', 'members', 'order']) &&\n Array.isArray(entry.members) &&\n (entry.members.length || Object.hasOwn(entry, 'order'))\n ) {\n const seen = new Set<string>();\n const members: MemberChange[] = [];\n for (const member of entry.members) {\n if (!transition(member, 'key') || typeof member.key !== 'string' || seen.has(member.key))\n return fail(at, 'invalid-changes', 'Malformed or duplicate member transition.');\n seen.add(member.key);\n members.push({ ...member, key: member.key });\n }\n const change: Extract<Change, { kind: 'members' }> = {\n kind: 'members',\n at,\n members: members.sort((a, b) => lexical(a.key, b.key)),\n };\n if (Object.hasOwn(entry, 'order')) {\n if (\n !isPlainObject(entry.order) ||\n !keys(entry.order, ['before', 'after']) ||\n !order(entry.order.before) ||\n !order(entry.order.after)\n )\n return fail(at, 'invalid-changes', 'Malformed container order.');\n result.push({ ...change, order: { before: entry.order.before, after: entry.order.after } });\n } else result.push(change);\n } else if (\n entry.kind === 'tree' &&\n keys(entry, ['kind', 'at', 'before', 'after', 'nodes']) &&\n (entry.before === null || typeof entry.before === 'string') &&\n (entry.after === null || typeof entry.after === 'string') &&\n Array.isArray(entry.nodes)\n ) {\n const seen = new Set<string>();\n for (const node of entry.nodes) {\n if (\n !transition(node, 'id') ||\n typeof node.id !== 'string' ||\n seen.has(node.id) ||\n (node.kind !== 'added' && !validNode(node.before)) ||\n (node.kind !== 'removed' && !validNode(node.after))\n )\n return fail(at, 'invalid-changes', 'Malformed or duplicate tree transition.');\n seen.add(node.id);\n }\n const nodes = entry.nodes as Extract<Change, { kind: 'tree' }>['nodes'];\n result.push({\n kind: 'tree',\n at,\n before: entry.before,\n after: entry.after,\n nodes: [...nodes].sort((a, b) => lexical(a.id, b.id)),\n });\n } else return fail(at, 'invalid-changes', 'Unknown or malformed change.');\n }\n return publication(normalizeChanges(result));\n};\n\nconst normalizeChanges = (changes: Change[]): Change[] => {\n const sorted = changes.sort(compareChanges);\n const groups = new AddressIndex<true>();\n const replacements = new AddressIndex<true>();\n const orders = new AddressIndex<true>();\n for (const change of sorted) {\n if (change.kind === 'reset') continue;\n if (change.kind === 'members') {\n if (groups.exact(change.at)?.size)\n return fail(change.at, 'invalid-changes', 'Duplicate member group.');\n groups.add(change.at, true);\n if (change.order) {\n if (replacements.hasAncestor(change.at))\n return fail(change.at, 'invalid-changes', 'Overlapping container order.');\n orders.add(change.at, true);\n }\n for (const member of change.members) {\n const at = change.at.concat(member.key);\n if (replacements.overlaps(at) || orders.hasDescendant(at))\n return fail(at, 'invalid-changes', 'Overlapping member transitions.');\n replacements.add(at, true);\n }\n } else if (change.kind === 'tree') {\n if (replacements.overlaps(change.at) || orders.hasDescendant(change.at))\n return fail(change.at, 'invalid-changes', 'Overlapping tree transitions.');\n replacements.add(change.at, true);\n }\n }\n return sorted;\n};\n\nexport const changeCount = (changes: ChangeSet): number => {\n let count = 0;\n for (const change of changes.changes)\n count +=\n change.kind === 'members'\n ? change.members.length + (change.order ? 1 : 0)\n : change.kind === 'tree'\n ? 1 + change.nodes.length\n : 1;\n return count;\n};\n","import type { CommitSource, DocumentRuntime } from './contract';\nimport type { ObjectNode } from '../schema';\n\nexport type RuntimeWriteIntent =\n | { readonly kind: 'update'; readonly source: Extract<CommitSource, 'local' | 'system'> }\n | { readonly kind: 'apply'; readonly source: CommitSource }\n | { readonly kind: 'replace'; readonly source: Extract<CommitSource, 'system' | 'remote'> };\n\nexport type RuntimeWriteDriver = {\n readonly assertWritable: (intent: RuntimeWriteIntent) => void;\n};\n\nexport type RuntimeWriteDriverLease = {\n readonly run: <TResult>(run: () => TResult) => TResult;\n readonly dispose: () => void;\n};\n\ntype RuntimeDriverState = {\n driver: RuntimeWriteDriver | undefined;\n bypassDepth: number;\n};\n\nconst states = new WeakMap<object, RuntimeDriverState>();\n\nconst stateOf = (runtime: object): RuntimeDriverState => {\n const state = states.get(runtime);\n if (!state) throw new Error('Unknown Doxum runtime.');\n return state;\n};\n\nexport const bindRuntimeDriver = (runtime: object): void => {\n states.set(runtime, { driver: undefined, bypassDepth: 0 });\n};\n\nexport const assertRuntimeWritable = (runtime: object, intent: RuntimeWriteIntent): void => {\n const state = stateOf(runtime);\n if (state.bypassDepth === 0) state.driver?.assertWritable(intent);\n};\n\nexport const installRuntimeWriteDriver = <TSchema extends ObjectNode>(\n runtime: DocumentRuntime<TSchema>,\n driver: RuntimeWriteDriver\n): RuntimeWriteDriverLease => {\n const state = stateOf(runtime);\n if (state.driver) throw new Error('Doxum runtime already has a write driver.');\n state.driver = driver;\n let active = true;\n return Object.freeze({\n run: <TResult>(run: () => TResult): TResult => {\n if (!active) throw new Error('Doxum runtime write driver is no longer active.');\n state.bypassDepth += 1;\n try {\n return run();\n } finally {\n state.bypassDepth -= 1;\n }\n },\n dispose: (): void => {\n if (!active) return;\n active = false;\n if (state.driver === driver) state.driver = undefined;\n },\n });\n};\n\nexport const disposeRuntimeDriver = (runtime: object): void => {\n states.delete(runtime);\n};\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as validNode, i as AddressIndex, n as fail, w as isPlainObject } from "./issue-
|
|
1
|
+
import { S as validNode, i as AddressIndex, n as fail, w as isPlainObject } from "./issue-9U6YLYz3.js";
|
|
2
2
|
//#region core/src/mutation/changes.ts
|
|
3
3
|
const validated = /* @__PURE__ */ new WeakSet();
|
|
4
4
|
const compareChanges = (a, b) => {
|
|
@@ -197,4 +197,4 @@ const disposeRuntimeDriver = (runtime) => {
|
|
|
197
197
|
//#endregion
|
|
198
198
|
export { changeCount as a, installRuntimeWriteDriver as i, bindRuntimeDriver as n, decodeChanges as o, disposeRuntimeDriver as r, sealChanges as s, assertRuntimeWritable as t };
|
|
199
199
|
|
|
200
|
-
//# sourceMappingURL=driver-
|
|
200
|
+
//# sourceMappingURL=driver-BqRjwFmU.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver-CLYJOGDQ.js","names":[],"sources":["../core/src/mutation/changes.ts","../core/src/runtime/driver.ts"],"sourcesContent":["import type { Change, ChangeSet, MemberChange, ValueTransition } from '../changes';\nimport { isPlainObject } from '../value/ownership';\nimport { AddressIndex } from '../address';\nimport { fail } from './issue';\nimport { validNode } from './tree';\n\nconst validated = new WeakSet<ChangeSet>();\n\nconst compareChanges = (a: Change, b: Change): number => {\n if (a.kind === 'reset' || b.kind === 'reset')\n return a.kind === b.kind ? 0 : a.kind === 'reset' ? -1 : 1;\n const length = Math.min(a.at.length, b.at.length);\n for (let i = 0; i < length; i++) if (a.at[i] !== b.at[i]) return lexical(a.at[i], b.at[i]);\n return a.at.length - b.at.length || lexical(a.kind, b.kind);\n};\n\nconst publication = (changes: Change[]): ChangeSet => {\n const result = { changes };\n validated.add(result);\n return result;\n};\n\n/** Register complete recorder groups; unknown input is validated separately. */\nexport const sealChanges = (changes: Change[]): ChangeSet => {\n changes.sort(compareChanges);\n return publication(changes);\n};\n\nconst keys = (value: Record<string, unknown>, expected: readonly string[]) =>\n Object.keys(value).every(key => expected.includes(key));\nconst strings = (value: unknown): value is readonly string[] => {\n if (!Array.isArray(value)) return false;\n for (const item of value) if (typeof item !== 'string') return false;\n return true;\n};\nconst order = (value: unknown): value is readonly string[] =>\n strings(value) && new Set(value).size === value.length;\nconst transition = (\n value: unknown,\n key: 'key' | 'id'\n): value is ValueTransition & Record<string, unknown> => {\n if (!isPlainObject(value) || typeof value[key] !== 'string') return false;\n if (value.kind === 'added')\n return keys(value, ['kind', key, 'after']) && Object.hasOwn(value, 'after');\n if (value.kind === 'removed')\n return keys(value, ['kind', key, 'before']) && Object.hasOwn(value, 'before');\n return (\n value.kind === 'updated' &&\n keys(value, ['kind', key, 'before', 'after']) &&\n Object.hasOwn(value, 'before') &&\n Object.hasOwn(value, 'after')\n );\n};\nconst lexical = (a: string, b: string) => (a < b ? -1 : a === b ? 0 : 1);\n\n/** The sole unknown ChangeSet boundary, including normalized logical-address conflicts. */\nexport const decodeChanges = (input: unknown): ChangeSet => {\n if (typeof input === 'object' && input !== null && validated.has(input as ChangeSet))\n return input as ChangeSet;\n if (!isPlainObject(input) || !keys(input, ['changes']) || !Array.isArray(input.changes))\n return fail([], 'invalid-changes', 'Expected a ChangeSet.');\n const result: Change[] = [];\n for (const entry of input.changes) {\n if (!isPlainObject(entry)) return fail([], 'invalid-changes', 'Expected a change.');\n if (entry.kind === 'reset') {\n if (\n input.changes.length !== 1 ||\n !keys(entry, ['kind', 'before', 'after']) ||\n !Object.hasOwn(entry, 'before') ||\n !Object.hasOwn(entry, 'after')\n )\n return fail(\n [],\n 'invalid-changes',\n 'A reset must be the only change and contain both values.'\n );\n return sealChanges([{ kind: 'reset', before: entry.before, after: entry.after }]);\n }\n if (!strings(entry.at))\n return fail([], 'invalid-changes', 'Change addresses must contain strings.');\n const at = entry.at;\n if (\n entry.kind === 'members' &&\n keys(entry, ['kind', 'at', 'members', 'order']) &&\n Array.isArray(entry.members) &&\n (entry.members.length || Object.hasOwn(entry, 'order'))\n ) {\n const seen = new Set<string>();\n const members: MemberChange[] = [];\n for (const member of entry.members) {\n if (!transition(member, 'key') || typeof member.key !== 'string' || seen.has(member.key))\n return fail(at, 'invalid-changes', 'Malformed or duplicate member transition.');\n seen.add(member.key);\n members.push({ ...member, key: member.key });\n }\n const change: Extract<Change, { kind: 'members' }> = {\n kind: 'members',\n at,\n members: members.sort((a, b) => lexical(a.key, b.key)),\n };\n if (Object.hasOwn(entry, 'order')) {\n if (\n !isPlainObject(entry.order) ||\n !keys(entry.order, ['before', 'after']) ||\n !order(entry.order.before) ||\n !order(entry.order.after)\n )\n return fail(at, 'invalid-changes', 'Malformed container order.');\n result.push({ ...change, order: { before: entry.order.before, after: entry.order.after } });\n } else result.push(change);\n } else if (\n entry.kind === 'tree' &&\n keys(entry, ['kind', 'at', 'before', 'after', 'nodes']) &&\n (entry.before === null || typeof entry.before === 'string') &&\n (entry.after === null || typeof entry.after === 'string') &&\n Array.isArray(entry.nodes)\n ) {\n const seen = new Set<string>();\n for (const node of entry.nodes) {\n if (\n !transition(node, 'id') ||\n typeof node.id !== 'string' ||\n seen.has(node.id) ||\n (node.kind !== 'added' && !validNode(node.before)) ||\n (node.kind !== 'removed' && !validNode(node.after))\n )\n return fail(at, 'invalid-changes', 'Malformed or duplicate tree transition.');\n seen.add(node.id);\n }\n const nodes = entry.nodes as Extract<Change, { kind: 'tree' }>['nodes'];\n result.push({\n kind: 'tree',\n at,\n before: entry.before,\n after: entry.after,\n nodes: [...nodes].sort((a, b) => lexical(a.id, b.id)),\n });\n } else return fail(at, 'invalid-changes', 'Unknown or malformed change.');\n }\n return publication(normalizeChanges(result));\n};\n\nconst normalizeChanges = (changes: Change[]): Change[] => {\n const sorted = changes.sort(compareChanges);\n const groups = new AddressIndex<true>();\n const replacements = new AddressIndex<true>();\n const orders = new AddressIndex<true>();\n for (const change of sorted) {\n if (change.kind === 'reset') continue;\n if (change.kind === 'members') {\n if (groups.exact(change.at)?.size)\n return fail(change.at, 'invalid-changes', 'Duplicate member group.');\n groups.add(change.at, true);\n if (change.order) {\n if (replacements.hasAncestor(change.at))\n return fail(change.at, 'invalid-changes', 'Overlapping container order.');\n orders.add(change.at, true);\n }\n for (const member of change.members) {\n const at = change.at.concat(member.key);\n if (replacements.overlaps(at) || orders.hasDescendant(at))\n return fail(at, 'invalid-changes', 'Overlapping member transitions.');\n replacements.add(at, true);\n }\n } else if (change.kind === 'tree') {\n if (replacements.overlaps(change.at) || orders.hasDescendant(change.at))\n return fail(change.at, 'invalid-changes', 'Overlapping tree transitions.');\n replacements.add(change.at, true);\n }\n }\n return sorted;\n};\n\nexport const changeCount = (changes: ChangeSet): number => {\n let count = 0;\n for (const change of changes.changes)\n count +=\n change.kind === 'members'\n ? change.members.length + (change.order ? 1 : 0)\n : change.kind === 'tree'\n ? 1 + change.nodes.length\n : 1;\n return count;\n};\n","import type { CommitSource, DocumentRuntime } from './contract';\nimport type { ObjectNode } from '../schema';\n\nexport type RuntimeWriteIntent =\n | { readonly kind: 'update'; readonly source: Extract<CommitSource, 'local' | 'system'> }\n | { readonly kind: 'apply'; readonly source: CommitSource }\n | { readonly kind: 'replace'; readonly source: Extract<CommitSource, 'system' | 'remote'> };\n\nexport type RuntimeWriteDriver = {\n readonly assertWritable: (intent: RuntimeWriteIntent) => void;\n};\n\nexport type RuntimeWriteDriverLease = {\n readonly run: <TResult>(run: () => TResult) => TResult;\n readonly dispose: () => void;\n};\n\ntype RuntimeDriverState = {\n driver: RuntimeWriteDriver | undefined;\n bypassDepth: number;\n};\n\nconst states = new WeakMap<object, RuntimeDriverState>();\n\nconst stateOf = (runtime: object): RuntimeDriverState => {\n const state = states.get(runtime);\n if (!state) throw new Error('Unknown Doxum runtime.');\n return state;\n};\n\nexport const bindRuntimeDriver = (runtime: object): void => {\n states.set(runtime, { driver: undefined, bypassDepth: 0 });\n};\n\nexport const assertRuntimeWritable = (runtime: object, intent: RuntimeWriteIntent): void => {\n const state = stateOf(runtime);\n if (state.bypassDepth === 0) state.driver?.assertWritable(intent);\n};\n\nexport const installRuntimeWriteDriver = <TSchema extends ObjectNode>(\n runtime: DocumentRuntime<TSchema>,\n driver: RuntimeWriteDriver\n): RuntimeWriteDriverLease => {\n const state = stateOf(runtime);\n if (state.driver) throw new Error('Doxum runtime already has a write driver.');\n state.driver = driver;\n let active = true;\n return Object.freeze({\n run: <TResult>(run: () => TResult): TResult => {\n if (!active) throw new Error('Doxum runtime write driver is no longer active.');\n state.bypassDepth += 1;\n try {\n return run();\n } finally {\n state.bypassDepth -= 1;\n }\n },\n dispose: (): void => {\n if (!active) return;\n active = false;\n if (state.driver === driver) state.driver = undefined;\n },\n });\n};\n\nexport const disposeRuntimeDriver = (runtime: object): void => {\n states.delete(runtime);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"driver-BqRjwFmU.js","names":[],"sources":["../core/src/mutation/changes.ts","../core/src/runtime/driver.ts"],"sourcesContent":["import type { Change, ChangeSet, MemberChange, ValueTransition } from '../changes';\nimport { isPlainObject } from '../value/ownership';\nimport { AddressIndex } from '../address';\nimport { fail } from './issue';\nimport { validNode } from './tree';\n\nconst validated = new WeakSet<ChangeSet>();\n\nconst compareChanges = (a: Change, b: Change): number => {\n if (a.kind === 'reset' || b.kind === 'reset')\n return a.kind === b.kind ? 0 : a.kind === 'reset' ? -1 : 1;\n const length = Math.min(a.at.length, b.at.length);\n for (let i = 0; i < length; i++) if (a.at[i] !== b.at[i]) return lexical(a.at[i], b.at[i]);\n return a.at.length - b.at.length || lexical(a.kind, b.kind);\n};\n\nconst publication = (changes: Change[]): ChangeSet => {\n const result = { changes };\n validated.add(result);\n return result;\n};\n\n/** Register complete recorder groups; unknown input is validated separately. */\nexport const sealChanges = (changes: Change[]): ChangeSet => {\n changes.sort(compareChanges);\n return publication(changes);\n};\n\nconst keys = (value: Record<string, unknown>, expected: readonly string[]) =>\n Object.keys(value).every(key => expected.includes(key));\nconst strings = (value: unknown): value is readonly string[] => {\n if (!Array.isArray(value)) return false;\n for (const item of value) if (typeof item !== 'string') return false;\n return true;\n};\nconst order = (value: unknown): value is readonly string[] =>\n strings(value) && new Set(value).size === value.length;\nconst transition = (\n value: unknown,\n key: 'key' | 'id'\n): value is ValueTransition & Record<string, unknown> => {\n if (!isPlainObject(value) || typeof value[key] !== 'string') return false;\n if (value.kind === 'added')\n return keys(value, ['kind', key, 'after']) && Object.hasOwn(value, 'after');\n if (value.kind === 'removed')\n return keys(value, ['kind', key, 'before']) && Object.hasOwn(value, 'before');\n return (\n value.kind === 'updated' &&\n keys(value, ['kind', key, 'before', 'after']) &&\n Object.hasOwn(value, 'before') &&\n Object.hasOwn(value, 'after')\n );\n};\nconst lexical = (a: string, b: string) => (a < b ? -1 : a === b ? 0 : 1);\n\n/** The sole unknown ChangeSet boundary, including normalized logical-address conflicts. */\nexport const decodeChanges = (input: unknown): ChangeSet => {\n if (typeof input === 'object' && input !== null && validated.has(input as ChangeSet))\n return input as ChangeSet;\n if (!isPlainObject(input) || !keys(input, ['changes']) || !Array.isArray(input.changes))\n return fail([], 'invalid-changes', 'Expected a ChangeSet.');\n const result: Change[] = [];\n for (const entry of input.changes) {\n if (!isPlainObject(entry)) return fail([], 'invalid-changes', 'Expected a change.');\n if (entry.kind === 'reset') {\n if (\n input.changes.length !== 1 ||\n !keys(entry, ['kind', 'before', 'after']) ||\n !Object.hasOwn(entry, 'before') ||\n !Object.hasOwn(entry, 'after')\n )\n return fail(\n [],\n 'invalid-changes',\n 'A reset must be the only change and contain both values.'\n );\n return sealChanges([{ kind: 'reset', before: entry.before, after: entry.after }]);\n }\n if (!strings(entry.at))\n return fail([], 'invalid-changes', 'Change addresses must contain strings.');\n const at = entry.at;\n if (\n entry.kind === 'members' &&\n keys(entry, ['kind', 'at', 'members', 'order']) &&\n Array.isArray(entry.members) &&\n (entry.members.length || Object.hasOwn(entry, 'order'))\n ) {\n const seen = new Set<string>();\n const members: MemberChange[] = [];\n for (const member of entry.members) {\n if (!transition(member, 'key') || typeof member.key !== 'string' || seen.has(member.key))\n return fail(at, 'invalid-changes', 'Malformed or duplicate member transition.');\n seen.add(member.key);\n members.push({ ...member, key: member.key });\n }\n const change: Extract<Change, { kind: 'members' }> = {\n kind: 'members',\n at,\n members: members.sort((a, b) => lexical(a.key, b.key)),\n };\n if (Object.hasOwn(entry, 'order')) {\n if (\n !isPlainObject(entry.order) ||\n !keys(entry.order, ['before', 'after']) ||\n !order(entry.order.before) ||\n !order(entry.order.after)\n )\n return fail(at, 'invalid-changes', 'Malformed container order.');\n result.push({ ...change, order: { before: entry.order.before, after: entry.order.after } });\n } else result.push(change);\n } else if (\n entry.kind === 'tree' &&\n keys(entry, ['kind', 'at', 'before', 'after', 'nodes']) &&\n (entry.before === null || typeof entry.before === 'string') &&\n (entry.after === null || typeof entry.after === 'string') &&\n Array.isArray(entry.nodes)\n ) {\n const seen = new Set<string>();\n for (const node of entry.nodes) {\n if (\n !transition(node, 'id') ||\n typeof node.id !== 'string' ||\n seen.has(node.id) ||\n (node.kind !== 'added' && !validNode(node.before)) ||\n (node.kind !== 'removed' && !validNode(node.after))\n )\n return fail(at, 'invalid-changes', 'Malformed or duplicate tree transition.');\n seen.add(node.id);\n }\n const nodes = entry.nodes as Extract<Change, { kind: 'tree' }>['nodes'];\n result.push({\n kind: 'tree',\n at,\n before: entry.before,\n after: entry.after,\n nodes: [...nodes].sort((a, b) => lexical(a.id, b.id)),\n });\n } else return fail(at, 'invalid-changes', 'Unknown or malformed change.');\n }\n return publication(normalizeChanges(result));\n};\n\nconst normalizeChanges = (changes: Change[]): Change[] => {\n const sorted = changes.sort(compareChanges);\n const groups = new AddressIndex<true>();\n const replacements = new AddressIndex<true>();\n const orders = new AddressIndex<true>();\n for (const change of sorted) {\n if (change.kind === 'reset') continue;\n if (change.kind === 'members') {\n if (groups.exact(change.at)?.size)\n return fail(change.at, 'invalid-changes', 'Duplicate member group.');\n groups.add(change.at, true);\n if (change.order) {\n if (replacements.hasAncestor(change.at))\n return fail(change.at, 'invalid-changes', 'Overlapping container order.');\n orders.add(change.at, true);\n }\n for (const member of change.members) {\n const at = change.at.concat(member.key);\n if (replacements.overlaps(at) || orders.hasDescendant(at))\n return fail(at, 'invalid-changes', 'Overlapping member transitions.');\n replacements.add(at, true);\n }\n } else if (change.kind === 'tree') {\n if (replacements.overlaps(change.at) || orders.hasDescendant(change.at))\n return fail(change.at, 'invalid-changes', 'Overlapping tree transitions.');\n replacements.add(change.at, true);\n }\n }\n return sorted;\n};\n\nexport const changeCount = (changes: ChangeSet): number => {\n let count = 0;\n for (const change of changes.changes)\n count +=\n change.kind === 'members'\n ? change.members.length + (change.order ? 1 : 0)\n : change.kind === 'tree'\n ? 1 + change.nodes.length\n : 1;\n return count;\n};\n","import type { CommitSource, DocumentRuntime } from './contract';\nimport type { ObjectNode } from '../schema';\n\nexport type RuntimeWriteIntent =\n | { readonly kind: 'update'; readonly source: Extract<CommitSource, 'local' | 'system'> }\n | { readonly kind: 'apply'; readonly source: CommitSource }\n | { readonly kind: 'replace'; readonly source: Extract<CommitSource, 'system' | 'remote'> };\n\nexport type RuntimeWriteDriver = {\n readonly assertWritable: (intent: RuntimeWriteIntent) => void;\n};\n\nexport type RuntimeWriteDriverLease = {\n readonly run: <TResult>(run: () => TResult) => TResult;\n readonly dispose: () => void;\n};\n\ntype RuntimeDriverState = {\n driver: RuntimeWriteDriver | undefined;\n bypassDepth: number;\n};\n\nconst states = new WeakMap<object, RuntimeDriverState>();\n\nconst stateOf = (runtime: object): RuntimeDriverState => {\n const state = states.get(runtime);\n if (!state) throw new Error('Unknown Doxum runtime.');\n return state;\n};\n\nexport const bindRuntimeDriver = (runtime: object): void => {\n states.set(runtime, { driver: undefined, bypassDepth: 0 });\n};\n\nexport const assertRuntimeWritable = (runtime: object, intent: RuntimeWriteIntent): void => {\n const state = stateOf(runtime);\n if (state.bypassDepth === 0) state.driver?.assertWritable(intent);\n};\n\nexport const installRuntimeWriteDriver = <TSchema extends ObjectNode>(\n runtime: DocumentRuntime<TSchema>,\n driver: RuntimeWriteDriver\n): RuntimeWriteDriverLease => {\n const state = stateOf(runtime);\n if (state.driver) throw new Error('Doxum runtime already has a write driver.');\n state.driver = driver;\n let active = true;\n return Object.freeze({\n run: <TResult>(run: () => TResult): TResult => {\n if (!active) throw new Error('Doxum runtime write driver is no longer active.');\n state.bypassDepth += 1;\n try {\n return run();\n } finally {\n state.bypassDepth -= 1;\n }\n },\n dispose: (): void => {\n if (!active) return;\n active = false;\n if (state.driver === driver) state.driver = undefined;\n },\n });\n};\n\nexport const disposeRuntimeDriver = (runtime: object): void => {\n states.delete(runtime);\n};\n"],"mappings":"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"}
|