@brightbeamai/chap-coordinator 0.2.8

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.
Files changed (53) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +271 -0
  3. package/dist/api-C3nkEk-B.d.cts +260 -0
  4. package/dist/api-CmSvlIqO.d.ts +260 -0
  5. package/dist/api.cjs +125 -0
  6. package/dist/api.cjs.map +1 -0
  7. package/dist/api.d.cts +4 -0
  8. package/dist/api.d.ts +4 -0
  9. package/dist/api.js +98 -0
  10. package/dist/api.js.map +1 -0
  11. package/dist/index.cjs +2804 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.d.cts +175 -0
  14. package/dist/index.d.ts +175 -0
  15. package/dist/index.js +2762 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/jsonrpc.cjs +103 -0
  18. package/dist/jsonrpc.cjs.map +1 -0
  19. package/dist/jsonrpc.d.cts +65 -0
  20. package/dist/jsonrpc.d.ts +65 -0
  21. package/dist/jsonrpc.js +76 -0
  22. package/dist/jsonrpc.js.map +1 -0
  23. package/dist/methods.cjs +19 -0
  24. package/dist/methods.cjs.map +1 -0
  25. package/dist/methods.d.cts +455 -0
  26. package/dist/methods.d.ts +455 -0
  27. package/dist/methods.js +1 -0
  28. package/dist/methods.js.map +1 -0
  29. package/dist/patch.cjs +277 -0
  30. package/dist/patch.cjs.map +1 -0
  31. package/dist/patch.d.cts +29 -0
  32. package/dist/patch.d.ts +29 -0
  33. package/dist/patch.js +250 -0
  34. package/dist/patch.js.map +1 -0
  35. package/dist/storage/sqlite.cjs +94 -0
  36. package/dist/storage/sqlite.cjs.map +1 -0
  37. package/dist/storage/sqlite.d.cts +67 -0
  38. package/dist/storage/sqlite.d.ts +67 -0
  39. package/dist/storage/sqlite.js +76 -0
  40. package/dist/storage/sqlite.js.map +1 -0
  41. package/dist/storage/store.cjs +45 -0
  42. package/dist/storage/store.cjs.map +1 -0
  43. package/dist/storage/store.d.cts +53 -0
  44. package/dist/storage/store.d.ts +53 -0
  45. package/dist/storage/store.js +20 -0
  46. package/dist/storage/store.js.map +1 -0
  47. package/dist/types.cjs +34 -0
  48. package/dist/types.cjs.map +1 -0
  49. package/dist/types.d.cts +287 -0
  50. package/dist/types.d.ts +287 -0
  51. package/dist/types.js +9 -0
  52. package/dist/types.js.map +1 -0
  53. package/package.json +52 -0
package/dist/patch.cjs ADDED
@@ -0,0 +1,277 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/patch.ts
21
+ var patch_exports = {};
22
+ __export(patch_exports, {
23
+ PatchError: () => PatchError,
24
+ applyJsonPatch: () => applyJsonPatch,
25
+ diffJsonPatch: () => diffJsonPatch
26
+ });
27
+ module.exports = __toCommonJS(patch_exports);
28
+ var PatchError = class extends Error {
29
+ };
30
+ var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
31
+ function unescape(token) {
32
+ return token.replace(/~1/g, "/").replace(/~0/g, "~");
33
+ }
34
+ function splitPath(path) {
35
+ if (path === "") return [];
36
+ if (!path.startsWith("/")) {
37
+ throw new PatchError(`JSON Pointer must start with '/': ${JSON.stringify(path)}`);
38
+ }
39
+ const segments = path.slice(1).split("/").map(unescape);
40
+ for (const seg of segments) {
41
+ if (DANGEROUS_KEYS.has(seg)) {
42
+ throw new PatchError(`Refusing unsafe path segment ${JSON.stringify(seg)}`);
43
+ }
44
+ }
45
+ return segments;
46
+ }
47
+ function navigate(doc, parts) {
48
+ if (parts.length === 0) {
49
+ throw new PatchError("Cannot operate on root with this helper.");
50
+ }
51
+ let parent = doc;
52
+ for (let i = 0; i < parts.length - 1; i++) {
53
+ const part = parts[i];
54
+ if (Array.isArray(parent)) {
55
+ const idx = Number(part);
56
+ if (!Number.isInteger(idx) || idx < 0 || idx >= parent.length) {
57
+ throw new PatchError(`Index out of range at /${parts.slice(0, i + 1).join("/")}`);
58
+ }
59
+ parent = parent[idx];
60
+ } else if (parent !== null && typeof parent === "object") {
61
+ if (!Object.prototype.hasOwnProperty.call(parent, part)) {
62
+ throw new PatchError(`Path not found: /${parts.slice(0, i + 1).join("/")}`);
63
+ }
64
+ parent = parent[part];
65
+ } else {
66
+ throw new PatchError(`Cannot traverse into ${typeof parent} at ${JSON.stringify(part)}`);
67
+ }
68
+ }
69
+ const last = parts[parts.length - 1];
70
+ if (Array.isArray(parent)) {
71
+ if (last === "-") return [parent, "-"];
72
+ const idx = Number(last);
73
+ if (!Number.isInteger(idx)) {
74
+ throw new PatchError(`Array index expected at ${JSON.stringify(last)}`);
75
+ }
76
+ return [parent, idx];
77
+ }
78
+ return [parent, last];
79
+ }
80
+ function getAt(doc, path) {
81
+ const parts = splitPath(path);
82
+ if (parts.length === 0) return doc;
83
+ const [parent, key] = navigate(doc, parts);
84
+ if (Array.isArray(parent)) {
85
+ if (key === "-") throw new PatchError("Cannot read '-' position.");
86
+ const idx = key;
87
+ if (idx < 0 || idx >= parent.length) throw new PatchError(`Index out of range: ${path}`);
88
+ return parent[idx];
89
+ }
90
+ if (parent === null || typeof parent !== "object" || !Object.prototype.hasOwnProperty.call(parent, key)) {
91
+ throw new PatchError(`Path not found: ${path}`);
92
+ }
93
+ return parent[key];
94
+ }
95
+ function clone(v) {
96
+ return v === void 0 ? v : JSON.parse(JSON.stringify(v));
97
+ }
98
+ function deepEqual(a, b) {
99
+ if (a === b) return true;
100
+ if (a === null || b === null) return a === b;
101
+ if (typeof a !== typeof b) return false;
102
+ if (typeof a !== "object") return a === b;
103
+ const aArr = Array.isArray(a);
104
+ if (aArr !== Array.isArray(b)) return false;
105
+ if (aArr) {
106
+ if (a.length !== b.length) return false;
107
+ for (let i = 0; i < a.length; i++) if (!deepEqual(a[i], b[i])) return false;
108
+ return true;
109
+ }
110
+ const ak = Object.keys(a);
111
+ const bk = Object.keys(b);
112
+ if (ak.length !== bk.length) return false;
113
+ for (const k of ak) {
114
+ if (!Object.prototype.hasOwnProperty.call(b, k)) return false;
115
+ if (!deepEqual(a[k], b[k])) return false;
116
+ }
117
+ return true;
118
+ }
119
+ function applyOne(doc, op) {
120
+ const kind = op.op;
121
+ const path = op.path ?? "";
122
+ if (kind === "add") {
123
+ if (!("value" in op)) throw new PatchError("'add' requires 'value'");
124
+ const parts = splitPath(path);
125
+ if (parts.length === 0) return op.value;
126
+ const [parent, key] = navigate(doc, parts);
127
+ if (Array.isArray(parent)) {
128
+ if (key === "-") {
129
+ parent.push(op.value);
130
+ } else {
131
+ const idx = key;
132
+ if (idx < 0 || idx > parent.length) {
133
+ throw new PatchError(`Index out of range for add: ${path}`);
134
+ }
135
+ parent.splice(idx, 0, op.value);
136
+ }
137
+ } else if (parent !== null && typeof parent === "object") {
138
+ parent[key] = op.value;
139
+ } else {
140
+ throw new PatchError(`Cannot add into ${typeof parent}`);
141
+ }
142
+ return doc;
143
+ }
144
+ if (kind === "replace") {
145
+ if (!("value" in op)) throw new PatchError("'replace' requires 'value'");
146
+ const parts = splitPath(path);
147
+ if (parts.length === 0) return op.value;
148
+ const [parent, key] = navigate(doc, parts);
149
+ if (Array.isArray(parent)) {
150
+ const idx = key;
151
+ if (idx < 0 || idx >= parent.length) {
152
+ throw new PatchError(`Path not found for replace: ${path}`);
153
+ }
154
+ parent[idx] = op.value;
155
+ } else if (parent !== null && typeof parent === "object") {
156
+ if (!Object.prototype.hasOwnProperty.call(parent, key)) {
157
+ throw new PatchError(`Path not found for replace: ${path}`);
158
+ }
159
+ parent[key] = op.value;
160
+ } else {
161
+ throw new PatchError(`Cannot replace in ${typeof parent}`);
162
+ }
163
+ return doc;
164
+ }
165
+ if (kind === "remove") {
166
+ const parts = splitPath(path);
167
+ if (parts.length === 0) throw new PatchError("Cannot remove root.");
168
+ const [parent, key] = navigate(doc, parts);
169
+ if (Array.isArray(parent)) {
170
+ const idx = key;
171
+ if (idx < 0 || idx >= parent.length) {
172
+ throw new PatchError(`Index out of range for remove: ${path}`);
173
+ }
174
+ parent.splice(idx, 1);
175
+ } else if (parent !== null && typeof parent === "object") {
176
+ if (!Object.prototype.hasOwnProperty.call(parent, key)) {
177
+ throw new PatchError(`Path not found for remove: ${path}`);
178
+ }
179
+ delete parent[key];
180
+ } else {
181
+ throw new PatchError(`Cannot remove from ${typeof parent}`);
182
+ }
183
+ return doc;
184
+ }
185
+ if (kind === "copy") {
186
+ const src = op.from;
187
+ if (src === void 0) throw new PatchError("'copy' requires 'from'");
188
+ const value = clone(getAt(doc, src));
189
+ return applyOne(doc, { op: "add", path, value });
190
+ }
191
+ if (kind === "move") {
192
+ const src = op.from;
193
+ if (src === void 0) throw new PatchError("'move' requires 'from'");
194
+ if (path.startsWith(src + "/")) {
195
+ throw new PatchError("'move' cannot move a location into its own child.");
196
+ }
197
+ const value = clone(getAt(doc, src));
198
+ doc = applyOne(doc, { op: "remove", path: src });
199
+ return applyOne(doc, { op: "add", path, value });
200
+ }
201
+ if (kind === "test") {
202
+ if (!("value" in op)) throw new PatchError("'test' requires 'value'");
203
+ const actual = getAt(doc, path);
204
+ if (!deepEqual(actual, op.value)) throw new PatchError(`'test' failed at ${path}`);
205
+ return doc;
206
+ }
207
+ throw new PatchError(`Unsupported op: ${JSON.stringify(kind)}`);
208
+ }
209
+ var MAX_PATCH_OPS = 1e3;
210
+ var MAX_DOCUMENT_NODES = 1e5;
211
+ function nodeCount(value) {
212
+ if (Array.isArray(value)) {
213
+ let n = 1;
214
+ for (const v of value) n += nodeCount(v);
215
+ return n;
216
+ }
217
+ if (value !== null && typeof value === "object") {
218
+ let n = 1;
219
+ for (const v of Object.values(value)) n += nodeCount(v);
220
+ return n;
221
+ }
222
+ return 1;
223
+ }
224
+ function applyJsonPatch(doc, ops) {
225
+ if (ops.length > MAX_PATCH_OPS) {
226
+ throw new PatchError(`Patch has too many operations (${ops.length} > ${MAX_PATCH_OPS})`);
227
+ }
228
+ let out = JSON.parse(JSON.stringify(doc));
229
+ for (const op of ops) {
230
+ out = applyOne(out, op);
231
+ if (nodeCount(out) > MAX_DOCUMENT_NODES) {
232
+ throw new PatchError(`Patched document exceeds the node limit (${MAX_DOCUMENT_NODES})`);
233
+ }
234
+ }
235
+ return out;
236
+ }
237
+ function diffJsonPatch(from, to, basePath = "") {
238
+ const ops = [];
239
+ if (typeof from !== typeof to || Array.isArray(from) !== Array.isArray(to)) {
240
+ ops.push({ op: "replace", path: basePath || "/", value: to });
241
+ return ops;
242
+ }
243
+ if (from === null || to === null || typeof from !== "object") {
244
+ if (from !== to) {
245
+ ops.push({ op: "replace", path: basePath || "/", value: to });
246
+ }
247
+ return ops;
248
+ }
249
+ if (Array.isArray(from) && Array.isArray(to)) {
250
+ if (JSON.stringify(from) !== JSON.stringify(to)) {
251
+ ops.push({ op: "replace", path: basePath || "/", value: to });
252
+ }
253
+ return ops;
254
+ }
255
+ const fromObj = from;
256
+ const toObj = to;
257
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(fromObj), ...Object.keys(toObj)]);
258
+ for (const key of allKeys) {
259
+ const escaped = key.replace(/~/g, "~0").replace(/\//g, "~1");
260
+ const path = `${basePath}/${escaped}`;
261
+ if (!(key in fromObj)) {
262
+ ops.push({ op: "add", path, value: toObj[key] });
263
+ } else if (!(key in toObj)) {
264
+ ops.push({ op: "remove", path });
265
+ } else {
266
+ ops.push(...diffJsonPatch(fromObj[key], toObj[key], path));
267
+ }
268
+ }
269
+ return ops;
270
+ }
271
+ // Annotate the CommonJS export names for ESM import in node:
272
+ 0 && (module.exports = {
273
+ PatchError,
274
+ applyJsonPatch,
275
+ diffJsonPatch
276
+ });
277
+ //# sourceMappingURL=patch.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/patch.ts"],"sourcesContent":["/**\n * @brightbeamai/chap-coordinator/patch\n *\n * RFC 6902 JSON Patch implementation, plus a small diff computer that\n * produces a patch from two values. Used by the Coordinator for\n * `decide.override` apply and by the playground UI (in the browser) to\n * compute the patch from a textarea edit.\n *\n * Implements all six RFC 6902 operations (add, remove, replace, move,\n * copy, test) with semantics identical to the Python reference. Path\n * segments that enable prototype pollution in a JavaScript runtime\n * (`__proto__`, `constructor`, `prototype`) are rejected, so the two\n * references accept and reject exactly the same patches.\n */\n\nimport type { JsonPatchOp } from \"./types.js\";\n\nexport class PatchError extends Error {}\n\n// Rejected in every JSON Pointer segment: these enable prototype pollution.\nconst DANGEROUS_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nfunction unescape(token: string): string {\n return token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\n\nfunction splitPath(path: string): string[] {\n if (path === \"\") return [];\n if (!path.startsWith(\"/\")) {\n throw new PatchError(`JSON Pointer must start with '/': ${JSON.stringify(path)}`);\n }\n const segments = path.slice(1).split(\"/\").map(unescape);\n for (const seg of segments) {\n if (DANGEROUS_KEYS.has(seg)) {\n throw new PatchError(`Refusing unsafe path segment ${JSON.stringify(seg)}`);\n }\n }\n return segments;\n}\n\n/** Navigate to the parent of the target; return [parent, lastKey]. */\nfunction navigate(doc: any, parts: string[]): [any, string | number] {\n if (parts.length === 0) {\n throw new PatchError(\"Cannot operate on root with this helper.\");\n }\n let parent = doc;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (Array.isArray(parent)) {\n const idx = Number(part);\n if (!Number.isInteger(idx) || idx < 0 || idx >= parent.length) {\n throw new PatchError(`Index out of range at /${parts.slice(0, i + 1).join(\"/\")}`);\n }\n parent = parent[idx];\n } else if (parent !== null && typeof parent === \"object\") {\n if (!Object.prototype.hasOwnProperty.call(parent, part)) {\n throw new PatchError(`Path not found: /${parts.slice(0, i + 1).join(\"/\")}`);\n }\n parent = parent[part];\n } else {\n throw new PatchError(`Cannot traverse into ${typeof parent} at ${JSON.stringify(part)}`);\n }\n }\n const last = parts[parts.length - 1];\n if (Array.isArray(parent)) {\n if (last === \"-\") return [parent, \"-\"];\n const idx = Number(last);\n if (!Number.isInteger(idx)) {\n throw new PatchError(`Array index expected at ${JSON.stringify(last)}`);\n }\n return [parent, idx];\n }\n return [parent, last];\n}\n\nfunction getAt(doc: any, path: string): any {\n const parts = splitPath(path);\n if (parts.length === 0) return doc;\n const [parent, key] = navigate(doc, parts);\n if (Array.isArray(parent)) {\n if (key === \"-\") throw new PatchError(\"Cannot read '-' position.\");\n const idx = key as number;\n if (idx < 0 || idx >= parent.length) throw new PatchError(`Index out of range: ${path}`);\n return parent[idx];\n }\n if (\n parent === null ||\n typeof parent !== \"object\" ||\n !Object.prototype.hasOwnProperty.call(parent, key)\n ) {\n throw new PatchError(`Path not found: ${path}`);\n }\n return parent[key as string];\n}\n\nfunction clone<T>(v: T): T {\n return v === undefined ? v : (JSON.parse(JSON.stringify(v)) as T);\n}\n\nfunction deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n if (a === null || b === null) return a === b;\n if (typeof a !== typeof b) return false;\n if (typeof a !== \"object\") return a === b;\n const aArr = Array.isArray(a);\n if (aArr !== Array.isArray(b)) return false;\n if (aArr) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) if (!deepEqual(a[i], b[i])) return false;\n return true;\n }\n const ak = Object.keys(a);\n const bk = Object.keys(b);\n if (ak.length !== bk.length) return false;\n for (const k of ak) {\n if (!Object.prototype.hasOwnProperty.call(b, k)) return false;\n if (!deepEqual(a[k], b[k])) return false;\n }\n return true;\n}\n\nfunction applyOne(doc: any, op: JsonPatchOp): any {\n const kind = op.op;\n const path = op.path ?? \"\";\n\n if (kind === \"add\") {\n if (!(\"value\" in op)) throw new PatchError(\"'add' requires 'value'\");\n const parts = splitPath(path);\n if (parts.length === 0) return op.value; // replace whole document\n const [parent, key] = navigate(doc, parts);\n if (Array.isArray(parent)) {\n if (key === \"-\") {\n parent.push(op.value);\n } else {\n const idx = key as number;\n if (idx < 0 || idx > parent.length) {\n throw new PatchError(`Index out of range for add: ${path}`);\n }\n parent.splice(idx, 0, op.value);\n }\n } else if (parent !== null && typeof parent === \"object\") {\n parent[key as string] = op.value;\n } else {\n throw new PatchError(`Cannot add into ${typeof parent}`);\n }\n return doc;\n }\n\n if (kind === \"replace\") {\n if (!(\"value\" in op)) throw new PatchError(\"'replace' requires 'value'\");\n const parts = splitPath(path);\n if (parts.length === 0) return op.value;\n const [parent, key] = navigate(doc, parts);\n if (Array.isArray(parent)) {\n const idx = key as number;\n if (idx < 0 || idx >= parent.length) {\n throw new PatchError(`Path not found for replace: ${path}`);\n }\n parent[idx] = op.value;\n } else if (parent !== null && typeof parent === \"object\") {\n if (!Object.prototype.hasOwnProperty.call(parent, key)) {\n throw new PatchError(`Path not found for replace: ${path}`);\n }\n parent[key as string] = op.value;\n } else {\n throw new PatchError(`Cannot replace in ${typeof parent}`);\n }\n return doc;\n }\n\n if (kind === \"remove\") {\n const parts = splitPath(path);\n if (parts.length === 0) throw new PatchError(\"Cannot remove root.\");\n const [parent, key] = navigate(doc, parts);\n if (Array.isArray(parent)) {\n const idx = key as number;\n if (idx < 0 || idx >= parent.length) {\n throw new PatchError(`Index out of range for remove: ${path}`);\n }\n parent.splice(idx, 1);\n } else if (parent !== null && typeof parent === \"object\") {\n if (!Object.prototype.hasOwnProperty.call(parent, key)) {\n throw new PatchError(`Path not found for remove: ${path}`);\n }\n delete parent[key as string];\n } else {\n throw new PatchError(`Cannot remove from ${typeof parent}`);\n }\n return doc;\n }\n\n if (kind === \"copy\") {\n const src = op.from;\n if (src === undefined) throw new PatchError(\"'copy' requires 'from'\");\n const value = clone(getAt(doc, src));\n return applyOne(doc, { op: \"add\", path, value });\n }\n\n if (kind === \"move\") {\n const src = op.from;\n if (src === undefined) throw new PatchError(\"'move' requires 'from'\");\n // RFC 6902 4.4: 'from' MUST NOT be a proper prefix of 'path'.\n if (path.startsWith(src + \"/\")) {\n throw new PatchError(\"'move' cannot move a location into its own child.\");\n }\n const value = clone(getAt(doc, src));\n doc = applyOne(doc, { op: \"remove\", path: src });\n return applyOne(doc, { op: \"add\", path, value });\n }\n\n if (kind === \"test\") {\n if (!(\"value\" in op)) throw new PatchError(\"'test' requires 'value'\");\n const actual = getAt(doc, path);\n if (!deepEqual(actual, op.value)) throw new PatchError(`'test' failed at ${path}`);\n return doc;\n }\n\n throw new PatchError(`Unsupported op: ${JSON.stringify(kind)}`);\n}\n\nconst MAX_PATCH_OPS = 1000;\nconst MAX_DOCUMENT_NODES = 100_000;\n\nfunction nodeCount(value: unknown): number {\n if (Array.isArray(value)) {\n let n = 1;\n for (const v of value) n += nodeCount(v);\n return n;\n }\n if (value !== null && typeof value === \"object\") {\n let n = 1;\n for (const v of Object.values(value as Record<string, unknown>)) n += nodeCount(v);\n return n;\n }\n return 1;\n}\n\nexport function applyJsonPatch(doc: unknown, ops: JsonPatchOp[]): unknown {\n if (ops.length > MAX_PATCH_OPS) {\n throw new PatchError(`Patch has too many operations (${ops.length} > ${MAX_PATCH_OPS})`);\n }\n let out: any = JSON.parse(JSON.stringify(doc));\n for (const op of ops) {\n out = applyOne(out, op);\n if (nodeCount(out) > MAX_DOCUMENT_NODES) {\n throw new PatchError(`Patched document exceeds the node limit (${MAX_DOCUMENT_NODES})`);\n }\n }\n return out;\n}\n\n// ============================================================\n// diff: produce a patch that transforms `from` into `to`\n// ============================================================\n\n/**\n * Compute an RFC 6902 patch that, when applied to `from`, produces\n * `to`. Walks objects key-by-key; arrays use a shallow whole-array\n * replace if any element differs. Sufficient for the playground's\n * draft-edit use case where drafts are small JSON objects.\n */\nexport function diffJsonPatch(from: unknown, to: unknown, basePath = \"\"): JsonPatchOp[] {\n const ops: JsonPatchOp[] = [];\n\n if (typeof from !== typeof to || Array.isArray(from) !== Array.isArray(to)) {\n ops.push({ op: \"replace\", path: basePath || \"/\", value: to });\n return ops;\n }\n\n if (from === null || to === null || typeof from !== \"object\") {\n if (from !== to) {\n ops.push({ op: \"replace\", path: basePath || \"/\", value: to });\n }\n return ops;\n }\n\n if (Array.isArray(from) && Array.isArray(to)) {\n if (JSON.stringify(from) !== JSON.stringify(to)) {\n ops.push({ op: \"replace\", path: basePath || \"/\", value: to });\n }\n return ops;\n }\n\n const fromObj = from as Record<string, unknown>;\n const toObj = to as Record<string, unknown>;\n const allKeys = new Set([...Object.keys(fromObj), ...Object.keys(toObj)]);\n\n for (const key of allKeys) {\n const escaped = key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n const path = `${basePath}/${escaped}`;\n if (!(key in fromObj)) {\n ops.push({ op: \"add\", path, value: toObj[key] });\n } else if (!(key in toObj)) {\n ops.push({ op: \"remove\", path });\n } else {\n ops.push(...diffJsonPatch(fromObj[key], toObj[key], path));\n }\n }\n\n return ops;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,29 @@
1
+ import { JsonPatchOp } from './types.cjs';
2
+
3
+ /**
4
+ * @brightbeamai/chap-coordinator/patch
5
+ *
6
+ * RFC 6902 JSON Patch implementation, plus a small diff computer that
7
+ * produces a patch from two values. Used by the Coordinator for
8
+ * `decide.override` apply and by the playground UI (in the browser) to
9
+ * compute the patch from a textarea edit.
10
+ *
11
+ * Implements all six RFC 6902 operations (add, remove, replace, move,
12
+ * copy, test) with semantics identical to the Python reference. Path
13
+ * segments that enable prototype pollution in a JavaScript runtime
14
+ * (`__proto__`, `constructor`, `prototype`) are rejected, so the two
15
+ * references accept and reject exactly the same patches.
16
+ */
17
+
18
+ declare class PatchError extends Error {
19
+ }
20
+ declare function applyJsonPatch(doc: unknown, ops: JsonPatchOp[]): unknown;
21
+ /**
22
+ * Compute an RFC 6902 patch that, when applied to `from`, produces
23
+ * `to`. Walks objects key-by-key; arrays use a shallow whole-array
24
+ * replace if any element differs. Sufficient for the playground's
25
+ * draft-edit use case where drafts are small JSON objects.
26
+ */
27
+ declare function diffJsonPatch(from: unknown, to: unknown, basePath?: string): JsonPatchOp[];
28
+
29
+ export { PatchError, applyJsonPatch, diffJsonPatch };
@@ -0,0 +1,29 @@
1
+ import { JsonPatchOp } from './types.js';
2
+
3
+ /**
4
+ * @brightbeamai/chap-coordinator/patch
5
+ *
6
+ * RFC 6902 JSON Patch implementation, plus a small diff computer that
7
+ * produces a patch from two values. Used by the Coordinator for
8
+ * `decide.override` apply and by the playground UI (in the browser) to
9
+ * compute the patch from a textarea edit.
10
+ *
11
+ * Implements all six RFC 6902 operations (add, remove, replace, move,
12
+ * copy, test) with semantics identical to the Python reference. Path
13
+ * segments that enable prototype pollution in a JavaScript runtime
14
+ * (`__proto__`, `constructor`, `prototype`) are rejected, so the two
15
+ * references accept and reject exactly the same patches.
16
+ */
17
+
18
+ declare class PatchError extends Error {
19
+ }
20
+ declare function applyJsonPatch(doc: unknown, ops: JsonPatchOp[]): unknown;
21
+ /**
22
+ * Compute an RFC 6902 patch that, when applied to `from`, produces
23
+ * `to`. Walks objects key-by-key; arrays use a shallow whole-array
24
+ * replace if any element differs. Sufficient for the playground's
25
+ * draft-edit use case where drafts are small JSON objects.
26
+ */
27
+ declare function diffJsonPatch(from: unknown, to: unknown, basePath?: string): JsonPatchOp[];
28
+
29
+ export { PatchError, applyJsonPatch, diffJsonPatch };
package/dist/patch.js ADDED
@@ -0,0 +1,250 @@
1
+ // src/patch.ts
2
+ var PatchError = class extends Error {
3
+ };
4
+ var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
5
+ function unescape(token) {
6
+ return token.replace(/~1/g, "/").replace(/~0/g, "~");
7
+ }
8
+ function splitPath(path) {
9
+ if (path === "") return [];
10
+ if (!path.startsWith("/")) {
11
+ throw new PatchError(`JSON Pointer must start with '/': ${JSON.stringify(path)}`);
12
+ }
13
+ const segments = path.slice(1).split("/").map(unescape);
14
+ for (const seg of segments) {
15
+ if (DANGEROUS_KEYS.has(seg)) {
16
+ throw new PatchError(`Refusing unsafe path segment ${JSON.stringify(seg)}`);
17
+ }
18
+ }
19
+ return segments;
20
+ }
21
+ function navigate(doc, parts) {
22
+ if (parts.length === 0) {
23
+ throw new PatchError("Cannot operate on root with this helper.");
24
+ }
25
+ let parent = doc;
26
+ for (let i = 0; i < parts.length - 1; i++) {
27
+ const part = parts[i];
28
+ if (Array.isArray(parent)) {
29
+ const idx = Number(part);
30
+ if (!Number.isInteger(idx) || idx < 0 || idx >= parent.length) {
31
+ throw new PatchError(`Index out of range at /${parts.slice(0, i + 1).join("/")}`);
32
+ }
33
+ parent = parent[idx];
34
+ } else if (parent !== null && typeof parent === "object") {
35
+ if (!Object.prototype.hasOwnProperty.call(parent, part)) {
36
+ throw new PatchError(`Path not found: /${parts.slice(0, i + 1).join("/")}`);
37
+ }
38
+ parent = parent[part];
39
+ } else {
40
+ throw new PatchError(`Cannot traverse into ${typeof parent} at ${JSON.stringify(part)}`);
41
+ }
42
+ }
43
+ const last = parts[parts.length - 1];
44
+ if (Array.isArray(parent)) {
45
+ if (last === "-") return [parent, "-"];
46
+ const idx = Number(last);
47
+ if (!Number.isInteger(idx)) {
48
+ throw new PatchError(`Array index expected at ${JSON.stringify(last)}`);
49
+ }
50
+ return [parent, idx];
51
+ }
52
+ return [parent, last];
53
+ }
54
+ function getAt(doc, path) {
55
+ const parts = splitPath(path);
56
+ if (parts.length === 0) return doc;
57
+ const [parent, key] = navigate(doc, parts);
58
+ if (Array.isArray(parent)) {
59
+ if (key === "-") throw new PatchError("Cannot read '-' position.");
60
+ const idx = key;
61
+ if (idx < 0 || idx >= parent.length) throw new PatchError(`Index out of range: ${path}`);
62
+ return parent[idx];
63
+ }
64
+ if (parent === null || typeof parent !== "object" || !Object.prototype.hasOwnProperty.call(parent, key)) {
65
+ throw new PatchError(`Path not found: ${path}`);
66
+ }
67
+ return parent[key];
68
+ }
69
+ function clone(v) {
70
+ return v === void 0 ? v : JSON.parse(JSON.stringify(v));
71
+ }
72
+ function deepEqual(a, b) {
73
+ if (a === b) return true;
74
+ if (a === null || b === null) return a === b;
75
+ if (typeof a !== typeof b) return false;
76
+ if (typeof a !== "object") return a === b;
77
+ const aArr = Array.isArray(a);
78
+ if (aArr !== Array.isArray(b)) return false;
79
+ if (aArr) {
80
+ if (a.length !== b.length) return false;
81
+ for (let i = 0; i < a.length; i++) if (!deepEqual(a[i], b[i])) return false;
82
+ return true;
83
+ }
84
+ const ak = Object.keys(a);
85
+ const bk = Object.keys(b);
86
+ if (ak.length !== bk.length) return false;
87
+ for (const k of ak) {
88
+ if (!Object.prototype.hasOwnProperty.call(b, k)) return false;
89
+ if (!deepEqual(a[k], b[k])) return false;
90
+ }
91
+ return true;
92
+ }
93
+ function applyOne(doc, op) {
94
+ const kind = op.op;
95
+ const path = op.path ?? "";
96
+ if (kind === "add") {
97
+ if (!("value" in op)) throw new PatchError("'add' requires 'value'");
98
+ const parts = splitPath(path);
99
+ if (parts.length === 0) return op.value;
100
+ const [parent, key] = navigate(doc, parts);
101
+ if (Array.isArray(parent)) {
102
+ if (key === "-") {
103
+ parent.push(op.value);
104
+ } else {
105
+ const idx = key;
106
+ if (idx < 0 || idx > parent.length) {
107
+ throw new PatchError(`Index out of range for add: ${path}`);
108
+ }
109
+ parent.splice(idx, 0, op.value);
110
+ }
111
+ } else if (parent !== null && typeof parent === "object") {
112
+ parent[key] = op.value;
113
+ } else {
114
+ throw new PatchError(`Cannot add into ${typeof parent}`);
115
+ }
116
+ return doc;
117
+ }
118
+ if (kind === "replace") {
119
+ if (!("value" in op)) throw new PatchError("'replace' requires 'value'");
120
+ const parts = splitPath(path);
121
+ if (parts.length === 0) return op.value;
122
+ const [parent, key] = navigate(doc, parts);
123
+ if (Array.isArray(parent)) {
124
+ const idx = key;
125
+ if (idx < 0 || idx >= parent.length) {
126
+ throw new PatchError(`Path not found for replace: ${path}`);
127
+ }
128
+ parent[idx] = op.value;
129
+ } else if (parent !== null && typeof parent === "object") {
130
+ if (!Object.prototype.hasOwnProperty.call(parent, key)) {
131
+ throw new PatchError(`Path not found for replace: ${path}`);
132
+ }
133
+ parent[key] = op.value;
134
+ } else {
135
+ throw new PatchError(`Cannot replace in ${typeof parent}`);
136
+ }
137
+ return doc;
138
+ }
139
+ if (kind === "remove") {
140
+ const parts = splitPath(path);
141
+ if (parts.length === 0) throw new PatchError("Cannot remove root.");
142
+ const [parent, key] = navigate(doc, parts);
143
+ if (Array.isArray(parent)) {
144
+ const idx = key;
145
+ if (idx < 0 || idx >= parent.length) {
146
+ throw new PatchError(`Index out of range for remove: ${path}`);
147
+ }
148
+ parent.splice(idx, 1);
149
+ } else if (parent !== null && typeof parent === "object") {
150
+ if (!Object.prototype.hasOwnProperty.call(parent, key)) {
151
+ throw new PatchError(`Path not found for remove: ${path}`);
152
+ }
153
+ delete parent[key];
154
+ } else {
155
+ throw new PatchError(`Cannot remove from ${typeof parent}`);
156
+ }
157
+ return doc;
158
+ }
159
+ if (kind === "copy") {
160
+ const src = op.from;
161
+ if (src === void 0) throw new PatchError("'copy' requires 'from'");
162
+ const value = clone(getAt(doc, src));
163
+ return applyOne(doc, { op: "add", path, value });
164
+ }
165
+ if (kind === "move") {
166
+ const src = op.from;
167
+ if (src === void 0) throw new PatchError("'move' requires 'from'");
168
+ if (path.startsWith(src + "/")) {
169
+ throw new PatchError("'move' cannot move a location into its own child.");
170
+ }
171
+ const value = clone(getAt(doc, src));
172
+ doc = applyOne(doc, { op: "remove", path: src });
173
+ return applyOne(doc, { op: "add", path, value });
174
+ }
175
+ if (kind === "test") {
176
+ if (!("value" in op)) throw new PatchError("'test' requires 'value'");
177
+ const actual = getAt(doc, path);
178
+ if (!deepEqual(actual, op.value)) throw new PatchError(`'test' failed at ${path}`);
179
+ return doc;
180
+ }
181
+ throw new PatchError(`Unsupported op: ${JSON.stringify(kind)}`);
182
+ }
183
+ var MAX_PATCH_OPS = 1e3;
184
+ var MAX_DOCUMENT_NODES = 1e5;
185
+ function nodeCount(value) {
186
+ if (Array.isArray(value)) {
187
+ let n = 1;
188
+ for (const v of value) n += nodeCount(v);
189
+ return n;
190
+ }
191
+ if (value !== null && typeof value === "object") {
192
+ let n = 1;
193
+ for (const v of Object.values(value)) n += nodeCount(v);
194
+ return n;
195
+ }
196
+ return 1;
197
+ }
198
+ function applyJsonPatch(doc, ops) {
199
+ if (ops.length > MAX_PATCH_OPS) {
200
+ throw new PatchError(`Patch has too many operations (${ops.length} > ${MAX_PATCH_OPS})`);
201
+ }
202
+ let out = JSON.parse(JSON.stringify(doc));
203
+ for (const op of ops) {
204
+ out = applyOne(out, op);
205
+ if (nodeCount(out) > MAX_DOCUMENT_NODES) {
206
+ throw new PatchError(`Patched document exceeds the node limit (${MAX_DOCUMENT_NODES})`);
207
+ }
208
+ }
209
+ return out;
210
+ }
211
+ function diffJsonPatch(from, to, basePath = "") {
212
+ const ops = [];
213
+ if (typeof from !== typeof to || Array.isArray(from) !== Array.isArray(to)) {
214
+ ops.push({ op: "replace", path: basePath || "/", value: to });
215
+ return ops;
216
+ }
217
+ if (from === null || to === null || typeof from !== "object") {
218
+ if (from !== to) {
219
+ ops.push({ op: "replace", path: basePath || "/", value: to });
220
+ }
221
+ return ops;
222
+ }
223
+ if (Array.isArray(from) && Array.isArray(to)) {
224
+ if (JSON.stringify(from) !== JSON.stringify(to)) {
225
+ ops.push({ op: "replace", path: basePath || "/", value: to });
226
+ }
227
+ return ops;
228
+ }
229
+ const fromObj = from;
230
+ const toObj = to;
231
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(fromObj), ...Object.keys(toObj)]);
232
+ for (const key of allKeys) {
233
+ const escaped = key.replace(/~/g, "~0").replace(/\//g, "~1");
234
+ const path = `${basePath}/${escaped}`;
235
+ if (!(key in fromObj)) {
236
+ ops.push({ op: "add", path, value: toObj[key] });
237
+ } else if (!(key in toObj)) {
238
+ ops.push({ op: "remove", path });
239
+ } else {
240
+ ops.push(...diffJsonPatch(fromObj[key], toObj[key], path));
241
+ }
242
+ }
243
+ return ops;
244
+ }
245
+ export {
246
+ PatchError,
247
+ applyJsonPatch,
248
+ diffJsonPatch
249
+ };
250
+ //# sourceMappingURL=patch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/patch.ts"],"sourcesContent":["/**\n * @brightbeamai/chap-coordinator/patch\n *\n * RFC 6902 JSON Patch implementation, plus a small diff computer that\n * produces a patch from two values. Used by the Coordinator for\n * `decide.override` apply and by the playground UI (in the browser) to\n * compute the patch from a textarea edit.\n *\n * Implements all six RFC 6902 operations (add, remove, replace, move,\n * copy, test) with semantics identical to the Python reference. Path\n * segments that enable prototype pollution in a JavaScript runtime\n * (`__proto__`, `constructor`, `prototype`) are rejected, so the two\n * references accept and reject exactly the same patches.\n */\n\nimport type { JsonPatchOp } from \"./types.js\";\n\nexport class PatchError extends Error {}\n\n// Rejected in every JSON Pointer segment: these enable prototype pollution.\nconst DANGEROUS_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nfunction unescape(token: string): string {\n return token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\n\nfunction splitPath(path: string): string[] {\n if (path === \"\") return [];\n if (!path.startsWith(\"/\")) {\n throw new PatchError(`JSON Pointer must start with '/': ${JSON.stringify(path)}`);\n }\n const segments = path.slice(1).split(\"/\").map(unescape);\n for (const seg of segments) {\n if (DANGEROUS_KEYS.has(seg)) {\n throw new PatchError(`Refusing unsafe path segment ${JSON.stringify(seg)}`);\n }\n }\n return segments;\n}\n\n/** Navigate to the parent of the target; return [parent, lastKey]. */\nfunction navigate(doc: any, parts: string[]): [any, string | number] {\n if (parts.length === 0) {\n throw new PatchError(\"Cannot operate on root with this helper.\");\n }\n let parent = doc;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (Array.isArray(parent)) {\n const idx = Number(part);\n if (!Number.isInteger(idx) || idx < 0 || idx >= parent.length) {\n throw new PatchError(`Index out of range at /${parts.slice(0, i + 1).join(\"/\")}`);\n }\n parent = parent[idx];\n } else if (parent !== null && typeof parent === \"object\") {\n if (!Object.prototype.hasOwnProperty.call(parent, part)) {\n throw new PatchError(`Path not found: /${parts.slice(0, i + 1).join(\"/\")}`);\n }\n parent = parent[part];\n } else {\n throw new PatchError(`Cannot traverse into ${typeof parent} at ${JSON.stringify(part)}`);\n }\n }\n const last = parts[parts.length - 1];\n if (Array.isArray(parent)) {\n if (last === \"-\") return [parent, \"-\"];\n const idx = Number(last);\n if (!Number.isInteger(idx)) {\n throw new PatchError(`Array index expected at ${JSON.stringify(last)}`);\n }\n return [parent, idx];\n }\n return [parent, last];\n}\n\nfunction getAt(doc: any, path: string): any {\n const parts = splitPath(path);\n if (parts.length === 0) return doc;\n const [parent, key] = navigate(doc, parts);\n if (Array.isArray(parent)) {\n if (key === \"-\") throw new PatchError(\"Cannot read '-' position.\");\n const idx = key as number;\n if (idx < 0 || idx >= parent.length) throw new PatchError(`Index out of range: ${path}`);\n return parent[idx];\n }\n if (\n parent === null ||\n typeof parent !== \"object\" ||\n !Object.prototype.hasOwnProperty.call(parent, key)\n ) {\n throw new PatchError(`Path not found: ${path}`);\n }\n return parent[key as string];\n}\n\nfunction clone<T>(v: T): T {\n return v === undefined ? v : (JSON.parse(JSON.stringify(v)) as T);\n}\n\nfunction deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n if (a === null || b === null) return a === b;\n if (typeof a !== typeof b) return false;\n if (typeof a !== \"object\") return a === b;\n const aArr = Array.isArray(a);\n if (aArr !== Array.isArray(b)) return false;\n if (aArr) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) if (!deepEqual(a[i], b[i])) return false;\n return true;\n }\n const ak = Object.keys(a);\n const bk = Object.keys(b);\n if (ak.length !== bk.length) return false;\n for (const k of ak) {\n if (!Object.prototype.hasOwnProperty.call(b, k)) return false;\n if (!deepEqual(a[k], b[k])) return false;\n }\n return true;\n}\n\nfunction applyOne(doc: any, op: JsonPatchOp): any {\n const kind = op.op;\n const path = op.path ?? \"\";\n\n if (kind === \"add\") {\n if (!(\"value\" in op)) throw new PatchError(\"'add' requires 'value'\");\n const parts = splitPath(path);\n if (parts.length === 0) return op.value; // replace whole document\n const [parent, key] = navigate(doc, parts);\n if (Array.isArray(parent)) {\n if (key === \"-\") {\n parent.push(op.value);\n } else {\n const idx = key as number;\n if (idx < 0 || idx > parent.length) {\n throw new PatchError(`Index out of range for add: ${path}`);\n }\n parent.splice(idx, 0, op.value);\n }\n } else if (parent !== null && typeof parent === \"object\") {\n parent[key as string] = op.value;\n } else {\n throw new PatchError(`Cannot add into ${typeof parent}`);\n }\n return doc;\n }\n\n if (kind === \"replace\") {\n if (!(\"value\" in op)) throw new PatchError(\"'replace' requires 'value'\");\n const parts = splitPath(path);\n if (parts.length === 0) return op.value;\n const [parent, key] = navigate(doc, parts);\n if (Array.isArray(parent)) {\n const idx = key as number;\n if (idx < 0 || idx >= parent.length) {\n throw new PatchError(`Path not found for replace: ${path}`);\n }\n parent[idx] = op.value;\n } else if (parent !== null && typeof parent === \"object\") {\n if (!Object.prototype.hasOwnProperty.call(parent, key)) {\n throw new PatchError(`Path not found for replace: ${path}`);\n }\n parent[key as string] = op.value;\n } else {\n throw new PatchError(`Cannot replace in ${typeof parent}`);\n }\n return doc;\n }\n\n if (kind === \"remove\") {\n const parts = splitPath(path);\n if (parts.length === 0) throw new PatchError(\"Cannot remove root.\");\n const [parent, key] = navigate(doc, parts);\n if (Array.isArray(parent)) {\n const idx = key as number;\n if (idx < 0 || idx >= parent.length) {\n throw new PatchError(`Index out of range for remove: ${path}`);\n }\n parent.splice(idx, 1);\n } else if (parent !== null && typeof parent === \"object\") {\n if (!Object.prototype.hasOwnProperty.call(parent, key)) {\n throw new PatchError(`Path not found for remove: ${path}`);\n }\n delete parent[key as string];\n } else {\n throw new PatchError(`Cannot remove from ${typeof parent}`);\n }\n return doc;\n }\n\n if (kind === \"copy\") {\n const src = op.from;\n if (src === undefined) throw new PatchError(\"'copy' requires 'from'\");\n const value = clone(getAt(doc, src));\n return applyOne(doc, { op: \"add\", path, value });\n }\n\n if (kind === \"move\") {\n const src = op.from;\n if (src === undefined) throw new PatchError(\"'move' requires 'from'\");\n // RFC 6902 4.4: 'from' MUST NOT be a proper prefix of 'path'.\n if (path.startsWith(src + \"/\")) {\n throw new PatchError(\"'move' cannot move a location into its own child.\");\n }\n const value = clone(getAt(doc, src));\n doc = applyOne(doc, { op: \"remove\", path: src });\n return applyOne(doc, { op: \"add\", path, value });\n }\n\n if (kind === \"test\") {\n if (!(\"value\" in op)) throw new PatchError(\"'test' requires 'value'\");\n const actual = getAt(doc, path);\n if (!deepEqual(actual, op.value)) throw new PatchError(`'test' failed at ${path}`);\n return doc;\n }\n\n throw new PatchError(`Unsupported op: ${JSON.stringify(kind)}`);\n}\n\nconst MAX_PATCH_OPS = 1000;\nconst MAX_DOCUMENT_NODES = 100_000;\n\nfunction nodeCount(value: unknown): number {\n if (Array.isArray(value)) {\n let n = 1;\n for (const v of value) n += nodeCount(v);\n return n;\n }\n if (value !== null && typeof value === \"object\") {\n let n = 1;\n for (const v of Object.values(value as Record<string, unknown>)) n += nodeCount(v);\n return n;\n }\n return 1;\n}\n\nexport function applyJsonPatch(doc: unknown, ops: JsonPatchOp[]): unknown {\n if (ops.length > MAX_PATCH_OPS) {\n throw new PatchError(`Patch has too many operations (${ops.length} > ${MAX_PATCH_OPS})`);\n }\n let out: any = JSON.parse(JSON.stringify(doc));\n for (const op of ops) {\n out = applyOne(out, op);\n if (nodeCount(out) > MAX_DOCUMENT_NODES) {\n throw new PatchError(`Patched document exceeds the node limit (${MAX_DOCUMENT_NODES})`);\n }\n }\n return out;\n}\n\n// ============================================================\n// diff: produce a patch that transforms `from` into `to`\n// ============================================================\n\n/**\n * Compute an RFC 6902 patch that, when applied to `from`, produces\n * `to`. Walks objects key-by-key; arrays use a shallow whole-array\n * replace if any element differs. Sufficient for the playground's\n * draft-edit use case where drafts are small JSON objects.\n */\nexport function diffJsonPatch(from: unknown, to: unknown, basePath = \"\"): JsonPatchOp[] {\n const ops: JsonPatchOp[] = [];\n\n if (typeof from !== typeof to || Array.isArray(from) !== Array.isArray(to)) {\n ops.push({ op: \"replace\", path: basePath || \"/\", value: to });\n return ops;\n }\n\n if (from === null || to === null || typeof from !== \"object\") {\n if (from !== to) {\n ops.push({ op: \"replace\", path: basePath || \"/\", value: to });\n }\n return ops;\n }\n\n if (Array.isArray(from) && Array.isArray(to)) {\n if (JSON.stringify(from) !== JSON.stringify(to)) {\n ops.push({ op: \"replace\", path: basePath || \"/\", value: to });\n }\n return ops;\n }\n\n const fromObj = from as Record<string, unknown>;\n const toObj = to as Record<string, unknown>;\n const allKeys = new Set([...Object.keys(fromObj), ...Object.keys(toObj)]);\n\n for (const key of allKeys) {\n const escaped = key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n const path = `${basePath}/${escaped}`;\n if (!(key in fromObj)) {\n ops.push({ op: \"add\", path, value: toObj[key] });\n } else if (!(key in toObj)) {\n ops.push({ op: \"remove\", path });\n } else {\n ops.push(...diffJsonPatch(fromObj[key], toObj[key], path));\n }\n }\n\n return ops;\n}\n"],"mappings":"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","names":[]}