@loro-extended/change 0.3.0 → 0.5.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/README.md +20 -15
- package/dist/index.d.ts +3 -2
- package/dist/index.js +29 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/conversion.ts +1 -4
- package/src/draft-nodes/text.ts +0 -2
- package/src/overlay.ts +16 -0
- package/src/shape.ts +9 -4
- package/src/string-literal.test.ts +42 -0
- package/src/utils/type-guards.ts +1 -0
- package/src/validation.ts +9 -1
package/README.md
CHANGED
|
@@ -318,18 +318,23 @@ const schema = Shape.doc({
|
|
|
318
318
|
- `Shape.text()` - Collaborative text editing
|
|
319
319
|
- `Shape.counter()` - Collaborative increment/decrement counters
|
|
320
320
|
- `Shape.list(itemSchema)` - Collaborative ordered lists
|
|
321
|
-
- `Shape.movableList(itemSchema)` - Collaborative
|
|
322
|
-
- `Shape.map(shape)` - Collaborative key-value maps
|
|
321
|
+
- `Shape.movableList(itemSchema)` - Collaborative reorderable lists
|
|
322
|
+
- `Shape.map(shape)` - Collaborative key-value maps with fixed keys
|
|
323
|
+
- `Shape.record(valueSchema)` - Collaborative key-value maps with dynamic string keys
|
|
323
324
|
- `Shape.tree(shape)` - Collaborative hierarchical tree structures (Note: incomplete implementation)
|
|
324
325
|
|
|
325
326
|
#### Value Types
|
|
326
327
|
|
|
327
|
-
- `Shape.plain.string()` - String values
|
|
328
|
+
- `Shape.plain.string()` - String values (optionally with literal union types)
|
|
328
329
|
- `Shape.plain.number()` - Number values
|
|
329
330
|
- `Shape.plain.boolean()` - Boolean values
|
|
330
331
|
- `Shape.plain.null()` - Null values
|
|
331
|
-
- `Shape.plain.
|
|
332
|
+
- `Shape.plain.undefined()` - Undefined values
|
|
333
|
+
- `Shape.plain.uint8Array()` - Binary data values
|
|
334
|
+
- `Shape.plain.object(shape)` - Object values with fixed keys
|
|
335
|
+
- `Shape.plain.record(valueShape)` - Object values with dynamic string keys
|
|
332
336
|
- `Shape.plain.array(itemShape)` - Array values
|
|
337
|
+
- `Shape.plain.union(shapes)` - Union of value types (e.g., `string | null`)
|
|
333
338
|
|
|
334
339
|
### TypedDoc Methods
|
|
335
340
|
|
|
@@ -404,20 +409,20 @@ Lists support familiar JavaScript array methods for filtering and finding items:
|
|
|
404
409
|
|
|
405
410
|
```typescript
|
|
406
411
|
// Find items (returns mutable draft objects)
|
|
407
|
-
const foundItem = draft.todos.find(todo => todo.completed);
|
|
408
|
-
const foundIndex = draft.todos.findIndex(todo => todo.id === "123");
|
|
412
|
+
const foundItem = draft.todos.find((todo) => todo.completed);
|
|
413
|
+
const foundIndex = draft.todos.findIndex((todo) => todo.id === "123");
|
|
409
414
|
|
|
410
415
|
// Filter items (returns array of mutable draft objects)
|
|
411
|
-
const completedTodos = draft.todos.filter(todo => todo.completed);
|
|
412
|
-
const activeTodos = draft.todos.filter(todo => !todo.completed);
|
|
416
|
+
const completedTodos = draft.todos.filter((todo) => todo.completed);
|
|
417
|
+
const activeTodos = draft.todos.filter((todo) => !todo.completed);
|
|
413
418
|
|
|
414
419
|
// Transform items (returns plain array, not mutable)
|
|
415
|
-
const todoTexts = draft.todos.map(todo => todo.text);
|
|
416
|
-
const todoIds = draft.todos.map(todo => todo.id);
|
|
420
|
+
const todoTexts = draft.todos.map((todo) => todo.text);
|
|
421
|
+
const todoIds = draft.todos.map((todo) => todo.id);
|
|
417
422
|
|
|
418
423
|
// Check conditions
|
|
419
|
-
const hasCompleted = draft.todos.some(todo => todo.completed);
|
|
420
|
-
const allCompleted = draft.todos.every(todo => todo.completed);
|
|
424
|
+
const hasCompleted = draft.todos.some((todo) => todo.completed);
|
|
425
|
+
const allCompleted = draft.todos.every((todo) => todo.completed);
|
|
421
426
|
|
|
422
427
|
// Iterate over items
|
|
423
428
|
draft.todos.forEach((todo, index) => {
|
|
@@ -430,15 +435,15 @@ draft.todos.forEach((todo, index) => {
|
|
|
430
435
|
```typescript
|
|
431
436
|
doc.change((draft) => {
|
|
432
437
|
// Find and mutate pattern - very common!
|
|
433
|
-
const todo = draft.todos.find(t => t.id === "123");
|
|
438
|
+
const todo = draft.todos.find((t) => t.id === "123");
|
|
434
439
|
if (todo) {
|
|
435
440
|
todo.completed = true; // ✅ This mutation will persist!
|
|
436
441
|
todo.text = "Updated text"; // ✅ This too!
|
|
437
442
|
}
|
|
438
443
|
|
|
439
444
|
// Filter and modify multiple items
|
|
440
|
-
const activeTodos = draft.todos.filter(t => !t.completed);
|
|
441
|
-
activeTodos.forEach(todo => {
|
|
445
|
+
const activeTodos = draft.todos.filter((t) => !t.completed);
|
|
446
|
+
activeTodos.forEach((todo) => {
|
|
442
447
|
todo.priority = "high"; // ✅ All mutations persist!
|
|
443
448
|
});
|
|
444
449
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -164,9 +164,10 @@ interface RecordContainerShape<NestedShape extends ContainerOrValueShape = Conta
|
|
|
164
164
|
}
|
|
165
165
|
type ContainerShape = CounterContainerShape | ListContainerShape | MapContainerShape | MovableListContainerShape | RecordContainerShape | TextContainerShape | TreeContainerShape;
|
|
166
166
|
type ContainerType = ContainerShape["_type"];
|
|
167
|
-
interface StringValueShape extends Shape<
|
|
167
|
+
interface StringValueShape<T extends string = string> extends Shape<T, T> {
|
|
168
168
|
readonly _type: "value";
|
|
169
169
|
readonly valueType: "string";
|
|
170
|
+
readonly options?: T[];
|
|
170
171
|
}
|
|
171
172
|
interface NumberValueShape extends Shape<number, number> {
|
|
172
173
|
readonly _type: "value";
|
|
@@ -236,7 +237,7 @@ declare const Shape: {
|
|
|
236
237
|
text: () => TextContainerShape;
|
|
237
238
|
tree: <T extends MapContainerShape>(shape: T) => TreeContainerShape;
|
|
238
239
|
plain: {
|
|
239
|
-
string: () => StringValueShape
|
|
240
|
+
string: <T extends string = string>(...options: T[]) => StringValueShape<T>;
|
|
240
241
|
number: () => NumberValueShape;
|
|
241
242
|
boolean: () => BooleanValueShape;
|
|
242
243
|
null: () => NullValueShape;
|
package/dist/index.js
CHANGED
|
@@ -62,7 +62,8 @@ function isValueShape(schema) {
|
|
|
62
62
|
"uint8array",
|
|
63
63
|
"object",
|
|
64
64
|
"record",
|
|
65
|
-
"array"
|
|
65
|
+
"array",
|
|
66
|
+
"union"
|
|
66
67
|
].includes(schema.valueType);
|
|
67
68
|
}
|
|
68
69
|
function isObjectValue(value) {
|
|
@@ -72,9 +73,7 @@ function isObjectValue(value) {
|
|
|
72
73
|
// src/conversion.ts
|
|
73
74
|
function convertTextInput(value) {
|
|
74
75
|
const text = new LoroText();
|
|
75
|
-
|
|
76
|
-
text.insert(0, value);
|
|
77
|
-
}
|
|
76
|
+
text.insert(0, value);
|
|
78
77
|
return text;
|
|
79
78
|
}
|
|
80
79
|
function convertCounterInput(value) {
|
|
@@ -702,7 +701,6 @@ var TextDraftNode = class extends DraftNode {
|
|
|
702
701
|
}
|
|
703
702
|
// Text methods
|
|
704
703
|
insert(index, content) {
|
|
705
|
-
if (content.length === 0) return;
|
|
706
704
|
this.container.insert(index, content);
|
|
707
705
|
}
|
|
708
706
|
delete(index, len) {
|
|
@@ -1093,6 +1091,20 @@ function mergeValue(shape, crdtValue, emptyValue) {
|
|
|
1093
1091
|
case "tree":
|
|
1094
1092
|
return crdtValue ?? emptyValue ?? [];
|
|
1095
1093
|
default:
|
|
1094
|
+
if (shape._type === "value" && shape.valueType === "object") {
|
|
1095
|
+
const crdtObj = crdtValue ?? {};
|
|
1096
|
+
const emptyObj = emptyValue ?? {};
|
|
1097
|
+
const result = { ...emptyObj };
|
|
1098
|
+
if (typeof crdtObj !== "object" || crdtObj === null) {
|
|
1099
|
+
return crdtValue ?? emptyValue;
|
|
1100
|
+
}
|
|
1101
|
+
for (const [key, propShape] of Object.entries(shape.shape)) {
|
|
1102
|
+
const propCrdt = crdtObj[key];
|
|
1103
|
+
const propEmpty = emptyObj[key];
|
|
1104
|
+
result[key] = mergeValue(propShape, propCrdt, propEmpty);
|
|
1105
|
+
}
|
|
1106
|
+
return result;
|
|
1107
|
+
}
|
|
1096
1108
|
return crdtValue ?? emptyValue;
|
|
1097
1109
|
}
|
|
1098
1110
|
}
|
|
@@ -1170,13 +1182,20 @@ function validateValue(value, schema, path = "") {
|
|
|
1170
1182
|
if (schema._type === "value") {
|
|
1171
1183
|
const valueSchema = schema;
|
|
1172
1184
|
switch (valueSchema.valueType) {
|
|
1173
|
-
case "string":
|
|
1185
|
+
case "string": {
|
|
1174
1186
|
if (typeof value !== "string") {
|
|
1175
1187
|
throw new Error(
|
|
1176
1188
|
`Expected string at path ${currentPath}, got ${typeof value}`
|
|
1177
1189
|
);
|
|
1178
1190
|
}
|
|
1191
|
+
const stringSchema = valueSchema;
|
|
1192
|
+
if (stringSchema.options && !stringSchema.options.includes(value)) {
|
|
1193
|
+
throw new Error(
|
|
1194
|
+
`Expected one of [${stringSchema.options.join(", ")}] at path ${currentPath}, got "${value}"`
|
|
1195
|
+
);
|
|
1196
|
+
}
|
|
1179
1197
|
return value;
|
|
1198
|
+
}
|
|
1180
1199
|
case "number":
|
|
1181
1200
|
if (typeof value !== "number") {
|
|
1182
1201
|
throw new Error(
|
|
@@ -1412,11 +1431,12 @@ var Shape = {
|
|
|
1412
1431
|
// "Last Write Wins", meaning there is no subtle convergent behavior here, just taking
|
|
1413
1432
|
// the most recent value based on the current available information.
|
|
1414
1433
|
plain: {
|
|
1415
|
-
string: () => ({
|
|
1434
|
+
string: (...options) => ({
|
|
1416
1435
|
_type: "value",
|
|
1417
1436
|
valueType: "string",
|
|
1418
|
-
_plain: "",
|
|
1419
|
-
_draft: ""
|
|
1437
|
+
_plain: options[0] ?? "",
|
|
1438
|
+
_draft: options[0] ?? "",
|
|
1439
|
+
options: options.length > 0 ? options : void 0
|
|
1420
1440
|
}),
|
|
1421
1441
|
number: () => ({
|
|
1422
1442
|
_type: "value",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/change.ts","../src/draft-nodes/base.ts","../src/draft-nodes/counter.ts","../src/conversion.ts","../src/utils/type-guards.ts","../src/draft-nodes/list-base.ts","../src/draft-nodes/list.ts","../src/draft-nodes/map.ts","../src/draft-nodes/movable-list.ts","../src/draft-nodes/record.ts","../src/draft-nodes/text.ts","../src/draft-nodes/tree.ts","../src/draft-nodes/utils.ts","../src/draft-nodes/doc.ts","../src/json-patch.ts","../src/overlay.ts","../src/validation.ts","../src/shape.ts"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noExplicitAny: fix later */\n\nimport { LoroDoc } from \"loro-crdt\"\nimport { DraftDoc } from \"./draft-nodes/doc.js\"\nimport {\n type JsonPatch,\n JsonPatchApplicator,\n type JsonPatchOperation,\n normalizePath,\n} from \"./json-patch.js\"\nimport { overlayEmptyState } from \"./overlay.js\"\nimport type { DocShape } from \"./shape.js\"\nimport type { Draft, InferPlainType } from \"./types.js\"\nimport { validateEmptyState } from \"./validation.js\"\n\n// Core TypedDoc abstraction around LoroDoc\nexport class TypedDoc<Shape extends DocShape> {\n constructor(\n private shape: Shape,\n private emptyState: InferPlainType<Shape>,\n private doc: LoroDoc = new LoroDoc(),\n ) {\n validateEmptyState(emptyState, shape)\n }\n\n get value(): InferPlainType<Shape> {\n const crdtValue = this.doc.toJSON()\n return overlayEmptyState(\n this.shape,\n crdtValue,\n this.emptyState,\n ) as InferPlainType<Shape>\n }\n\n change(fn: (draft: Draft<Shape>) => void): InferPlainType<Shape> {\n // Reuse existing DocumentDraft system with empty state integration\n const draft = new DraftDoc({\n shape: this.shape,\n emptyState: this.emptyState,\n doc: this.doc,\n })\n fn(draft as unknown as Draft<Shape>)\n draft.absorbPlainValues()\n this.doc.commit()\n return this.value\n }\n\n /**\n * Apply JSON Patch operations to the document\n *\n * @param patch - Array of JSON Patch operations (RFC 6902)\n * @param pathPrefix - Optional path prefix for scoped operations\n * @returns Updated document value\n *\n * @example\n * ```typescript\n * const result = typedDoc.applyPatch([\n * { op: 'add', path: '/users/0/name', value: 'Alice' },\n * { op: 'replace', path: '/settings/theme', value: 'dark' }\n * ])\n * ```\n */\n applyPatch(\n patch: JsonPatch,\n pathPrefix?: (string | number)[],\n ): InferPlainType<Shape> {\n return this.change(draft => {\n const applicator = new JsonPatchApplicator(draft)\n\n // Apply path prefix if provided\n const prefixedPatch = pathPrefix\n ? patch.map((op: JsonPatchOperation) => ({\n ...op,\n path: [...pathPrefix, ...normalizePath(op.path)],\n }))\n : patch\n\n applicator.applyPatch(prefixedPatch)\n })\n }\n\n // Expose underlying doc for advanced use cases\n get loroDoc(): LoroDoc {\n return this.doc\n }\n\n // Expose shape for internal use\n get docShape(): Shape {\n return this.shape\n }\n\n // Get raw CRDT value without overlay\n get rawValue(): any {\n return this.doc.toJSON()\n }\n}\n\n// Factory function for TypedLoroDoc\nexport function createTypedDoc<Shape extends DocShape>(\n shape: Shape,\n emptyState: InferPlainType<Shape>,\n existingDoc?: LoroDoc,\n): TypedDoc<Shape> {\n return new TypedDoc<Shape>(shape, emptyState, existingDoc || new LoroDoc())\n}\n","import type { ContainerShape, DocShape, ShapeToContainer } from \"../shape.js\"\nimport type { InferPlainType } from \"../types.js\"\n\nexport type DraftNodeParams<Shape extends DocShape | ContainerShape> = {\n shape: Shape\n emptyState?: InferPlainType<Shape>\n getContainer: () => ShapeToContainer<Shape>\n}\n\n// Base class for all draft nodes\nexport abstract class DraftNode<Shape extends DocShape | ContainerShape> {\n protected _cachedContainer?: ShapeToContainer<Shape>\n\n constructor(protected _params: DraftNodeParams<Shape>) {}\n\n abstract absorbPlainValues(): void\n\n protected get shape(): Shape {\n return this._params.shape\n }\n\n protected get emptyState(): InferPlainType<Shape> | undefined {\n return this._params.emptyState\n }\n\n protected get container(): ShapeToContainer<Shape> {\n if (!this._cachedContainer) {\n const container = this._params.getContainer()\n this._cachedContainer = container\n return container\n }\n return this._cachedContainer\n }\n}\n","import type { CounterContainerShape } from \"../shape.js\"\nimport { DraftNode } from \"./base.js\"\n\n// Counter draft node\nexport class CounterDraftNode extends DraftNode<CounterContainerShape> {\n absorbPlainValues() {\n // no plain values contained within\n }\n\n increment(value: number): void {\n this.container.increment(value)\n }\n\n decrement(value: number): void {\n this.container.decrement(value)\n }\n\n get value(): number {\n return this.container.value\n }\n}\n","import {\n type Container,\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n type Value,\n} from \"loro-crdt\"\nimport type {\n ArrayValueShape,\n ContainerOrValueShape,\n ListContainerShape,\n MapContainerShape,\n MovableListContainerShape,\n ObjectValueShape,\n RecordContainerShape,\n RecordValueShape,\n} from \"./shape.js\"\nimport {\n isContainer,\n isContainerShape,\n isObjectValue,\n isValueShape,\n} from \"./utils/type-guards.js\"\n\n/**\n * Converts string input to LoroText container\n */\nfunction convertTextInput(value: string): LoroText {\n const text = new LoroText()\n\n // TODO(duane): condition can be removed when https://github.com/loro-dev/loro/issues/872 is addressed\n if (value.length > 0) {\n text.insert(0, value)\n }\n\n return text\n}\n\n/**\n * Converts number input to LoroCounter container\n */\nfunction convertCounterInput(value: number): LoroCounter {\n const counter = new LoroCounter()\n counter.increment(value)\n return counter\n}\n\n/**\n * Converts array input to LoroList container\n */\nfunction convertListInput(\n value: Value[],\n shape: ListContainerShape | ArrayValueShape,\n // parentPath: string[],\n): LoroList | Value[] {\n if (!isContainerShape(shape)) {\n return value\n }\n\n const list = new LoroList()\n\n for (const item of value) {\n const convertedItem = convertInputToNode(item, shape.shape)\n if (isContainer(convertedItem)) {\n list.pushContainer(convertedItem)\n } else {\n list.push(convertedItem)\n }\n }\n\n return list\n}\n\n/**\n * Converts array input to LoroMovableList container\n */\nfunction convertMovableListInput(\n value: Value[],\n shape: MovableListContainerShape | ArrayValueShape,\n // parentPath: string[],\n): LoroMovableList | Value[] {\n if (!isContainerShape(shape)) {\n return value\n }\n\n const list = new LoroMovableList()\n\n for (const item of value) {\n const convertedItem = convertInputToNode(item, shape.shape)\n if (isContainer(convertedItem)) {\n list.pushContainer(convertedItem)\n } else {\n list.push(convertedItem)\n }\n }\n\n return list\n}\n\n/**\n * Converts object input to LoroMap container\n */\nfunction convertMapInput(\n value: { [key: string]: Value },\n shape: MapContainerShape | ObjectValueShape,\n): LoroMap | { [key: string]: Value } {\n if (!isContainerShape(shape)) {\n return value\n }\n\n const map = new LoroMap()\n for (const [k, v] of Object.entries(value)) {\n const nestedSchema = shape.shapes[k]\n if (nestedSchema) {\n const convertedValue = convertInputToNode(v, nestedSchema)\n if (isContainer(convertedValue)) {\n map.setContainer(k, convertedValue)\n } else {\n map.set(k, convertedValue)\n }\n } else {\n map.set(k, value)\n }\n }\n\n return map\n}\n\n/**\n * Converts object input to LoroMap container (Record)\n */\nfunction convertRecordInput(\n value: { [key: string]: Value },\n shape: RecordContainerShape | RecordValueShape,\n): LoroMap | { [key: string]: Value } {\n if (!isContainerShape(shape)) {\n return value\n }\n\n const map = new LoroMap()\n for (const [k, v] of Object.entries(value)) {\n const convertedValue = convertInputToNode(v, shape.shape)\n if (isContainer(convertedValue)) {\n map.setContainer(k, convertedValue)\n } else {\n map.set(k, convertedValue)\n }\n }\n\n return map\n}\n\n/**\n * Main conversion function that transforms input values to appropriate CRDT containers\n * based on schema definitions\n */\nexport function convertInputToNode<Shape extends ContainerOrValueShape>(\n value: Value,\n shape: Shape,\n): Container | Value {\n switch (shape._type) {\n case \"text\": {\n if (typeof value !== \"string\") {\n throw new Error(\"string expected\")\n }\n\n return convertTextInput(value)\n }\n case \"counter\": {\n if (typeof value !== \"number\") {\n throw new Error(\"number expected\")\n }\n\n return convertCounterInput(value)\n }\n case \"list\": {\n if (!Array.isArray(value)) {\n throw new Error(\"array expected\")\n }\n\n return convertListInput(value, shape)\n }\n case \"movableList\": {\n if (!Array.isArray(value)) {\n throw new Error(\"array expected\")\n }\n\n return convertMovableListInput(value, shape)\n }\n case \"map\": {\n if (!isObjectValue(value)) {\n throw new Error(\"object expected\")\n }\n\n return convertMapInput(value, shape)\n }\n case \"record\": {\n if (!isObjectValue(value)) {\n throw new Error(\"object expected\")\n }\n\n return convertRecordInput(value, shape)\n }\n case \"value\": {\n if (!isValueShape(shape)) {\n throw new Error(\"value expected\")\n }\n\n return value\n }\n\n case \"tree\":\n throw new Error(\"tree type unimplemented\")\n\n default:\n throw new Error(`unexpected type: ${(shape as Shape)._type}`)\n }\n}\n","import type {\n Container,\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n LoroTree,\n LoroTreeNode,\n Value,\n} from \"loro-crdt\"\nimport type {\n ContainerOrValueShape,\n ContainerShape,\n CounterContainerShape,\n ListContainerShape,\n MapContainerShape,\n MovableListContainerShape,\n RecordContainerShape,\n TextContainerShape,\n TreeContainerShape,\n ValueShape,\n} from \"../shape.js\"\n\nexport { isContainer, isContainerId } from \"loro-crdt\"\n\n/**\n * Type guard to check if a container is a LoroCounter\n */\nexport function isLoroCounter(container: Container): container is LoroCounter {\n return container.kind() === \"Counter\"\n}\n\n/**\n * Type guard to check if a container is a LoroList\n */\nexport function isLoroList(container: Container): container is LoroList {\n return container.kind() === \"List\"\n}\n\n/**\n * Type guard to check if a container is a LoroMap\n */\nexport function isLoroMap(container: Container): container is LoroMap {\n return container.kind() === \"Map\"\n}\n\n/**\n * Type guard to check if a container is a LoroMovableList\n */\nexport function isLoroMovableList(\n container: Container,\n): container is LoroMovableList {\n return container.kind() === \"MovableList\"\n}\n\n/**\n * Type guard to check if a container is a LoroText\n */\nexport function isLoroText(container: Container): container is LoroText {\n return container.kind() === \"Text\"\n}\n\n/**\n * Type guard to check if a container is a LoroTree\n */\nexport function isLoroTree(container: Container): container is LoroTree {\n return container.kind() === \"Tree\"\n}\n\n/**\n * Type guard to check if an object is a LoroTreeNode\n * Note: LoroTreeNode is not a Container, so we check for its specific properties\n */\nexport function isLoroTreeNode(obj: any): obj is LoroTreeNode {\n return (\n obj &&\n typeof obj === \"object\" &&\n typeof obj.id === \"string\" &&\n typeof obj.data === \"object\" &&\n typeof obj.parent === \"function\" &&\n typeof obj.children === \"function\" &&\n typeof obj.createNode === \"function\"\n )\n}\n\n/**\n * Type guard to ensure cached container matches expected type using kind() method\n */\nexport function assertContainerType<T extends Container>(\n cached: Container,\n expected: T,\n context: string = \"container operation\",\n): asserts cached is T {\n if (cached.kind() !== expected.kind()) {\n throw new Error(\n `Type safety violation in ${context}: ` +\n `cached container kind '${cached.kind()}' does not match ` +\n `expected kind '${expected.kind()}'`,\n )\n }\n\n // Additional safety check: ensure IDs match\n if (cached.id !== expected.id) {\n throw new Error(\n `Container ID mismatch in ${context}: ` +\n `cached ID '${cached.id}' does not match expected ID '${expected.id}'`,\n )\n }\n}\n\n/**\n * Type guard to check if a schema is for TextDraftNode\n */\nexport function isTextShape(\n schema: ContainerOrValueShape,\n): schema is TextContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"text\"\n}\n\n/**\n * Type guard to check if a schema is for CounterDraftNode\n */\nexport function isCounterShape(\n schema: ContainerOrValueShape,\n): schema is CounterContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"counter\"\n}\n\n/**\n * Type guard to check if a schema is for ListDraftNode\n */\nexport function isListShape(\n schema: ContainerOrValueShape,\n): schema is ListContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"list\"\n}\n\n/**\n * Type guard to check if a schema is for MovableListDraftNode\n */\nexport function isMovableListShape(\n schema: ContainerOrValueShape,\n): schema is MovableListContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"movableList\"\n}\n\n/**\n * Type guard to check if a schema is for MapDraftNode\n */\nexport function isMapShape(\n schema: ContainerOrValueShape,\n): schema is MapContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"map\"\n}\n\n/**\n * Type guard to check if a schema is for RecordDraftNode\n */\nexport function isRecordShape(\n schema: ContainerOrValueShape,\n): schema is RecordContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"record\"\n}\n\n/**\n * Type guard to check if a schema is for TreeDraftNode\n */\nexport function isTreeShape(\n schema: ContainerOrValueShape,\n): schema is TreeContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"tree\"\n}\n\nexport function isContainerShape(\n schema: ContainerOrValueShape,\n): schema is ContainerShape {\n return schema._type && schema._type !== \"value\"\n}\n\n/**\n * Type guard to check if a schema is any of the Value shapes\n */\nexport function isValueShape(\n schema: ContainerOrValueShape,\n): schema is ValueShape {\n return (\n schema._type === \"value\" &&\n [\n \"string\",\n \"number\",\n \"boolean\",\n \"null\",\n \"undefined\",\n \"uint8array\",\n \"object\",\n \"record\",\n \"array\",\n ].includes(schema.valueType)\n )\n}\n\nexport function isObjectValue(value: Value): value is { [key: string]: Value } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Uint8Array)\n )\n}\n","import type { Container, LoroList, LoroMovableList } from \"loro-crdt\"\nimport { convertInputToNode } from \"../conversion.js\"\nimport type {\n ContainerOrValueShape,\n ContainerShape,\n ListContainerShape,\n MovableListContainerShape,\n} from \"../shape.js\"\nimport { isContainer, isValueShape } from \"../utils/type-guards.js\"\nimport { DraftNode, type DraftNodeParams } from \"./base.js\"\nimport { createContainerDraftNode } from \"./utils.js\"\n\n// Shared logic for list operations\nexport abstract class ListDraftNodeBase<\n NestedShape extends ContainerOrValueShape,\n Item = NestedShape[\"_plain\"],\n DraftItem = NestedShape[\"_draft\"],\n> extends DraftNode<any> {\n // Cache for items returned by array methods to track mutations\n private itemCache = new Map<number, any>()\n\n protected get container(): LoroList | LoroMovableList {\n return super.container as LoroList | LoroMovableList\n }\n\n protected get shape():\n | ListContainerShape<NestedShape>\n | MovableListContainerShape<NestedShape> {\n return super.shape as\n | ListContainerShape<NestedShape>\n | MovableListContainerShape<NestedShape>\n }\n\n absorbPlainValues() {\n // Critical function: absorb mutated plain values back into Loro containers\n // This is called at the end of change() to persist mutations made to plain objects\n for (const [index, cachedItem] of this.itemCache.entries()) {\n if (cachedItem) {\n if (isValueShape(this.shape.shape)) {\n // For value shapes, delegate to subclass-specific absorption logic\n this.absorbValueAtIndex(index, cachedItem)\n } else {\n // For container shapes, the item should be a draft node that handles its own absorption\n if (\n cachedItem &&\n typeof cachedItem === \"object\" &&\n \"absorbPlainValues\" in cachedItem\n ) {\n ;(cachedItem as any).absorbPlainValues()\n }\n }\n }\n }\n\n // Clear the cache after absorbing values\n this.itemCache.clear()\n }\n\n // Abstract method to be implemented by subclasses\n // Each subclass knows how to handle its specific container type\n protected abstract absorbValueAtIndex(index: number, value: any): void\n\n protected insertWithConversion(index: number, item: Item): void {\n const convertedItem = convertInputToNode(item as any, this.shape.shape)\n if (isContainer(convertedItem)) {\n this.container.insertContainer(index, convertedItem)\n } else {\n this.container.insert(index, convertedItem)\n }\n }\n\n protected pushWithConversion(item: Item): void {\n const convertedItem = convertInputToNode(item as any, this.shape.shape)\n if (isContainer(convertedItem)) {\n this.container.pushContainer(convertedItem)\n } else {\n this.container.push(convertedItem)\n }\n }\n\n getDraftNodeParams(\n index: number,\n shape: ContainerShape,\n ): DraftNodeParams<ContainerShape> {\n return {\n shape,\n emptyState: undefined, // List items don't have empty state\n getContainer: () => {\n const containerItem = this.container.get(index)\n if (!containerItem || !isContainer(containerItem)) {\n throw new Error(`No container found at index ${index}`)\n }\n return containerItem\n },\n }\n }\n\n // Get item for predicate functions - always returns plain Item for filtering logic\n protected getPredicateItem(index: number): Item {\n // CRITICAL FIX: For predicates to work correctly with mutations,\n // we need to check if there's a cached (mutated) version first\n const cachedItem = this.itemCache.get(index)\n if (cachedItem && isValueShape(this.shape.shape)) {\n // For value shapes, if we have a cached item, use it so predicates see mutations\n return cachedItem as Item\n }\n\n const containerItem = this.container.get(index)\n if (containerItem === undefined) {\n return undefined as Item\n }\n\n if (isValueShape(this.shape.shape)) {\n // For value shapes, return the plain value directly\n return containerItem as Item\n } else {\n // For container shapes, we need to return the plain object representation\n // This allows predicates to access nested properties like article.metadata.author\n if (isContainer(containerItem)) {\n // Convert container to plain object for predicate logic\n // Handle different container types that may not have toJSON method\n if (\n typeof containerItem === \"object\" &&\n containerItem !== null &&\n \"toJSON\" in containerItem\n ) {\n return (containerItem as any).toJSON() as Item\n } else if (\n typeof containerItem === \"object\" &&\n containerItem !== null &&\n \"getShallowValue\" in containerItem\n ) {\n // For containers like LoroCounter that don't have toJSON but have getShallowValue\n return (containerItem as any).getShallowValue() as Item\n } else {\n // Fallback for other container types\n return containerItem as Item\n }\n }\n return containerItem as Item\n }\n }\n\n // Get item for return values - returns DraftItem that can be mutated\n protected getDraftItem(index: number): DraftItem {\n // Check if we already have a cached item for this index\n let cachedItem = this.itemCache.get(index)\n if (cachedItem) {\n return cachedItem\n }\n\n // Get the raw container item\n const containerItem = this.container.get(index)\n if (containerItem === undefined) {\n return undefined as DraftItem\n }\n\n if (isValueShape(this.shape.shape)) {\n // For value shapes, we need to ensure mutations persist\n // The key insight: we must return the SAME object for the same index\n // so that mutations to filtered/found items persist back to the cache\n if (typeof containerItem === \"object\" && containerItem !== null) {\n // Create a deep copy for objects so mutations can be tracked\n // IMPORTANT: Only create the copy once, then always return the same cached object\n cachedItem = JSON.parse(JSON.stringify(containerItem))\n } else {\n // For primitives, just use the value directly\n cachedItem = containerItem\n }\n this.itemCache.set(index, cachedItem)\n return cachedItem as DraftItem\n } else {\n // For container shapes, create a proper draft node using the new pattern\n cachedItem = createContainerDraftNode(\n this.getDraftNodeParams(index, this.shape.shape as ContainerShape),\n )\n this.itemCache.set(index, cachedItem)\n return cachedItem as DraftItem\n }\n }\n\n // Array-like methods for better developer experience\n // DUAL INTERFACE: Predicates get Item (plain data), return values are DraftItem (mutable)\n\n find(\n predicate: (item: Item, index: number) => boolean,\n ): DraftItem | undefined {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (predicate(predicateItem, i)) {\n return this.getDraftItem(i) // Return mutable draft item\n }\n }\n return undefined\n }\n\n findIndex(predicate: (item: Item, index: number) => boolean): number {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (predicate(predicateItem, i)) {\n return i\n }\n }\n return -1\n }\n\n map<ReturnType>(\n callback: (item: Item, index: number) => ReturnType,\n ): ReturnType[] {\n const result: ReturnType[] = []\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n result.push(callback(predicateItem, i))\n }\n return result\n }\n\n filter(predicate: (item: Item, index: number) => boolean): DraftItem[] {\n const result: DraftItem[] = []\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (predicate(predicateItem, i)) {\n result.push(this.getDraftItem(i)) // Return mutable draft items\n }\n }\n return result\n }\n\n forEach(callback: (item: Item, index: number) => void): void {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n callback(predicateItem, i)\n }\n }\n\n some(predicate: (item: Item, index: number) => boolean): boolean {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (predicate(predicateItem, i)) {\n return true\n }\n }\n return false\n }\n\n every(predicate: (item: Item, index: number) => boolean): boolean {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (!predicate(predicateItem, i)) {\n return false\n }\n }\n return true\n }\n\n insert(index: number, item: Item): void {\n // Update cache indices before performing the insert operation\n this.updateCacheForInsert(index)\n this.insertWithConversion(index, item)\n }\n\n delete(index: number, len: number): void {\n // Update cache indices before performing the delete operation\n this.updateCacheForDelete(index, len)\n this.container.delete(index, len)\n }\n\n push(item: Item): void {\n this.pushWithConversion(item)\n }\n\n pushContainer(container: Container): Container {\n return this.container.pushContainer(container)\n }\n\n insertContainer(index: number, container: Container): Container {\n return this.container.insertContainer(index, container)\n }\n\n get(index: number): DraftItem {\n return this.getDraftItem(index)\n }\n\n toArray(): Item[] {\n return this.container.toArray() as Item[]\n }\n\n get length(): number {\n return this.container.length\n }\n\n // Update cache indices when items are deleted\n private updateCacheForDelete(deleteIndex: number, deleteLen: number): void {\n const newCache = new Map<number, any>()\n\n for (const [cachedIndex, cachedItem] of this.itemCache.entries()) {\n if (cachedIndex < deleteIndex) {\n // Items before the deletion point keep their indices\n newCache.set(cachedIndex, cachedItem)\n } else if (cachedIndex >= deleteIndex + deleteLen) {\n // Items after the deletion range shift down by deleteLen\n newCache.set(cachedIndex - deleteLen, cachedItem)\n }\n // Items within the deletion range are removed from cache\n }\n\n this.itemCache = newCache\n }\n\n // Update cache indices when items are inserted\n private updateCacheForInsert(insertIndex: number): void {\n const newCache = new Map<number, any>()\n\n for (const [cachedIndex, cachedItem] of this.itemCache.entries()) {\n if (cachedIndex < insertIndex) {\n // Items before the insertion point keep their indices\n newCache.set(cachedIndex, cachedItem)\n } else {\n // Items at or after the insertion point shift up by 1\n newCache.set(cachedIndex + 1, cachedItem)\n }\n }\n\n this.itemCache = newCache\n }\n}\n","import type { LoroList } from \"loro-crdt\"\nimport type { ContainerOrValueShape } from \"../shape.js\"\nimport { ListDraftNodeBase } from \"./list-base.js\"\n\n// List draft node\nexport class ListDraftNode<\n NestedShape extends ContainerOrValueShape,\n> extends ListDraftNodeBase<NestedShape> {\n protected get container(): LoroList {\n return super.container as LoroList\n }\n\n protected absorbValueAtIndex(index: number, value: any): void {\n // LoroList doesn't have set method, need to delete and insert\n this.container.delete(index, 1)\n this.container.insert(index, value)\n }\n}\n","import {\n type Container,\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n LoroTree,\n type Value,\n} from \"loro-crdt\"\nimport type {\n ContainerOrValueShape,\n ContainerShape,\n MapContainerShape,\n ValueShape,\n} from \"../shape.js\"\nimport { isContainerShape, isValueShape } from \"../utils/type-guards.js\"\nimport { DraftNode, type DraftNodeParams } from \"./base.js\"\nimport { createContainerDraftNode } from \"./utils.js\"\n\nconst containerConstructor = {\n counter: LoroCounter,\n list: LoroList,\n map: LoroMap,\n movableList: LoroMovableList,\n record: LoroMap,\n text: LoroText,\n tree: LoroTree,\n} as const\n\n// Map draft node\nexport class MapDraftNode<\n NestedShapes extends Record<string, ContainerOrValueShape>,\n> extends DraftNode<any> {\n private propertyCache = new Map<string, DraftNode<ContainerShape> | Value>()\n\n constructor(params: DraftNodeParams<MapContainerShape<NestedShapes>>) {\n super(params)\n this.createLazyProperties()\n }\n\n protected get shape(): MapContainerShape<NestedShapes> {\n return super.shape as MapContainerShape<NestedShapes>\n }\n\n protected get container(): LoroMap {\n return super.container as LoroMap\n }\n\n absorbPlainValues() {\n for (const [key, node] of this.propertyCache.entries()) {\n if (node instanceof DraftNode) {\n // Contains a DraftNode, not a plain Value: keep recursing\n node.absorbPlainValues()\n continue\n }\n\n // Plain value!\n this.container.set(key, node)\n }\n }\n\n getDraftNodeParams<S extends ContainerShape>(\n key: string,\n shape: S,\n ): DraftNodeParams<ContainerShape> {\n const emptyState = (this.emptyState as any)?.[key]\n\n const LoroContainer = containerConstructor[shape._type]\n\n return {\n shape,\n emptyState,\n getContainer: () =>\n this.container.getOrCreateContainer(key, new (LoroContainer as any)()),\n }\n }\n\n getOrCreateNode<Shape extends ContainerShape | ValueShape>(\n key: string,\n shape: Shape,\n ): Shape extends ContainerShape ? DraftNode<Shape> : Value {\n let node = this.propertyCache.get(key)\n if (!node) {\n if (isContainerShape(shape)) {\n node = createContainerDraftNode(this.getDraftNodeParams(key, shape))\n } else {\n // For value shapes, first try to get the value from the container\n const containerValue = this.container.get(key)\n if (containerValue !== undefined) {\n node = containerValue as Value\n } else {\n // Only fall back to empty state if the container doesn't have the value\n const emptyState = (this.emptyState as any)?.[key]\n if (!emptyState) {\n throw new Error(\"empty state required\")\n }\n node = emptyState as Value\n }\n }\n if (!node) throw new Error(\"no container made\")\n this.propertyCache.set(key, node)\n }\n\n return node as Shape extends ContainerShape ? DraftNode<Shape> : Value\n }\n\n private createLazyProperties(): void {\n for (const key in this.shape.shapes) {\n const shape = this.shape.shapes[key]\n Object.defineProperty(this, key, {\n get: () => this.getOrCreateNode(key, shape),\n set: isValueShape(shape)\n ? value => {\n // console.log(\"set value\", value)\n this.container.set(key, value)\n }\n : undefined,\n })\n }\n }\n\n // TOOD(duane): return correct type here\n get(key: string): any {\n return this.container.get(key)\n }\n\n set(key: string, value: Value): void {\n this.container.set(key, value)\n }\n\n setContainer<C extends Container>(key: string, container: C): C {\n return this.container.setContainer(key, container)\n }\n\n delete(key: string): void {\n this.container.delete(key)\n }\n\n has(key: string): boolean {\n // LoroMap doesn't have a has method, so we check if get returns undefined\n return this.container.get(key) !== undefined\n }\n\n keys(): string[] {\n return this.container.keys()\n }\n\n values(): any[] {\n return this.container.values()\n }\n\n get size(): number {\n return this.container.size\n }\n}\n","import type { Container, LoroMovableList } from \"loro-crdt\"\nimport type { ContainerOrValueShape } from \"../shape.js\"\nimport { ListDraftNodeBase } from \"./list-base.js\"\n\n// Movable list draft node\nexport class MovableListDraftNode<\n NestedShape extends ContainerOrValueShape,\n Item = NestedShape[\"_plain\"],\n> extends ListDraftNodeBase<NestedShape> {\n protected get container(): LoroMovableList {\n return super.container as LoroMovableList\n }\n\n protected absorbValueAtIndex(index: number, value: any): void {\n // LoroMovableList has set method\n this.container.set(index, value)\n }\n\n move(from: number, to: number): void {\n this.container.move(from, to)\n }\n\n set(index: number, item: Exclude<Item, Container>) {\n return this.container.set(index, item)\n }\n}\n","import {\n type Container,\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n LoroTree,\n type Value,\n} from \"loro-crdt\"\nimport type {\n ContainerOrValueShape,\n ContainerShape,\n RecordContainerShape,\n} from \"../shape.js\"\nimport type { InferDraftType } from \"../types.js\"\nimport { isContainerShape, isValueShape } from \"../utils/type-guards.js\"\nimport { DraftNode, type DraftNodeParams } from \"./base.js\"\nimport { createContainerDraftNode } from \"./utils.js\"\n\nconst containerConstructor = {\n counter: LoroCounter,\n list: LoroList,\n map: LoroMap,\n movableList: LoroMovableList,\n record: LoroMap,\n text: LoroText,\n tree: LoroTree,\n} as const\n\n// Record draft node\nexport class RecordDraftNode<\n NestedShape extends ContainerOrValueShape,\n> extends DraftNode<any> {\n private nodeCache = new Map<string, DraftNode<ContainerShape> | Value>()\n\n constructor(params: DraftNodeParams<RecordContainerShape<NestedShape>>) {\n super(params)\n // We don't need to create lazy properties because keys are dynamic\n // But we could use a Proxy if we wanted property access syntax like record.key\n // However, for now let's stick to get/set methods or maybe Proxy for better DX?\n // The requirement says \"records with uniform specific key type and value\".\n // Usually records are accessed via keys.\n // If we want `draft.record.key`, we need a Proxy.\n // biome-ignore lint/correctness/noConstructorReturn: Proxy return is intentional\n return new Proxy(this, {\n get: (target, prop) => {\n if (typeof prop === \"string\" && !(prop in target)) {\n return target.get(prop)\n }\n return Reflect.get(target, prop)\n },\n set: (target, prop, value) => {\n if (typeof prop === \"string\" && !(prop in target)) {\n target.set(prop, value)\n return true\n }\n return Reflect.set(target, prop, value)\n },\n deleteProperty: (target, prop) => {\n if (typeof prop === \"string\" && !(prop in target)) {\n target.delete(prop)\n return true\n }\n return Reflect.deleteProperty(target, prop)\n },\n ownKeys: target => {\n return target.keys()\n },\n getOwnPropertyDescriptor: (target, prop) => {\n if (typeof prop === \"string\" && target.has(prop)) {\n return {\n configurable: true,\n enumerable: true,\n value: target.get(prop),\n }\n }\n return Reflect.getOwnPropertyDescriptor(target, prop)\n },\n })\n }\n\n protected get shape(): RecordContainerShape<NestedShape> {\n return super.shape as RecordContainerShape<NestedShape>\n }\n\n protected get container(): LoroMap {\n return super.container as LoroMap\n }\n\n absorbPlainValues() {\n for (const [key, node] of this.nodeCache.entries()) {\n if (node instanceof DraftNode) {\n // Contains a DraftNode, not a plain Value: keep recursing\n node.absorbPlainValues()\n continue\n }\n\n // Plain value!\n this.container.set(key, node)\n }\n }\n\n getDraftNodeParams<S extends ContainerShape>(\n key: string,\n shape: S,\n ): DraftNodeParams<ContainerShape> {\n const emptyState = (this.emptyState as any)?.[key]\n\n const LoroContainer = containerConstructor[shape._type]\n\n return {\n shape,\n emptyState,\n getContainer: () =>\n this.container.getOrCreateContainer(key, new (LoroContainer as any)()),\n }\n }\n\n getOrCreateNode(key: string): InferDraftType<NestedShape> {\n let node = this.nodeCache.get(key)\n if (!node) {\n const shape = this.shape.shape\n if (isContainerShape(shape)) {\n node = createContainerDraftNode(\n this.getDraftNodeParams(key, shape as ContainerShape),\n )\n } else {\n // For value shapes, first try to get the value from the container\n const containerValue = this.container.get(key)\n if (containerValue !== undefined) {\n node = containerValue as Value\n } else {\n // Only fall back to empty state if the container doesn't have the value\n const emptyState = (this.emptyState as any)?.[key]\n // For records, empty state might not have the key, which is fine?\n // But if we are accessing it, maybe we expect it to exist or be created?\n // If it's a value type, we can't really \"create\" it without a value.\n // So if it's undefined in container and empty state, we return undefined?\n // But the return type expects Value.\n // Let's check MapDraftNode.\n // MapDraftNode throws \"empty state required\" if not found.\n // But for Record, keys are dynamic.\n if (emptyState === undefined) {\n // If it's a value type and not in container or empty state,\n // we should probably return undefined if the type allows it,\n // or maybe the default value for that type?\n // But we don't have a default value generator for shapes.\n // Actually Shape.plain.* factories have _plain and _draft which are defaults.\n node = (shape as any)._plain\n } else {\n node = emptyState as Value\n }\n }\n }\n if (node !== undefined) {\n this.nodeCache.set(key, node)\n }\n }\n\n return node as any\n }\n\n get(key: string): InferDraftType<NestedShape> {\n return this.getOrCreateNode(key)\n }\n\n set(key: string, value: any): void {\n if (isValueShape(this.shape.shape)) {\n this.container.set(key, value)\n // Update cache if needed?\n // MapDraftNode updates container directly for values.\n // But we also cache values in nodeCache for consistency?\n // MapDraftNode doesn't cache values in propertyCache if they are set via setter?\n // Actually MapDraftNode setter:\n // set: isValueShape(shape) ? value => this.container.set(key, value) : undefined\n // It doesn't update propertyCache.\n // But getOrCreateNode checks propertyCache first.\n // So if we set it, we should probably update propertyCache or clear it for that key.\n this.nodeCache.set(key, value)\n } else {\n // For containers, we can't set them directly usually.\n // But if the user passes a plain object that matches the shape, maybe we should convert it?\n // But typically we modify the draft node.\n throw new Error(\n \"Cannot set container directly, modify the draft node instead\",\n )\n }\n }\n\n setContainer<C extends Container>(key: string, container: C): C {\n return this.container.setContainer(key, container)\n }\n\n delete(key: string): void {\n this.container.delete(key)\n this.nodeCache.delete(key)\n }\n\n has(key: string): boolean {\n return this.container.get(key) !== undefined\n }\n\n keys(): string[] {\n return this.container.keys()\n }\n\n values(): any[] {\n return this.container.values()\n }\n\n get size(): number {\n return this.container.size\n }\n}\n","import type { TextContainerShape } from \"../shape.js\"\nimport { DraftNode } from \"./base.js\"\n\n// Text draft node\nexport class TextDraftNode extends DraftNode<TextContainerShape> {\n absorbPlainValues() {\n // no plain values contained within\n }\n\n // Text methods\n insert(index: number, content: string): void {\n // TODO(duane): condition can be removed when https://github.com/loro-dev/loro/issues/872 is addressed\n if (content.length === 0) return\n this.container.insert(index, content)\n }\n\n delete(index: number, len: number): void {\n this.container.delete(index, len)\n }\n\n toString(): string {\n return this.container.toString()\n }\n\n update(text: string): void {\n this.container.update(text)\n }\n\n mark(range: { start: number; end: number }, key: string, value: any): void {\n this.container.mark(range, key, value)\n }\n\n unmark(range: { start: number; end: number }, key: string): void {\n this.container.unmark(range, key)\n }\n\n toDelta(): any[] {\n return this.container.toDelta()\n }\n\n applyDelta(delta: any[]): void {\n this.container.applyDelta(delta)\n }\n\n get length(): number {\n return this.container.length\n }\n}\n","import type { TreeContainerShape } from \"../shape.js\"\nimport { DraftNode } from \"./base.js\"\n\n// Tree draft node\nexport class TreeDraftNode<T extends TreeContainerShape> extends DraftNode<T> {\n absorbPlainValues() {\n // TODO(duane): implement for trees\n }\n\n createNode(parent?: any, index?: number): any {\n return this.container.createNode(parent, index)\n }\n\n move(target: any, parent?: any, index?: number): void {\n this.container.move(target, parent, index)\n }\n\n delete(target: any): void {\n this.container.delete(target)\n }\n\n has(target: any): boolean {\n return this.container.has(target)\n }\n\n getNodeByID(id: any): any {\n return this.container.getNodeByID\n ? this.container.getNodeByID(id)\n : undefined\n }\n}\n","import type {\n ContainerShape,\n CounterContainerShape,\n ListContainerShape,\n MapContainerShape,\n MovableListContainerShape,\n RecordContainerShape,\n TextContainerShape,\n TreeContainerShape,\n} from \"../shape.js\"\nimport type { DraftNode, DraftNodeParams } from \"./base.js\"\nimport { CounterDraftNode } from \"./counter.js\"\nimport { ListDraftNode } from \"./list.js\"\nimport { MapDraftNode } from \"./map.js\"\nimport { MovableListDraftNode } from \"./movable-list.js\"\nimport { RecordDraftNode } from \"./record.js\"\nimport { TextDraftNode } from \"./text.js\"\nimport { TreeDraftNode } from \"./tree.js\"\n\n// Generic catch-all overload\nexport function createContainerDraftNode<T extends ContainerShape>(\n params: DraftNodeParams<T>,\n): DraftNode<T>\n\n// Implementation\nexport function createContainerDraftNode(\n params: DraftNodeParams<ContainerShape>,\n): DraftNode<ContainerShape> {\n switch (params.shape._type) {\n case \"counter\":\n return new CounterDraftNode(\n params as DraftNodeParams<CounterContainerShape>,\n )\n case \"list\":\n return new ListDraftNode(params as DraftNodeParams<ListContainerShape>)\n case \"map\":\n return new MapDraftNode(params as DraftNodeParams<MapContainerShape>)\n case \"movableList\":\n return new MovableListDraftNode(\n params as DraftNodeParams<MovableListContainerShape>,\n )\n case \"record\":\n return new RecordDraftNode(\n params as DraftNodeParams<RecordContainerShape>,\n )\n case \"text\":\n return new TextDraftNode(params as DraftNodeParams<TextContainerShape>)\n case \"tree\":\n return new TreeDraftNode(params as DraftNodeParams<TreeContainerShape>)\n default:\n throw new Error(\n `Unknown container type: ${(params.shape as ContainerShape)._type}`,\n )\n }\n}\n","import type { LoroDoc } from \"loro-crdt\"\nimport type { InferPlainType } from \"../index.js\"\nimport type { ContainerShape, DocShape } from \"../shape.js\"\nimport { DraftNode, type DraftNodeParams } from \"./base.js\"\nimport { createContainerDraftNode } from \"./utils.js\"\n\nconst containerGetter = {\n counter: \"getCounter\",\n list: \"getList\",\n map: \"getMap\",\n movableList: \"getMovableList\",\n record: \"getMap\",\n text: \"getText\",\n tree: \"getTree\",\n} as const\n\n// Draft Document class -- the actual object passed to the change `mutation` function\nexport class DraftDoc<Shape extends DocShape> extends DraftNode<Shape> {\n private doc: LoroDoc\n private propertyCache = new Map<string, DraftNode<ContainerShape>>()\n private requiredEmptyState!: InferPlainType<Shape>\n\n constructor(\n _params: Omit<DraftNodeParams<Shape>, \"getContainer\"> & { doc: LoroDoc },\n ) {\n super({\n ..._params,\n getContainer: () => {\n throw new Error(\"can't get container on DraftDoc\")\n },\n })\n if (!_params.emptyState) throw new Error(\"emptyState required\")\n this.doc = _params.doc\n this.requiredEmptyState = _params.emptyState\n this.createLazyProperties()\n }\n\n getDraftNodeParams<S extends ContainerShape>(\n key: string,\n shape: S,\n ): DraftNodeParams<ContainerShape> {\n const getter = this.doc[containerGetter[shape._type]].bind(this.doc)\n\n return {\n shape,\n emptyState: this.requiredEmptyState[key],\n getContainer: () => getter(key),\n }\n }\n\n getOrCreateDraftNode(\n key: string,\n shape: ContainerShape,\n ): DraftNode<ContainerShape> {\n let node = this.propertyCache.get(key)\n\n if (!node) {\n node = createContainerDraftNode(this.getDraftNodeParams(key, shape))\n this.propertyCache.set(key, node)\n }\n\n return node\n }\n\n private createLazyProperties(): void {\n for (const key in this.shape.shapes) {\n const shape = this.shape.shapes[key]\n Object.defineProperty(this, key, {\n get: () => this.getOrCreateDraftNode(key, shape),\n })\n }\n }\n\n absorbPlainValues(): void {\n // By iterating over the propertyCache, we achieve a small optimization\n // by only absorbing values that have been 'touched' in some way\n for (const [, node] of this.propertyCache.entries()) {\n node.absorbPlainValues()\n }\n }\n}\n","/** biome-ignore-all lint/suspicious/noExplicitAny: JSON Patch values can be any type */\n\nimport type { DocShape } from \"./shape.js\"\nimport type { Draft } from \"./types.js\"\n\n// =============================================================================\n// JSON PATCH TYPES - Discriminated Union for Type Safety\n// =============================================================================\n\nexport type JsonPatchAddOperation = {\n op: \"add\"\n path: string | (string | number)[]\n value: any\n}\n\nexport type JsonPatchRemoveOperation = {\n op: \"remove\"\n path: string | (string | number)[]\n}\n\nexport type JsonPatchReplaceOperation = {\n op: \"replace\"\n path: string | (string | number)[]\n value: any\n}\n\nexport type JsonPatchMoveOperation = {\n op: \"move\"\n path: string | (string | number)[]\n from: string | (string | number)[]\n}\n\nexport type JsonPatchCopyOperation = {\n op: \"copy\"\n path: string | (string | number)[]\n from: string | (string | number)[]\n}\n\nexport type JsonPatchTestOperation = {\n op: \"test\"\n path: string | (string | number)[]\n value: any\n}\n\nexport type JsonPatchOperation =\n | JsonPatchAddOperation\n | JsonPatchRemoveOperation\n | JsonPatchReplaceOperation\n | JsonPatchMoveOperation\n | JsonPatchCopyOperation\n | JsonPatchTestOperation\n\nexport type JsonPatch = JsonPatchOperation[]\n\n// =============================================================================\n// PATH NAVIGATION UTILITIES\n// =============================================================================\n\n/**\n * Normalize JSON Pointer string to path array\n * Handles RFC 6901 escaping: ~1 -> /, ~0 -> ~\n */\nexport function normalizePath(\n path: string | (string | number)[],\n): (string | number)[] {\n if (Array.isArray(path)) {\n return path\n }\n\n // Handle JSON Pointer format (RFC 6901)\n if (path.startsWith(\"/\")) {\n return path\n .slice(1) // Remove leading slash\n .split(\"/\")\n .map(segment => {\n // Handle JSON Pointer escaping\n const unescaped = segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\")\n // Try to parse as number for array indices\n const asNumber = Number(unescaped)\n return Number.isInteger(asNumber) && asNumber >= 0\n ? asNumber\n : unescaped\n })\n }\n\n // Handle simple dot notation or single segment\n return path.split(\".\").map(segment => {\n const asNumber = Number(segment)\n return Number.isInteger(asNumber) && asNumber >= 0 ? asNumber : segment\n })\n}\n\n/**\n * Navigate to a target path using natural DraftNode property access\n * This follows the existing patterns from the test suite\n */\nfunction navigateToPath<T extends DocShape>(\n draft: Draft<T>,\n path: (string | number)[],\n): { parent: any; key: string | number } {\n if (path.length === 0) {\n throw new Error(\"Cannot navigate to empty path\")\n }\n\n let current = draft as any\n\n // Navigate to parent of target\n for (let i = 0; i < path.length - 1; i++) {\n const segment = path[i]\n\n if (typeof segment === \"string\") {\n // Use natural property access - this leverages existing DraftNode lazy creation\n current = current[segment]\n if (current === undefined) {\n throw new Error(`Cannot navigate to path segment: ${segment}`)\n }\n } else if (typeof segment === \"number\") {\n // List/array access using get() method (following existing patterns)\n if (current.get && typeof current.get === \"function\") {\n current = current.get(segment)\n if (current === undefined) {\n throw new Error(`List index ${segment} does not exist`)\n }\n } else {\n throw new Error(`Cannot use numeric index ${segment} on non-list`)\n }\n } else {\n throw new Error(`Invalid path segment type: ${typeof segment}`)\n }\n }\n\n const targetKey = path[path.length - 1]\n return { parent: current, key: targetKey }\n}\n\n/**\n * Get value at path using natural DraftNode access patterns\n */\nfunction getValueAtPath<T extends DocShape>(\n draft: Draft<T>,\n path: (string | number)[],\n): any {\n if (path.length === 0) {\n return draft\n }\n\n const { parent, key } = navigateToPath(draft, path)\n\n if (typeof key === \"string\") {\n // Use natural property access or get() method\n if (parent.get && typeof parent.get === \"function\") {\n return parent.get(key)\n }\n return parent[key]\n } else if (typeof key === \"number\") {\n // List access using get() method\n if (parent.get && typeof parent.get === \"function\") {\n return parent.get(key)\n }\n throw new Error(`Cannot use numeric index ${key} on non-list`)\n }\n\n throw new Error(`Invalid key type: ${typeof key}`)\n}\n\n// =============================================================================\n// OPERATION HANDLERS - Following existing DraftNode patterns\n// =============================================================================\n\n/**\n * Handle 'add' operation using existing DraftNode methods\n */\nfunction handleAdd<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchAddOperation,\n): void {\n const path = normalizePath(operation.path)\n const { parent, key } = navigateToPath(draft, path)\n\n if (typeof key === \"string\") {\n // Map-like operations - use natural assignment or set() method\n if (parent.set && typeof parent.set === \"function\") {\n parent.set(key, operation.value)\n } else {\n // Natural property assignment (follows existing test patterns)\n parent[key] = operation.value\n }\n } else if (typeof key === \"number\") {\n // List operations - use insert() method (follows existing patterns)\n if (parent.insert && typeof parent.insert === \"function\") {\n parent.insert(key, operation.value)\n } else {\n throw new Error(`Cannot insert at numeric index ${key} on non-list`)\n }\n } else {\n throw new Error(`Invalid key type: ${typeof key}`)\n }\n}\n\n/**\n * Handle 'remove' operation using existing DraftNode methods\n */\nfunction handleRemove<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchRemoveOperation,\n): void {\n const path = normalizePath(operation.path)\n const { parent, key } = navigateToPath(draft, path)\n\n if (typeof key === \"string\") {\n // Map-like operations - use delete() method (follows existing patterns)\n if (parent.delete && typeof parent.delete === \"function\") {\n parent.delete(key)\n } else {\n delete parent[key]\n }\n } else if (typeof key === \"number\") {\n // List operations - use delete() method with count (follows existing patterns)\n if (parent.delete && typeof parent.delete === \"function\") {\n parent.delete(key, 1)\n } else {\n throw new Error(`Cannot remove at numeric index ${key} on non-list`)\n }\n } else {\n throw new Error(`Invalid key type: ${typeof key}`)\n }\n}\n\n/**\n * Handle 'replace' operation using existing DraftNode methods\n */\nfunction handleReplace<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchReplaceOperation,\n): void {\n const path = normalizePath(operation.path)\n const { parent, key } = navigateToPath(draft, path)\n\n if (typeof key === \"string\") {\n // Map-like operations - use set() method or natural assignment\n if (parent.set && typeof parent.set === \"function\") {\n parent.set(key, operation.value)\n } else {\n parent[key] = operation.value\n }\n } else if (typeof key === \"number\") {\n // List operations - delete then insert (follows existing patterns)\n if (\n parent.delete &&\n parent.insert &&\n typeof parent.delete === \"function\" &&\n typeof parent.insert === \"function\"\n ) {\n parent.delete(key, 1)\n parent.insert(key, operation.value)\n } else {\n throw new Error(`Cannot replace at numeric index ${key} on non-list`)\n }\n } else {\n throw new Error(`Invalid key type: ${typeof key}`)\n }\n}\n\n/**\n * Handle 'move' operation using existing DraftNode methods\n */\nfunction handleMove<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchMoveOperation,\n): void {\n const fromPath = normalizePath(operation.from)\n const toPath = normalizePath(operation.path)\n\n // For list moves within the same parent, we need special handling\n if (\n fromPath.length === toPath.length &&\n fromPath.slice(0, -1).every((segment, i) => segment === toPath[i])\n ) {\n // Same parent container - use list move operation if available\n const fromIndex = fromPath[fromPath.length - 1]\n const toIndex = toPath[toPath.length - 1]\n\n if (typeof fromIndex === \"number\" && typeof toIndex === \"number\") {\n const { parent } = navigateToPath(draft, fromPath.slice(0, -1))\n\n // Check if the parent has a move method (like LoroMovableList)\n if (parent.move && typeof parent.move === \"function\") {\n parent.move(fromIndex, toIndex)\n return\n }\n\n // Otherwise, get value, remove, then add at target index\n const value = getValueAtPath(draft, fromPath)\n handleRemove(draft, { op: \"remove\", path: operation.from })\n\n // For JSON Patch move semantics, the target index refers to the position\n // in the final array, not the intermediate array after removal.\n // No index adjustment needed - use the original target index.\n handleAdd(draft, { op: \"add\", path: operation.path, value })\n return\n }\n }\n\n // Different parents or non-numeric indices - standard move\n const value = getValueAtPath(draft, fromPath)\n handleRemove(draft, { op: \"remove\", path: operation.from })\n handleAdd(draft, { op: \"add\", path: operation.path, value })\n}\n\n/**\n * Handle 'copy' operation using existing DraftNode methods\n */\nfunction handleCopy<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchCopyOperation,\n): void {\n const fromPath = normalizePath(operation.from)\n\n // Get the value to copy\n const value = getValueAtPath(draft, fromPath)\n\n // Add to destination (no removal)\n handleAdd(draft, { op: \"add\", path: operation.path, value })\n}\n\n/**\n * Handle 'test' operation using existing DraftNode value access\n */\nfunction handleTest<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchTestOperation,\n): boolean {\n const path = normalizePath(operation.path)\n const actualValue = getValueAtPath(draft, path)\n\n // Deep equality check for test operation\n return JSON.stringify(actualValue) === JSON.stringify(operation.value)\n}\n\n// =============================================================================\n// MAIN APPLICATOR - Simple orchestration following existing patterns\n// =============================================================================\n\n/**\n * Main JSON Patch applicator - follows existing change() patterns\n */\nexport class JsonPatchApplicator<T extends DocShape> {\n constructor(private rootDraft: Draft<T>) {}\n\n /**\n * Apply a single JSON Patch operation\n */\n applyOperation(operation: JsonPatchOperation): void {\n switch (operation.op) {\n case \"add\":\n handleAdd(this.rootDraft, operation)\n break\n case \"remove\":\n handleRemove(this.rootDraft, operation)\n break\n case \"replace\":\n handleReplace(this.rootDraft, operation)\n break\n case \"move\":\n handleMove(this.rootDraft, operation)\n break\n case \"copy\":\n handleCopy(this.rootDraft, operation)\n break\n case \"test\":\n if (!handleTest(this.rootDraft, operation)) {\n throw new Error(`JSON Patch test failed at path: ${operation.path}`)\n }\n break\n default:\n // TypeScript will catch this at compile time with proper discriminated union\n throw new Error(\n `Unsupported JSON Patch operation: ${(operation as any).op}`,\n )\n }\n }\n\n /**\n * Apply multiple JSON Patch operations in sequence\n */\n applyPatch(patch: JsonPatch): void {\n for (const operation of patch) {\n this.applyOperation(operation)\n }\n }\n}\n","import type { Value } from \"loro-crdt\"\nimport type { ContainerShape, DocShape, ValueShape } from \"./shape.js\"\nimport { isObjectValue } from \"./utils/type-guards.js\"\n\n/**\n * Overlays CRDT state with empty state defaults\n */\nexport function overlayEmptyState<Shape extends DocShape>(\n shape: Shape,\n crdtValue: { [key: string]: Value },\n emptyValue: { [key: string]: Value },\n): { [key: string]: Value } {\n if (typeof crdtValue !== \"object\") {\n throw new Error(\"crdt object is required\")\n }\n\n if (typeof emptyValue !== \"object\") {\n throw new Error(\"empty object is required\")\n }\n\n const result = { ...emptyValue }\n\n for (const [key, propShape] of Object.entries(shape.shapes)) {\n const propCrdtValue = crdtValue[key]\n\n const propEmptyValue = emptyValue[key as keyof typeof emptyValue]\n\n result[key as keyof typeof result] = mergeValue(\n propShape,\n propCrdtValue,\n propEmptyValue,\n )\n }\n\n return result\n}\n\n/**\n * Merges individual CRDT values with empty state defaults\n */\nexport function mergeValue<Shape extends ContainerShape | ValueShape>(\n shape: Shape,\n crdtValue: Value,\n emptyValue: Value,\n): Value {\n if (crdtValue === undefined && emptyValue === undefined) {\n throw new Error(\"either crdt or empty value must be defined\")\n }\n\n switch (shape._type) {\n case \"text\":\n return crdtValue ?? emptyValue ?? \"\"\n case \"counter\":\n return crdtValue ?? emptyValue ?? 0\n case \"list\":\n case \"movableList\":\n return crdtValue ?? emptyValue ?? []\n case \"map\": {\n if (!isObjectValue(crdtValue) && crdtValue !== undefined) {\n throw new Error(\"map crdt must be object\")\n }\n\n const crdtMapValue = crdtValue ?? {}\n\n if (!isObjectValue(emptyValue) && emptyValue !== undefined) {\n throw new Error(\"map empty state must be object\")\n }\n\n const emptyMapValue = emptyValue ?? {}\n\n const result = { ...emptyMapValue }\n for (const [key, nestedShape] of Object.entries(shape.shapes)) {\n const nestedCrdtValue = crdtMapValue[key]\n const nestedEmptyValue = emptyMapValue[key]\n\n result[key as keyof typeof result] = mergeValue(\n nestedShape,\n nestedCrdtValue,\n nestedEmptyValue,\n )\n }\n\n return result\n }\n case \"tree\":\n return crdtValue ?? emptyValue ?? []\n default:\n return crdtValue ?? emptyValue\n }\n}\n","import type {\n ArrayValueShape,\n ContainerOrValueShape,\n DocShape,\n ListContainerShape,\n MapContainerShape,\n MovableListContainerShape,\n ObjectValueShape,\n RecordContainerShape,\n RecordValueShape,\n UnionValueShape,\n ValueShape,\n} from \"./shape.js\"\nimport type { InferPlainType } from \"./types.js\"\n\n/**\n * Validates a value against a ContainerShape or ValueShape schema\n */\nexport function validateValue(\n value: unknown,\n schema: ContainerOrValueShape,\n path: string = \"\",\n): unknown {\n if (!schema || typeof schema !== \"object\" || !(\"_type\" in schema)) {\n throw new Error(`Invalid schema at path ${path}: missing _type`)\n }\n\n const currentPath = path || \"root\"\n\n // Handle ContainerShape types\n if (schema._type === \"text\") {\n if (typeof value !== \"string\") {\n throw new Error(\n `Expected string at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n }\n\n if (schema._type === \"counter\") {\n if (typeof value !== \"number\") {\n throw new Error(\n `Expected number at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n }\n\n if (schema._type === \"list\" || schema._type === \"movableList\") {\n if (!Array.isArray(value)) {\n throw new Error(\n `Expected array at path ${currentPath}, got ${typeof value}`,\n )\n }\n const listSchema = schema as ListContainerShape | MovableListContainerShape\n return value.map((item, index) =>\n validateValue(item, listSchema.shape, `${currentPath}[${index}]`),\n )\n }\n\n if (schema._type === \"map\") {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\n `Expected object at path ${currentPath}, got ${typeof value}`,\n )\n }\n const mapSchema = schema as MapContainerShape\n const result: Record<string, unknown> = {}\n\n // Validate each property in the map shape\n for (const [key, nestedSchema] of Object.entries(mapSchema.shapes)) {\n const nestedPath = `${currentPath}.${key}`\n const nestedValue = (value as Record<string, unknown>)[key]\n result[key] = validateValue(nestedValue, nestedSchema, nestedPath)\n }\n return result\n }\n\n if (schema._type === \"record\") {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\n `Expected object at path ${currentPath}, got ${typeof value}`,\n )\n }\n const recordSchema = schema as RecordContainerShape\n const result: Record<string, unknown> = {}\n\n // Validate each property in the record\n for (const [key, nestedValue] of Object.entries(value)) {\n const nestedPath = `${currentPath}.${key}`\n result[key] = validateValue(nestedValue, recordSchema.shape, nestedPath)\n }\n return result\n }\n\n if (schema._type === \"tree\") {\n if (!Array.isArray(value)) {\n throw new Error(\n `Expected array for tree at path ${currentPath}, got ${typeof value}`,\n )\n }\n // Trees can contain any structure, so we just validate it's an array\n return value\n }\n\n // Handle ValueShape types\n if (schema._type === \"value\") {\n const valueSchema = schema as ValueShape\n\n switch (valueSchema.valueType) {\n case \"string\":\n if (typeof value !== \"string\") {\n throw new Error(\n `Expected string at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"number\":\n if (typeof value !== \"number\") {\n throw new Error(\n `Expected number at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n throw new Error(\n `Expected boolean at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"null\":\n if (value !== null) {\n throw new Error(\n `Expected null at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"undefined\":\n if (value !== undefined) {\n throw new Error(\n `Expected undefined at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"uint8array\":\n if (!(value instanceof Uint8Array)) {\n throw new Error(\n `Expected Uint8Array at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"object\": {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\n `Expected object at path ${currentPath}, got ${typeof value}`,\n )\n }\n const objectSchema = valueSchema as ObjectValueShape\n const result: Record<string, unknown> = {}\n\n // Validate each property in the object shape\n for (const [key, nestedSchema] of Object.entries(objectSchema.shape)) {\n const nestedPath = `${currentPath}.${key}`\n const nestedValue = (value as Record<string, unknown>)[key]\n result[key] = validateValue(nestedValue, nestedSchema, nestedPath)\n }\n return result\n }\n\n case \"record\": {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\n `Expected object at path ${currentPath}, got ${typeof value}`,\n )\n }\n const recordSchema = valueSchema as RecordValueShape\n const result: Record<string, unknown> = {}\n\n // Validate each property in the record\n for (const [key, nestedValue] of Object.entries(value)) {\n const nestedPath = `${currentPath}.${key}`\n result[key] = validateValue(\n nestedValue,\n recordSchema.shape,\n nestedPath,\n )\n }\n return result\n }\n\n case \"array\": {\n if (!Array.isArray(value)) {\n throw new Error(\n `Expected array at path ${currentPath}, got ${typeof value}`,\n )\n }\n const arraySchema = valueSchema as ArrayValueShape\n return value.map((item, index) =>\n validateValue(item, arraySchema.shape, `${currentPath}[${index}]`),\n )\n }\n\n case \"union\": {\n const unionSchema = valueSchema as UnionValueShape\n let lastError: Error | null = null\n\n // Try to validate against each shape in the union\n for (const shape of unionSchema.shapes) {\n try {\n return validateValue(value, shape, currentPath)\n } catch (error) {\n lastError = error as Error\n }\n }\n\n throw new Error(\n `Value at path ${currentPath} does not match any union type: ${lastError?.message}`,\n )\n }\n\n default:\n throw new Error(`Unknown value type: ${(valueSchema as any).valueType}`)\n }\n }\n\n throw new Error(`Unknown schema type: ${(schema as any)._type}`)\n}\n\n/**\n * Validates empty state against schema structure without using Zod\n * Combines the functionality of createEmptyStateValidator and createValueValidator\n */\nexport function validateEmptyState<T extends DocShape>(\n emptyState: unknown,\n schema: T,\n): InferPlainType<T> {\n if (\n !emptyState ||\n typeof emptyState !== \"object\" ||\n Array.isArray(emptyState)\n ) {\n throw new Error(\"Empty state must be an object\")\n }\n\n const result: Record<string, unknown> = {}\n\n // Validate each property in the document schema\n for (const [key, schemaValue] of Object.entries(schema.shapes)) {\n const value = (emptyState as Record<string, unknown>)[key]\n result[key] = validateValue(value, schemaValue, key)\n }\n\n return result as InferPlainType<T>\n}\n","// biome-ignore-all lint/suspicious/noExplicitAny: required\n\nimport type {\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n LoroTree,\n} from \"loro-crdt\"\n\nimport type { CounterDraftNode } from \"./draft-nodes/counter.js\"\nimport type { ListDraftNode } from \"./draft-nodes/list.js\"\nimport type { MapDraftNode } from \"./draft-nodes/map.js\"\nimport type { MovableListDraftNode } from \"./draft-nodes/movable-list.js\"\nimport type { RecordDraftNode } from \"./draft-nodes/record.js\"\nimport type { TextDraftNode } from \"./draft-nodes/text.js\"\n\nexport interface Shape<Plain, Draft> {\n readonly _type: string\n readonly _plain: Plain\n readonly _draft: Draft\n}\n\nexport interface DocShape<\n NestedShapes extends Record<string, ContainerShape> = Record<\n string,\n ContainerShape\n >,\n> extends Shape<\n { [K in keyof NestedShapes]: NestedShapes[K][\"_plain\"] },\n { [K in keyof NestedShapes]: NestedShapes[K][\"_draft\"] }\n > {\n readonly _type: \"doc\"\n // A doc's root containers each separately has its own shape, hence 'shapes'\n readonly shapes: NestedShapes\n}\n\nexport interface TextContainerShape extends Shape<string, TextDraftNode> {\n readonly _type: \"text\"\n}\nexport interface CounterContainerShape extends Shape<number, CounterDraftNode> {\n readonly _type: \"counter\"\n}\nexport interface TreeContainerShape<NestedShape = ContainerOrValueShape>\n extends Shape<any, any> {\n readonly _type: \"tree\"\n // TODO(duane): What does a tree contain? One type, or many?\n readonly shape: NestedShape\n}\n\n// Container schemas using interfaces for recursive references\nexport interface ListContainerShape<\n NestedShape extends ContainerOrValueShape = ContainerOrValueShape,\n> extends Shape<NestedShape[\"_plain\"][], ListDraftNode<NestedShape>> {\n readonly _type: \"list\"\n // A list contains many elements, all of the same 'shape'\n readonly shape: NestedShape\n}\n\nexport interface MovableListContainerShape<\n NestedShape extends ContainerOrValueShape = ContainerOrValueShape,\n> extends Shape<NestedShape[\"_plain\"][], MovableListDraftNode<NestedShape>> {\n readonly _type: \"movableList\"\n // A list contains many elements, all of the same 'shape'\n readonly shape: NestedShape\n}\n\nexport interface MapContainerShape<\n NestedShapes extends Record<string, ContainerOrValueShape> = Record<\n string,\n ContainerOrValueShape\n >,\n> extends Shape<\n { [K in keyof NestedShapes]: NestedShapes[K][\"_plain\"] },\n MapDraftNode<NestedShapes> & {\n [K in keyof NestedShapes]: NestedShapes[K][\"_draft\"]\n }\n > {\n readonly _type: \"map\"\n // Each map property has its own shape, hence 'shapes'\n readonly shapes: NestedShapes\n}\n\nexport interface RecordContainerShape<\n NestedShape extends ContainerOrValueShape = ContainerOrValueShape,\n> extends Shape<\n Record<string, NestedShape[\"_plain\"]>,\n RecordDraftNode<NestedShape>\n > {\n readonly _type: \"record\"\n readonly shape: NestedShape\n}\n\nexport type ContainerShape =\n | CounterContainerShape\n | ListContainerShape\n | MapContainerShape\n | MovableListContainerShape\n | RecordContainerShape\n | TextContainerShape\n | TreeContainerShape\n\nexport type ContainerType = ContainerShape[\"_type\"]\n\n// LoroValue shape types - a shape for each of Loro's Value types\nexport interface StringValueShape extends Shape<string, string> {\n readonly _type: \"value\"\n readonly valueType: \"string\"\n}\nexport interface NumberValueShape extends Shape<number, number> {\n readonly _type: \"value\"\n readonly valueType: \"number\"\n}\nexport interface BooleanValueShape extends Shape<boolean, boolean> {\n readonly _type: \"value\"\n readonly valueType: \"boolean\"\n}\nexport interface NullValueShape extends Shape<null, null> {\n readonly _type: \"value\"\n readonly valueType: \"null\"\n}\nexport interface UndefinedValueShape extends Shape<undefined, undefined> {\n readonly _type: \"value\"\n readonly valueType: \"undefined\"\n}\nexport interface Uint8ArrayValueShape extends Shape<Uint8Array, Uint8Array> {\n readonly _type: \"value\"\n readonly valueType: \"uint8array\"\n}\n\nexport interface ObjectValueShape<\n T extends Record<string, ValueShape> = Record<string, ValueShape>,\n> extends Shape<\n { [K in keyof T]: T[K][\"_plain\"] },\n { [K in keyof T]: T[K][\"_draft\"] }\n > {\n readonly _type: \"value\"\n readonly valueType: \"object\"\n readonly shape: T\n}\n\nexport interface RecordValueShape<T extends ValueShape = ValueShape>\n extends Shape<Record<string, T[\"_plain\"]>, Record<string, T[\"_draft\"]>> {\n readonly _type: \"value\"\n readonly valueType: \"record\"\n readonly shape: T\n}\n\nexport interface ArrayValueShape<T extends ValueShape = ValueShape>\n extends Shape<T[\"_plain\"][], T[\"_draft\"][]> {\n readonly _type: \"value\"\n readonly valueType: \"array\"\n readonly shape: T\n}\n\nexport interface UnionValueShape<T extends ValueShape[] = ValueShape[]>\n extends Shape<T[number][\"_plain\"], T[number][\"_draft\"]> {\n readonly _type: \"value\"\n readonly valueType: \"union\"\n readonly shapes: T\n}\n\n// Union of all ValueShapes - these can only contain other ValueShapes, not ContainerShapes\nexport type ValueShape =\n | StringValueShape\n | NumberValueShape\n | BooleanValueShape\n | NullValueShape\n | UndefinedValueShape\n | Uint8ArrayValueShape\n | ObjectValueShape\n | RecordValueShape\n | ArrayValueShape\n | UnionValueShape\n\nexport type ContainerOrValueShape = ContainerShape | ValueShape\n\n/**\n * The LoroShape factory object\n *\n * If a container has a `shape` type variable, it refers to the shape it contains--\n * so for example, a `LoroShape.list(LoroShape.text())` would return a value of type\n * `ListContainerShape<TextContainerShape>`.\n */\nexport const Shape = {\n doc: <T extends Record<string, ContainerShape>>(shape: T): DocShape<T> => ({\n _type: \"doc\" as const,\n shapes: shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n // CRDTs are represented by Loro Containers--they converge on state using Loro's\n // various CRDT algorithms\n counter: (): CounterContainerShape => ({\n _type: \"counter\" as const,\n _plain: 0,\n _draft: {} as CounterDraftNode,\n }),\n\n list: <T extends ContainerOrValueShape>(shape: T): ListContainerShape<T> => ({\n _type: \"list\" as const,\n shape,\n _plain: [] as any,\n _draft: {} as any,\n }),\n\n map: <T extends Record<string, ContainerOrValueShape>>(\n shape: T,\n ): MapContainerShape<T> => ({\n _type: \"map\" as const,\n shapes: shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n record: <T extends ContainerOrValueShape>(\n shape: T,\n ): RecordContainerShape<T> => ({\n _type: \"record\" as const,\n shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n movableList: <T extends ContainerOrValueShape>(\n shape: T,\n ): MovableListContainerShape<T> => ({\n _type: \"movableList\" as const,\n shape,\n _plain: [] as any,\n _draft: {} as any,\n }),\n\n text: (): TextContainerShape => ({\n _type: \"text\" as const,\n _plain: \"\",\n _draft: {} as TextDraftNode,\n }),\n\n tree: <T extends MapContainerShape>(shape: T): TreeContainerShape => ({\n _type: \"tree\" as const,\n shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n // Values are represented as plain JS objects, with the limitation that they MUST be\n // representable as a Loro \"Value\"--basically JSON. The behavior of a Value is basically\n // \"Last Write Wins\", meaning there is no subtle convergent behavior here, just taking\n // the most recent value based on the current available information.\n plain: {\n string: (): StringValueShape => ({\n _type: \"value\" as const,\n valueType: \"string\" as const,\n _plain: \"\",\n _draft: \"\",\n }),\n\n number: (): NumberValueShape => ({\n _type: \"value\" as const,\n valueType: \"number\" as const,\n _plain: 0,\n _draft: 0,\n }),\n\n boolean: (): BooleanValueShape => ({\n _type: \"value\" as const,\n valueType: \"boolean\" as const,\n _plain: false,\n _draft: false,\n }),\n\n null: (): NullValueShape => ({\n _type: \"value\" as const,\n valueType: \"null\" as const,\n _plain: null,\n _draft: null,\n }),\n\n undefined: (): UndefinedValueShape => ({\n _type: \"value\" as const,\n valueType: \"undefined\" as const,\n _plain: undefined,\n _draft: undefined,\n }),\n\n uint8Array: (): Uint8ArrayValueShape => ({\n _type: \"value\" as const,\n valueType: \"uint8array\" as const,\n _plain: new Uint8Array(),\n _draft: new Uint8Array(),\n }),\n\n object: <T extends Record<string, ValueShape>>(\n shape: T,\n ): ObjectValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"object\" as const,\n shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n record: <T extends ValueShape>(shape: T): RecordValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"record\" as const,\n shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n array: <T extends ValueShape>(shape: T): ArrayValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"array\" as const,\n shape,\n _plain: [] as any,\n _draft: [] as any,\n }),\n\n // Special value type that helps make things like `string | null` representable\n // TODO(duane): should this be a more general type for containers too?\n union: <T extends ValueShape[]>(shapes: T): UnionValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"union\" as const,\n shapes,\n _plain: {} as any,\n _draft: {} as any,\n }),\n },\n}\n\n// Add this type mapping near the top of your file, after the imports\nexport type ShapeToContainer<T extends DocShape | ContainerShape> =\n T extends TextContainerShape\n ? LoroText\n : T extends CounterContainerShape\n ? LoroCounter\n : T extends ListContainerShape\n ? LoroList\n : T extends MovableListContainerShape\n ? LoroMovableList\n : T extends MapContainerShape | RecordContainerShape\n ? LoroMap\n : T extends TreeContainerShape\n ? LoroTree\n : never // not a container\n"],"mappings":"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","names":["LoroCounter","LoroList","LoroMap","LoroMovableList","LoroText","LoroCounter","LoroList","LoroMap","LoroMovableList","LoroText","LoroCounter","LoroList","LoroMap","LoroMovableList","LoroText","LoroTree","containerConstructor","LoroCounter","LoroList","LoroMap","LoroMovableList","LoroText","LoroTree","value"]}
|
|
1
|
+
{"version":3,"sources":["../src/change.ts","../src/draft-nodes/base.ts","../src/draft-nodes/counter.ts","../src/conversion.ts","../src/utils/type-guards.ts","../src/draft-nodes/list-base.ts","../src/draft-nodes/list.ts","../src/draft-nodes/map.ts","../src/draft-nodes/movable-list.ts","../src/draft-nodes/record.ts","../src/draft-nodes/text.ts","../src/draft-nodes/tree.ts","../src/draft-nodes/utils.ts","../src/draft-nodes/doc.ts","../src/json-patch.ts","../src/overlay.ts","../src/validation.ts","../src/shape.ts"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noExplicitAny: fix later */\n\nimport { LoroDoc } from \"loro-crdt\"\nimport { DraftDoc } from \"./draft-nodes/doc.js\"\nimport {\n type JsonPatch,\n JsonPatchApplicator,\n type JsonPatchOperation,\n normalizePath,\n} from \"./json-patch.js\"\nimport { overlayEmptyState } from \"./overlay.js\"\nimport type { DocShape } from \"./shape.js\"\nimport type { Draft, InferPlainType } from \"./types.js\"\nimport { validateEmptyState } from \"./validation.js\"\n\n// Core TypedDoc abstraction around LoroDoc\nexport class TypedDoc<Shape extends DocShape> {\n constructor(\n private shape: Shape,\n private emptyState: InferPlainType<Shape>,\n private doc: LoroDoc = new LoroDoc(),\n ) {\n validateEmptyState(emptyState, shape)\n }\n\n get value(): InferPlainType<Shape> {\n const crdtValue = this.doc.toJSON()\n return overlayEmptyState(\n this.shape,\n crdtValue,\n this.emptyState,\n ) as InferPlainType<Shape>\n }\n\n change(fn: (draft: Draft<Shape>) => void): InferPlainType<Shape> {\n // Reuse existing DocumentDraft system with empty state integration\n const draft = new DraftDoc({\n shape: this.shape,\n emptyState: this.emptyState,\n doc: this.doc,\n })\n fn(draft as unknown as Draft<Shape>)\n draft.absorbPlainValues()\n this.doc.commit()\n return this.value\n }\n\n /**\n * Apply JSON Patch operations to the document\n *\n * @param patch - Array of JSON Patch operations (RFC 6902)\n * @param pathPrefix - Optional path prefix for scoped operations\n * @returns Updated document value\n *\n * @example\n * ```typescript\n * const result = typedDoc.applyPatch([\n * { op: 'add', path: '/users/0/name', value: 'Alice' },\n * { op: 'replace', path: '/settings/theme', value: 'dark' }\n * ])\n * ```\n */\n applyPatch(\n patch: JsonPatch,\n pathPrefix?: (string | number)[],\n ): InferPlainType<Shape> {\n return this.change(draft => {\n const applicator = new JsonPatchApplicator(draft)\n\n // Apply path prefix if provided\n const prefixedPatch = pathPrefix\n ? patch.map((op: JsonPatchOperation) => ({\n ...op,\n path: [...pathPrefix, ...normalizePath(op.path)],\n }))\n : patch\n\n applicator.applyPatch(prefixedPatch)\n })\n }\n\n // Expose underlying doc for advanced use cases\n get loroDoc(): LoroDoc {\n return this.doc\n }\n\n // Expose shape for internal use\n get docShape(): Shape {\n return this.shape\n }\n\n // Get raw CRDT value without overlay\n get rawValue(): any {\n return this.doc.toJSON()\n }\n}\n\n// Factory function for TypedLoroDoc\nexport function createTypedDoc<Shape extends DocShape>(\n shape: Shape,\n emptyState: InferPlainType<Shape>,\n existingDoc?: LoroDoc,\n): TypedDoc<Shape> {\n return new TypedDoc<Shape>(shape, emptyState, existingDoc || new LoroDoc())\n}\n","import type { ContainerShape, DocShape, ShapeToContainer } from \"../shape.js\"\nimport type { InferPlainType } from \"../types.js\"\n\nexport type DraftNodeParams<Shape extends DocShape | ContainerShape> = {\n shape: Shape\n emptyState?: InferPlainType<Shape>\n getContainer: () => ShapeToContainer<Shape>\n}\n\n// Base class for all draft nodes\nexport abstract class DraftNode<Shape extends DocShape | ContainerShape> {\n protected _cachedContainer?: ShapeToContainer<Shape>\n\n constructor(protected _params: DraftNodeParams<Shape>) {}\n\n abstract absorbPlainValues(): void\n\n protected get shape(): Shape {\n return this._params.shape\n }\n\n protected get emptyState(): InferPlainType<Shape> | undefined {\n return this._params.emptyState\n }\n\n protected get container(): ShapeToContainer<Shape> {\n if (!this._cachedContainer) {\n const container = this._params.getContainer()\n this._cachedContainer = container\n return container\n }\n return this._cachedContainer\n }\n}\n","import type { CounterContainerShape } from \"../shape.js\"\nimport { DraftNode } from \"./base.js\"\n\n// Counter draft node\nexport class CounterDraftNode extends DraftNode<CounterContainerShape> {\n absorbPlainValues() {\n // no plain values contained within\n }\n\n increment(value: number): void {\n this.container.increment(value)\n }\n\n decrement(value: number): void {\n this.container.decrement(value)\n }\n\n get value(): number {\n return this.container.value\n }\n}\n","import {\n type Container,\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n type Value,\n} from \"loro-crdt\"\nimport type {\n ArrayValueShape,\n ContainerOrValueShape,\n ListContainerShape,\n MapContainerShape,\n MovableListContainerShape,\n ObjectValueShape,\n RecordContainerShape,\n RecordValueShape,\n} from \"./shape.js\"\nimport {\n isContainer,\n isContainerShape,\n isObjectValue,\n isValueShape,\n} from \"./utils/type-guards.js\"\n\n/**\n * Converts string input to LoroText container\n */\nfunction convertTextInput(value: string): LoroText {\n const text = new LoroText()\n\n text.insert(0, value)\n\n return text\n}\n\n/**\n * Converts number input to LoroCounter container\n */\nfunction convertCounterInput(value: number): LoroCounter {\n const counter = new LoroCounter()\n counter.increment(value)\n return counter\n}\n\n/**\n * Converts array input to LoroList container\n */\nfunction convertListInput(\n value: Value[],\n shape: ListContainerShape | ArrayValueShape,\n // parentPath: string[],\n): LoroList | Value[] {\n if (!isContainerShape(shape)) {\n return value\n }\n\n const list = new LoroList()\n\n for (const item of value) {\n const convertedItem = convertInputToNode(item, shape.shape)\n if (isContainer(convertedItem)) {\n list.pushContainer(convertedItem)\n } else {\n list.push(convertedItem)\n }\n }\n\n return list\n}\n\n/**\n * Converts array input to LoroMovableList container\n */\nfunction convertMovableListInput(\n value: Value[],\n shape: MovableListContainerShape | ArrayValueShape,\n // parentPath: string[],\n): LoroMovableList | Value[] {\n if (!isContainerShape(shape)) {\n return value\n }\n\n const list = new LoroMovableList()\n\n for (const item of value) {\n const convertedItem = convertInputToNode(item, shape.shape)\n if (isContainer(convertedItem)) {\n list.pushContainer(convertedItem)\n } else {\n list.push(convertedItem)\n }\n }\n\n return list\n}\n\n/**\n * Converts object input to LoroMap container\n */\nfunction convertMapInput(\n value: { [key: string]: Value },\n shape: MapContainerShape | ObjectValueShape,\n): LoroMap | { [key: string]: Value } {\n if (!isContainerShape(shape)) {\n return value\n }\n\n const map = new LoroMap()\n for (const [k, v] of Object.entries(value)) {\n const nestedSchema = shape.shapes[k]\n if (nestedSchema) {\n const convertedValue = convertInputToNode(v, nestedSchema)\n if (isContainer(convertedValue)) {\n map.setContainer(k, convertedValue)\n } else {\n map.set(k, convertedValue)\n }\n } else {\n map.set(k, value)\n }\n }\n\n return map\n}\n\n/**\n * Converts object input to LoroMap container (Record)\n */\nfunction convertRecordInput(\n value: { [key: string]: Value },\n shape: RecordContainerShape | RecordValueShape,\n): LoroMap | { [key: string]: Value } {\n if (!isContainerShape(shape)) {\n return value\n }\n\n const map = new LoroMap()\n for (const [k, v] of Object.entries(value)) {\n const convertedValue = convertInputToNode(v, shape.shape)\n if (isContainer(convertedValue)) {\n map.setContainer(k, convertedValue)\n } else {\n map.set(k, convertedValue)\n }\n }\n\n return map\n}\n\n/**\n * Main conversion function that transforms input values to appropriate CRDT containers\n * based on schema definitions\n */\nexport function convertInputToNode<Shape extends ContainerOrValueShape>(\n value: Value,\n shape: Shape,\n): Container | Value {\n switch (shape._type) {\n case \"text\": {\n if (typeof value !== \"string\") {\n throw new Error(\"string expected\")\n }\n\n return convertTextInput(value)\n }\n case \"counter\": {\n if (typeof value !== \"number\") {\n throw new Error(\"number expected\")\n }\n\n return convertCounterInput(value)\n }\n case \"list\": {\n if (!Array.isArray(value)) {\n throw new Error(\"array expected\")\n }\n\n return convertListInput(value, shape)\n }\n case \"movableList\": {\n if (!Array.isArray(value)) {\n throw new Error(\"array expected\")\n }\n\n return convertMovableListInput(value, shape)\n }\n case \"map\": {\n if (!isObjectValue(value)) {\n throw new Error(\"object expected\")\n }\n\n return convertMapInput(value, shape)\n }\n case \"record\": {\n if (!isObjectValue(value)) {\n throw new Error(\"object expected\")\n }\n\n return convertRecordInput(value, shape)\n }\n case \"value\": {\n if (!isValueShape(shape)) {\n throw new Error(\"value expected\")\n }\n\n return value\n }\n\n case \"tree\":\n throw new Error(\"tree type unimplemented\")\n\n default:\n throw new Error(`unexpected type: ${(shape as Shape)._type}`)\n }\n}\n","import type {\n Container,\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n LoroTree,\n LoroTreeNode,\n Value,\n} from \"loro-crdt\"\nimport type {\n ContainerOrValueShape,\n ContainerShape,\n CounterContainerShape,\n ListContainerShape,\n MapContainerShape,\n MovableListContainerShape,\n RecordContainerShape,\n TextContainerShape,\n TreeContainerShape,\n ValueShape,\n} from \"../shape.js\"\n\nexport { isContainer, isContainerId } from \"loro-crdt\"\n\n/**\n * Type guard to check if a container is a LoroCounter\n */\nexport function isLoroCounter(container: Container): container is LoroCounter {\n return container.kind() === \"Counter\"\n}\n\n/**\n * Type guard to check if a container is a LoroList\n */\nexport function isLoroList(container: Container): container is LoroList {\n return container.kind() === \"List\"\n}\n\n/**\n * Type guard to check if a container is a LoroMap\n */\nexport function isLoroMap(container: Container): container is LoroMap {\n return container.kind() === \"Map\"\n}\n\n/**\n * Type guard to check if a container is a LoroMovableList\n */\nexport function isLoroMovableList(\n container: Container,\n): container is LoroMovableList {\n return container.kind() === \"MovableList\"\n}\n\n/**\n * Type guard to check if a container is a LoroText\n */\nexport function isLoroText(container: Container): container is LoroText {\n return container.kind() === \"Text\"\n}\n\n/**\n * Type guard to check if a container is a LoroTree\n */\nexport function isLoroTree(container: Container): container is LoroTree {\n return container.kind() === \"Tree\"\n}\n\n/**\n * Type guard to check if an object is a LoroTreeNode\n * Note: LoroTreeNode is not a Container, so we check for its specific properties\n */\nexport function isLoroTreeNode(obj: any): obj is LoroTreeNode {\n return (\n obj &&\n typeof obj === \"object\" &&\n typeof obj.id === \"string\" &&\n typeof obj.data === \"object\" &&\n typeof obj.parent === \"function\" &&\n typeof obj.children === \"function\" &&\n typeof obj.createNode === \"function\"\n )\n}\n\n/**\n * Type guard to ensure cached container matches expected type using kind() method\n */\nexport function assertContainerType<T extends Container>(\n cached: Container,\n expected: T,\n context: string = \"container operation\",\n): asserts cached is T {\n if (cached.kind() !== expected.kind()) {\n throw new Error(\n `Type safety violation in ${context}: ` +\n `cached container kind '${cached.kind()}' does not match ` +\n `expected kind '${expected.kind()}'`,\n )\n }\n\n // Additional safety check: ensure IDs match\n if (cached.id !== expected.id) {\n throw new Error(\n `Container ID mismatch in ${context}: ` +\n `cached ID '${cached.id}' does not match expected ID '${expected.id}'`,\n )\n }\n}\n\n/**\n * Type guard to check if a schema is for TextDraftNode\n */\nexport function isTextShape(\n schema: ContainerOrValueShape,\n): schema is TextContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"text\"\n}\n\n/**\n * Type guard to check if a schema is for CounterDraftNode\n */\nexport function isCounterShape(\n schema: ContainerOrValueShape,\n): schema is CounterContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"counter\"\n}\n\n/**\n * Type guard to check if a schema is for ListDraftNode\n */\nexport function isListShape(\n schema: ContainerOrValueShape,\n): schema is ListContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"list\"\n}\n\n/**\n * Type guard to check if a schema is for MovableListDraftNode\n */\nexport function isMovableListShape(\n schema: ContainerOrValueShape,\n): schema is MovableListContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"movableList\"\n}\n\n/**\n * Type guard to check if a schema is for MapDraftNode\n */\nexport function isMapShape(\n schema: ContainerOrValueShape,\n): schema is MapContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"map\"\n}\n\n/**\n * Type guard to check if a schema is for RecordDraftNode\n */\nexport function isRecordShape(\n schema: ContainerOrValueShape,\n): schema is RecordContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"record\"\n}\n\n/**\n * Type guard to check if a schema is for TreeDraftNode\n */\nexport function isTreeShape(\n schema: ContainerOrValueShape,\n): schema is TreeContainerShape {\n return schema && typeof schema === \"object\" && schema._type === \"tree\"\n}\n\nexport function isContainerShape(\n schema: ContainerOrValueShape,\n): schema is ContainerShape {\n return schema._type && schema._type !== \"value\"\n}\n\n/**\n * Type guard to check if a schema is any of the Value shapes\n */\nexport function isValueShape(\n schema: ContainerOrValueShape,\n): schema is ValueShape {\n return (\n schema._type === \"value\" &&\n [\n \"string\",\n \"number\",\n \"boolean\",\n \"null\",\n \"undefined\",\n \"uint8array\",\n \"object\",\n \"record\",\n \"array\",\n \"union\",\n ].includes(schema.valueType)\n )\n}\n\nexport function isObjectValue(value: Value): value is { [key: string]: Value } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Uint8Array)\n )\n}\n","import type { Container, LoroList, LoroMovableList } from \"loro-crdt\"\nimport { convertInputToNode } from \"../conversion.js\"\nimport type {\n ContainerOrValueShape,\n ContainerShape,\n ListContainerShape,\n MovableListContainerShape,\n} from \"../shape.js\"\nimport { isContainer, isValueShape } from \"../utils/type-guards.js\"\nimport { DraftNode, type DraftNodeParams } from \"./base.js\"\nimport { createContainerDraftNode } from \"./utils.js\"\n\n// Shared logic for list operations\nexport abstract class ListDraftNodeBase<\n NestedShape extends ContainerOrValueShape,\n Item = NestedShape[\"_plain\"],\n DraftItem = NestedShape[\"_draft\"],\n> extends DraftNode<any> {\n // Cache for items returned by array methods to track mutations\n private itemCache = new Map<number, any>()\n\n protected get container(): LoroList | LoroMovableList {\n return super.container as LoroList | LoroMovableList\n }\n\n protected get shape():\n | ListContainerShape<NestedShape>\n | MovableListContainerShape<NestedShape> {\n return super.shape as\n | ListContainerShape<NestedShape>\n | MovableListContainerShape<NestedShape>\n }\n\n absorbPlainValues() {\n // Critical function: absorb mutated plain values back into Loro containers\n // This is called at the end of change() to persist mutations made to plain objects\n for (const [index, cachedItem] of this.itemCache.entries()) {\n if (cachedItem) {\n if (isValueShape(this.shape.shape)) {\n // For value shapes, delegate to subclass-specific absorption logic\n this.absorbValueAtIndex(index, cachedItem)\n } else {\n // For container shapes, the item should be a draft node that handles its own absorption\n if (\n cachedItem &&\n typeof cachedItem === \"object\" &&\n \"absorbPlainValues\" in cachedItem\n ) {\n ;(cachedItem as any).absorbPlainValues()\n }\n }\n }\n }\n\n // Clear the cache after absorbing values\n this.itemCache.clear()\n }\n\n // Abstract method to be implemented by subclasses\n // Each subclass knows how to handle its specific container type\n protected abstract absorbValueAtIndex(index: number, value: any): void\n\n protected insertWithConversion(index: number, item: Item): void {\n const convertedItem = convertInputToNode(item as any, this.shape.shape)\n if (isContainer(convertedItem)) {\n this.container.insertContainer(index, convertedItem)\n } else {\n this.container.insert(index, convertedItem)\n }\n }\n\n protected pushWithConversion(item: Item): void {\n const convertedItem = convertInputToNode(item as any, this.shape.shape)\n if (isContainer(convertedItem)) {\n this.container.pushContainer(convertedItem)\n } else {\n this.container.push(convertedItem)\n }\n }\n\n getDraftNodeParams(\n index: number,\n shape: ContainerShape,\n ): DraftNodeParams<ContainerShape> {\n return {\n shape,\n emptyState: undefined, // List items don't have empty state\n getContainer: () => {\n const containerItem = this.container.get(index)\n if (!containerItem || !isContainer(containerItem)) {\n throw new Error(`No container found at index ${index}`)\n }\n return containerItem\n },\n }\n }\n\n // Get item for predicate functions - always returns plain Item for filtering logic\n protected getPredicateItem(index: number): Item {\n // CRITICAL FIX: For predicates to work correctly with mutations,\n // we need to check if there's a cached (mutated) version first\n const cachedItem = this.itemCache.get(index)\n if (cachedItem && isValueShape(this.shape.shape)) {\n // For value shapes, if we have a cached item, use it so predicates see mutations\n return cachedItem as Item\n }\n\n const containerItem = this.container.get(index)\n if (containerItem === undefined) {\n return undefined as Item\n }\n\n if (isValueShape(this.shape.shape)) {\n // For value shapes, return the plain value directly\n return containerItem as Item\n } else {\n // For container shapes, we need to return the plain object representation\n // This allows predicates to access nested properties like article.metadata.author\n if (isContainer(containerItem)) {\n // Convert container to plain object for predicate logic\n // Handle different container types that may not have toJSON method\n if (\n typeof containerItem === \"object\" &&\n containerItem !== null &&\n \"toJSON\" in containerItem\n ) {\n return (containerItem as any).toJSON() as Item\n } else if (\n typeof containerItem === \"object\" &&\n containerItem !== null &&\n \"getShallowValue\" in containerItem\n ) {\n // For containers like LoroCounter that don't have toJSON but have getShallowValue\n return (containerItem as any).getShallowValue() as Item\n } else {\n // Fallback for other container types\n return containerItem as Item\n }\n }\n return containerItem as Item\n }\n }\n\n // Get item for return values - returns DraftItem that can be mutated\n protected getDraftItem(index: number): DraftItem {\n // Check if we already have a cached item for this index\n let cachedItem = this.itemCache.get(index)\n if (cachedItem) {\n return cachedItem\n }\n\n // Get the raw container item\n const containerItem = this.container.get(index)\n if (containerItem === undefined) {\n return undefined as DraftItem\n }\n\n if (isValueShape(this.shape.shape)) {\n // For value shapes, we need to ensure mutations persist\n // The key insight: we must return the SAME object for the same index\n // so that mutations to filtered/found items persist back to the cache\n if (typeof containerItem === \"object\" && containerItem !== null) {\n // Create a deep copy for objects so mutations can be tracked\n // IMPORTANT: Only create the copy once, then always return the same cached object\n cachedItem = JSON.parse(JSON.stringify(containerItem))\n } else {\n // For primitives, just use the value directly\n cachedItem = containerItem\n }\n this.itemCache.set(index, cachedItem)\n return cachedItem as DraftItem\n } else {\n // For container shapes, create a proper draft node using the new pattern\n cachedItem = createContainerDraftNode(\n this.getDraftNodeParams(index, this.shape.shape as ContainerShape),\n )\n this.itemCache.set(index, cachedItem)\n return cachedItem as DraftItem\n }\n }\n\n // Array-like methods for better developer experience\n // DUAL INTERFACE: Predicates get Item (plain data), return values are DraftItem (mutable)\n\n find(\n predicate: (item: Item, index: number) => boolean,\n ): DraftItem | undefined {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (predicate(predicateItem, i)) {\n return this.getDraftItem(i) // Return mutable draft item\n }\n }\n return undefined\n }\n\n findIndex(predicate: (item: Item, index: number) => boolean): number {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (predicate(predicateItem, i)) {\n return i\n }\n }\n return -1\n }\n\n map<ReturnType>(\n callback: (item: Item, index: number) => ReturnType,\n ): ReturnType[] {\n const result: ReturnType[] = []\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n result.push(callback(predicateItem, i))\n }\n return result\n }\n\n filter(predicate: (item: Item, index: number) => boolean): DraftItem[] {\n const result: DraftItem[] = []\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (predicate(predicateItem, i)) {\n result.push(this.getDraftItem(i)) // Return mutable draft items\n }\n }\n return result\n }\n\n forEach(callback: (item: Item, index: number) => void): void {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n callback(predicateItem, i)\n }\n }\n\n some(predicate: (item: Item, index: number) => boolean): boolean {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (predicate(predicateItem, i)) {\n return true\n }\n }\n return false\n }\n\n every(predicate: (item: Item, index: number) => boolean): boolean {\n for (let i = 0; i < this.length; i++) {\n const predicateItem = this.getPredicateItem(i)\n if (!predicate(predicateItem, i)) {\n return false\n }\n }\n return true\n }\n\n insert(index: number, item: Item): void {\n // Update cache indices before performing the insert operation\n this.updateCacheForInsert(index)\n this.insertWithConversion(index, item)\n }\n\n delete(index: number, len: number): void {\n // Update cache indices before performing the delete operation\n this.updateCacheForDelete(index, len)\n this.container.delete(index, len)\n }\n\n push(item: Item): void {\n this.pushWithConversion(item)\n }\n\n pushContainer(container: Container): Container {\n return this.container.pushContainer(container)\n }\n\n insertContainer(index: number, container: Container): Container {\n return this.container.insertContainer(index, container)\n }\n\n get(index: number): DraftItem {\n return this.getDraftItem(index)\n }\n\n toArray(): Item[] {\n return this.container.toArray() as Item[]\n }\n\n get length(): number {\n return this.container.length\n }\n\n // Update cache indices when items are deleted\n private updateCacheForDelete(deleteIndex: number, deleteLen: number): void {\n const newCache = new Map<number, any>()\n\n for (const [cachedIndex, cachedItem] of this.itemCache.entries()) {\n if (cachedIndex < deleteIndex) {\n // Items before the deletion point keep their indices\n newCache.set(cachedIndex, cachedItem)\n } else if (cachedIndex >= deleteIndex + deleteLen) {\n // Items after the deletion range shift down by deleteLen\n newCache.set(cachedIndex - deleteLen, cachedItem)\n }\n // Items within the deletion range are removed from cache\n }\n\n this.itemCache = newCache\n }\n\n // Update cache indices when items are inserted\n private updateCacheForInsert(insertIndex: number): void {\n const newCache = new Map<number, any>()\n\n for (const [cachedIndex, cachedItem] of this.itemCache.entries()) {\n if (cachedIndex < insertIndex) {\n // Items before the insertion point keep their indices\n newCache.set(cachedIndex, cachedItem)\n } else {\n // Items at or after the insertion point shift up by 1\n newCache.set(cachedIndex + 1, cachedItem)\n }\n }\n\n this.itemCache = newCache\n }\n}\n","import type { LoroList } from \"loro-crdt\"\nimport type { ContainerOrValueShape } from \"../shape.js\"\nimport { ListDraftNodeBase } from \"./list-base.js\"\n\n// List draft node\nexport class ListDraftNode<\n NestedShape extends ContainerOrValueShape,\n> extends ListDraftNodeBase<NestedShape> {\n protected get container(): LoroList {\n return super.container as LoroList\n }\n\n protected absorbValueAtIndex(index: number, value: any): void {\n // LoroList doesn't have set method, need to delete and insert\n this.container.delete(index, 1)\n this.container.insert(index, value)\n }\n}\n","import {\n type Container,\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n LoroTree,\n type Value,\n} from \"loro-crdt\"\nimport type {\n ContainerOrValueShape,\n ContainerShape,\n MapContainerShape,\n ValueShape,\n} from \"../shape.js\"\nimport { isContainerShape, isValueShape } from \"../utils/type-guards.js\"\nimport { DraftNode, type DraftNodeParams } from \"./base.js\"\nimport { createContainerDraftNode } from \"./utils.js\"\n\nconst containerConstructor = {\n counter: LoroCounter,\n list: LoroList,\n map: LoroMap,\n movableList: LoroMovableList,\n record: LoroMap,\n text: LoroText,\n tree: LoroTree,\n} as const\n\n// Map draft node\nexport class MapDraftNode<\n NestedShapes extends Record<string, ContainerOrValueShape>,\n> extends DraftNode<any> {\n private propertyCache = new Map<string, DraftNode<ContainerShape> | Value>()\n\n constructor(params: DraftNodeParams<MapContainerShape<NestedShapes>>) {\n super(params)\n this.createLazyProperties()\n }\n\n protected get shape(): MapContainerShape<NestedShapes> {\n return super.shape as MapContainerShape<NestedShapes>\n }\n\n protected get container(): LoroMap {\n return super.container as LoroMap\n }\n\n absorbPlainValues() {\n for (const [key, node] of this.propertyCache.entries()) {\n if (node instanceof DraftNode) {\n // Contains a DraftNode, not a plain Value: keep recursing\n node.absorbPlainValues()\n continue\n }\n\n // Plain value!\n this.container.set(key, node)\n }\n }\n\n getDraftNodeParams<S extends ContainerShape>(\n key: string,\n shape: S,\n ): DraftNodeParams<ContainerShape> {\n const emptyState = (this.emptyState as any)?.[key]\n\n const LoroContainer = containerConstructor[shape._type]\n\n return {\n shape,\n emptyState,\n getContainer: () =>\n this.container.getOrCreateContainer(key, new (LoroContainer as any)()),\n }\n }\n\n getOrCreateNode<Shape extends ContainerShape | ValueShape>(\n key: string,\n shape: Shape,\n ): Shape extends ContainerShape ? DraftNode<Shape> : Value {\n let node = this.propertyCache.get(key)\n if (!node) {\n if (isContainerShape(shape)) {\n node = createContainerDraftNode(this.getDraftNodeParams(key, shape))\n } else {\n // For value shapes, first try to get the value from the container\n const containerValue = this.container.get(key)\n if (containerValue !== undefined) {\n node = containerValue as Value\n } else {\n // Only fall back to empty state if the container doesn't have the value\n const emptyState = (this.emptyState as any)?.[key]\n if (!emptyState) {\n throw new Error(\"empty state required\")\n }\n node = emptyState as Value\n }\n }\n if (!node) throw new Error(\"no container made\")\n this.propertyCache.set(key, node)\n }\n\n return node as Shape extends ContainerShape ? DraftNode<Shape> : Value\n }\n\n private createLazyProperties(): void {\n for (const key in this.shape.shapes) {\n const shape = this.shape.shapes[key]\n Object.defineProperty(this, key, {\n get: () => this.getOrCreateNode(key, shape),\n set: isValueShape(shape)\n ? value => {\n // console.log(\"set value\", value)\n this.container.set(key, value)\n }\n : undefined,\n })\n }\n }\n\n // TOOD(duane): return correct type here\n get(key: string): any {\n return this.container.get(key)\n }\n\n set(key: string, value: Value): void {\n this.container.set(key, value)\n }\n\n setContainer<C extends Container>(key: string, container: C): C {\n return this.container.setContainer(key, container)\n }\n\n delete(key: string): void {\n this.container.delete(key)\n }\n\n has(key: string): boolean {\n // LoroMap doesn't have a has method, so we check if get returns undefined\n return this.container.get(key) !== undefined\n }\n\n keys(): string[] {\n return this.container.keys()\n }\n\n values(): any[] {\n return this.container.values()\n }\n\n get size(): number {\n return this.container.size\n }\n}\n","import type { Container, LoroMovableList } from \"loro-crdt\"\nimport type { ContainerOrValueShape } from \"../shape.js\"\nimport { ListDraftNodeBase } from \"./list-base.js\"\n\n// Movable list draft node\nexport class MovableListDraftNode<\n NestedShape extends ContainerOrValueShape,\n Item = NestedShape[\"_plain\"],\n> extends ListDraftNodeBase<NestedShape> {\n protected get container(): LoroMovableList {\n return super.container as LoroMovableList\n }\n\n protected absorbValueAtIndex(index: number, value: any): void {\n // LoroMovableList has set method\n this.container.set(index, value)\n }\n\n move(from: number, to: number): void {\n this.container.move(from, to)\n }\n\n set(index: number, item: Exclude<Item, Container>) {\n return this.container.set(index, item)\n }\n}\n","import {\n type Container,\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n LoroTree,\n type Value,\n} from \"loro-crdt\"\nimport type {\n ContainerOrValueShape,\n ContainerShape,\n RecordContainerShape,\n} from \"../shape.js\"\nimport type { InferDraftType } from \"../types.js\"\nimport { isContainerShape, isValueShape } from \"../utils/type-guards.js\"\nimport { DraftNode, type DraftNodeParams } from \"./base.js\"\nimport { createContainerDraftNode } from \"./utils.js\"\n\nconst containerConstructor = {\n counter: LoroCounter,\n list: LoroList,\n map: LoroMap,\n movableList: LoroMovableList,\n record: LoroMap,\n text: LoroText,\n tree: LoroTree,\n} as const\n\n// Record draft node\nexport class RecordDraftNode<\n NestedShape extends ContainerOrValueShape,\n> extends DraftNode<any> {\n private nodeCache = new Map<string, DraftNode<ContainerShape> | Value>()\n\n constructor(params: DraftNodeParams<RecordContainerShape<NestedShape>>) {\n super(params)\n // We don't need to create lazy properties because keys are dynamic\n // But we could use a Proxy if we wanted property access syntax like record.key\n // However, for now let's stick to get/set methods or maybe Proxy for better DX?\n // The requirement says \"records with uniform specific key type and value\".\n // Usually records are accessed via keys.\n // If we want `draft.record.key`, we need a Proxy.\n // biome-ignore lint/correctness/noConstructorReturn: Proxy return is intentional\n return new Proxy(this, {\n get: (target, prop) => {\n if (typeof prop === \"string\" && !(prop in target)) {\n return target.get(prop)\n }\n return Reflect.get(target, prop)\n },\n set: (target, prop, value) => {\n if (typeof prop === \"string\" && !(prop in target)) {\n target.set(prop, value)\n return true\n }\n return Reflect.set(target, prop, value)\n },\n deleteProperty: (target, prop) => {\n if (typeof prop === \"string\" && !(prop in target)) {\n target.delete(prop)\n return true\n }\n return Reflect.deleteProperty(target, prop)\n },\n ownKeys: target => {\n return target.keys()\n },\n getOwnPropertyDescriptor: (target, prop) => {\n if (typeof prop === \"string\" && target.has(prop)) {\n return {\n configurable: true,\n enumerable: true,\n value: target.get(prop),\n }\n }\n return Reflect.getOwnPropertyDescriptor(target, prop)\n },\n })\n }\n\n protected get shape(): RecordContainerShape<NestedShape> {\n return super.shape as RecordContainerShape<NestedShape>\n }\n\n protected get container(): LoroMap {\n return super.container as LoroMap\n }\n\n absorbPlainValues() {\n for (const [key, node] of this.nodeCache.entries()) {\n if (node instanceof DraftNode) {\n // Contains a DraftNode, not a plain Value: keep recursing\n node.absorbPlainValues()\n continue\n }\n\n // Plain value!\n this.container.set(key, node)\n }\n }\n\n getDraftNodeParams<S extends ContainerShape>(\n key: string,\n shape: S,\n ): DraftNodeParams<ContainerShape> {\n const emptyState = (this.emptyState as any)?.[key]\n\n const LoroContainer = containerConstructor[shape._type]\n\n return {\n shape,\n emptyState,\n getContainer: () =>\n this.container.getOrCreateContainer(key, new (LoroContainer as any)()),\n }\n }\n\n getOrCreateNode(key: string): InferDraftType<NestedShape> {\n let node = this.nodeCache.get(key)\n if (!node) {\n const shape = this.shape.shape\n if (isContainerShape(shape)) {\n node = createContainerDraftNode(\n this.getDraftNodeParams(key, shape as ContainerShape),\n )\n } else {\n // For value shapes, first try to get the value from the container\n const containerValue = this.container.get(key)\n if (containerValue !== undefined) {\n node = containerValue as Value\n } else {\n // Only fall back to empty state if the container doesn't have the value\n const emptyState = (this.emptyState as any)?.[key]\n // For records, empty state might not have the key, which is fine?\n // But if we are accessing it, maybe we expect it to exist or be created?\n // If it's a value type, we can't really \"create\" it without a value.\n // So if it's undefined in container and empty state, we return undefined?\n // But the return type expects Value.\n // Let's check MapDraftNode.\n // MapDraftNode throws \"empty state required\" if not found.\n // But for Record, keys are dynamic.\n if (emptyState === undefined) {\n // If it's a value type and not in container or empty state,\n // we should probably return undefined if the type allows it,\n // or maybe the default value for that type?\n // But we don't have a default value generator for shapes.\n // Actually Shape.plain.* factories have _plain and _draft which are defaults.\n node = (shape as any)._plain\n } else {\n node = emptyState as Value\n }\n }\n }\n if (node !== undefined) {\n this.nodeCache.set(key, node)\n }\n }\n\n return node as any\n }\n\n get(key: string): InferDraftType<NestedShape> {\n return this.getOrCreateNode(key)\n }\n\n set(key: string, value: any): void {\n if (isValueShape(this.shape.shape)) {\n this.container.set(key, value)\n // Update cache if needed?\n // MapDraftNode updates container directly for values.\n // But we also cache values in nodeCache for consistency?\n // MapDraftNode doesn't cache values in propertyCache if they are set via setter?\n // Actually MapDraftNode setter:\n // set: isValueShape(shape) ? value => this.container.set(key, value) : undefined\n // It doesn't update propertyCache.\n // But getOrCreateNode checks propertyCache first.\n // So if we set it, we should probably update propertyCache or clear it for that key.\n this.nodeCache.set(key, value)\n } else {\n // For containers, we can't set them directly usually.\n // But if the user passes a plain object that matches the shape, maybe we should convert it?\n // But typically we modify the draft node.\n throw new Error(\n \"Cannot set container directly, modify the draft node instead\",\n )\n }\n }\n\n setContainer<C extends Container>(key: string, container: C): C {\n return this.container.setContainer(key, container)\n }\n\n delete(key: string): void {\n this.container.delete(key)\n this.nodeCache.delete(key)\n }\n\n has(key: string): boolean {\n return this.container.get(key) !== undefined\n }\n\n keys(): string[] {\n return this.container.keys()\n }\n\n values(): any[] {\n return this.container.values()\n }\n\n get size(): number {\n return this.container.size\n }\n}\n","import type { TextContainerShape } from \"../shape.js\"\nimport { DraftNode } from \"./base.js\"\n\n// Text draft node\nexport class TextDraftNode extends DraftNode<TextContainerShape> {\n absorbPlainValues() {\n // no plain values contained within\n }\n\n // Text methods\n insert(index: number, content: string): void {\n this.container.insert(index, content)\n }\n\n delete(index: number, len: number): void {\n this.container.delete(index, len)\n }\n\n toString(): string {\n return this.container.toString()\n }\n\n update(text: string): void {\n this.container.update(text)\n }\n\n mark(range: { start: number; end: number }, key: string, value: any): void {\n this.container.mark(range, key, value)\n }\n\n unmark(range: { start: number; end: number }, key: string): void {\n this.container.unmark(range, key)\n }\n\n toDelta(): any[] {\n return this.container.toDelta()\n }\n\n applyDelta(delta: any[]): void {\n this.container.applyDelta(delta)\n }\n\n get length(): number {\n return this.container.length\n }\n}\n","import type { TreeContainerShape } from \"../shape.js\"\nimport { DraftNode } from \"./base.js\"\n\n// Tree draft node\nexport class TreeDraftNode<T extends TreeContainerShape> extends DraftNode<T> {\n absorbPlainValues() {\n // TODO(duane): implement for trees\n }\n\n createNode(parent?: any, index?: number): any {\n return this.container.createNode(parent, index)\n }\n\n move(target: any, parent?: any, index?: number): void {\n this.container.move(target, parent, index)\n }\n\n delete(target: any): void {\n this.container.delete(target)\n }\n\n has(target: any): boolean {\n return this.container.has(target)\n }\n\n getNodeByID(id: any): any {\n return this.container.getNodeByID\n ? this.container.getNodeByID(id)\n : undefined\n }\n}\n","import type {\n ContainerShape,\n CounterContainerShape,\n ListContainerShape,\n MapContainerShape,\n MovableListContainerShape,\n RecordContainerShape,\n TextContainerShape,\n TreeContainerShape,\n} from \"../shape.js\"\nimport type { DraftNode, DraftNodeParams } from \"./base.js\"\nimport { CounterDraftNode } from \"./counter.js\"\nimport { ListDraftNode } from \"./list.js\"\nimport { MapDraftNode } from \"./map.js\"\nimport { MovableListDraftNode } from \"./movable-list.js\"\nimport { RecordDraftNode } from \"./record.js\"\nimport { TextDraftNode } from \"./text.js\"\nimport { TreeDraftNode } from \"./tree.js\"\n\n// Generic catch-all overload\nexport function createContainerDraftNode<T extends ContainerShape>(\n params: DraftNodeParams<T>,\n): DraftNode<T>\n\n// Implementation\nexport function createContainerDraftNode(\n params: DraftNodeParams<ContainerShape>,\n): DraftNode<ContainerShape> {\n switch (params.shape._type) {\n case \"counter\":\n return new CounterDraftNode(\n params as DraftNodeParams<CounterContainerShape>,\n )\n case \"list\":\n return new ListDraftNode(params as DraftNodeParams<ListContainerShape>)\n case \"map\":\n return new MapDraftNode(params as DraftNodeParams<MapContainerShape>)\n case \"movableList\":\n return new MovableListDraftNode(\n params as DraftNodeParams<MovableListContainerShape>,\n )\n case \"record\":\n return new RecordDraftNode(\n params as DraftNodeParams<RecordContainerShape>,\n )\n case \"text\":\n return new TextDraftNode(params as DraftNodeParams<TextContainerShape>)\n case \"tree\":\n return new TreeDraftNode(params as DraftNodeParams<TreeContainerShape>)\n default:\n throw new Error(\n `Unknown container type: ${(params.shape as ContainerShape)._type}`,\n )\n }\n}\n","import type { LoroDoc } from \"loro-crdt\"\nimport type { InferPlainType } from \"../index.js\"\nimport type { ContainerShape, DocShape } from \"../shape.js\"\nimport { DraftNode, type DraftNodeParams } from \"./base.js\"\nimport { createContainerDraftNode } from \"./utils.js\"\n\nconst containerGetter = {\n counter: \"getCounter\",\n list: \"getList\",\n map: \"getMap\",\n movableList: \"getMovableList\",\n record: \"getMap\",\n text: \"getText\",\n tree: \"getTree\",\n} as const\n\n// Draft Document class -- the actual object passed to the change `mutation` function\nexport class DraftDoc<Shape extends DocShape> extends DraftNode<Shape> {\n private doc: LoroDoc\n private propertyCache = new Map<string, DraftNode<ContainerShape>>()\n private requiredEmptyState!: InferPlainType<Shape>\n\n constructor(\n _params: Omit<DraftNodeParams<Shape>, \"getContainer\"> & { doc: LoroDoc },\n ) {\n super({\n ..._params,\n getContainer: () => {\n throw new Error(\"can't get container on DraftDoc\")\n },\n })\n if (!_params.emptyState) throw new Error(\"emptyState required\")\n this.doc = _params.doc\n this.requiredEmptyState = _params.emptyState\n this.createLazyProperties()\n }\n\n getDraftNodeParams<S extends ContainerShape>(\n key: string,\n shape: S,\n ): DraftNodeParams<ContainerShape> {\n const getter = this.doc[containerGetter[shape._type]].bind(this.doc)\n\n return {\n shape,\n emptyState: this.requiredEmptyState[key],\n getContainer: () => getter(key),\n }\n }\n\n getOrCreateDraftNode(\n key: string,\n shape: ContainerShape,\n ): DraftNode<ContainerShape> {\n let node = this.propertyCache.get(key)\n\n if (!node) {\n node = createContainerDraftNode(this.getDraftNodeParams(key, shape))\n this.propertyCache.set(key, node)\n }\n\n return node\n }\n\n private createLazyProperties(): void {\n for (const key in this.shape.shapes) {\n const shape = this.shape.shapes[key]\n Object.defineProperty(this, key, {\n get: () => this.getOrCreateDraftNode(key, shape),\n })\n }\n }\n\n absorbPlainValues(): void {\n // By iterating over the propertyCache, we achieve a small optimization\n // by only absorbing values that have been 'touched' in some way\n for (const [, node] of this.propertyCache.entries()) {\n node.absorbPlainValues()\n }\n }\n}\n","/** biome-ignore-all lint/suspicious/noExplicitAny: JSON Patch values can be any type */\n\nimport type { DocShape } from \"./shape.js\"\nimport type { Draft } from \"./types.js\"\n\n// =============================================================================\n// JSON PATCH TYPES - Discriminated Union for Type Safety\n// =============================================================================\n\nexport type JsonPatchAddOperation = {\n op: \"add\"\n path: string | (string | number)[]\n value: any\n}\n\nexport type JsonPatchRemoveOperation = {\n op: \"remove\"\n path: string | (string | number)[]\n}\n\nexport type JsonPatchReplaceOperation = {\n op: \"replace\"\n path: string | (string | number)[]\n value: any\n}\n\nexport type JsonPatchMoveOperation = {\n op: \"move\"\n path: string | (string | number)[]\n from: string | (string | number)[]\n}\n\nexport type JsonPatchCopyOperation = {\n op: \"copy\"\n path: string | (string | number)[]\n from: string | (string | number)[]\n}\n\nexport type JsonPatchTestOperation = {\n op: \"test\"\n path: string | (string | number)[]\n value: any\n}\n\nexport type JsonPatchOperation =\n | JsonPatchAddOperation\n | JsonPatchRemoveOperation\n | JsonPatchReplaceOperation\n | JsonPatchMoveOperation\n | JsonPatchCopyOperation\n | JsonPatchTestOperation\n\nexport type JsonPatch = JsonPatchOperation[]\n\n// =============================================================================\n// PATH NAVIGATION UTILITIES\n// =============================================================================\n\n/**\n * Normalize JSON Pointer string to path array\n * Handles RFC 6901 escaping: ~1 -> /, ~0 -> ~\n */\nexport function normalizePath(\n path: string | (string | number)[],\n): (string | number)[] {\n if (Array.isArray(path)) {\n return path\n }\n\n // Handle JSON Pointer format (RFC 6901)\n if (path.startsWith(\"/\")) {\n return path\n .slice(1) // Remove leading slash\n .split(\"/\")\n .map(segment => {\n // Handle JSON Pointer escaping\n const unescaped = segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\")\n // Try to parse as number for array indices\n const asNumber = Number(unescaped)\n return Number.isInteger(asNumber) && asNumber >= 0\n ? asNumber\n : unescaped\n })\n }\n\n // Handle simple dot notation or single segment\n return path.split(\".\").map(segment => {\n const asNumber = Number(segment)\n return Number.isInteger(asNumber) && asNumber >= 0 ? asNumber : segment\n })\n}\n\n/**\n * Navigate to a target path using natural DraftNode property access\n * This follows the existing patterns from the test suite\n */\nfunction navigateToPath<T extends DocShape>(\n draft: Draft<T>,\n path: (string | number)[],\n): { parent: any; key: string | number } {\n if (path.length === 0) {\n throw new Error(\"Cannot navigate to empty path\")\n }\n\n let current = draft as any\n\n // Navigate to parent of target\n for (let i = 0; i < path.length - 1; i++) {\n const segment = path[i]\n\n if (typeof segment === \"string\") {\n // Use natural property access - this leverages existing DraftNode lazy creation\n current = current[segment]\n if (current === undefined) {\n throw new Error(`Cannot navigate to path segment: ${segment}`)\n }\n } else if (typeof segment === \"number\") {\n // List/array access using get() method (following existing patterns)\n if (current.get && typeof current.get === \"function\") {\n current = current.get(segment)\n if (current === undefined) {\n throw new Error(`List index ${segment} does not exist`)\n }\n } else {\n throw new Error(`Cannot use numeric index ${segment} on non-list`)\n }\n } else {\n throw new Error(`Invalid path segment type: ${typeof segment}`)\n }\n }\n\n const targetKey = path[path.length - 1]\n return { parent: current, key: targetKey }\n}\n\n/**\n * Get value at path using natural DraftNode access patterns\n */\nfunction getValueAtPath<T extends DocShape>(\n draft: Draft<T>,\n path: (string | number)[],\n): any {\n if (path.length === 0) {\n return draft\n }\n\n const { parent, key } = navigateToPath(draft, path)\n\n if (typeof key === \"string\") {\n // Use natural property access or get() method\n if (parent.get && typeof parent.get === \"function\") {\n return parent.get(key)\n }\n return parent[key]\n } else if (typeof key === \"number\") {\n // List access using get() method\n if (parent.get && typeof parent.get === \"function\") {\n return parent.get(key)\n }\n throw new Error(`Cannot use numeric index ${key} on non-list`)\n }\n\n throw new Error(`Invalid key type: ${typeof key}`)\n}\n\n// =============================================================================\n// OPERATION HANDLERS - Following existing DraftNode patterns\n// =============================================================================\n\n/**\n * Handle 'add' operation using existing DraftNode methods\n */\nfunction handleAdd<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchAddOperation,\n): void {\n const path = normalizePath(operation.path)\n const { parent, key } = navigateToPath(draft, path)\n\n if (typeof key === \"string\") {\n // Map-like operations - use natural assignment or set() method\n if (parent.set && typeof parent.set === \"function\") {\n parent.set(key, operation.value)\n } else {\n // Natural property assignment (follows existing test patterns)\n parent[key] = operation.value\n }\n } else if (typeof key === \"number\") {\n // List operations - use insert() method (follows existing patterns)\n if (parent.insert && typeof parent.insert === \"function\") {\n parent.insert(key, operation.value)\n } else {\n throw new Error(`Cannot insert at numeric index ${key} on non-list`)\n }\n } else {\n throw new Error(`Invalid key type: ${typeof key}`)\n }\n}\n\n/**\n * Handle 'remove' operation using existing DraftNode methods\n */\nfunction handleRemove<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchRemoveOperation,\n): void {\n const path = normalizePath(operation.path)\n const { parent, key } = navigateToPath(draft, path)\n\n if (typeof key === \"string\") {\n // Map-like operations - use delete() method (follows existing patterns)\n if (parent.delete && typeof parent.delete === \"function\") {\n parent.delete(key)\n } else {\n delete parent[key]\n }\n } else if (typeof key === \"number\") {\n // List operations - use delete() method with count (follows existing patterns)\n if (parent.delete && typeof parent.delete === \"function\") {\n parent.delete(key, 1)\n } else {\n throw new Error(`Cannot remove at numeric index ${key} on non-list`)\n }\n } else {\n throw new Error(`Invalid key type: ${typeof key}`)\n }\n}\n\n/**\n * Handle 'replace' operation using existing DraftNode methods\n */\nfunction handleReplace<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchReplaceOperation,\n): void {\n const path = normalizePath(operation.path)\n const { parent, key } = navigateToPath(draft, path)\n\n if (typeof key === \"string\") {\n // Map-like operations - use set() method or natural assignment\n if (parent.set && typeof parent.set === \"function\") {\n parent.set(key, operation.value)\n } else {\n parent[key] = operation.value\n }\n } else if (typeof key === \"number\") {\n // List operations - delete then insert (follows existing patterns)\n if (\n parent.delete &&\n parent.insert &&\n typeof parent.delete === \"function\" &&\n typeof parent.insert === \"function\"\n ) {\n parent.delete(key, 1)\n parent.insert(key, operation.value)\n } else {\n throw new Error(`Cannot replace at numeric index ${key} on non-list`)\n }\n } else {\n throw new Error(`Invalid key type: ${typeof key}`)\n }\n}\n\n/**\n * Handle 'move' operation using existing DraftNode methods\n */\nfunction handleMove<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchMoveOperation,\n): void {\n const fromPath = normalizePath(operation.from)\n const toPath = normalizePath(operation.path)\n\n // For list moves within the same parent, we need special handling\n if (\n fromPath.length === toPath.length &&\n fromPath.slice(0, -1).every((segment, i) => segment === toPath[i])\n ) {\n // Same parent container - use list move operation if available\n const fromIndex = fromPath[fromPath.length - 1]\n const toIndex = toPath[toPath.length - 1]\n\n if (typeof fromIndex === \"number\" && typeof toIndex === \"number\") {\n const { parent } = navigateToPath(draft, fromPath.slice(0, -1))\n\n // Check if the parent has a move method (like LoroMovableList)\n if (parent.move && typeof parent.move === \"function\") {\n parent.move(fromIndex, toIndex)\n return\n }\n\n // Otherwise, get value, remove, then add at target index\n const value = getValueAtPath(draft, fromPath)\n handleRemove(draft, { op: \"remove\", path: operation.from })\n\n // For JSON Patch move semantics, the target index refers to the position\n // in the final array, not the intermediate array after removal.\n // No index adjustment needed - use the original target index.\n handleAdd(draft, { op: \"add\", path: operation.path, value })\n return\n }\n }\n\n // Different parents or non-numeric indices - standard move\n const value = getValueAtPath(draft, fromPath)\n handleRemove(draft, { op: \"remove\", path: operation.from })\n handleAdd(draft, { op: \"add\", path: operation.path, value })\n}\n\n/**\n * Handle 'copy' operation using existing DraftNode methods\n */\nfunction handleCopy<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchCopyOperation,\n): void {\n const fromPath = normalizePath(operation.from)\n\n // Get the value to copy\n const value = getValueAtPath(draft, fromPath)\n\n // Add to destination (no removal)\n handleAdd(draft, { op: \"add\", path: operation.path, value })\n}\n\n/**\n * Handle 'test' operation using existing DraftNode value access\n */\nfunction handleTest<T extends DocShape>(\n draft: Draft<T>,\n operation: JsonPatchTestOperation,\n): boolean {\n const path = normalizePath(operation.path)\n const actualValue = getValueAtPath(draft, path)\n\n // Deep equality check for test operation\n return JSON.stringify(actualValue) === JSON.stringify(operation.value)\n}\n\n// =============================================================================\n// MAIN APPLICATOR - Simple orchestration following existing patterns\n// =============================================================================\n\n/**\n * Main JSON Patch applicator - follows existing change() patterns\n */\nexport class JsonPatchApplicator<T extends DocShape> {\n constructor(private rootDraft: Draft<T>) {}\n\n /**\n * Apply a single JSON Patch operation\n */\n applyOperation(operation: JsonPatchOperation): void {\n switch (operation.op) {\n case \"add\":\n handleAdd(this.rootDraft, operation)\n break\n case \"remove\":\n handleRemove(this.rootDraft, operation)\n break\n case \"replace\":\n handleReplace(this.rootDraft, operation)\n break\n case \"move\":\n handleMove(this.rootDraft, operation)\n break\n case \"copy\":\n handleCopy(this.rootDraft, operation)\n break\n case \"test\":\n if (!handleTest(this.rootDraft, operation)) {\n throw new Error(`JSON Patch test failed at path: ${operation.path}`)\n }\n break\n default:\n // TypeScript will catch this at compile time with proper discriminated union\n throw new Error(\n `Unsupported JSON Patch operation: ${(operation as any).op}`,\n )\n }\n }\n\n /**\n * Apply multiple JSON Patch operations in sequence\n */\n applyPatch(patch: JsonPatch): void {\n for (const operation of patch) {\n this.applyOperation(operation)\n }\n }\n}\n","import type { Value } from \"loro-crdt\"\nimport type { ContainerShape, DocShape, ValueShape } from \"./shape.js\"\nimport { isObjectValue } from \"./utils/type-guards.js\"\n\n/**\n * Overlays CRDT state with empty state defaults\n */\nexport function overlayEmptyState<Shape extends DocShape>(\n shape: Shape,\n crdtValue: { [key: string]: Value },\n emptyValue: { [key: string]: Value },\n): { [key: string]: Value } {\n if (typeof crdtValue !== \"object\") {\n throw new Error(\"crdt object is required\")\n }\n\n if (typeof emptyValue !== \"object\") {\n throw new Error(\"empty object is required\")\n }\n\n const result = { ...emptyValue }\n\n for (const [key, propShape] of Object.entries(shape.shapes)) {\n const propCrdtValue = crdtValue[key]\n\n const propEmptyValue = emptyValue[key as keyof typeof emptyValue]\n\n result[key as keyof typeof result] = mergeValue(\n propShape,\n propCrdtValue,\n propEmptyValue,\n )\n }\n\n return result\n}\n\n/**\n * Merges individual CRDT values with empty state defaults\n */\nexport function mergeValue<Shape extends ContainerShape | ValueShape>(\n shape: Shape,\n crdtValue: Value,\n emptyValue: Value,\n): Value {\n if (crdtValue === undefined && emptyValue === undefined) {\n throw new Error(\"either crdt or empty value must be defined\")\n }\n\n switch (shape._type) {\n case \"text\":\n return crdtValue ?? emptyValue ?? \"\"\n case \"counter\":\n return crdtValue ?? emptyValue ?? 0\n case \"list\":\n case \"movableList\":\n return crdtValue ?? emptyValue ?? []\n case \"map\": {\n if (!isObjectValue(crdtValue) && crdtValue !== undefined) {\n throw new Error(\"map crdt must be object\")\n }\n\n const crdtMapValue = crdtValue ?? {}\n\n if (!isObjectValue(emptyValue) && emptyValue !== undefined) {\n throw new Error(\"map empty state must be object\")\n }\n\n const emptyMapValue = emptyValue ?? {}\n\n const result = { ...emptyMapValue }\n for (const [key, nestedShape] of Object.entries(shape.shapes)) {\n const nestedCrdtValue = crdtMapValue[key]\n const nestedEmptyValue = emptyMapValue[key]\n\n result[key as keyof typeof result] = mergeValue(\n nestedShape,\n nestedCrdtValue,\n nestedEmptyValue,\n )\n }\n\n return result\n }\n case \"tree\":\n return crdtValue ?? emptyValue ?? []\n default:\n if (shape._type === \"value\" && shape.valueType === \"object\") {\n const crdtObj = (crdtValue as any) ?? {}\n const emptyObj = (emptyValue as any) ?? {}\n const result = { ...emptyObj }\n\n if (typeof crdtObj !== \"object\" || crdtObj === null) {\n return crdtValue ?? emptyValue\n }\n\n for (const [key, propShape] of Object.entries(shape.shape)) {\n const propCrdt = crdtObj[key]\n const propEmpty = emptyObj[key]\n result[key] = mergeValue(propShape, propCrdt, propEmpty)\n }\n return result\n }\n return crdtValue ?? emptyValue\n }\n}\n","import type {\n ArrayValueShape,\n ContainerOrValueShape,\n DocShape,\n ListContainerShape,\n MapContainerShape,\n MovableListContainerShape,\n ObjectValueShape,\n RecordContainerShape,\n RecordValueShape,\n StringValueShape,\n UnionValueShape,\n ValueShape,\n} from \"./shape.js\"\nimport type { InferPlainType } from \"./types.js\"\n\n/**\n * Validates a value against a ContainerShape or ValueShape schema\n */\nexport function validateValue(\n value: unknown,\n schema: ContainerOrValueShape,\n path: string = \"\",\n): unknown {\n if (!schema || typeof schema !== \"object\" || !(\"_type\" in schema)) {\n throw new Error(`Invalid schema at path ${path}: missing _type`)\n }\n\n const currentPath = path || \"root\"\n\n // Handle ContainerShape types\n if (schema._type === \"text\") {\n if (typeof value !== \"string\") {\n throw new Error(\n `Expected string at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n }\n\n if (schema._type === \"counter\") {\n if (typeof value !== \"number\") {\n throw new Error(\n `Expected number at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n }\n\n if (schema._type === \"list\" || schema._type === \"movableList\") {\n if (!Array.isArray(value)) {\n throw new Error(\n `Expected array at path ${currentPath}, got ${typeof value}`,\n )\n }\n const listSchema = schema as ListContainerShape | MovableListContainerShape\n return value.map((item, index) =>\n validateValue(item, listSchema.shape, `${currentPath}[${index}]`),\n )\n }\n\n if (schema._type === \"map\") {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\n `Expected object at path ${currentPath}, got ${typeof value}`,\n )\n }\n const mapSchema = schema as MapContainerShape\n const result: Record<string, unknown> = {}\n\n // Validate each property in the map shape\n for (const [key, nestedSchema] of Object.entries(mapSchema.shapes)) {\n const nestedPath = `${currentPath}.${key}`\n const nestedValue = (value as Record<string, unknown>)[key]\n result[key] = validateValue(nestedValue, nestedSchema, nestedPath)\n }\n return result\n }\n\n if (schema._type === \"record\") {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\n `Expected object at path ${currentPath}, got ${typeof value}`,\n )\n }\n const recordSchema = schema as RecordContainerShape\n const result: Record<string, unknown> = {}\n\n // Validate each property in the record\n for (const [key, nestedValue] of Object.entries(value)) {\n const nestedPath = `${currentPath}.${key}`\n result[key] = validateValue(nestedValue, recordSchema.shape, nestedPath)\n }\n return result\n }\n\n if (schema._type === \"tree\") {\n if (!Array.isArray(value)) {\n throw new Error(\n `Expected array for tree at path ${currentPath}, got ${typeof value}`,\n )\n }\n // Trees can contain any structure, so we just validate it's an array\n return value\n }\n\n // Handle ValueShape types\n if (schema._type === \"value\") {\n const valueSchema = schema as ValueShape\n\n switch (valueSchema.valueType) {\n case \"string\": {\n if (typeof value !== \"string\") {\n throw new Error(\n `Expected string at path ${currentPath}, got ${typeof value}`,\n )\n }\n const stringSchema = valueSchema as StringValueShape\n if (stringSchema.options && !stringSchema.options.includes(value)) {\n throw new Error(\n `Expected one of [${stringSchema.options.join(\", \")}] at path ${currentPath}, got \"${value}\"`,\n )\n }\n return value\n }\n\n case \"number\":\n if (typeof value !== \"number\") {\n throw new Error(\n `Expected number at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n throw new Error(\n `Expected boolean at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"null\":\n if (value !== null) {\n throw new Error(\n `Expected null at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"undefined\":\n if (value !== undefined) {\n throw new Error(\n `Expected undefined at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"uint8array\":\n if (!(value instanceof Uint8Array)) {\n throw new Error(\n `Expected Uint8Array at path ${currentPath}, got ${typeof value}`,\n )\n }\n return value\n\n case \"object\": {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\n `Expected object at path ${currentPath}, got ${typeof value}`,\n )\n }\n const objectSchema = valueSchema as ObjectValueShape\n const result: Record<string, unknown> = {}\n\n // Validate each property in the object shape\n for (const [key, nestedSchema] of Object.entries(objectSchema.shape)) {\n const nestedPath = `${currentPath}.${key}`\n const nestedValue = (value as Record<string, unknown>)[key]\n result[key] = validateValue(nestedValue, nestedSchema, nestedPath)\n }\n return result\n }\n\n case \"record\": {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\n `Expected object at path ${currentPath}, got ${typeof value}`,\n )\n }\n const recordSchema = valueSchema as RecordValueShape\n const result: Record<string, unknown> = {}\n\n // Validate each property in the record\n for (const [key, nestedValue] of Object.entries(value)) {\n const nestedPath = `${currentPath}.${key}`\n result[key] = validateValue(\n nestedValue,\n recordSchema.shape,\n nestedPath,\n )\n }\n return result\n }\n\n case \"array\": {\n if (!Array.isArray(value)) {\n throw new Error(\n `Expected array at path ${currentPath}, got ${typeof value}`,\n )\n }\n const arraySchema = valueSchema as ArrayValueShape\n return value.map((item, index) =>\n validateValue(item, arraySchema.shape, `${currentPath}[${index}]`),\n )\n }\n\n case \"union\": {\n const unionSchema = valueSchema as UnionValueShape\n let lastError: Error | null = null\n\n // Try to validate against each shape in the union\n for (const shape of unionSchema.shapes) {\n try {\n return validateValue(value, shape, currentPath)\n } catch (error) {\n lastError = error as Error\n }\n }\n\n throw new Error(\n `Value at path ${currentPath} does not match any union type: ${lastError?.message}`,\n )\n }\n\n default:\n throw new Error(`Unknown value type: ${(valueSchema as any).valueType}`)\n }\n }\n\n throw new Error(`Unknown schema type: ${(schema as any)._type}`)\n}\n\n/**\n * Validates empty state against schema structure without using Zod\n * Combines the functionality of createEmptyStateValidator and createValueValidator\n */\nexport function validateEmptyState<T extends DocShape>(\n emptyState: unknown,\n schema: T,\n): InferPlainType<T> {\n if (\n !emptyState ||\n typeof emptyState !== \"object\" ||\n Array.isArray(emptyState)\n ) {\n throw new Error(\"Empty state must be an object\")\n }\n\n const result: Record<string, unknown> = {}\n\n // Validate each property in the document schema\n for (const [key, schemaValue] of Object.entries(schema.shapes)) {\n const value = (emptyState as Record<string, unknown>)[key]\n result[key] = validateValue(value, schemaValue, key)\n }\n\n return result as InferPlainType<T>\n}\n","// biome-ignore-all lint/suspicious/noExplicitAny: required\n\nimport type {\n LoroCounter,\n LoroList,\n LoroMap,\n LoroMovableList,\n LoroText,\n LoroTree,\n} from \"loro-crdt\"\n\nimport type { CounterDraftNode } from \"./draft-nodes/counter.js\"\nimport type { ListDraftNode } from \"./draft-nodes/list.js\"\nimport type { MapDraftNode } from \"./draft-nodes/map.js\"\nimport type { MovableListDraftNode } from \"./draft-nodes/movable-list.js\"\nimport type { RecordDraftNode } from \"./draft-nodes/record.js\"\nimport type { TextDraftNode } from \"./draft-nodes/text.js\"\n\nexport interface Shape<Plain, Draft> {\n readonly _type: string\n readonly _plain: Plain\n readonly _draft: Draft\n}\n\nexport interface DocShape<\n NestedShapes extends Record<string, ContainerShape> = Record<\n string,\n ContainerShape\n >,\n> extends Shape<\n { [K in keyof NestedShapes]: NestedShapes[K][\"_plain\"] },\n { [K in keyof NestedShapes]: NestedShapes[K][\"_draft\"] }\n > {\n readonly _type: \"doc\"\n // A doc's root containers each separately has its own shape, hence 'shapes'\n readonly shapes: NestedShapes\n}\n\nexport interface TextContainerShape extends Shape<string, TextDraftNode> {\n readonly _type: \"text\"\n}\nexport interface CounterContainerShape extends Shape<number, CounterDraftNode> {\n readonly _type: \"counter\"\n}\nexport interface TreeContainerShape<NestedShape = ContainerOrValueShape>\n extends Shape<any, any> {\n readonly _type: \"tree\"\n // TODO(duane): What does a tree contain? One type, or many?\n readonly shape: NestedShape\n}\n\n// Container schemas using interfaces for recursive references\nexport interface ListContainerShape<\n NestedShape extends ContainerOrValueShape = ContainerOrValueShape,\n> extends Shape<NestedShape[\"_plain\"][], ListDraftNode<NestedShape>> {\n readonly _type: \"list\"\n // A list contains many elements, all of the same 'shape'\n readonly shape: NestedShape\n}\n\nexport interface MovableListContainerShape<\n NestedShape extends ContainerOrValueShape = ContainerOrValueShape,\n> extends Shape<NestedShape[\"_plain\"][], MovableListDraftNode<NestedShape>> {\n readonly _type: \"movableList\"\n // A list contains many elements, all of the same 'shape'\n readonly shape: NestedShape\n}\n\nexport interface MapContainerShape<\n NestedShapes extends Record<string, ContainerOrValueShape> = Record<\n string,\n ContainerOrValueShape\n >,\n> extends Shape<\n { [K in keyof NestedShapes]: NestedShapes[K][\"_plain\"] },\n MapDraftNode<NestedShapes> & {\n [K in keyof NestedShapes]: NestedShapes[K][\"_draft\"]\n }\n > {\n readonly _type: \"map\"\n // Each map property has its own shape, hence 'shapes'\n readonly shapes: NestedShapes\n}\n\nexport interface RecordContainerShape<\n NestedShape extends ContainerOrValueShape = ContainerOrValueShape,\n> extends Shape<\n Record<string, NestedShape[\"_plain\"]>,\n RecordDraftNode<NestedShape>\n > {\n readonly _type: \"record\"\n readonly shape: NestedShape\n}\n\nexport type ContainerShape =\n | CounterContainerShape\n | ListContainerShape\n | MapContainerShape\n | MovableListContainerShape\n | RecordContainerShape\n | TextContainerShape\n | TreeContainerShape\n\nexport type ContainerType = ContainerShape[\"_type\"]\n\n// LoroValue shape types - a shape for each of Loro's Value types\nexport interface StringValueShape<T extends string = string>\n extends Shape<T, T> {\n readonly _type: \"value\"\n readonly valueType: \"string\"\n readonly options?: T[]\n}\nexport interface NumberValueShape extends Shape<number, number> {\n readonly _type: \"value\"\n readonly valueType: \"number\"\n}\nexport interface BooleanValueShape extends Shape<boolean, boolean> {\n readonly _type: \"value\"\n readonly valueType: \"boolean\"\n}\nexport interface NullValueShape extends Shape<null, null> {\n readonly _type: \"value\"\n readonly valueType: \"null\"\n}\nexport interface UndefinedValueShape extends Shape<undefined, undefined> {\n readonly _type: \"value\"\n readonly valueType: \"undefined\"\n}\nexport interface Uint8ArrayValueShape extends Shape<Uint8Array, Uint8Array> {\n readonly _type: \"value\"\n readonly valueType: \"uint8array\"\n}\n\nexport interface ObjectValueShape<\n T extends Record<string, ValueShape> = Record<string, ValueShape>,\n> extends Shape<\n { [K in keyof T]: T[K][\"_plain\"] },\n { [K in keyof T]: T[K][\"_draft\"] }\n > {\n readonly _type: \"value\"\n readonly valueType: \"object\"\n readonly shape: T\n}\n\nexport interface RecordValueShape<T extends ValueShape = ValueShape>\n extends Shape<Record<string, T[\"_plain\"]>, Record<string, T[\"_draft\"]>> {\n readonly _type: \"value\"\n readonly valueType: \"record\"\n readonly shape: T\n}\n\nexport interface ArrayValueShape<T extends ValueShape = ValueShape>\n extends Shape<T[\"_plain\"][], T[\"_draft\"][]> {\n readonly _type: \"value\"\n readonly valueType: \"array\"\n readonly shape: T\n}\n\nexport interface UnionValueShape<T extends ValueShape[] = ValueShape[]>\n extends Shape<T[number][\"_plain\"], T[number][\"_draft\"]> {\n readonly _type: \"value\"\n readonly valueType: \"union\"\n readonly shapes: T\n}\n\n// Union of all ValueShapes - these can only contain other ValueShapes, not ContainerShapes\nexport type ValueShape =\n | StringValueShape\n | NumberValueShape\n | BooleanValueShape\n | NullValueShape\n | UndefinedValueShape\n | Uint8ArrayValueShape\n | ObjectValueShape\n | RecordValueShape\n | ArrayValueShape\n | UnionValueShape\n\nexport type ContainerOrValueShape = ContainerShape | ValueShape\n\n/**\n * The LoroShape factory object\n *\n * If a container has a `shape` type variable, it refers to the shape it contains--\n * so for example, a `LoroShape.list(LoroShape.text())` would return a value of type\n * `ListContainerShape<TextContainerShape>`.\n */\nexport const Shape = {\n doc: <T extends Record<string, ContainerShape>>(shape: T): DocShape<T> => ({\n _type: \"doc\" as const,\n shapes: shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n // CRDTs are represented by Loro Containers--they converge on state using Loro's\n // various CRDT algorithms\n counter: (): CounterContainerShape => ({\n _type: \"counter\" as const,\n _plain: 0,\n _draft: {} as CounterDraftNode,\n }),\n\n list: <T extends ContainerOrValueShape>(shape: T): ListContainerShape<T> => ({\n _type: \"list\" as const,\n shape,\n _plain: [] as any,\n _draft: {} as any,\n }),\n\n map: <T extends Record<string, ContainerOrValueShape>>(\n shape: T,\n ): MapContainerShape<T> => ({\n _type: \"map\" as const,\n shapes: shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n record: <T extends ContainerOrValueShape>(\n shape: T,\n ): RecordContainerShape<T> => ({\n _type: \"record\" as const,\n shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n movableList: <T extends ContainerOrValueShape>(\n shape: T,\n ): MovableListContainerShape<T> => ({\n _type: \"movableList\" as const,\n shape,\n _plain: [] as any,\n _draft: {} as any,\n }),\n\n text: (): TextContainerShape => ({\n _type: \"text\" as const,\n _plain: \"\",\n _draft: {} as TextDraftNode,\n }),\n\n tree: <T extends MapContainerShape>(shape: T): TreeContainerShape => ({\n _type: \"tree\" as const,\n shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n // Values are represented as plain JS objects, with the limitation that they MUST be\n // representable as a Loro \"Value\"--basically JSON. The behavior of a Value is basically\n // \"Last Write Wins\", meaning there is no subtle convergent behavior here, just taking\n // the most recent value based on the current available information.\n plain: {\n string: <T extends string = string>(\n ...options: T[]\n ): StringValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"string\" as const,\n _plain: (options[0] ?? \"\") as T,\n _draft: (options[0] ?? \"\") as T,\n options: options.length > 0 ? options : undefined,\n }),\n\n number: (): NumberValueShape => ({\n _type: \"value\" as const,\n valueType: \"number\" as const,\n _plain: 0,\n _draft: 0,\n }),\n\n boolean: (): BooleanValueShape => ({\n _type: \"value\" as const,\n valueType: \"boolean\" as const,\n _plain: false,\n _draft: false,\n }),\n\n null: (): NullValueShape => ({\n _type: \"value\" as const,\n valueType: \"null\" as const,\n _plain: null,\n _draft: null,\n }),\n\n undefined: (): UndefinedValueShape => ({\n _type: \"value\" as const,\n valueType: \"undefined\" as const,\n _plain: undefined,\n _draft: undefined,\n }),\n\n uint8Array: (): Uint8ArrayValueShape => ({\n _type: \"value\" as const,\n valueType: \"uint8array\" as const,\n _plain: new Uint8Array(),\n _draft: new Uint8Array(),\n }),\n\n object: <T extends Record<string, ValueShape>>(\n shape: T,\n ): ObjectValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"object\" as const,\n shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n record: <T extends ValueShape>(shape: T): RecordValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"record\" as const,\n shape,\n _plain: {} as any,\n _draft: {} as any,\n }),\n\n array: <T extends ValueShape>(shape: T): ArrayValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"array\" as const,\n shape,\n _plain: [] as any,\n _draft: [] as any,\n }),\n\n // Special value type that helps make things like `string | null` representable\n // TODO(duane): should this be a more general type for containers too?\n union: <T extends ValueShape[]>(shapes: T): UnionValueShape<T> => ({\n _type: \"value\" as const,\n valueType: \"union\" as const,\n shapes,\n _plain: {} as any,\n _draft: {} as any,\n }),\n },\n}\n\n// Add this type mapping near the top of your file, after the imports\nexport type ShapeToContainer<T extends DocShape | ContainerShape> =\n T extends TextContainerShape\n ? LoroText\n : T extends CounterContainerShape\n ? LoroCounter\n : T extends ListContainerShape\n ? LoroList\n : T extends MovableListContainerShape\n ? LoroMovableList\n : T extends MapContainerShape | RecordContainerShape\n ? LoroMap\n : T extends TreeContainerShape\n ? LoroTree\n : never // not a container\n"],"mappings":"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","names":["LoroCounter","LoroList","LoroMap","LoroMovableList","LoroText","LoroCounter","LoroList","LoroMap","LoroMovableList","LoroText","LoroCounter","LoroList","LoroMap","LoroMovableList","LoroText","LoroTree","containerConstructor","LoroCounter","LoroList","LoroMap","LoroMovableList","LoroText","LoroTree","value"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loro-extended/change",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A schema-driven, type-safe wrapper for Loro CRDT that provides natural JavaScript syntax for collaborative data mutations",
|
|
5
5
|
"author": "Duane Johnson",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"./src/*": "./src/*"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"loro-crdt": "^1.
|
|
24
|
+
"loro-crdt": "^1.10.2"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"tsup": "^8.5.0",
|
package/src/conversion.ts
CHANGED
|
@@ -30,10 +30,7 @@ import {
|
|
|
30
30
|
function convertTextInput(value: string): LoroText {
|
|
31
31
|
const text = new LoroText()
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
if (value.length > 0) {
|
|
35
|
-
text.insert(0, value)
|
|
36
|
-
}
|
|
33
|
+
text.insert(0, value)
|
|
37
34
|
|
|
38
35
|
return text
|
|
39
36
|
}
|
package/src/draft-nodes/text.ts
CHANGED
|
@@ -9,8 +9,6 @@ export class TextDraftNode extends DraftNode<TextContainerShape> {
|
|
|
9
9
|
|
|
10
10
|
// Text methods
|
|
11
11
|
insert(index: number, content: string): void {
|
|
12
|
-
// TODO(duane): condition can be removed when https://github.com/loro-dev/loro/issues/872 is addressed
|
|
13
|
-
if (content.length === 0) return
|
|
14
12
|
this.container.insert(index, content)
|
|
15
13
|
}
|
|
16
14
|
|
package/src/overlay.ts
CHANGED
|
@@ -85,6 +85,22 @@ export function mergeValue<Shape extends ContainerShape | ValueShape>(
|
|
|
85
85
|
case "tree":
|
|
86
86
|
return crdtValue ?? emptyValue ?? []
|
|
87
87
|
default:
|
|
88
|
+
if (shape._type === "value" && shape.valueType === "object") {
|
|
89
|
+
const crdtObj = (crdtValue as any) ?? {}
|
|
90
|
+
const emptyObj = (emptyValue as any) ?? {}
|
|
91
|
+
const result = { ...emptyObj }
|
|
92
|
+
|
|
93
|
+
if (typeof crdtObj !== "object" || crdtObj === null) {
|
|
94
|
+
return crdtValue ?? emptyValue
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const [key, propShape] of Object.entries(shape.shape)) {
|
|
98
|
+
const propCrdt = crdtObj[key]
|
|
99
|
+
const propEmpty = emptyObj[key]
|
|
100
|
+
result[key] = mergeValue(propShape, propCrdt, propEmpty)
|
|
101
|
+
}
|
|
102
|
+
return result
|
|
103
|
+
}
|
|
88
104
|
return crdtValue ?? emptyValue
|
|
89
105
|
}
|
|
90
106
|
}
|
package/src/shape.ts
CHANGED
|
@@ -104,9 +104,11 @@ export type ContainerShape =
|
|
|
104
104
|
export type ContainerType = ContainerShape["_type"]
|
|
105
105
|
|
|
106
106
|
// LoroValue shape types - a shape for each of Loro's Value types
|
|
107
|
-
export interface StringValueShape extends
|
|
107
|
+
export interface StringValueShape<T extends string = string>
|
|
108
|
+
extends Shape<T, T> {
|
|
108
109
|
readonly _type: "value"
|
|
109
110
|
readonly valueType: "string"
|
|
111
|
+
readonly options?: T[]
|
|
110
112
|
}
|
|
111
113
|
export interface NumberValueShape extends Shape<number, number> {
|
|
112
114
|
readonly _type: "value"
|
|
@@ -251,11 +253,14 @@ export const Shape = {
|
|
|
251
253
|
// "Last Write Wins", meaning there is no subtle convergent behavior here, just taking
|
|
252
254
|
// the most recent value based on the current available information.
|
|
253
255
|
plain: {
|
|
254
|
-
string:
|
|
256
|
+
string: <T extends string = string>(
|
|
257
|
+
...options: T[]
|
|
258
|
+
): StringValueShape<T> => ({
|
|
255
259
|
_type: "value" as const,
|
|
256
260
|
valueType: "string" as const,
|
|
257
|
-
_plain: "",
|
|
258
|
-
_draft: "",
|
|
261
|
+
_plain: (options[0] ?? "") as T,
|
|
262
|
+
_draft: (options[0] ?? "") as T,
|
|
263
|
+
options: options.length > 0 ? options : undefined,
|
|
259
264
|
}),
|
|
260
265
|
|
|
261
266
|
number: (): NumberValueShape => ({
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest"
|
|
2
|
+
import { Shape } from "./shape.js"
|
|
3
|
+
import { validateValue } from "./validation.js"
|
|
4
|
+
|
|
5
|
+
describe("String Literal Shape", () => {
|
|
6
|
+
it("should support type inference for string unions", () => {
|
|
7
|
+
const schema = Shape.plain.string<"user" | "ai">()
|
|
8
|
+
|
|
9
|
+
// This is a type-level check, we can't easily assert it at runtime without options
|
|
10
|
+
// But we can check that it validates strings
|
|
11
|
+
expect(validateValue("user", schema)).toBe("user")
|
|
12
|
+
expect(validateValue("ai", schema)).toBe("ai")
|
|
13
|
+
expect(validateValue("other", schema)).toBe("other") // No runtime validation without options
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it("should support runtime validation when options are provided", () => {
|
|
17
|
+
const schema = Shape.plain.string("user", "ai")
|
|
18
|
+
|
|
19
|
+
expect(validateValue("user", schema)).toBe("user")
|
|
20
|
+
expect(validateValue("ai", schema)).toBe("ai")
|
|
21
|
+
|
|
22
|
+
expect(() => validateValue("other", schema)).toThrow(
|
|
23
|
+
'Expected one of [user, ai] at path root, got "other"',
|
|
24
|
+
)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it("should work with single option", () => {
|
|
28
|
+
const schema = Shape.plain.string("fixed")
|
|
29
|
+
|
|
30
|
+
expect(validateValue("fixed", schema)).toBe("fixed")
|
|
31
|
+
expect(() => validateValue("other", schema)).toThrow(
|
|
32
|
+
'Expected one of [fixed] at path root, got "other"',
|
|
33
|
+
)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it("should maintain backward compatibility", () => {
|
|
37
|
+
const schema = Shape.plain.string()
|
|
38
|
+
|
|
39
|
+
expect(validateValue("any", schema)).toBe("any")
|
|
40
|
+
expect(validateValue("", schema)).toBe("")
|
|
41
|
+
})
|
|
42
|
+
})
|
package/src/utils/type-guards.ts
CHANGED
package/src/validation.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
ObjectValueShape,
|
|
9
9
|
RecordContainerShape,
|
|
10
10
|
RecordValueShape,
|
|
11
|
+
StringValueShape,
|
|
11
12
|
UnionValueShape,
|
|
12
13
|
ValueShape,
|
|
13
14
|
} from "./shape.js"
|
|
@@ -108,13 +109,20 @@ export function validateValue(
|
|
|
108
109
|
const valueSchema = schema as ValueShape
|
|
109
110
|
|
|
110
111
|
switch (valueSchema.valueType) {
|
|
111
|
-
case "string":
|
|
112
|
+
case "string": {
|
|
112
113
|
if (typeof value !== "string") {
|
|
113
114
|
throw new Error(
|
|
114
115
|
`Expected string at path ${currentPath}, got ${typeof value}`,
|
|
115
116
|
)
|
|
116
117
|
}
|
|
118
|
+
const stringSchema = valueSchema as StringValueShape
|
|
119
|
+
if (stringSchema.options && !stringSchema.options.includes(value)) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
`Expected one of [${stringSchema.options.join(", ")}] at path ${currentPath}, got "${value}"`,
|
|
122
|
+
)
|
|
123
|
+
}
|
|
117
124
|
return value
|
|
125
|
+
}
|
|
118
126
|
|
|
119
127
|
case "number":
|
|
120
128
|
if (typeof value !== "number") {
|