@ny4n/chord 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +261 -2
- package/dist/api.d.ts +20 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +77 -0
- package/dist/api.js.map +1 -0
- package/dist/bundler.d.ts +6 -0
- package/dist/bundler.d.ts.map +1 -0
- package/dist/bundler.js +3 -0
- package/dist/bundler.js.map +1 -0
- package/dist/context/index.d.ts +24 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +97 -0
- package/dist/context/index.js.map +1 -0
- package/dist/delta/apply-immutable-trusted.d.ts +4 -0
- package/dist/delta/apply-immutable-trusted.d.ts.map +1 -0
- package/dist/delta/apply-immutable-trusted.js +127 -0
- package/dist/delta/apply-immutable-trusted.js.map +1 -0
- package/dist/delta/core.d.ts +108 -0
- package/dist/delta/core.d.ts.map +1 -0
- package/dist/delta/core.js +645 -0
- package/dist/delta/core.js.map +1 -0
- package/dist/delta/diff.d.ts +5 -0
- package/dist/delta/diff.d.ts.map +1 -0
- package/dist/delta/diff.js +433 -0
- package/dist/delta/diff.js.map +1 -0
- package/dist/delta/draft.d.ts +5 -0
- package/dist/delta/draft.d.ts.map +1 -0
- package/dist/delta/draft.js +2 -0
- package/dist/delta/draft.js.map +1 -0
- package/dist/delta/index.d.ts +5 -0
- package/dist/delta/index.d.ts.map +1 -0
- package/dist/delta/index.js +6 -0
- package/dist/delta/index.js.map +1 -0
- package/dist/delta/revision-validator.d.ts +7 -0
- package/dist/delta/revision-validator.d.ts.map +1 -0
- package/dist/delta/revision-validator.js +71 -0
- package/dist/delta/revision-validator.js.map +1 -0
- package/dist/delta/tracker.d.ts +26 -0
- package/dist/delta/tracker.d.ts.map +1 -0
- package/dist/delta/tracker.js +2069 -0
- package/dist/delta/tracker.js.map +1 -0
- package/dist/facets/host.d.ts +12 -0
- package/dist/facets/host.d.ts.map +1 -0
- package/dist/facets/host.js +763 -0
- package/dist/facets/host.js.map +1 -0
- package/dist/facets/loader.d.ts +3 -0
- package/dist/facets/loader.d.ts.map +1 -0
- package/dist/facets/loader.js +5 -0
- package/dist/facets/loader.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +10 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +124 -0
- package/dist/json.js.map +1 -0
- package/dist/node/bundle-loader.d.ts +30 -0
- package/dist/node/bundle-loader.d.ts.map +1 -0
- package/dist/node/bundle-loader.js +377 -0
- package/dist/node/bundle-loader.js.map +1 -0
- package/dist/node/bundle.d.ts +26 -0
- package/dist/node/bundle.d.ts.map +1 -0
- package/dist/node/bundle.js +183 -0
- package/dist/node/bundle.js.map +1 -0
- package/dist/node/manifest.d.ts +36 -0
- package/dist/node/manifest.d.ts.map +1 -0
- package/dist/node/manifest.js +6 -0
- package/dist/node/manifest.js.map +1 -0
- package/dist/node/package.d.ts +15 -0
- package/dist/node/package.d.ts.map +1 -0
- package/dist/node/package.js +199 -0
- package/dist/node/package.js.map +1 -0
- package/dist/node.d.ts +5 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +3 -0
- package/dist/node.js.map +1 -0
- package/dist/services/consumer.d.ts +11 -0
- package/dist/services/consumer.d.ts.map +1 -0
- package/dist/services/consumer.js +585 -0
- package/dist/services/consumer.js.map +1 -0
- package/dist/services/errors.d.ts +8 -0
- package/dist/services/errors.d.ts.map +1 -0
- package/dist/services/errors.js +22 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/handle.d.ts +15 -0
- package/dist/services/handle.d.ts.map +1 -0
- package/dist/services/handle.js +101 -0
- package/dist/services/handle.js.map +1 -0
- package/dist/services/instances.d.ts +26 -0
- package/dist/services/instances.d.ts.map +1 -0
- package/dist/services/instances.js +140 -0
- package/dist/services/instances.js.map +1 -0
- package/dist/services/loopback.d.ts +5 -0
- package/dist/services/loopback.d.ts.map +1 -0
- package/dist/services/loopback.js +15 -0
- package/dist/services/loopback.js.map +1 -0
- package/dist/services/provider.d.ts +37 -0
- package/dist/services/provider.d.ts.map +1 -0
- package/dist/services/provider.js +521 -0
- package/dist/services/provider.js.map +1 -0
- package/dist/services/state-codec.d.ts +15 -0
- package/dist/services/state-codec.d.ts.map +1 -0
- package/dist/services/state-codec.js +133 -0
- package/dist/services/state-codec.js.map +1 -0
- package/dist/services/state-internals.d.ts +13 -0
- package/dist/services/state-internals.d.ts.map +1 -0
- package/dist/services/state-internals.js +10 -0
- package/dist/services/state-internals.js.map +1 -0
- package/dist/services/state.d.ts +28 -0
- package/dist/services/state.d.ts.map +1 -0
- package/dist/services/state.js +397 -0
- package/dist/services/state.js.map +1 -0
- package/dist/services/wire.d.ts +63 -0
- package/dist/services/wire.d.ts.map +1 -0
- package/dist/services/wire.js +186 -0
- package/dist/services/wire.js.map +1 -0
- package/dist/types.d.ts +277 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -5
- package/src/delta/README.md +191 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
const DATA_DESCRIPTOR = {
|
|
2
|
+
value: undefined,
|
|
3
|
+
writable: true,
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
};
|
|
7
|
+
/** Apply self-produced trusted operations while copying each touched container once. */
|
|
8
|
+
export function applyImmutableTrusted(target, operations) {
|
|
9
|
+
let root = target;
|
|
10
|
+
const owned = new WeakSet();
|
|
11
|
+
for (const operation of operations) {
|
|
12
|
+
if (operation[0] === "r") {
|
|
13
|
+
root = operation[1];
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (operation[0] === "p" || operation[0] === "m") {
|
|
17
|
+
const copied = copyPath(root, operation[1], operation[1].length, owned);
|
|
18
|
+
root = copied.root;
|
|
19
|
+
if (!Array.isArray(copied.target))
|
|
20
|
+
throw new TypeError("Trusted array operation target is not an array");
|
|
21
|
+
if (operation[0] === "p")
|
|
22
|
+
spliceTrusted(copied.target, operation[2], operation[3], operation[4]);
|
|
23
|
+
else
|
|
24
|
+
permuteTrusted(copied.target, operation[2]);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const path = operation[1];
|
|
28
|
+
const copied = copyPath(root, path, path.length - 1, owned);
|
|
29
|
+
root = copied.root;
|
|
30
|
+
const key = path[path.length - 1];
|
|
31
|
+
switch (operation[0]) {
|
|
32
|
+
case "s":
|
|
33
|
+
defineData(copied.target, key, operation[2]);
|
|
34
|
+
break;
|
|
35
|
+
case "d":
|
|
36
|
+
if (Array.isArray(copied.target)) {
|
|
37
|
+
if (typeof key !== "number")
|
|
38
|
+
throw new TypeError("Trusted array deletion key is not numeric");
|
|
39
|
+
spliceTrusted(copied.target, key, 1, []);
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
Reflect.deleteProperty(copied.target, key);
|
|
43
|
+
break;
|
|
44
|
+
case "a": {
|
|
45
|
+
const current = read(copied.target, key);
|
|
46
|
+
if (typeof current !== "string")
|
|
47
|
+
throw new TypeError("Trusted append target is not a string");
|
|
48
|
+
defineData(copied.target, key, `${current}${operation[2]}`);
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case "t": {
|
|
52
|
+
const current = read(copied.target, key);
|
|
53
|
+
if (typeof current !== "string")
|
|
54
|
+
throw new TypeError("Trusted truncate target is not a string");
|
|
55
|
+
defineData(copied.target, key, current.slice(operation[2]));
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return root;
|
|
61
|
+
}
|
|
62
|
+
function copyPath(root, path, length, owned) {
|
|
63
|
+
if (!isContainer(root))
|
|
64
|
+
throw new TypeError("Trusted operation root is not a container");
|
|
65
|
+
let copiedRoot = root;
|
|
66
|
+
if (!owned.has(root)) {
|
|
67
|
+
copiedRoot = shallowCopy(root);
|
|
68
|
+
owned.add(copiedRoot);
|
|
69
|
+
}
|
|
70
|
+
let destination = copiedRoot;
|
|
71
|
+
for (let index = 0; index < length; index++) {
|
|
72
|
+
const segment = path[index];
|
|
73
|
+
const child = read(destination, segment);
|
|
74
|
+
if (!isContainer(child))
|
|
75
|
+
throw new TypeError("Trusted operation path is not a container");
|
|
76
|
+
if (owned.has(child)) {
|
|
77
|
+
destination = child;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const copy = shallowCopy(child);
|
|
81
|
+
defineData(destination, segment, copy);
|
|
82
|
+
owned.add(copy);
|
|
83
|
+
destination = copy;
|
|
84
|
+
}
|
|
85
|
+
return { root: copiedRoot, target: destination };
|
|
86
|
+
}
|
|
87
|
+
function shallowCopy(value) {
|
|
88
|
+
if (Array.isArray(value))
|
|
89
|
+
return Array.from(value);
|
|
90
|
+
const result = Object.create(Object.getPrototypeOf(value) === null ? null : Object.prototype);
|
|
91
|
+
for (const key of Object.keys(value))
|
|
92
|
+
defineData(result, key, value[key]);
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
function read(target, key) {
|
|
96
|
+
return target[key];
|
|
97
|
+
}
|
|
98
|
+
function defineData(target, key, value) {
|
|
99
|
+
DATA_DESCRIPTOR.value = value;
|
|
100
|
+
Object.defineProperty(target, key, DATA_DESCRIPTOR);
|
|
101
|
+
DATA_DESCRIPTOR.value = undefined;
|
|
102
|
+
}
|
|
103
|
+
function spliceTrusted(target, start, remove, items) {
|
|
104
|
+
const oldLength = target.length;
|
|
105
|
+
const delta = items.length - remove;
|
|
106
|
+
if (delta > 0) {
|
|
107
|
+
target.length = oldLength + delta;
|
|
108
|
+
target.copyWithin(start + items.length, start + remove, oldLength);
|
|
109
|
+
}
|
|
110
|
+
else if (delta < 0) {
|
|
111
|
+
target.copyWithin(start + items.length, start + remove, oldLength);
|
|
112
|
+
target.length = oldLength + delta;
|
|
113
|
+
}
|
|
114
|
+
for (let index = 0; index < items.length; index++)
|
|
115
|
+
defineData(target, start + index, items[index]);
|
|
116
|
+
}
|
|
117
|
+
function permuteTrusted(target, permutation) {
|
|
118
|
+
if (target.length !== permutation.length)
|
|
119
|
+
throw new TypeError("Trusted permutation length mismatch");
|
|
120
|
+
const previous = target.slice();
|
|
121
|
+
for (let index = 0; index < permutation.length; index++)
|
|
122
|
+
target[index] = previous[permutation[index]];
|
|
123
|
+
}
|
|
124
|
+
function isContainer(value) {
|
|
125
|
+
return value !== null && typeof value === "object";
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=apply-immutable-trusted.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-immutable-trusted.js","sourceRoot":"","sources":["../../src/delta/apply-immutable-trusted.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonValue } from \"../types.ts\";\nimport type { Op, Path, Seg } from \"./index.ts\";\n\ntype JsonContainer = JsonValue[] | Record<string, JsonValue>;\ntype CopiedPath = { root: JsonValue; target: JsonContainer };\n\nconst DATA_DESCRIPTOR: PropertyDescriptor = {\n\tvalue: undefined,\n\twritable: true,\n\tenumerable: true,\n\tconfigurable: true,\n};\n\n/** Apply self-produced trusted operations while copying each touched container once. */\nexport function applyImmutableTrusted<T>(target: T, operations: readonly Op[]): T {\n\tlet root = target as unknown as JsonValue;\n\tconst owned = new WeakSet<object>();\n\tfor (const operation of operations) {\n\t\tif (operation[0] === \"r\") {\n\t\t\troot = operation[1];\n\t\t\tcontinue;\n\t\t}\n\t\tif (operation[0] === \"p\" || operation[0] === \"m\") {\n\t\t\tconst copied = copyPath(root, operation[1], operation[1].length, owned);\n\t\t\troot = copied.root;\n\t\t\tif (!Array.isArray(copied.target)) throw new TypeError(\"Trusted array operation target is not an array\");\n\t\t\tif (operation[0] === \"p\") spliceTrusted(copied.target, operation[2], operation[3], operation[4]);\n\t\t\telse permuteTrusted(copied.target, operation[2]);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst path = operation[1];\n\t\tconst copied = copyPath(root, path, path.length - 1, owned);\n\t\troot = copied.root;\n\t\tconst key = path[path.length - 1]!;\n\t\tswitch (operation[0]) {\n\t\t\tcase \"s\":\n\t\t\t\tdefineData(copied.target, key, operation[2]);\n\t\t\t\tbreak;\n\t\t\tcase \"d\":\n\t\t\t\tif (Array.isArray(copied.target)) {\n\t\t\t\t\tif (typeof key !== \"number\") throw new TypeError(\"Trusted array deletion key is not numeric\");\n\t\t\t\t\tspliceTrusted(copied.target, key, 1, []);\n\t\t\t\t} else Reflect.deleteProperty(copied.target, key);\n\t\t\t\tbreak;\n\t\t\tcase \"a\": {\n\t\t\t\tconst current = read(copied.target, key);\n\t\t\t\tif (typeof current !== \"string\") throw new TypeError(\"Trusted append target is not a string\");\n\t\t\t\tdefineData(copied.target, key, `${current}${operation[2]}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"t\": {\n\t\t\t\tconst current = read(copied.target, key);\n\t\t\t\tif (typeof current !== \"string\") throw new TypeError(\"Trusted truncate target is not a string\");\n\t\t\t\tdefineData(copied.target, key, current.slice(operation[2]));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn root as unknown as T;\n}\n\nfunction copyPath(root: JsonValue, path: Path, length: number, owned: WeakSet<object>): CopiedPath {\n\tif (!isContainer(root)) throw new TypeError(\"Trusted operation root is not a container\");\n\tlet copiedRoot = root;\n\tif (!owned.has(root)) {\n\t\tcopiedRoot = shallowCopy(root);\n\t\towned.add(copiedRoot);\n\t}\n\tlet destination = copiedRoot as JsonContainer;\n\tfor (let index = 0; index < length; index++) {\n\t\tconst segment = path[index]!;\n\t\tconst child = read(destination, segment);\n\t\tif (!isContainer(child)) throw new TypeError(\"Trusted operation path is not a container\");\n\t\tif (owned.has(child)) {\n\t\t\tdestination = child;\n\t\t\tcontinue;\n\t\t}\n\t\tconst copy = shallowCopy(child);\n\t\tdefineData(destination, segment, copy);\n\t\towned.add(copy);\n\t\tdestination = copy;\n\t}\n\treturn { root: copiedRoot, target: destination };\n}\n\nfunction shallowCopy(value: JsonContainer): JsonContainer {\n\tif (Array.isArray(value)) return Array.from(value);\n\tconst result = Object.create(Object.getPrototypeOf(value) === null ? null : Object.prototype) as Record<\n\t\tstring,\n\t\tJsonValue\n\t>;\n\tfor (const key of Object.keys(value)) defineData(result, key, value[key]!);\n\treturn result;\n}\n\nfunction read(target: JsonContainer, key: Seg): JsonValue {\n\treturn (target as Record<Seg, JsonValue>)[key]!;\n}\n\nfunction defineData(target: JsonContainer, key: Seg, value: JsonValue): void {\n\tDATA_DESCRIPTOR.value = value;\n\tObject.defineProperty(target, key, DATA_DESCRIPTOR);\n\tDATA_DESCRIPTOR.value = undefined;\n}\n\nfunction spliceTrusted(target: JsonValue[], start: number, remove: number, items: readonly JsonValue[]): void {\n\tconst oldLength = target.length;\n\tconst delta = items.length - remove;\n\tif (delta > 0) {\n\t\ttarget.length = oldLength + delta;\n\t\ttarget.copyWithin(start + items.length, start + remove, oldLength);\n\t} else if (delta < 0) {\n\t\ttarget.copyWithin(start + items.length, start + remove, oldLength);\n\t\ttarget.length = oldLength + delta;\n\t}\n\tfor (let index = 0; index < items.length; index++) defineData(target, start + index, items[index]!);\n}\n\nfunction permuteTrusted(target: JsonValue[], permutation: readonly number[]): void {\n\tif (target.length !== permutation.length) throw new TypeError(\"Trusted permutation length mismatch\");\n\tconst previous = target.slice();\n\tfor (let index = 0; index < permutation.length; index++) target[index] = previous[permutation[index]!]!;\n}\n\nfunction isContainer(value: unknown): value is JsonContainer {\n\treturn value !== null && typeof value === \"object\";\n}\n"]}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { JsonValue } from "../types.ts";
|
|
2
|
+
export type { JsonValue } from "../types.ts";
|
|
3
|
+
export type Seg = string | number;
|
|
4
|
+
export type Path = readonly Seg[];
|
|
5
|
+
export type NonEmptyPath = readonly [Seg, ...Seg[]];
|
|
6
|
+
/** A path inline, or an id assigned by the encoder on second use. */
|
|
7
|
+
export type PathRef<P extends Path = Path> = P | number;
|
|
8
|
+
/**
|
|
9
|
+
* Tuples are the form — in memory, on the wire, on disk.
|
|
10
|
+
*
|
|
11
|
+
* `r` is the ONLY op that replaces a whole value. `s`/`d`/`a`/`t` cannot target
|
|
12
|
+
* the root: the type forbids it. `p` and `m` may, because a tracked value can
|
|
13
|
+
* itself be an array. Operation shape is not canonical: an array may be emptied by either
|
|
14
|
+
* a replacement or a root splice.
|
|
15
|
+
*
|
|
16
|
+
* `Op` knows nothing about the path dictionary. Interning, id references and
|
|
17
|
+
* omitted paths live in `WireOp` and exist only between `encode` and `decode`.
|
|
18
|
+
*/
|
|
19
|
+
export type Op = readonly ["r", JsonValue] | readonly ["s", NonEmptyPath, JsonValue] | readonly ["d", NonEmptyPath] | readonly ["a", NonEmptyPath, string] | readonly ["t", NonEmptyPath, number] | readonly ["p", Path, number, number, JsonValue[]]
|
|
20
|
+
/** Reorder an array in place: `new[i] = old[permutation[i]]`. */
|
|
21
|
+
| readonly ["m", Path, number[]];
|
|
22
|
+
/**
|
|
23
|
+
* What crosses a boundary. Adds two compressions and nothing else:
|
|
24
|
+
*
|
|
25
|
+
* ["#", id, path] defines an id, emitted on a path's SECOND use
|
|
26
|
+
* a numeric PathRef references a previously defined id
|
|
27
|
+
* a shortened tuple reuses the previous op's path; arity disambiguates
|
|
28
|
+
*
|
|
29
|
+
* ["r", value] carries no path, so it encodes to itself — which is why isBase
|
|
30
|
+
* works unchanged on either vocabulary.
|
|
31
|
+
*/
|
|
32
|
+
export type WireOp = readonly ["r", JsonValue] | readonly ["s", PathRef<NonEmptyPath>, JsonValue] | readonly ["s", JsonValue] | readonly ["d", PathRef<NonEmptyPath>] | readonly ["d"] | readonly ["a", PathRef<NonEmptyPath>, string] | readonly ["a", string] | readonly ["t", PathRef<NonEmptyPath>, number] | readonly ["t", number] | readonly ["p", PathRef, number, number, JsonValue[]] | readonly ["p", number, number, JsonValue[]] | readonly ["m", PathRef, number[]] | readonly ["m", number[]] | readonly ["#", number, Path];
|
|
33
|
+
export declare const isReplace: (op: Op | WireOp) => boolean;
|
|
34
|
+
/**
|
|
35
|
+
* A batch begins with a replacement. Flush guarantees `r` is at index 0 or absent,
|
|
36
|
+
* so this is exact rather than a heuristic.
|
|
37
|
+
*/
|
|
38
|
+
export declare const isBase: (ops: readonly (Op | WireOp)[]) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Longest suffix of `a` that is a prefix of `b`. Probes with indexOf and verifies
|
|
41
|
+
* exact substring equality, so the hot loops are native. A hand-written KMP is
|
|
42
|
+
* asymptotically equivalent and much slower in practice.
|
|
43
|
+
*
|
|
44
|
+
* Always correct: the returned n satisfies a.slice(a.length - n) === b.slice(0, n).
|
|
45
|
+
*/
|
|
46
|
+
export declare function overlap(a: string, b: string, scan: number, probe?: number, maxCandidates?: number): number;
|
|
47
|
+
/**
|
|
48
|
+
* Segments that reach the prototype chain.
|
|
49
|
+
*
|
|
50
|
+
* `JSON.parse` is safe on its own — it makes `__proto__` an own property. What is
|
|
51
|
+
* not safe is `parent[key] = value`, which is exactly what an applier does, and
|
|
52
|
+
* paths are data: `["s", ["__proto__", "isAdmin"], true]` pollutes
|
|
53
|
+
* `Object.prototype` for the whole process.
|
|
54
|
+
*
|
|
55
|
+
* Ops arrive from a facet, a plugin compartment, or a tool whose details may echo
|
|
56
|
+
* model output, so none of it is trusted input.
|
|
57
|
+
*/
|
|
58
|
+
export declare const RESERVED_SEGMENTS: ReadonlySet<string>;
|
|
59
|
+
export declare class UnsafePathError extends Error {
|
|
60
|
+
readonly segment: Seg;
|
|
61
|
+
constructor(segment: Seg);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Verb, arity and payload shape for a **decoded** op: paths inline, no `#`, no
|
|
65
|
+
* short forms. `apply` uses this.
|
|
66
|
+
*
|
|
67
|
+
* Validating `Op` against the wire grammar would be laxer than the type: a
|
|
68
|
+
* two-element `["s", value]` would pass, and `apply` would then read the value as
|
|
69
|
+
* a path. Each vocabulary gets the validator that matches it.
|
|
70
|
+
*/
|
|
71
|
+
export declare function assertValidOp(op: unknown): asserts op is Op;
|
|
72
|
+
/** The same, for the wire grammar: ids and short forms are legal here. */
|
|
73
|
+
export declare function assertValidWireOp(op: unknown): asserts op is WireOp;
|
|
74
|
+
export declare function assertSafePath(path: Path): void;
|
|
75
|
+
export declare class PathError extends Error {
|
|
76
|
+
readonly path: Path | number;
|
|
77
|
+
constructor(path: Path | number);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Apply ops to a plain mutable value. Returns the value, because `r` replaces it
|
|
81
|
+
* outright and cannot be done in place.
|
|
82
|
+
*
|
|
83
|
+
* Takes decoded ops. Path ids and omitted paths are a wire concern — run
|
|
84
|
+
* `decode` first if the ops came from a boundary.
|
|
85
|
+
*/
|
|
86
|
+
export declare function apply<T>(target: T | undefined, ops: readonly Op[]): T;
|
|
87
|
+
/** Apply one decoded operation batch without mutating the previous immutable value. */
|
|
88
|
+
export declare function applyImmutable<T>(target: T | undefined, ops: readonly Op[]): T;
|
|
89
|
+
/**
|
|
90
|
+
* Apply decoded operation batches as one final-result-only replay.
|
|
91
|
+
*
|
|
92
|
+
* Containers copied for an earlier batch may be mutated while applying a later
|
|
93
|
+
* batch, so this deliberately exposes no intermediate revisions.
|
|
94
|
+
*/
|
|
95
|
+
export declare function applyImmutableBatches<T>(target: T | undefined, batches: Iterable<readonly Op[]>): T;
|
|
96
|
+
export interface Encoder {
|
|
97
|
+
encode(ops: readonly Op[]): WireOp[];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Intern on SECOND use. A definition costs more than the path it replaces, so
|
|
101
|
+
* interning on first use loses on the many paths written exactly once.
|
|
102
|
+
*/
|
|
103
|
+
export declare function encoder(): Encoder;
|
|
104
|
+
export interface Decoder {
|
|
105
|
+
decode(wire: readonly WireOp[]): Op[];
|
|
106
|
+
}
|
|
107
|
+
export declare function decoder(): Decoder;
|
|
108
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/delta/core.ts"],"names":[],"mappings":"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"}
|