json-patch-to-crdt 0.1.0 → 0.1.1
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 +5 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/internals.d.mts +2 -2
- package/dist/internals.d.ts +2 -2
- package/dist/internals.js +1 -1
- package/dist/internals.mjs +1 -1
- package/dist/{merge-BrNGGkXj.d.mts → merge-B8nmGV-o.d.ts} +11 -2
- package/dist/{merge-CtJfKEt1.js → merge-BAfuC6bf.js} +162 -21
- package/dist/{merge-BqROEw61.mjs → merge-CKcP1ZPt.mjs} +162 -21
- package/dist/{merge-DW1-p9Hj.d.ts → merge-DQ_KDtnE.d.mts} +11 -2
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -64,6 +64,7 @@ import { applyPatch, createState, forkState, mergeState, toJson } from "json-pat
|
|
|
64
64
|
const origin = createState({ count: 0, items: ["a"] }, { actor: "origin" });
|
|
65
65
|
|
|
66
66
|
// Fork shared-origin replicas with local actor identities.
|
|
67
|
+
// Actor IDs must be unique per live peer (same-actor reuse is rejected by default).
|
|
67
68
|
const peerA = forkState(origin, "A");
|
|
68
69
|
const peerB = forkState(origin, "B");
|
|
69
70
|
|
|
@@ -315,7 +316,7 @@ Internals helpers like `jsonPatchToCrdtSafe` and `tryMergeDoc` return the same s
|
|
|
315
316
|
### State helpers
|
|
316
317
|
|
|
317
318
|
- `createState(initial, { actor, start? })` - Create a new CRDT state from JSON.
|
|
318
|
-
- `forkState(origin, actor)` - Fork a shared-origin replica with a new local actor ID.
|
|
319
|
+
- `forkState(origin, actor, options?)` - Fork a shared-origin replica with a new local actor ID. Reusing `origin` actor IDs is rejected by default (`options.allowActorReuse: true` to opt in explicitly).
|
|
319
320
|
- `applyPatch(state, patch, options?)` - Apply a patch immutably, returning a new state (`semantics: "sequential"` by default).
|
|
320
321
|
- `applyPatchInPlace(state, patch, options?)` - Apply a patch by mutating state in place (`atomic: true` by default).
|
|
321
322
|
- `tryApplyPatch(state, patch, options?)` - Non-throwing immutable apply (`{ ok: true, state }` or `{ ok: false, error }`).
|
|
@@ -394,6 +395,9 @@ No. It is deterministic and usually compact, but not guaranteed to be minimal.
|
|
|
394
395
|
**How do I merge states from two peers?**
|
|
395
396
|
Use `forkState(origin, actor)` to create each peer from the same origin, then `mergeState(local, remote, { actor: localActorId })`. Each peer should keep a stable unique actor ID across merges. See the [Multi-Peer Sync](#multi-peer-sync) example above.
|
|
396
397
|
|
|
398
|
+
**Why did `forkState` throw about actor uniqueness?**
|
|
399
|
+
By default, `forkState` blocks reusing `origin.clock.actor` because same-actor forks can mint duplicate dots and produce order-dependent merges. If you intentionally need same-actor cloning, pass `forkState(origin, actor, { allowActorReuse: true })`.
|
|
400
|
+
|
|
397
401
|
**Why can my local counter jump after a merge?**
|
|
398
402
|
Array inserts that target an existing predecessor may need to outrank sibling insert dots for deterministic ordering. The library can fast-forward the local counter in constant time to avoid expensive loops, but the resulting counter value may still jump upward when merging with peers that already have high counters.
|
|
399
403
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { type ActorId, type ApplyError, type ApplyPatchInPlaceOptions, type ApplyPatchOptions, type CrdtState, type DiffOptions, type JsonPatch, type JsonPatchOp, type JsonPrimitive, type JsonValue, MergeError, type MergeStateOptions, PatchError, type PatchErrorReason, type PatchSemantics, type SerializedState, type TryApplyPatchInPlaceResult, type TryApplyPatchResult, type TryMergeStateResult, type ValidatePatchResult, applyPatch, applyPatchInPlace, createState, deserializeState, diffJsonPatch, forkState, mergeState, serializeState, toJson, tryApplyPatch, tryApplyPatchInPlace, tryMergeState, validateJsonPatch };
|
|
1
|
+
import { C as toJson, D as ActorId, E as validateJsonPatch, I as CrdtState, K as JsonPrimitive, L as DiffOptions, M as ApplyPatchOptions, O as ApplyError, S as forkState, T as tryApplyPatchInPlace, U as JsonPatch, V as ForkStateOptions, W as JsonPatchOp, X as MergeStateOptions, _ as PatchError, a as tryMergeState, b as applyPatchInPlace, dt as TryApplyPatchResult, et as PatchErrorReason, f as diffJsonPatch, j as ApplyPatchInPlaceOptions, l as serializeState, lt as SerializedState, mt as ValidatePatchResult, pt as TryMergeStateResult, q as JsonValue, r as mergeState, s as deserializeState, t as MergeError, tt as PatchSemantics, ut as TryApplyPatchInPlaceResult, v as applyPatch, w as tryApplyPatch, x as createState } from "./merge-DQ_KDtnE.mjs";
|
|
2
|
+
export { type ActorId, type ApplyError, type ApplyPatchInPlaceOptions, type ApplyPatchOptions, type CrdtState, type DiffOptions, type ForkStateOptions, type JsonPatch, type JsonPatchOp, type JsonPrimitive, type JsonValue, MergeError, type MergeStateOptions, PatchError, type PatchErrorReason, type PatchSemantics, type SerializedState, type TryApplyPatchInPlaceResult, type TryApplyPatchResult, type TryMergeStateResult, type ValidatePatchResult, applyPatch, applyPatchInPlace, createState, deserializeState, diffJsonPatch, forkState, mergeState, serializeState, toJson, tryApplyPatch, tryApplyPatchInPlace, tryMergeState, validateJsonPatch };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { type ActorId, type ApplyError, type ApplyPatchInPlaceOptions, type ApplyPatchOptions, type CrdtState, type DiffOptions, type JsonPatch, type JsonPatchOp, type JsonPrimitive, type JsonValue, MergeError, type MergeStateOptions, PatchError, type PatchErrorReason, type PatchSemantics, type SerializedState, type TryApplyPatchInPlaceResult, type TryApplyPatchResult, type TryMergeStateResult, type ValidatePatchResult, applyPatch, applyPatchInPlace, createState, deserializeState, diffJsonPatch, forkState, mergeState, serializeState, toJson, tryApplyPatch, tryApplyPatchInPlace, tryMergeState, validateJsonPatch };
|
|
1
|
+
import { C as toJson, D as ActorId, E as validateJsonPatch, I as CrdtState, K as JsonPrimitive, L as DiffOptions, M as ApplyPatchOptions, O as ApplyError, S as forkState, T as tryApplyPatchInPlace, U as JsonPatch, V as ForkStateOptions, W as JsonPatchOp, X as MergeStateOptions, _ as PatchError, a as tryMergeState, b as applyPatchInPlace, dt as TryApplyPatchResult, et as PatchErrorReason, f as diffJsonPatch, j as ApplyPatchInPlaceOptions, l as serializeState, lt as SerializedState, mt as ValidatePatchResult, pt as TryMergeStateResult, q as JsonValue, r as mergeState, s as deserializeState, t as MergeError, tt as PatchSemantics, ut as TryApplyPatchInPlaceResult, v as applyPatch, w as tryApplyPatch, x as createState } from "./merge-B8nmGV-o.js";
|
|
2
|
+
export { type ActorId, type ApplyError, type ApplyPatchInPlaceOptions, type ApplyPatchOptions, type CrdtState, type DiffOptions, type ForkStateOptions, type JsonPatch, type JsonPatchOp, type JsonPrimitive, type JsonValue, MergeError, type MergeStateOptions, PatchError, type PatchErrorReason, type PatchSemantics, type SerializedState, type TryApplyPatchInPlaceResult, type TryApplyPatchResult, type TryMergeStateResult, type ValidatePatchResult, applyPatch, applyPatchInPlace, createState, deserializeState, diffJsonPatch, forkState, mergeState, serializeState, toJson, tryApplyPatch, tryApplyPatchInPlace, tryMergeState, validateJsonPatch };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_merge = require('./merge-
|
|
2
|
+
const require_merge = require('./merge-BAfuC6bf.js');
|
|
3
3
|
|
|
4
4
|
exports.MergeError = require_merge.MergeError;
|
|
5
5
|
exports.PatchError = require_merge.PatchError;
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { _ as tryApplyPatch, a as tryMergeState, d as applyPatch, g as toJson, h as forkState, j as diffJsonPatch, l as serializeState, m as createState, p as applyPatchInPlace, r as mergeState, s as deserializeState, t as MergeError, u as PatchError, v as tryApplyPatchInPlace, y as validateJsonPatch } from "./merge-
|
|
1
|
+
import { _ as tryApplyPatch, a as tryMergeState, d as applyPatch, g as toJson, h as forkState, j as diffJsonPatch, l as serializeState, m as createState, p as applyPatchInPlace, r as mergeState, s as deserializeState, t as MergeError, u as PatchError, v as tryApplyPatchInPlace, y as validateJsonPatch } from "./merge-CKcP1ZPt.mjs";
|
|
2
2
|
|
|
3
3
|
export { MergeError, PatchError, applyPatch, applyPatchInPlace, createState, deserializeState, diffJsonPatch, forkState, mergeState, serializeState, toJson, tryApplyPatch, tryApplyPatchInPlace, tryMergeState, validateJsonPatch };
|
package/dist/internals.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as ObjNode, A as ApplyPatchAsActorResult, B as ElemId, C as toJson, D as ActorId, E as validateJsonPatch, F as CompilePatchOptions, G as JsonPatchToCrdtOptions, H as IntentOp, I as CrdtState, J as LwwReg, K as JsonPrimitive, L as DiffOptions, M as ApplyPatchOptions, N as ApplyResult, O as ApplyError, P as Clock, Q as ObjEntry, R as Doc, S as forkState, T as tryApplyPatchInPlace, U as JsonPatch, V as ForkStateOptions, W as JsonPatchOp, X as MergeStateOptions, Y as MergeDocOptions, Z as Node, _ as PatchError, a as tryMergeState, at as SerializedClock, b as applyPatchInPlace, c as serializeDoc, ct as SerializedRgaElem, d as compileJsonPatchToIntent, dt as TryApplyPatchResult, et as PatchErrorReason, f as diffJsonPatch, ft as TryMergeDocResult, g as stringifyJsonPointer, h as parseJsonPointer, ht as VersionVector, i as tryMergeDoc, it as RgaSeq, j as ApplyPatchInPlaceOptions, k as ApplyPatchAsActorOptions, l as serializeState, lt as SerializedState, m as jsonEquals, mt as ValidatePatchResult, n as mergeDoc, nt as ROOT_KEY, o as deserializeDoc, ot as SerializedDoc, p as getAtJson, pt as TryMergeStateResult, q as JsonValue, r as mergeState, rt as RgaElem, s as deserializeState, st as SerializedNode, t as MergeError, tt as PatchSemantics, u as PatchCompileError, ut as TryApplyPatchInPlaceResult, v as applyPatch, w as tryApplyPatch, x as createState, y as applyPatchAsActor, z as Dot } from "./merge-DQ_KDtnE.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/clock.d.ts
|
|
4
4
|
/**
|
|
@@ -100,4 +100,4 @@ declare function rgaDelete(seq: RgaSeq, id: ElemId): void;
|
|
|
100
100
|
declare function rgaIdAtIndex(seq: RgaSeq, index: number): ElemId | undefined;
|
|
101
101
|
declare function rgaPrevForInsertAtIndex(seq: RgaSeq, index: number): ElemId;
|
|
102
102
|
//#endregion
|
|
103
|
-
export { ActorId, ApplyError, type ApplyPatchAsActorOptions, type ApplyPatchAsActorResult, ApplyPatchInPlaceOptions, ApplyPatchOptions, type ApplyResult, type Clock, type CompilePatchOptions, CrdtState, DiffOptions, type Doc, type Dot, type ElemId, HEAD, type IntentOp, JsonPatch, JsonPatchOp, type JsonPatchToCrdtOptions, JsonPrimitive, JsonValue, type LwwReg, type MergeDocOptions, MergeError, MergeStateOptions, type Node, type ObjEntry, type ObjNode, PatchCompileError, PatchError, PatchErrorReason, PatchSemantics, ROOT_KEY, type RgaElem, type RgaSeq, type SerializedClock, type SerializedDoc, type SerializedNode, type SerializedRgaElem, SerializedState, TryApplyPatchInPlaceResult, TryApplyPatchResult, type TryMergeDocResult, TryMergeStateResult, ValidatePatchResult, type VersionVector, applyIntentsToCrdt, applyPatch, applyPatchAsActor, applyPatchInPlace, cloneClock, cloneDoc, compareDot, compileJsonPatchToIntent, crdtToFullReplace, crdtToJsonPatch, createClock, createState, deserializeDoc, deserializeState, diffJsonPatch, docFromJson, docFromJsonWithDot, dotToElemId, forkState, getAtJson, jsonEquals, jsonPatchToCrdt, jsonPatchToCrdtSafe, lwwSet, materialize, mergeDoc, mergeState, newObj, newReg, newSeq, nextDotForActor, objRemove, objSet, observeDot, parseJsonPointer, rgaDelete, rgaIdAtIndex, rgaInsertAfter, rgaLinearizeIds, rgaPrevForInsertAtIndex, serializeDoc, serializeState, stringifyJsonPointer, toJson, tryApplyPatch, tryApplyPatchInPlace, tryJsonPatchToCrdt, tryMergeDoc, tryMergeState, validateJsonPatch, vvHasDot, vvMerge };
|
|
103
|
+
export { ActorId, ApplyError, type ApplyPatchAsActorOptions, type ApplyPatchAsActorResult, ApplyPatchInPlaceOptions, ApplyPatchOptions, type ApplyResult, type Clock, type CompilePatchOptions, CrdtState, DiffOptions, type Doc, type Dot, type ElemId, ForkStateOptions, HEAD, type IntentOp, JsonPatch, JsonPatchOp, type JsonPatchToCrdtOptions, JsonPrimitive, JsonValue, type LwwReg, type MergeDocOptions, MergeError, MergeStateOptions, type Node, type ObjEntry, type ObjNode, PatchCompileError, PatchError, PatchErrorReason, PatchSemantics, ROOT_KEY, type RgaElem, type RgaSeq, type SerializedClock, type SerializedDoc, type SerializedNode, type SerializedRgaElem, SerializedState, TryApplyPatchInPlaceResult, TryApplyPatchResult, type TryMergeDocResult, TryMergeStateResult, ValidatePatchResult, type VersionVector, applyIntentsToCrdt, applyPatch, applyPatchAsActor, applyPatchInPlace, cloneClock, cloneDoc, compareDot, compileJsonPatchToIntent, crdtToFullReplace, crdtToJsonPatch, createClock, createState, deserializeDoc, deserializeState, diffJsonPatch, docFromJson, docFromJsonWithDot, dotToElemId, forkState, getAtJson, jsonEquals, jsonPatchToCrdt, jsonPatchToCrdtSafe, lwwSet, materialize, mergeDoc, mergeState, newObj, newReg, newSeq, nextDotForActor, objRemove, objSet, observeDot, parseJsonPointer, rgaDelete, rgaIdAtIndex, rgaInsertAfter, rgaLinearizeIds, rgaPrevForInsertAtIndex, serializeDoc, serializeState, stringifyJsonPointer, toJson, tryApplyPatch, tryApplyPatchInPlace, tryJsonPatchToCrdt, tryMergeDoc, tryMergeState, validateJsonPatch, vvHasDot, vvMerge };
|
package/dist/internals.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as ObjNode, A as ApplyPatchAsActorResult, B as ElemId, C as toJson, D as ActorId, E as validateJsonPatch, F as CompilePatchOptions, G as JsonPatchToCrdtOptions, H as IntentOp, I as CrdtState, J as LwwReg, K as JsonPrimitive, L as DiffOptions, M as ApplyPatchOptions, N as ApplyResult, O as ApplyError, P as Clock, Q as ObjEntry, R as Doc, S as forkState, T as tryApplyPatchInPlace, U as JsonPatch, V as ForkStateOptions, W as JsonPatchOp, X as MergeStateOptions, Y as MergeDocOptions, Z as Node, _ as PatchError, a as tryMergeState, at as SerializedClock, b as applyPatchInPlace, c as serializeDoc, ct as SerializedRgaElem, d as compileJsonPatchToIntent, dt as TryApplyPatchResult, et as PatchErrorReason, f as diffJsonPatch, ft as TryMergeDocResult, g as stringifyJsonPointer, h as parseJsonPointer, ht as VersionVector, i as tryMergeDoc, it as RgaSeq, j as ApplyPatchInPlaceOptions, k as ApplyPatchAsActorOptions, l as serializeState, lt as SerializedState, m as jsonEquals, mt as ValidatePatchResult, n as mergeDoc, nt as ROOT_KEY, o as deserializeDoc, ot as SerializedDoc, p as getAtJson, pt as TryMergeStateResult, q as JsonValue, r as mergeState, rt as RgaElem, s as deserializeState, st as SerializedNode, t as MergeError, tt as PatchSemantics, u as PatchCompileError, ut as TryApplyPatchInPlaceResult, v as applyPatch, w as tryApplyPatch, x as createState, y as applyPatchAsActor, z as Dot } from "./merge-B8nmGV-o.js";
|
|
2
2
|
|
|
3
3
|
//#region src/clock.d.ts
|
|
4
4
|
/**
|
|
@@ -100,4 +100,4 @@ declare function rgaDelete(seq: RgaSeq, id: ElemId): void;
|
|
|
100
100
|
declare function rgaIdAtIndex(seq: RgaSeq, index: number): ElemId | undefined;
|
|
101
101
|
declare function rgaPrevForInsertAtIndex(seq: RgaSeq, index: number): ElemId;
|
|
102
102
|
//#endregion
|
|
103
|
-
export { ActorId, ApplyError, type ApplyPatchAsActorOptions, type ApplyPatchAsActorResult, ApplyPatchInPlaceOptions, ApplyPatchOptions, type ApplyResult, type Clock, type CompilePatchOptions, CrdtState, DiffOptions, type Doc, type Dot, type ElemId, HEAD, type IntentOp, JsonPatch, JsonPatchOp, type JsonPatchToCrdtOptions, JsonPrimitive, JsonValue, type LwwReg, type MergeDocOptions, MergeError, MergeStateOptions, type Node, type ObjEntry, type ObjNode, PatchCompileError, PatchError, PatchErrorReason, PatchSemantics, ROOT_KEY, type RgaElem, type RgaSeq, type SerializedClock, type SerializedDoc, type SerializedNode, type SerializedRgaElem, SerializedState, TryApplyPatchInPlaceResult, TryApplyPatchResult, type TryMergeDocResult, TryMergeStateResult, ValidatePatchResult, type VersionVector, applyIntentsToCrdt, applyPatch, applyPatchAsActor, applyPatchInPlace, cloneClock, cloneDoc, compareDot, compileJsonPatchToIntent, crdtToFullReplace, crdtToJsonPatch, createClock, createState, deserializeDoc, deserializeState, diffJsonPatch, docFromJson, docFromJsonWithDot, dotToElemId, forkState, getAtJson, jsonEquals, jsonPatchToCrdt, jsonPatchToCrdtSafe, lwwSet, materialize, mergeDoc, mergeState, newObj, newReg, newSeq, nextDotForActor, objRemove, objSet, observeDot, parseJsonPointer, rgaDelete, rgaIdAtIndex, rgaInsertAfter, rgaLinearizeIds, rgaPrevForInsertAtIndex, serializeDoc, serializeState, stringifyJsonPointer, toJson, tryApplyPatch, tryApplyPatchInPlace, tryJsonPatchToCrdt, tryMergeDoc, tryMergeState, validateJsonPatch, vvHasDot, vvMerge };
|
|
103
|
+
export { ActorId, ApplyError, type ApplyPatchAsActorOptions, type ApplyPatchAsActorResult, ApplyPatchInPlaceOptions, ApplyPatchOptions, type ApplyResult, type Clock, type CompilePatchOptions, CrdtState, DiffOptions, type Doc, type Dot, type ElemId, ForkStateOptions, HEAD, type IntentOp, JsonPatch, JsonPatchOp, type JsonPatchToCrdtOptions, JsonPrimitive, JsonValue, type LwwReg, type MergeDocOptions, MergeError, MergeStateOptions, type Node, type ObjEntry, type ObjNode, PatchCompileError, PatchError, PatchErrorReason, PatchSemantics, ROOT_KEY, type RgaElem, type RgaSeq, type SerializedClock, type SerializedDoc, type SerializedNode, type SerializedRgaElem, SerializedState, TryApplyPatchInPlaceResult, TryApplyPatchResult, type TryMergeDocResult, TryMergeStateResult, ValidatePatchResult, type VersionVector, applyIntentsToCrdt, applyPatch, applyPatchAsActor, applyPatchInPlace, cloneClock, cloneDoc, compareDot, compileJsonPatchToIntent, crdtToFullReplace, crdtToJsonPatch, createClock, createState, deserializeDoc, deserializeState, diffJsonPatch, docFromJson, docFromJsonWithDot, dotToElemId, forkState, getAtJson, jsonEquals, jsonPatchToCrdt, jsonPatchToCrdtSafe, lwwSet, materialize, mergeDoc, mergeState, newObj, newReg, newSeq, nextDotForActor, objRemove, objSet, observeDot, parseJsonPointer, rgaDelete, rgaIdAtIndex, rgaInsertAfter, rgaLinearizeIds, rgaPrevForInsertAtIndex, serializeDoc, serializeState, stringifyJsonPointer, toJson, tryApplyPatch, tryApplyPatchInPlace, tryJsonPatchToCrdt, tryMergeDoc, tryMergeState, validateJsonPatch, vvHasDot, vvMerge };
|
package/dist/internals.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_merge = require('./merge-
|
|
2
|
+
const require_merge = require('./merge-BAfuC6bf.js');
|
|
3
3
|
|
|
4
4
|
exports.HEAD = require_merge.HEAD;
|
|
5
5
|
exports.MergeError = require_merge.MergeError;
|
package/dist/internals.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { $ as vvMerge, A as compileJsonPatchToIntent, B as newSeq, C as crdtToJsonPatch, D as jsonPatchToCrdtSafe, E as jsonPatchToCrdt, F as stringifyJsonPointer, G as rgaDelete, H as objSet, I as ROOT_KEY, J as rgaLinearizeIds, K as rgaIdAtIndex, L as lwwSet, M as getAtJson, N as jsonEquals, O as tryJsonPatchToCrdt, P as parseJsonPointer, Q as vvHasDot, R as newObj, S as crdtToFullReplace, T as docFromJsonWithDot, U as materialize, V as objRemove, W as HEAD, X as compareDot, Y as rgaPrevForInsertAtIndex, Z as dotToElemId, _ as tryApplyPatch, a as tryMergeState, b as applyIntentsToCrdt, c as serializeDoc, d as applyPatch, et as cloneClock, f as applyPatchAsActor, g as toJson, h as forkState, i as tryMergeDoc, j as diffJsonPatch, k as PatchCompileError, l as serializeState, m as createState, n as mergeDoc, nt as nextDotForActor, o as deserializeDoc, p as applyPatchInPlace, q as rgaInsertAfter, r as mergeState, rt as observeDot, s as deserializeState, t as MergeError, tt as createClock, u as PatchError, v as tryApplyPatchInPlace, w as docFromJson, x as cloneDoc, y as validateJsonPatch, z as newReg } from "./merge-
|
|
1
|
+
import { $ as vvMerge, A as compileJsonPatchToIntent, B as newSeq, C as crdtToJsonPatch, D as jsonPatchToCrdtSafe, E as jsonPatchToCrdt, F as stringifyJsonPointer, G as rgaDelete, H as objSet, I as ROOT_KEY, J as rgaLinearizeIds, K as rgaIdAtIndex, L as lwwSet, M as getAtJson, N as jsonEquals, O as tryJsonPatchToCrdt, P as parseJsonPointer, Q as vvHasDot, R as newObj, S as crdtToFullReplace, T as docFromJsonWithDot, U as materialize, V as objRemove, W as HEAD, X as compareDot, Y as rgaPrevForInsertAtIndex, Z as dotToElemId, _ as tryApplyPatch, a as tryMergeState, b as applyIntentsToCrdt, c as serializeDoc, d as applyPatch, et as cloneClock, f as applyPatchAsActor, g as toJson, h as forkState, i as tryMergeDoc, j as diffJsonPatch, k as PatchCompileError, l as serializeState, m as createState, n as mergeDoc, nt as nextDotForActor, o as deserializeDoc, p as applyPatchInPlace, q as rgaInsertAfter, r as mergeState, rt as observeDot, s as deserializeState, t as MergeError, tt as createClock, u as PatchError, v as tryApplyPatchInPlace, w as docFromJson, x as cloneDoc, y as validateJsonPatch, z as newReg } from "./merge-CKcP1ZPt.mjs";
|
|
2
2
|
|
|
3
3
|
export { HEAD, MergeError, PatchCompileError, PatchError, ROOT_KEY, applyIntentsToCrdt, applyPatch, applyPatchAsActor, applyPatchInPlace, cloneClock, cloneDoc, compareDot, compileJsonPatchToIntent, crdtToFullReplace, crdtToJsonPatch, createClock, createState, deserializeDoc, deserializeState, diffJsonPatch, docFromJson, docFromJsonWithDot, dotToElemId, forkState, getAtJson, jsonEquals, jsonPatchToCrdt, jsonPatchToCrdtSafe, lwwSet, materialize, mergeDoc, mergeState, newObj, newReg, newSeq, nextDotForActor, objRemove, objSet, observeDot, parseJsonPointer, rgaDelete, rgaIdAtIndex, rgaInsertAfter, rgaLinearizeIds, rgaPrevForInsertAtIndex, serializeDoc, serializeState, stringifyJsonPointer, toJson, tryApplyPatch, tryApplyPatchInPlace, tryJsonPatchToCrdt, tryMergeDoc, tryMergeState, validateJsonPatch, vvHasDot, vvMerge };
|
|
@@ -161,6 +161,14 @@ type CrdtState = {
|
|
|
161
161
|
doc: Doc;
|
|
162
162
|
clock: Clock;
|
|
163
163
|
};
|
|
164
|
+
/** Options for `forkState`. */
|
|
165
|
+
interface ForkStateOptions {
|
|
166
|
+
/**
|
|
167
|
+
* Allow reusing the origin actor ID when forking.
|
|
168
|
+
* Defaults to `false` to prevent duplicate-dot collisions across replicas.
|
|
169
|
+
*/
|
|
170
|
+
allowActorReuse?: boolean;
|
|
171
|
+
}
|
|
164
172
|
/** Result from applying a patch for a specific actor using a shared version vector. */
|
|
165
173
|
type ApplyPatchAsActorResult = {
|
|
166
174
|
/** Updated CRDT state for the actor that produced this patch. */state: CrdtState; /** Updated version vector after applying the patch. */
|
|
@@ -310,8 +318,9 @@ declare function createState(initial: JsonValue, options: {
|
|
|
310
318
|
/**
|
|
311
319
|
* Fork a replica from a shared origin state while assigning a new local actor ID.
|
|
312
320
|
* The forked state has an independent document clone and clock.
|
|
321
|
+
* By default this rejects actor reuse to prevent duplicate-dot collisions across peers.
|
|
313
322
|
*/
|
|
314
|
-
declare function forkState(origin: CrdtState, actor: ActorId): CrdtState;
|
|
323
|
+
declare function forkState(origin: CrdtState, actor: ActorId, options?: ForkStateOptions): CrdtState;
|
|
315
324
|
/**
|
|
316
325
|
* Materialize a CRDT document or state back to a plain JSON value.
|
|
317
326
|
* @param target - A `Doc` or `CrdtState` to materialize.
|
|
@@ -442,4 +451,4 @@ declare function mergeState(a: CrdtState, b: CrdtState, options?: MergeStateOpti
|
|
|
442
451
|
/** Non-throwing `mergeState` variant with structured conflict details. */
|
|
443
452
|
declare function tryMergeState(a: CrdtState, b: CrdtState, options?: MergeStateOptions): TryMergeStateResult;
|
|
444
453
|
//#endregion
|
|
445
|
-
export {
|
|
454
|
+
export { ObjNode as $, ApplyPatchAsActorResult as A, ElemId as B, toJson as C, ActorId as D, validateJsonPatch as E, CompilePatchOptions as F, JsonPatchToCrdtOptions as G, IntentOp as H, CrdtState as I, LwwReg as J, JsonPrimitive as K, DiffOptions as L, ApplyPatchOptions as M, ApplyResult as N, ApplyError as O, Clock as P, ObjEntry as Q, Doc as R, forkState as S, tryApplyPatchInPlace as T, JsonPatch as U, ForkStateOptions as V, JsonPatchOp as W, MergeStateOptions as X, MergeDocOptions as Y, Node as Z, PatchError as _, tryMergeState as a, SerializedClock as at, applyPatchInPlace as b, serializeDoc as c, SerializedRgaElem as ct, compileJsonPatchToIntent as d, TryApplyPatchResult as dt, PatchErrorReason as et, diffJsonPatch as f, TryMergeDocResult as ft, stringifyJsonPointer as g, parseJsonPointer as h, VersionVector as ht, tryMergeDoc as i, RgaSeq as it, ApplyPatchInPlaceOptions as j, ApplyPatchAsActorOptions as k, serializeState as l, SerializedState as lt, jsonEquals as m, ValidatePatchResult as mt, mergeDoc as n, ROOT_KEY as nt, deserializeDoc as o, SerializedDoc as ot, getAtJson as p, TryMergeStateResult as pt, JsonValue as q, mergeState as r, RgaElem as rt, deserializeState as s, SerializedNode as st, MergeError as t, PatchSemantics as tt, PatchCompileError as u, TryApplyPatchInPlaceResult as ut, applyPatch as v, tryApplyPatch as w, createState as x, applyPatchAsActor as y, Dot as z };
|
|
@@ -216,13 +216,37 @@ var PatchCompileError = class extends Error {
|
|
|
216
216
|
function parseJsonPointer(ptr) {
|
|
217
217
|
if (ptr === "") return [];
|
|
218
218
|
if (!ptr.startsWith("/")) throw new Error(`Invalid pointer: ${ptr}`);
|
|
219
|
-
return ptr.slice(1).split("/").map(
|
|
219
|
+
return ptr.slice(1).split("/").map(unescapeJsonPointerToken);
|
|
220
220
|
}
|
|
221
221
|
/** Convert a path array back to an RFC 6901 JSON Pointer string. */
|
|
222
222
|
function stringifyJsonPointer(path) {
|
|
223
223
|
if (path.length === 0) return "";
|
|
224
224
|
return `/${path.map(escapeJsonPointer).join("/")}`;
|
|
225
225
|
}
|
|
226
|
+
function unescapeJsonPointerToken(token) {
|
|
227
|
+
let out = "";
|
|
228
|
+
for (let i = 0; i < token.length; i++) {
|
|
229
|
+
const ch = token[i];
|
|
230
|
+
if (ch !== "~") {
|
|
231
|
+
out += ch;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
const esc = token[i + 1];
|
|
235
|
+
if (esc === "0") {
|
|
236
|
+
out += "~";
|
|
237
|
+
i += 1;
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (esc === "1") {
|
|
241
|
+
out += "/";
|
|
242
|
+
i += 1;
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
const sequence = esc === void 0 ? "~" : `~${esc}`;
|
|
246
|
+
throw new Error(`Invalid pointer escape sequence '${sequence}'`);
|
|
247
|
+
}
|
|
248
|
+
return out;
|
|
249
|
+
}
|
|
226
250
|
/**
|
|
227
251
|
* Navigate a JSON value by path and return the value at that location.
|
|
228
252
|
* Throws if the path is invalid, out of bounds, or traverses a non-container.
|
|
@@ -230,8 +254,8 @@ function stringifyJsonPointer(path) {
|
|
|
230
254
|
function getAtJson(base, path) {
|
|
231
255
|
let cur = base;
|
|
232
256
|
for (const seg of path) if (Array.isArray(cur)) {
|
|
233
|
-
|
|
234
|
-
|
|
257
|
+
if (!ARRAY_INDEX_TOKEN_PATTERN.test(seg)) throw new Error(`Expected array index, got ${seg}`);
|
|
258
|
+
const idx = Number(seg);
|
|
235
259
|
if (idx < 0 || idx >= cur.length) throw new Error(`Index out of bounds at ${seg}`);
|
|
236
260
|
cur = cur[idx];
|
|
237
261
|
} else if (cur && typeof cur === "object") {
|
|
@@ -255,7 +279,7 @@ function compileJsonPatchToIntent(baseJson, patch, options = {}) {
|
|
|
255
279
|
for (let opIndex = 0; opIndex < patch.length; opIndex++) {
|
|
256
280
|
const op = patch[opIndex];
|
|
257
281
|
const compileBase = semantics === "sequential" ? workingBase : baseJson;
|
|
258
|
-
intents.push(...compileSingleOp(compileBase, op, opIndex));
|
|
282
|
+
intents.push(...compileSingleOp(compileBase, op, opIndex, semantics));
|
|
259
283
|
if (semantics === "sequential") workingBase = applyPatchOpToJson(workingBase, op, opIndex);
|
|
260
284
|
}
|
|
261
285
|
return intents;
|
|
@@ -398,6 +422,7 @@ function jsonEquals(a, b) {
|
|
|
398
422
|
function isPlainObject(value) {
|
|
399
423
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
400
424
|
}
|
|
425
|
+
const ARRAY_INDEX_TOKEN_PATTERN = /^(0|[1-9][0-9]*)$/;
|
|
401
426
|
function hasOwn(value, key) {
|
|
402
427
|
return Object.prototype.hasOwnProperty.call(value, key);
|
|
403
428
|
}
|
|
@@ -408,7 +433,7 @@ function pathValueAt(base, path) {
|
|
|
408
433
|
function assertNever$1(_value, message) {
|
|
409
434
|
throw new Error(message);
|
|
410
435
|
}
|
|
411
|
-
function compileSingleOp(baseJson, op, opIndex) {
|
|
436
|
+
function compileSingleOp(baseJson, op, opIndex, semantics) {
|
|
412
437
|
if (op.op === "test") return [{
|
|
413
438
|
t: "Test",
|
|
414
439
|
path: parsePointerOrThrow(op.path, op.path, opIndex),
|
|
@@ -419,15 +444,29 @@ function compileSingleOp(baseJson, op, opIndex) {
|
|
|
419
444
|
const toPath = parsePointerOrThrow(op.path, op.path, opIndex);
|
|
420
445
|
if (op.op === "move" && isStrictDescendantPath(fromPath, toPath)) throw compileError("INVALID_MOVE", `cannot move a value into one of its descendants at ${op.path}`, op.path, opIndex);
|
|
421
446
|
const val = lookupValueOrThrow(baseJson, fromPath, op.from, opIndex);
|
|
447
|
+
if (op.op === "move" && isSamePath(fromPath, toPath)) return [];
|
|
448
|
+
if (op.op === "move" && semantics === "sequential") {
|
|
449
|
+
const removeOp = {
|
|
450
|
+
op: "remove",
|
|
451
|
+
path: op.from
|
|
452
|
+
};
|
|
453
|
+
const addOp = {
|
|
454
|
+
op: "add",
|
|
455
|
+
path: op.path,
|
|
456
|
+
value: val
|
|
457
|
+
};
|
|
458
|
+
const baseAfterRemove = applyPatchOpToJson(baseJson, removeOp, opIndex);
|
|
459
|
+
return [...compileSingleOp(baseJson, removeOp, opIndex, semantics), ...compileSingleOp(baseAfterRemove, addOp, opIndex, semantics)];
|
|
460
|
+
}
|
|
422
461
|
const out = compileSingleOp(baseJson, {
|
|
423
462
|
op: "add",
|
|
424
463
|
path: op.path,
|
|
425
464
|
value: val
|
|
426
|
-
}, opIndex);
|
|
465
|
+
}, opIndex, semantics);
|
|
427
466
|
if (op.op === "move") out.push(...compileSingleOp(baseJson, {
|
|
428
467
|
op: "remove",
|
|
429
468
|
path: op.from
|
|
430
|
-
}, opIndex));
|
|
469
|
+
}, opIndex, semantics));
|
|
431
470
|
return out;
|
|
432
471
|
}
|
|
433
472
|
const path = parsePointerOrThrow(op.path, op.path, opIndex);
|
|
@@ -563,7 +602,7 @@ function parseArrayIndexToken(token, op, arrLength, path, opIndex) {
|
|
|
563
602
|
if (op !== "add") throw compileError("INVALID_POINTER", `'-' index is only valid for add at ${path}`, path, opIndex);
|
|
564
603
|
return Number.POSITIVE_INFINITY;
|
|
565
604
|
}
|
|
566
|
-
if (
|
|
605
|
+
if (!ARRAY_INDEX_TOKEN_PATTERN.test(token)) throw compileError("INVALID_POINTER", `expected array index at ${path}`, path, opIndex);
|
|
567
606
|
const index = Number(token);
|
|
568
607
|
if (!Number.isSafeInteger(index)) throw compileError("OUT_OF_BOUNDS", `array index is too large at ${path}`, path, opIndex);
|
|
569
608
|
if (op === "add") {
|
|
@@ -572,12 +611,31 @@ function parseArrayIndexToken(token, op, arrLength, path, opIndex) {
|
|
|
572
611
|
return index;
|
|
573
612
|
}
|
|
574
613
|
function compileErrorFromLookup(error, path, opIndex) {
|
|
614
|
+
const mapped = mapLookupErrorToPatchReason(error);
|
|
615
|
+
return compileError(mapped.reason, mapped.message, path, opIndex);
|
|
616
|
+
}
|
|
617
|
+
function mapLookupErrorToPatchReason(error) {
|
|
575
618
|
const message = error instanceof Error ? error.message : "invalid path";
|
|
576
|
-
if (message.includes("Expected array index")) return
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
619
|
+
if (message.includes("Expected array index")) return {
|
|
620
|
+
reason: "INVALID_POINTER",
|
|
621
|
+
message
|
|
622
|
+
};
|
|
623
|
+
if (message.includes("Index out of bounds")) return {
|
|
624
|
+
reason: "OUT_OF_BOUNDS",
|
|
625
|
+
message
|
|
626
|
+
};
|
|
627
|
+
if (message.includes("Missing key")) return {
|
|
628
|
+
reason: "MISSING_PARENT",
|
|
629
|
+
message
|
|
630
|
+
};
|
|
631
|
+
if (message.includes("Cannot traverse into non-container")) return {
|
|
632
|
+
reason: "INVALID_TARGET",
|
|
633
|
+
message
|
|
634
|
+
};
|
|
635
|
+
return {
|
|
636
|
+
reason: "INVALID_PATCH",
|
|
637
|
+
message
|
|
638
|
+
};
|
|
581
639
|
}
|
|
582
640
|
function compileError(reason, message, path, opIndex) {
|
|
583
641
|
return new PatchCompileError(reason, message, path, opIndex);
|
|
@@ -587,6 +645,11 @@ function isStrictDescendantPath(from, to) {
|
|
|
587
645
|
for (let i = 0; i < from.length; i++) if (from[i] !== to[i]) return false;
|
|
588
646
|
return true;
|
|
589
647
|
}
|
|
648
|
+
function isSamePath(a, b) {
|
|
649
|
+
if (a.length !== b.length) return false;
|
|
650
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
590
653
|
|
|
591
654
|
//#endregion
|
|
592
655
|
//#region src/doc.ts
|
|
@@ -1057,8 +1120,7 @@ function jsonPatchToCrdtInternal(options) {
|
|
|
1057
1120
|
const shadowBump = (ctr) => {
|
|
1058
1121
|
if (shadowCtr < ctr) shadowCtr = ctr;
|
|
1059
1122
|
};
|
|
1060
|
-
|
|
1061
|
-
const op = options.patch[opIndex];
|
|
1123
|
+
const applySequentialOp = (op, opIndex) => {
|
|
1062
1124
|
const baseJson = materialize(shadowBase.root);
|
|
1063
1125
|
let intents;
|
|
1064
1126
|
try {
|
|
@@ -1072,6 +1134,42 @@ function jsonPatchToCrdtInternal(options) {
|
|
|
1072
1134
|
const shadowStep = applyIntentsToCrdt(shadowBase, shadowBase, intents, shadowDot, "base", shadowBump);
|
|
1073
1135
|
if (!shadowStep.ok) return withOpIndex(shadowStep, opIndex);
|
|
1074
1136
|
} else shadowBase = cloneDoc(options.head);
|
|
1137
|
+
return { ok: true };
|
|
1138
|
+
};
|
|
1139
|
+
for (let opIndex = 0; opIndex < options.patch.length; opIndex++) {
|
|
1140
|
+
const op = options.patch[opIndex];
|
|
1141
|
+
if (op.op === "move") {
|
|
1142
|
+
const baseJson = materialize(shadowBase.root);
|
|
1143
|
+
let fromValue;
|
|
1144
|
+
try {
|
|
1145
|
+
fromValue = structuredClone(getAtJson(baseJson, parseJsonPointer(op.from)));
|
|
1146
|
+
} catch {
|
|
1147
|
+
try {
|
|
1148
|
+
compileJsonPatchToIntent(baseJson, [{
|
|
1149
|
+
op: "remove",
|
|
1150
|
+
path: op.from
|
|
1151
|
+
}], { semantics: "sequential" });
|
|
1152
|
+
} catch (error) {
|
|
1153
|
+
return withOpIndex(toApplyError$1(error), opIndex);
|
|
1154
|
+
}
|
|
1155
|
+
return withOpIndex(toApplyError$1(/* @__PURE__ */ new Error(`failed to resolve move source at ${op.from}`)), opIndex);
|
|
1156
|
+
}
|
|
1157
|
+
if (op.from === op.path) continue;
|
|
1158
|
+
const removeStep = applySequentialOp({
|
|
1159
|
+
op: "remove",
|
|
1160
|
+
path: op.from
|
|
1161
|
+
}, opIndex);
|
|
1162
|
+
if (!removeStep.ok) return removeStep;
|
|
1163
|
+
const addStep = applySequentialOp({
|
|
1164
|
+
op: "add",
|
|
1165
|
+
path: op.path,
|
|
1166
|
+
value: fromValue
|
|
1167
|
+
}, opIndex);
|
|
1168
|
+
if (!addStep.ok) return addStep;
|
|
1169
|
+
continue;
|
|
1170
|
+
}
|
|
1171
|
+
const step = applySequentialOp(op, opIndex);
|
|
1172
|
+
if (!step.ok) return step;
|
|
1075
1173
|
}
|
|
1076
1174
|
return { ok: true };
|
|
1077
1175
|
}
|
|
@@ -1143,8 +1241,10 @@ function createState(initial, options) {
|
|
|
1143
1241
|
/**
|
|
1144
1242
|
* Fork a replica from a shared origin state while assigning a new local actor ID.
|
|
1145
1243
|
* The forked state has an independent document clone and clock.
|
|
1244
|
+
* By default this rejects actor reuse to prevent duplicate-dot collisions across peers.
|
|
1146
1245
|
*/
|
|
1147
|
-
function forkState(origin, actor) {
|
|
1246
|
+
function forkState(origin, actor, options = {}) {
|
|
1247
|
+
if (actor === origin.clock.actor && !options.allowActorReuse) throw new Error(`forkState actor must be unique; refusing to reuse origin actor '${actor}'`);
|
|
1148
1248
|
return {
|
|
1149
1249
|
doc: cloneDoc(origin.doc),
|
|
1150
1250
|
clock: createClock(actor, origin.clock.ctr)
|
|
@@ -1262,8 +1362,8 @@ function applyPatchInternal(state, patch, options) {
|
|
|
1262
1362
|
doc: cloneDoc(options.base.doc),
|
|
1263
1363
|
clock: createClock("__base__", 0)
|
|
1264
1364
|
} : null;
|
|
1265
|
-
for (const op of patch) {
|
|
1266
|
-
const step = applyPatchOpSequential(state, op, options, explicitBaseState ? explicitBaseState.doc : cloneDoc(state.doc));
|
|
1365
|
+
for (const [opIndex, op] of patch.entries()) {
|
|
1366
|
+
const step = applyPatchOpSequential(state, op, options, explicitBaseState ? explicitBaseState.doc : cloneDoc(state.doc), opIndex);
|
|
1267
1367
|
if (!step.ok) return step;
|
|
1268
1368
|
if (explicitBaseState && op.op !== "test") {
|
|
1269
1369
|
const baseStep = applyPatchInternal(explicitBaseState, [op], {
|
|
@@ -1280,10 +1380,12 @@ function applyPatchInternal(state, patch, options) {
|
|
|
1280
1380
|
if (!compiled.ok) return compiled;
|
|
1281
1381
|
return applyIntentsToCrdt(baseDoc, state.doc, compiled.intents, () => state.clock.next(), options.testAgainst ?? "head", (ctr) => bumpClockCounter(state, ctr));
|
|
1282
1382
|
}
|
|
1283
|
-
function applyPatchOpSequential(state, op, options, baseDoc) {
|
|
1383
|
+
function applyPatchOpSequential(state, op, options, baseDoc, opIndex) {
|
|
1284
1384
|
const baseJson = materialize(baseDoc.root);
|
|
1285
1385
|
if (op.op === "move") {
|
|
1286
|
-
const
|
|
1386
|
+
const fromResolved = resolveValueAtPointer(baseJson, op.from, opIndex);
|
|
1387
|
+
if (!fromResolved.ok) return fromResolved;
|
|
1388
|
+
const fromValue = fromResolved.value;
|
|
1287
1389
|
const removeRes = applySinglePatchOp(state, baseDoc, {
|
|
1288
1390
|
op: "remove",
|
|
1289
1391
|
path: op.from
|
|
@@ -1296,7 +1398,9 @@ function applyPatchOpSequential(state, op, options, baseDoc) {
|
|
|
1296
1398
|
}, options);
|
|
1297
1399
|
}
|
|
1298
1400
|
if (op.op === "copy") {
|
|
1299
|
-
const
|
|
1401
|
+
const fromResolved = resolveValueAtPointer(baseJson, op.from, opIndex);
|
|
1402
|
+
if (!fromResolved.ok) return fromResolved;
|
|
1403
|
+
const fromValue = fromResolved.value;
|
|
1300
1404
|
return applySinglePatchOp(state, baseDoc, {
|
|
1301
1405
|
op: "add",
|
|
1302
1406
|
path: op.path,
|
|
@@ -1305,6 +1409,22 @@ function applyPatchOpSequential(state, op, options, baseDoc) {
|
|
|
1305
1409
|
}
|
|
1306
1410
|
return applySinglePatchOp(state, baseDoc, op, options);
|
|
1307
1411
|
}
|
|
1412
|
+
function resolveValueAtPointer(baseJson, pointer, opIndex) {
|
|
1413
|
+
let path;
|
|
1414
|
+
try {
|
|
1415
|
+
path = parseJsonPointer(pointer);
|
|
1416
|
+
} catch (error) {
|
|
1417
|
+
return toPointerParseApplyError(error, pointer, opIndex);
|
|
1418
|
+
}
|
|
1419
|
+
try {
|
|
1420
|
+
return {
|
|
1421
|
+
ok: true,
|
|
1422
|
+
value: getAtJson(baseJson, path)
|
|
1423
|
+
};
|
|
1424
|
+
} catch (error) {
|
|
1425
|
+
return toPointerLookupApplyError(error, pointer, opIndex);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1308
1428
|
function applySinglePatchOp(state, baseDoc, op, options) {
|
|
1309
1429
|
const compiled = compileIntents(materialize(baseDoc.root), [op], "sequential");
|
|
1310
1430
|
if (!compiled.ok) return compiled;
|
|
@@ -1363,6 +1483,27 @@ function toApplyError(error) {
|
|
|
1363
1483
|
message: error instanceof Error ? error.message : "failed to compile patch"
|
|
1364
1484
|
};
|
|
1365
1485
|
}
|
|
1486
|
+
function toPointerParseApplyError(error, pointer, opIndex) {
|
|
1487
|
+
return {
|
|
1488
|
+
ok: false,
|
|
1489
|
+
code: 409,
|
|
1490
|
+
reason: "INVALID_POINTER",
|
|
1491
|
+
message: error instanceof Error ? error.message : "invalid pointer",
|
|
1492
|
+
path: pointer,
|
|
1493
|
+
opIndex
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
function toPointerLookupApplyError(error, pointer, opIndex) {
|
|
1497
|
+
const mapped = mapLookupErrorToPatchReason(error);
|
|
1498
|
+
return {
|
|
1499
|
+
ok: false,
|
|
1500
|
+
code: 409,
|
|
1501
|
+
reason: mapped.reason,
|
|
1502
|
+
message: mapped.message,
|
|
1503
|
+
path: pointer,
|
|
1504
|
+
opIndex
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1366
1507
|
|
|
1367
1508
|
//#endregion
|
|
1368
1509
|
//#region src/serialize.ts
|
|
@@ -215,13 +215,37 @@ var PatchCompileError = class extends Error {
|
|
|
215
215
|
function parseJsonPointer(ptr) {
|
|
216
216
|
if (ptr === "") return [];
|
|
217
217
|
if (!ptr.startsWith("/")) throw new Error(`Invalid pointer: ${ptr}`);
|
|
218
|
-
return ptr.slice(1).split("/").map(
|
|
218
|
+
return ptr.slice(1).split("/").map(unescapeJsonPointerToken);
|
|
219
219
|
}
|
|
220
220
|
/** Convert a path array back to an RFC 6901 JSON Pointer string. */
|
|
221
221
|
function stringifyJsonPointer(path) {
|
|
222
222
|
if (path.length === 0) return "";
|
|
223
223
|
return `/${path.map(escapeJsonPointer).join("/")}`;
|
|
224
224
|
}
|
|
225
|
+
function unescapeJsonPointerToken(token) {
|
|
226
|
+
let out = "";
|
|
227
|
+
for (let i = 0; i < token.length; i++) {
|
|
228
|
+
const ch = token[i];
|
|
229
|
+
if (ch !== "~") {
|
|
230
|
+
out += ch;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
const esc = token[i + 1];
|
|
234
|
+
if (esc === "0") {
|
|
235
|
+
out += "~";
|
|
236
|
+
i += 1;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (esc === "1") {
|
|
240
|
+
out += "/";
|
|
241
|
+
i += 1;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const sequence = esc === void 0 ? "~" : `~${esc}`;
|
|
245
|
+
throw new Error(`Invalid pointer escape sequence '${sequence}'`);
|
|
246
|
+
}
|
|
247
|
+
return out;
|
|
248
|
+
}
|
|
225
249
|
/**
|
|
226
250
|
* Navigate a JSON value by path and return the value at that location.
|
|
227
251
|
* Throws if the path is invalid, out of bounds, or traverses a non-container.
|
|
@@ -229,8 +253,8 @@ function stringifyJsonPointer(path) {
|
|
|
229
253
|
function getAtJson(base, path) {
|
|
230
254
|
let cur = base;
|
|
231
255
|
for (const seg of path) if (Array.isArray(cur)) {
|
|
232
|
-
|
|
233
|
-
|
|
256
|
+
if (!ARRAY_INDEX_TOKEN_PATTERN.test(seg)) throw new Error(`Expected array index, got ${seg}`);
|
|
257
|
+
const idx = Number(seg);
|
|
234
258
|
if (idx < 0 || idx >= cur.length) throw new Error(`Index out of bounds at ${seg}`);
|
|
235
259
|
cur = cur[idx];
|
|
236
260
|
} else if (cur && typeof cur === "object") {
|
|
@@ -254,7 +278,7 @@ function compileJsonPatchToIntent(baseJson, patch, options = {}) {
|
|
|
254
278
|
for (let opIndex = 0; opIndex < patch.length; opIndex++) {
|
|
255
279
|
const op = patch[opIndex];
|
|
256
280
|
const compileBase = semantics === "sequential" ? workingBase : baseJson;
|
|
257
|
-
intents.push(...compileSingleOp(compileBase, op, opIndex));
|
|
281
|
+
intents.push(...compileSingleOp(compileBase, op, opIndex, semantics));
|
|
258
282
|
if (semantics === "sequential") workingBase = applyPatchOpToJson(workingBase, op, opIndex);
|
|
259
283
|
}
|
|
260
284
|
return intents;
|
|
@@ -397,6 +421,7 @@ function jsonEquals(a, b) {
|
|
|
397
421
|
function isPlainObject(value) {
|
|
398
422
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
399
423
|
}
|
|
424
|
+
const ARRAY_INDEX_TOKEN_PATTERN = /^(0|[1-9][0-9]*)$/;
|
|
400
425
|
function hasOwn(value, key) {
|
|
401
426
|
return Object.prototype.hasOwnProperty.call(value, key);
|
|
402
427
|
}
|
|
@@ -407,7 +432,7 @@ function pathValueAt(base, path) {
|
|
|
407
432
|
function assertNever$1(_value, message) {
|
|
408
433
|
throw new Error(message);
|
|
409
434
|
}
|
|
410
|
-
function compileSingleOp(baseJson, op, opIndex) {
|
|
435
|
+
function compileSingleOp(baseJson, op, opIndex, semantics) {
|
|
411
436
|
if (op.op === "test") return [{
|
|
412
437
|
t: "Test",
|
|
413
438
|
path: parsePointerOrThrow(op.path, op.path, opIndex),
|
|
@@ -418,15 +443,29 @@ function compileSingleOp(baseJson, op, opIndex) {
|
|
|
418
443
|
const toPath = parsePointerOrThrow(op.path, op.path, opIndex);
|
|
419
444
|
if (op.op === "move" && isStrictDescendantPath(fromPath, toPath)) throw compileError("INVALID_MOVE", `cannot move a value into one of its descendants at ${op.path}`, op.path, opIndex);
|
|
420
445
|
const val = lookupValueOrThrow(baseJson, fromPath, op.from, opIndex);
|
|
446
|
+
if (op.op === "move" && isSamePath(fromPath, toPath)) return [];
|
|
447
|
+
if (op.op === "move" && semantics === "sequential") {
|
|
448
|
+
const removeOp = {
|
|
449
|
+
op: "remove",
|
|
450
|
+
path: op.from
|
|
451
|
+
};
|
|
452
|
+
const addOp = {
|
|
453
|
+
op: "add",
|
|
454
|
+
path: op.path,
|
|
455
|
+
value: val
|
|
456
|
+
};
|
|
457
|
+
const baseAfterRemove = applyPatchOpToJson(baseJson, removeOp, opIndex);
|
|
458
|
+
return [...compileSingleOp(baseJson, removeOp, opIndex, semantics), ...compileSingleOp(baseAfterRemove, addOp, opIndex, semantics)];
|
|
459
|
+
}
|
|
421
460
|
const out = compileSingleOp(baseJson, {
|
|
422
461
|
op: "add",
|
|
423
462
|
path: op.path,
|
|
424
463
|
value: val
|
|
425
|
-
}, opIndex);
|
|
464
|
+
}, opIndex, semantics);
|
|
426
465
|
if (op.op === "move") out.push(...compileSingleOp(baseJson, {
|
|
427
466
|
op: "remove",
|
|
428
467
|
path: op.from
|
|
429
|
-
}, opIndex));
|
|
468
|
+
}, opIndex, semantics));
|
|
430
469
|
return out;
|
|
431
470
|
}
|
|
432
471
|
const path = parsePointerOrThrow(op.path, op.path, opIndex);
|
|
@@ -562,7 +601,7 @@ function parseArrayIndexToken(token, op, arrLength, path, opIndex) {
|
|
|
562
601
|
if (op !== "add") throw compileError("INVALID_POINTER", `'-' index is only valid for add at ${path}`, path, opIndex);
|
|
563
602
|
return Number.POSITIVE_INFINITY;
|
|
564
603
|
}
|
|
565
|
-
if (
|
|
604
|
+
if (!ARRAY_INDEX_TOKEN_PATTERN.test(token)) throw compileError("INVALID_POINTER", `expected array index at ${path}`, path, opIndex);
|
|
566
605
|
const index = Number(token);
|
|
567
606
|
if (!Number.isSafeInteger(index)) throw compileError("OUT_OF_BOUNDS", `array index is too large at ${path}`, path, opIndex);
|
|
568
607
|
if (op === "add") {
|
|
@@ -571,12 +610,31 @@ function parseArrayIndexToken(token, op, arrLength, path, opIndex) {
|
|
|
571
610
|
return index;
|
|
572
611
|
}
|
|
573
612
|
function compileErrorFromLookup(error, path, opIndex) {
|
|
613
|
+
const mapped = mapLookupErrorToPatchReason(error);
|
|
614
|
+
return compileError(mapped.reason, mapped.message, path, opIndex);
|
|
615
|
+
}
|
|
616
|
+
function mapLookupErrorToPatchReason(error) {
|
|
574
617
|
const message = error instanceof Error ? error.message : "invalid path";
|
|
575
|
-
if (message.includes("Expected array index")) return
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
618
|
+
if (message.includes("Expected array index")) return {
|
|
619
|
+
reason: "INVALID_POINTER",
|
|
620
|
+
message
|
|
621
|
+
};
|
|
622
|
+
if (message.includes("Index out of bounds")) return {
|
|
623
|
+
reason: "OUT_OF_BOUNDS",
|
|
624
|
+
message
|
|
625
|
+
};
|
|
626
|
+
if (message.includes("Missing key")) return {
|
|
627
|
+
reason: "MISSING_PARENT",
|
|
628
|
+
message
|
|
629
|
+
};
|
|
630
|
+
if (message.includes("Cannot traverse into non-container")) return {
|
|
631
|
+
reason: "INVALID_TARGET",
|
|
632
|
+
message
|
|
633
|
+
};
|
|
634
|
+
return {
|
|
635
|
+
reason: "INVALID_PATCH",
|
|
636
|
+
message
|
|
637
|
+
};
|
|
580
638
|
}
|
|
581
639
|
function compileError(reason, message, path, opIndex) {
|
|
582
640
|
return new PatchCompileError(reason, message, path, opIndex);
|
|
@@ -586,6 +644,11 @@ function isStrictDescendantPath(from, to) {
|
|
|
586
644
|
for (let i = 0; i < from.length; i++) if (from[i] !== to[i]) return false;
|
|
587
645
|
return true;
|
|
588
646
|
}
|
|
647
|
+
function isSamePath(a, b) {
|
|
648
|
+
if (a.length !== b.length) return false;
|
|
649
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
650
|
+
return true;
|
|
651
|
+
}
|
|
589
652
|
|
|
590
653
|
//#endregion
|
|
591
654
|
//#region src/doc.ts
|
|
@@ -1056,8 +1119,7 @@ function jsonPatchToCrdtInternal(options) {
|
|
|
1056
1119
|
const shadowBump = (ctr) => {
|
|
1057
1120
|
if (shadowCtr < ctr) shadowCtr = ctr;
|
|
1058
1121
|
};
|
|
1059
|
-
|
|
1060
|
-
const op = options.patch[opIndex];
|
|
1122
|
+
const applySequentialOp = (op, opIndex) => {
|
|
1061
1123
|
const baseJson = materialize(shadowBase.root);
|
|
1062
1124
|
let intents;
|
|
1063
1125
|
try {
|
|
@@ -1071,6 +1133,42 @@ function jsonPatchToCrdtInternal(options) {
|
|
|
1071
1133
|
const shadowStep = applyIntentsToCrdt(shadowBase, shadowBase, intents, shadowDot, "base", shadowBump);
|
|
1072
1134
|
if (!shadowStep.ok) return withOpIndex(shadowStep, opIndex);
|
|
1073
1135
|
} else shadowBase = cloneDoc(options.head);
|
|
1136
|
+
return { ok: true };
|
|
1137
|
+
};
|
|
1138
|
+
for (let opIndex = 0; opIndex < options.patch.length; opIndex++) {
|
|
1139
|
+
const op = options.patch[opIndex];
|
|
1140
|
+
if (op.op === "move") {
|
|
1141
|
+
const baseJson = materialize(shadowBase.root);
|
|
1142
|
+
let fromValue;
|
|
1143
|
+
try {
|
|
1144
|
+
fromValue = structuredClone(getAtJson(baseJson, parseJsonPointer(op.from)));
|
|
1145
|
+
} catch {
|
|
1146
|
+
try {
|
|
1147
|
+
compileJsonPatchToIntent(baseJson, [{
|
|
1148
|
+
op: "remove",
|
|
1149
|
+
path: op.from
|
|
1150
|
+
}], { semantics: "sequential" });
|
|
1151
|
+
} catch (error) {
|
|
1152
|
+
return withOpIndex(toApplyError$1(error), opIndex);
|
|
1153
|
+
}
|
|
1154
|
+
return withOpIndex(toApplyError$1(/* @__PURE__ */ new Error(`failed to resolve move source at ${op.from}`)), opIndex);
|
|
1155
|
+
}
|
|
1156
|
+
if (op.from === op.path) continue;
|
|
1157
|
+
const removeStep = applySequentialOp({
|
|
1158
|
+
op: "remove",
|
|
1159
|
+
path: op.from
|
|
1160
|
+
}, opIndex);
|
|
1161
|
+
if (!removeStep.ok) return removeStep;
|
|
1162
|
+
const addStep = applySequentialOp({
|
|
1163
|
+
op: "add",
|
|
1164
|
+
path: op.path,
|
|
1165
|
+
value: fromValue
|
|
1166
|
+
}, opIndex);
|
|
1167
|
+
if (!addStep.ok) return addStep;
|
|
1168
|
+
continue;
|
|
1169
|
+
}
|
|
1170
|
+
const step = applySequentialOp(op, opIndex);
|
|
1171
|
+
if (!step.ok) return step;
|
|
1074
1172
|
}
|
|
1075
1173
|
return { ok: true };
|
|
1076
1174
|
}
|
|
@@ -1142,8 +1240,10 @@ function createState(initial, options) {
|
|
|
1142
1240
|
/**
|
|
1143
1241
|
* Fork a replica from a shared origin state while assigning a new local actor ID.
|
|
1144
1242
|
* The forked state has an independent document clone and clock.
|
|
1243
|
+
* By default this rejects actor reuse to prevent duplicate-dot collisions across peers.
|
|
1145
1244
|
*/
|
|
1146
|
-
function forkState(origin, actor) {
|
|
1245
|
+
function forkState(origin, actor, options = {}) {
|
|
1246
|
+
if (actor === origin.clock.actor && !options.allowActorReuse) throw new Error(`forkState actor must be unique; refusing to reuse origin actor '${actor}'`);
|
|
1147
1247
|
return {
|
|
1148
1248
|
doc: cloneDoc(origin.doc),
|
|
1149
1249
|
clock: createClock(actor, origin.clock.ctr)
|
|
@@ -1261,8 +1361,8 @@ function applyPatchInternal(state, patch, options) {
|
|
|
1261
1361
|
doc: cloneDoc(options.base.doc),
|
|
1262
1362
|
clock: createClock("__base__", 0)
|
|
1263
1363
|
} : null;
|
|
1264
|
-
for (const op of patch) {
|
|
1265
|
-
const step = applyPatchOpSequential(state, op, options, explicitBaseState ? explicitBaseState.doc : cloneDoc(state.doc));
|
|
1364
|
+
for (const [opIndex, op] of patch.entries()) {
|
|
1365
|
+
const step = applyPatchOpSequential(state, op, options, explicitBaseState ? explicitBaseState.doc : cloneDoc(state.doc), opIndex);
|
|
1266
1366
|
if (!step.ok) return step;
|
|
1267
1367
|
if (explicitBaseState && op.op !== "test") {
|
|
1268
1368
|
const baseStep = applyPatchInternal(explicitBaseState, [op], {
|
|
@@ -1279,10 +1379,12 @@ function applyPatchInternal(state, patch, options) {
|
|
|
1279
1379
|
if (!compiled.ok) return compiled;
|
|
1280
1380
|
return applyIntentsToCrdt(baseDoc, state.doc, compiled.intents, () => state.clock.next(), options.testAgainst ?? "head", (ctr) => bumpClockCounter(state, ctr));
|
|
1281
1381
|
}
|
|
1282
|
-
function applyPatchOpSequential(state, op, options, baseDoc) {
|
|
1382
|
+
function applyPatchOpSequential(state, op, options, baseDoc, opIndex) {
|
|
1283
1383
|
const baseJson = materialize(baseDoc.root);
|
|
1284
1384
|
if (op.op === "move") {
|
|
1285
|
-
const
|
|
1385
|
+
const fromResolved = resolveValueAtPointer(baseJson, op.from, opIndex);
|
|
1386
|
+
if (!fromResolved.ok) return fromResolved;
|
|
1387
|
+
const fromValue = fromResolved.value;
|
|
1286
1388
|
const removeRes = applySinglePatchOp(state, baseDoc, {
|
|
1287
1389
|
op: "remove",
|
|
1288
1390
|
path: op.from
|
|
@@ -1295,7 +1397,9 @@ function applyPatchOpSequential(state, op, options, baseDoc) {
|
|
|
1295
1397
|
}, options);
|
|
1296
1398
|
}
|
|
1297
1399
|
if (op.op === "copy") {
|
|
1298
|
-
const
|
|
1400
|
+
const fromResolved = resolveValueAtPointer(baseJson, op.from, opIndex);
|
|
1401
|
+
if (!fromResolved.ok) return fromResolved;
|
|
1402
|
+
const fromValue = fromResolved.value;
|
|
1299
1403
|
return applySinglePatchOp(state, baseDoc, {
|
|
1300
1404
|
op: "add",
|
|
1301
1405
|
path: op.path,
|
|
@@ -1304,6 +1408,22 @@ function applyPatchOpSequential(state, op, options, baseDoc) {
|
|
|
1304
1408
|
}
|
|
1305
1409
|
return applySinglePatchOp(state, baseDoc, op, options);
|
|
1306
1410
|
}
|
|
1411
|
+
function resolveValueAtPointer(baseJson, pointer, opIndex) {
|
|
1412
|
+
let path;
|
|
1413
|
+
try {
|
|
1414
|
+
path = parseJsonPointer(pointer);
|
|
1415
|
+
} catch (error) {
|
|
1416
|
+
return toPointerParseApplyError(error, pointer, opIndex);
|
|
1417
|
+
}
|
|
1418
|
+
try {
|
|
1419
|
+
return {
|
|
1420
|
+
ok: true,
|
|
1421
|
+
value: getAtJson(baseJson, path)
|
|
1422
|
+
};
|
|
1423
|
+
} catch (error) {
|
|
1424
|
+
return toPointerLookupApplyError(error, pointer, opIndex);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1307
1427
|
function applySinglePatchOp(state, baseDoc, op, options) {
|
|
1308
1428
|
const compiled = compileIntents(materialize(baseDoc.root), [op], "sequential");
|
|
1309
1429
|
if (!compiled.ok) return compiled;
|
|
@@ -1362,6 +1482,27 @@ function toApplyError(error) {
|
|
|
1362
1482
|
message: error instanceof Error ? error.message : "failed to compile patch"
|
|
1363
1483
|
};
|
|
1364
1484
|
}
|
|
1485
|
+
function toPointerParseApplyError(error, pointer, opIndex) {
|
|
1486
|
+
return {
|
|
1487
|
+
ok: false,
|
|
1488
|
+
code: 409,
|
|
1489
|
+
reason: "INVALID_POINTER",
|
|
1490
|
+
message: error instanceof Error ? error.message : "invalid pointer",
|
|
1491
|
+
path: pointer,
|
|
1492
|
+
opIndex
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
function toPointerLookupApplyError(error, pointer, opIndex) {
|
|
1496
|
+
const mapped = mapLookupErrorToPatchReason(error);
|
|
1497
|
+
return {
|
|
1498
|
+
ok: false,
|
|
1499
|
+
code: 409,
|
|
1500
|
+
reason: mapped.reason,
|
|
1501
|
+
message: mapped.message,
|
|
1502
|
+
path: pointer,
|
|
1503
|
+
opIndex
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1365
1506
|
|
|
1366
1507
|
//#endregion
|
|
1367
1508
|
//#region src/serialize.ts
|
|
@@ -161,6 +161,14 @@ type CrdtState = {
|
|
|
161
161
|
doc: Doc;
|
|
162
162
|
clock: Clock;
|
|
163
163
|
};
|
|
164
|
+
/** Options for `forkState`. */
|
|
165
|
+
interface ForkStateOptions {
|
|
166
|
+
/**
|
|
167
|
+
* Allow reusing the origin actor ID when forking.
|
|
168
|
+
* Defaults to `false` to prevent duplicate-dot collisions across replicas.
|
|
169
|
+
*/
|
|
170
|
+
allowActorReuse?: boolean;
|
|
171
|
+
}
|
|
164
172
|
/** Result from applying a patch for a specific actor using a shared version vector. */
|
|
165
173
|
type ApplyPatchAsActorResult = {
|
|
166
174
|
/** Updated CRDT state for the actor that produced this patch. */state: CrdtState; /** Updated version vector after applying the patch. */
|
|
@@ -310,8 +318,9 @@ declare function createState(initial: JsonValue, options: {
|
|
|
310
318
|
/**
|
|
311
319
|
* Fork a replica from a shared origin state while assigning a new local actor ID.
|
|
312
320
|
* The forked state has an independent document clone and clock.
|
|
321
|
+
* By default this rejects actor reuse to prevent duplicate-dot collisions across peers.
|
|
313
322
|
*/
|
|
314
|
-
declare function forkState(origin: CrdtState, actor: ActorId): CrdtState;
|
|
323
|
+
declare function forkState(origin: CrdtState, actor: ActorId, options?: ForkStateOptions): CrdtState;
|
|
315
324
|
/**
|
|
316
325
|
* Materialize a CRDT document or state back to a plain JSON value.
|
|
317
326
|
* @param target - A `Doc` or `CrdtState` to materialize.
|
|
@@ -442,4 +451,4 @@ declare function mergeState(a: CrdtState, b: CrdtState, options?: MergeStateOpti
|
|
|
442
451
|
/** Non-throwing `mergeState` variant with structured conflict details. */
|
|
443
452
|
declare function tryMergeState(a: CrdtState, b: CrdtState, options?: MergeStateOptions): TryMergeStateResult;
|
|
444
453
|
//#endregion
|
|
445
|
-
export {
|
|
454
|
+
export { ObjNode as $, ApplyPatchAsActorResult as A, ElemId as B, toJson as C, ActorId as D, validateJsonPatch as E, CompilePatchOptions as F, JsonPatchToCrdtOptions as G, IntentOp as H, CrdtState as I, LwwReg as J, JsonPrimitive as K, DiffOptions as L, ApplyPatchOptions as M, ApplyResult as N, ApplyError as O, Clock as P, ObjEntry as Q, Doc as R, forkState as S, tryApplyPatchInPlace as T, JsonPatch as U, ForkStateOptions as V, JsonPatchOp as W, MergeStateOptions as X, MergeDocOptions as Y, Node as Z, PatchError as _, tryMergeState as a, SerializedClock as at, applyPatchInPlace as b, serializeDoc as c, SerializedRgaElem as ct, compileJsonPatchToIntent as d, TryApplyPatchResult as dt, PatchErrorReason as et, diffJsonPatch as f, TryMergeDocResult as ft, stringifyJsonPointer as g, parseJsonPointer as h, VersionVector as ht, tryMergeDoc as i, RgaSeq as it, ApplyPatchInPlaceOptions as j, ApplyPatchAsActorOptions as k, serializeState as l, SerializedState as lt, jsonEquals as m, ValidatePatchResult as mt, mergeDoc as n, ROOT_KEY as nt, deserializeDoc as o, SerializedDoc as ot, getAtJson as p, TryMergeStateResult as pt, JsonValue as q, mergeState as r, RgaElem as rt, deserializeState as s, SerializedNode as st, MergeError as t, PatchSemantics as tt, PatchCompileError as u, TryApplyPatchInPlaceResult as ut, applyPatch as v, tryApplyPatch as w, createState as x, applyPatchAsActor as y, Dot as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-patch-to-crdt",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Convert JSON Patch (RFC 6902) to and from a CRDT-friendly representation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"crdt",
|
|
@@ -54,8 +54,5 @@
|
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"typescript": "^5"
|
|
57
|
-
},
|
|
58
|
-
"engines": {
|
|
59
|
-
"node": ">=18"
|
|
60
57
|
}
|
|
61
58
|
}
|