@portabletext/plugin-sdk-value 7.0.36-crx.0 → 7.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/dist/index.js +316 -141
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { useEditDocument, useSanityInstance, useApplyDocumentActions, getDocumen
|
|
|
7
7
|
import { useActorRef } from "@xstate/react";
|
|
8
8
|
import "react";
|
|
9
9
|
import { fromCallback, setup } from "xstate";
|
|
10
|
+
const ARRAYIFY_ERROR_MESSAGE = "Unexpected path format from diffValue output. Please report this issue.";
|
|
10
11
|
function* getSegments(node) {
|
|
11
12
|
node.base && (yield* getSegments(node.base)), node.segment.type !== "This" && (yield node.segment);
|
|
12
13
|
}
|
|
@@ -14,92 +15,77 @@ function isKeyPath(node) {
|
|
|
14
15
|
return node.type !== "Path" || node.base || node.recursive || node.segment.type !== "Identifier" ? !1 : node.segment.name === "_key";
|
|
15
16
|
}
|
|
16
17
|
function arrayifyPath(pathExpr) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (segment.
|
|
28
|
-
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
if (segment.type !== "Subscript" || segment.elements.length !== 1)
|
|
32
|
-
return null;
|
|
18
|
+
const node = parsePath(pathExpr);
|
|
19
|
+
if (!node)
|
|
20
|
+
return [];
|
|
21
|
+
if (node.type !== "Path")
|
|
22
|
+
throw new Error(ARRAYIFY_ERROR_MESSAGE);
|
|
23
|
+
return Array.from(getSegments(node)).map((segment) => {
|
|
24
|
+
if (segment.type === "Identifier")
|
|
25
|
+
return segment.name;
|
|
26
|
+
if (segment.type !== "Subscript")
|
|
27
|
+
throw new Error(ARRAYIFY_ERROR_MESSAGE);
|
|
28
|
+
if (segment.elements.length !== 1)
|
|
29
|
+
throw new Error(ARRAYIFY_ERROR_MESSAGE);
|
|
33
30
|
const [element] = segment.elements;
|
|
34
|
-
if (element.type === "Number")
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (element.
|
|
39
|
-
|
|
31
|
+
if (element.type === "Number")
|
|
32
|
+
return element.value;
|
|
33
|
+
if (element.type !== "Comparison")
|
|
34
|
+
throw new Error(ARRAYIFY_ERROR_MESSAGE);
|
|
35
|
+
if (element.operator !== "==")
|
|
36
|
+
throw new Error(ARRAYIFY_ERROR_MESSAGE);
|
|
40
37
|
const keyPathNode = [element.left, element.right].find(isKeyPath);
|
|
41
38
|
if (!keyPathNode)
|
|
42
|
-
|
|
39
|
+
throw new Error(ARRAYIFY_ERROR_MESSAGE);
|
|
43
40
|
const other = element.left === keyPathNode ? element.right : element.left;
|
|
44
41
|
if (other.type !== "String")
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
throw new Error(ARRAYIFY_ERROR_MESSAGE);
|
|
43
|
+
return {
|
|
47
44
|
_key: other.value
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return path;
|
|
45
|
+
};
|
|
46
|
+
});
|
|
51
47
|
}
|
|
52
48
|
function convertPatches(patches) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}] : (incomplete = !0, []);
|
|
80
|
-
}) : [];
|
|
81
|
-
case "insert": {
|
|
82
|
-
const {
|
|
83
|
-
items,
|
|
84
|
-
...rest
|
|
85
|
-
} = values, position = Object.keys(rest).at(0);
|
|
86
|
-
if (!position)
|
|
87
|
-
return [];
|
|
88
|
-
const pathExpr = rest[position], path = arrayifyPath(pathExpr);
|
|
89
|
-
return path ? [{
|
|
90
|
-
type,
|
|
91
|
-
origin,
|
|
92
|
-
position,
|
|
93
|
-
path,
|
|
94
|
-
items
|
|
95
|
-
}] : (incomplete = !0, []);
|
|
96
|
-
}
|
|
97
|
-
default:
|
|
49
|
+
return patches.flatMap((p) => Object.entries(p).flatMap(([type, values]) => {
|
|
50
|
+
const origin = "remote";
|
|
51
|
+
switch (type) {
|
|
52
|
+
case "set":
|
|
53
|
+
case "setIfMissing":
|
|
54
|
+
case "diffMatchPatch":
|
|
55
|
+
case "inc":
|
|
56
|
+
case "dec":
|
|
57
|
+
return Object.entries(values).map(([pathExpr, value]) => ({
|
|
58
|
+
type,
|
|
59
|
+
value,
|
|
60
|
+
origin,
|
|
61
|
+
path: arrayifyPath(pathExpr)
|
|
62
|
+
}));
|
|
63
|
+
case "unset":
|
|
64
|
+
return Array.isArray(values) ? values.map(arrayifyPath).map((path) => ({
|
|
65
|
+
type,
|
|
66
|
+
origin,
|
|
67
|
+
path
|
|
68
|
+
})) : [];
|
|
69
|
+
case "insert": {
|
|
70
|
+
const {
|
|
71
|
+
items,
|
|
72
|
+
...rest
|
|
73
|
+
} = values, position = Object.keys(rest).at(0);
|
|
74
|
+
if (!position)
|
|
98
75
|
return [];
|
|
76
|
+
const pathExpr = rest[position];
|
|
77
|
+
return [{
|
|
78
|
+
type,
|
|
79
|
+
origin,
|
|
80
|
+
position,
|
|
81
|
+
path: arrayifyPath(pathExpr),
|
|
82
|
+
items
|
|
83
|
+
}];
|
|
99
84
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
85
|
+
default:
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
103
89
|
}
|
|
104
90
|
const STRINGIFY_ERROR_MESSAGE = "Unable to convert an editor patch path to a Sanity path expression.";
|
|
105
91
|
function stringifyPatchPath(path) {
|
|
@@ -134,6 +120,14 @@ function convertPatchesToSanity(patches, options) {
|
|
|
134
120
|
[pathExpression]: patch.value
|
|
135
121
|
}
|
|
136
122
|
};
|
|
123
|
+
case "unset":
|
|
124
|
+
return patch.path.length === 0 ? {
|
|
125
|
+
set: {
|
|
126
|
+
[pathExpression]: []
|
|
127
|
+
}
|
|
128
|
+
} : {
|
|
129
|
+
unset: [pathExpression]
|
|
130
|
+
};
|
|
137
131
|
case "diffMatchPatch":
|
|
138
132
|
return {
|
|
139
133
|
diffMatchPatch: {
|
|
@@ -152,10 +146,6 @@ function convertPatchesToSanity(patches, options) {
|
|
|
152
146
|
[pathExpression]: patch.value
|
|
153
147
|
}
|
|
154
148
|
};
|
|
155
|
-
case "unset":
|
|
156
|
-
return {
|
|
157
|
-
unset: [pathExpression]
|
|
158
|
-
};
|
|
159
149
|
case "insert":
|
|
160
150
|
return {
|
|
161
151
|
insert: {
|
|
@@ -171,17 +161,132 @@ function convertPatchesToSanity(patches, options) {
|
|
|
171
161
|
function segmentsEqual(a, b) {
|
|
172
162
|
return typeof a == "string" || typeof a == "number" ? a === b : typeof b == "string" || typeof b == "number" || Array.isArray(a) || Array.isArray(b) ? !1 : a._key === b._key;
|
|
173
163
|
}
|
|
164
|
+
function pathsEqual(a, b) {
|
|
165
|
+
return a.length === b.length && a.every((segment, index) => segmentsEqual(segment, b[index]));
|
|
166
|
+
}
|
|
167
|
+
function findSidecarArrayPath(path) {
|
|
168
|
+
let expectNode = !0;
|
|
169
|
+
for (let index = 0; index < path.length; index++) {
|
|
170
|
+
const segment = path[index];
|
|
171
|
+
if (typeof segment == "string")
|
|
172
|
+
expectNode = segment === "children";
|
|
173
|
+
else {
|
|
174
|
+
if (!expectNode)
|
|
175
|
+
return path.slice(0, index);
|
|
176
|
+
expectNode = !1;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
function getValueAtPath(value, path) {
|
|
182
|
+
let current = value;
|
|
183
|
+
for (const segment of path) {
|
|
184
|
+
if (current == null)
|
|
185
|
+
return;
|
|
186
|
+
if (typeof segment == "number") {
|
|
187
|
+
if (!Array.isArray(current))
|
|
188
|
+
return;
|
|
189
|
+
current = current[segment < 0 ? current.length + segment : segment];
|
|
190
|
+
} else if (typeof segment == "string") {
|
|
191
|
+
if (typeof current != "object" || Array.isArray(current))
|
|
192
|
+
return;
|
|
193
|
+
current = current[segment];
|
|
194
|
+
} else {
|
|
195
|
+
if (Array.isArray(segment) || !Array.isArray(current))
|
|
196
|
+
return;
|
|
197
|
+
current = current.find((item) => typeof item == "object" && item !== null && !Array.isArray(item) && item._key === segment._key);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return current;
|
|
201
|
+
}
|
|
202
|
+
function toEngineSafePatches(patches, targetValue) {
|
|
203
|
+
const safe = [], sidecarPaths = [];
|
|
204
|
+
for (const patch of patches) {
|
|
205
|
+
const sidecarPath = findSidecarArrayPath(patch.path);
|
|
206
|
+
if (!sidecarPath) {
|
|
207
|
+
safe.push(patch);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
sidecarPaths.some((existing) => pathsEqual(existing, sidecarPath)) || sidecarPaths.push(sidecarPath);
|
|
211
|
+
}
|
|
212
|
+
for (const sidecarPath of sidecarPaths) {
|
|
213
|
+
const value = getValueAtPath(targetValue, sidecarPath);
|
|
214
|
+
safe.push(value === void 0 ? {
|
|
215
|
+
type: "unset",
|
|
216
|
+
path: sidecarPath,
|
|
217
|
+
origin: "remote"
|
|
218
|
+
} : {
|
|
219
|
+
type: "set",
|
|
220
|
+
path: sidecarPath,
|
|
221
|
+
value,
|
|
222
|
+
origin: "remote"
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
return safe;
|
|
226
|
+
}
|
|
227
|
+
function toMergeableMarkDefsPatches(patches, getCurrentValue) {
|
|
228
|
+
return patches.flatMap((patch) => {
|
|
229
|
+
if (patch.type !== "set" || patch.path.at(-1) !== "markDefs" || !Array.isArray(patch.value))
|
|
230
|
+
return [patch];
|
|
231
|
+
const currentValue = getCurrentValue();
|
|
232
|
+
if (!currentValue)
|
|
233
|
+
return [patch];
|
|
234
|
+
const root = currentValue, storeMarkDefs = getValueAtPath(root, patch.path), storeBlock = getValueAtPath(root, patch.path.slice(0, -1));
|
|
235
|
+
if (!Array.isArray(storeMarkDefs) || typeof storeBlock != "object" || storeBlock === null)
|
|
236
|
+
return [patch];
|
|
237
|
+
const local = patch.value, store = storeMarkDefs;
|
|
238
|
+
if (local.some((item) => item._key === void 0))
|
|
239
|
+
return [patch];
|
|
240
|
+
const referencedKeys = new Set((storeBlock.children ?? []).flatMap((child) => child.marks ?? [])), storeByKey = new Map(store.map((item) => [item._key, item])), localKeys = new Set(local.map((item) => item._key)), origin = patch.origin, ops = [], inserted = local.filter((item) => !storeByKey.has(item._key));
|
|
241
|
+
inserted.length > 0 && ops.push({
|
|
242
|
+
type: "insert",
|
|
243
|
+
origin,
|
|
244
|
+
position: "after",
|
|
245
|
+
path: [...patch.path, -1],
|
|
246
|
+
items: inserted
|
|
247
|
+
});
|
|
248
|
+
for (const item of local) {
|
|
249
|
+
const existing = storeByKey.get(item._key);
|
|
250
|
+
existing && JSON.stringify(existing) !== JSON.stringify(item) && ops.push({
|
|
251
|
+
type: "set",
|
|
252
|
+
origin,
|
|
253
|
+
path: [...patch.path, {
|
|
254
|
+
_key: item._key
|
|
255
|
+
}],
|
|
256
|
+
value: item
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
for (const item of store)
|
|
260
|
+
item._key !== void 0 && !localKeys.has(item._key) && !referencedKeys.has(item._key) && ops.push({
|
|
261
|
+
type: "unset",
|
|
262
|
+
origin,
|
|
263
|
+
path: [...patch.path, {
|
|
264
|
+
_key: item._key
|
|
265
|
+
}]
|
|
266
|
+
});
|
|
267
|
+
return ops;
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function canApplyToValue(patch, value) {
|
|
271
|
+
if (!value)
|
|
272
|
+
return !0;
|
|
273
|
+
const root = value;
|
|
274
|
+
switch (patch.type) {
|
|
275
|
+
// unset needs the node itself; insert needs the sibling at `path`;
|
|
276
|
+
// diffMatchPatch needs the existing string
|
|
277
|
+
case "unset":
|
|
278
|
+
case "insert":
|
|
279
|
+
case "diffMatchPatch":
|
|
280
|
+
return getValueAtPath(root, patch.path) !== void 0;
|
|
281
|
+
// set creates its target property, so only the parent must resolve
|
|
282
|
+
case "set":
|
|
283
|
+
return patch.path.length === 0 || getValueAtPath(root, patch.path.slice(0, -1)) !== void 0;
|
|
284
|
+
default:
|
|
285
|
+
return !0;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
174
288
|
function scopeRemotePatches(patches, fieldPath) {
|
|
175
|
-
const prefix = arrayifyPath(fieldPath);
|
|
176
|
-
if (!prefix)
|
|
177
|
-
return null;
|
|
178
|
-
const {
|
|
179
|
-
patches: converted,
|
|
180
|
-
incomplete
|
|
181
|
-
} = convertPatches(patches);
|
|
182
|
-
if (incomplete)
|
|
183
|
-
return null;
|
|
184
|
-
const scoped = [];
|
|
289
|
+
const prefix = arrayifyPath(fieldPath), converted = convertPatches(patches), scoped = [];
|
|
185
290
|
for (const patch of converted) {
|
|
186
291
|
const overlap = Math.min(patch.path.length, prefix.length);
|
|
187
292
|
let touchesField = !0;
|
|
@@ -201,6 +306,16 @@ function scopeRemotePatches(patches, fieldPath) {
|
|
|
201
306
|
}
|
|
202
307
|
return scoped;
|
|
203
308
|
}
|
|
309
|
+
function syncDebugEnabled() {
|
|
310
|
+
return globalThis.__PTE_SYNC_DEBUG === !0;
|
|
311
|
+
}
|
|
312
|
+
function syncDebug(kind, detail) {
|
|
313
|
+
syncDebugEnabled() && console.debug(`[pte-sync] ${kind} ${JSON.stringify(detail())}`);
|
|
314
|
+
}
|
|
315
|
+
function debugTextOf(value) {
|
|
316
|
+
return Array.isArray(value) ? value.map((block) => Array.isArray(block.children) ? (block.children ?? []).map((child) => child.text ?? "").join("") : "").join(`
|
|
317
|
+
`) : "";
|
|
318
|
+
}
|
|
204
319
|
function applySync({
|
|
205
320
|
editor,
|
|
206
321
|
getRemoteValue
|
|
@@ -208,31 +323,41 @@ function applySync({
|
|
|
208
323
|
const remoteValue = getRemoteValue();
|
|
209
324
|
if (!remoteValue)
|
|
210
325
|
return;
|
|
211
|
-
const snapshot = editor.getSnapshot().context.value
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
326
|
+
const snapshot = editor.getSnapshot().context.value;
|
|
327
|
+
if (syncDebugEnabled()) {
|
|
328
|
+
const editorText = debugTextOf(snapshot), remoteText = debugTextOf(remoteValue);
|
|
329
|
+
editorText !== remoteText && syncDebug("applySync:texts-differ", () => ({
|
|
330
|
+
editorText,
|
|
331
|
+
remoteText
|
|
332
|
+
}));
|
|
333
|
+
}
|
|
334
|
+
let patches;
|
|
335
|
+
try {
|
|
336
|
+
patches = toEngineSafePatches(convertPatches(diffValue(snapshot, remoteValue)), remoteValue);
|
|
337
|
+
} catch {
|
|
338
|
+
editor.send({
|
|
339
|
+
type: "update value",
|
|
340
|
+
value: remoteValue
|
|
219
341
|
});
|
|
220
342
|
return;
|
|
221
343
|
}
|
|
222
|
-
patches.length
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
344
|
+
if (patches.length) {
|
|
345
|
+
syncDebug("applySync:repair-patches", () => ({
|
|
346
|
+
patches
|
|
347
|
+
})), editor.send({
|
|
348
|
+
type: "patches",
|
|
349
|
+
patches,
|
|
350
|
+
snapshot
|
|
351
|
+
});
|
|
352
|
+
const valueAfterPatches = editor.getSnapshot().context.value;
|
|
353
|
+
diffValue(valueAfterPatches, remoteValue).length > 0 && (syncDebug("applySync:escalate-update-value", () => ({
|
|
354
|
+
editorText: debugTextOf(valueAfterPatches),
|
|
355
|
+
remoteText: debugTextOf(remoteValue)
|
|
356
|
+
})), editor.send({
|
|
357
|
+
type: "update value",
|
|
358
|
+
value: remoteValue
|
|
359
|
+
}));
|
|
360
|
+
}
|
|
236
361
|
}
|
|
237
362
|
const listenToEditor = fromCallback(({
|
|
238
363
|
sendBack,
|
|
@@ -243,7 +368,10 @@ const listenToEditor = fromCallback(({
|
|
|
243
368
|
type: "patch emitted"
|
|
244
369
|
});
|
|
245
370
|
}), mutationSubscription = input.editor.on("mutation", (event) => {
|
|
246
|
-
|
|
371
|
+
syncDebug("event:mutation-flushed", () => ({
|
|
372
|
+
flushText: debugTextOf(event.value),
|
|
373
|
+
snapshotText: debugTextOf(input.editor.getSnapshot().context.value)
|
|
374
|
+
})), sendBack({
|
|
247
375
|
type: "mutation flushed",
|
|
248
376
|
value: event.value,
|
|
249
377
|
patches: event.patches
|
|
@@ -267,7 +395,7 @@ const listenToEditor = fromCallback(({
|
|
|
267
395
|
type: "remote patches received",
|
|
268
396
|
patches
|
|
269
397
|
});
|
|
270
|
-
})), valueSyncMachine = setup({
|
|
398
|
+
})), QUIESCENT_REPAIR_DELAY = 500, valueSyncMachine = setup({
|
|
271
399
|
types: {
|
|
272
400
|
context: {},
|
|
273
401
|
input: {},
|
|
@@ -277,9 +405,9 @@ const listenToEditor = fromCallback(({
|
|
|
277
405
|
"send initial value": ({
|
|
278
406
|
context
|
|
279
407
|
}) => {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
408
|
+
context.editor.send({
|
|
409
|
+
type: "update value",
|
|
410
|
+
value: context.getRemoteValue() ?? []
|
|
283
411
|
});
|
|
284
412
|
},
|
|
285
413
|
"push to remote": () => {
|
|
@@ -293,24 +421,20 @@ const listenToEditor = fromCallback(({
|
|
|
293
421
|
getRemoteValue: context.getRemoteValue
|
|
294
422
|
});
|
|
295
423
|
},
|
|
296
|
-
"defer then apply sync": ({
|
|
297
|
-
context
|
|
298
|
-
}) => {
|
|
299
|
-
queueMicrotask(() => {
|
|
300
|
-
applySync({
|
|
301
|
-
editor: context.editor,
|
|
302
|
-
getRemoteValue: context.getRemoteValue
|
|
303
|
-
});
|
|
304
|
-
});
|
|
305
|
-
},
|
|
306
424
|
"apply remote patches": ({
|
|
307
425
|
context,
|
|
308
426
|
event
|
|
309
427
|
}) => {
|
|
310
|
-
event.type
|
|
428
|
+
if (event.type !== "remote patches received")
|
|
429
|
+
return;
|
|
430
|
+
syncDebug("apply-remote-patches", () => ({
|
|
431
|
+
patches: event.patches
|
|
432
|
+
}));
|
|
433
|
+
const snapshot = context.editor.getSnapshot().context.value, remoteValue = context.getRemoteValue(), patches = (remoteValue ? toEngineSafePatches(event.patches, remoteValue) : event.patches).filter((patch) => canApplyToValue(patch, snapshot));
|
|
434
|
+
patches.length !== 0 && context.editor.send({
|
|
311
435
|
type: "patches",
|
|
312
|
-
patches
|
|
313
|
-
snapshot
|
|
436
|
+
patches,
|
|
437
|
+
snapshot
|
|
314
438
|
});
|
|
315
439
|
}
|
|
316
440
|
},
|
|
@@ -352,22 +476,50 @@ const listenToEditor = fromCallback(({
|
|
|
352
476
|
onRemotePatches: context.onRemotePatches
|
|
353
477
|
})
|
|
354
478
|
}],
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
479
|
+
// Two invariants, learned the hard way:
|
|
480
|
+
//
|
|
481
|
+
// 1. EVERY 'mutation flushed' event must be pushed, in every state. The
|
|
482
|
+
// editor emits mutation events in bursts (one per input batch, e.g.
|
|
483
|
+
// each backspace of a quick delete), and any state without a handler
|
|
484
|
+
// silently drops the flush. A dropped flush permanently diverges the
|
|
485
|
+
// store from the editor, and the whole-value repair then "heals" the
|
|
486
|
+
// editor backwards, resurrecting deleted text.
|
|
487
|
+
// 2. The whole-value repair must only run when no local edits can be in
|
|
488
|
+
// flight (quiescent 'idle'). Running it mid-typing diffs the editor
|
|
489
|
+
// against a store that lags the user's keystrokes and stomps them.
|
|
490
|
+
//
|
|
491
|
+
// Operational patches from other clients still apply immediately in
|
|
492
|
+
// every state; the editor merges them with in-flight local changes.
|
|
362
493
|
initial: "idle",
|
|
363
494
|
states: {
|
|
364
495
|
idle: {
|
|
496
|
+
// One-shot repair after a quiet period. Covers divergence left by
|
|
497
|
+
// best-effort patch application while local edits were in flight
|
|
498
|
+
// (those states never repair; see below) when no further store
|
|
499
|
+
// event arrives to trigger the on-change repair.
|
|
500
|
+
after: {
|
|
501
|
+
[QUIESCENT_REPAIR_DELAY]: {
|
|
502
|
+
actions: ["apply sync"]
|
|
503
|
+
}
|
|
504
|
+
},
|
|
365
505
|
on: {
|
|
366
506
|
"patch emitted": {
|
|
367
507
|
target: "local write"
|
|
368
508
|
},
|
|
509
|
+
// Mutation events arrive in bursts (one per input batch), so a
|
|
510
|
+
// flush can land after a sibling flush already advanced the state.
|
|
511
|
+
"mutation flushed": {
|
|
512
|
+
target: "pushing to remote",
|
|
513
|
+
actions: ["push to remote"]
|
|
514
|
+
},
|
|
369
515
|
"remote value changed": {
|
|
370
516
|
actions: ["apply sync"]
|
|
517
|
+
},
|
|
518
|
+
// No immediate repair here: every remote patch batch also updates
|
|
519
|
+
// the store value, so the accompanying 'remote value changed'
|
|
520
|
+
// event runs the whole-value repair right after.
|
|
521
|
+
"remote patches received": {
|
|
522
|
+
actions: ["apply remote patches"]
|
|
371
523
|
}
|
|
372
524
|
}
|
|
373
525
|
},
|
|
@@ -380,6 +532,10 @@ const listenToEditor = fromCallback(({
|
|
|
380
532
|
},
|
|
381
533
|
"remote value changed": {
|
|
382
534
|
target: "pending sync"
|
|
535
|
+
},
|
|
536
|
+
"remote patches received": {
|
|
537
|
+
target: "pending sync",
|
|
538
|
+
actions: ["apply remote patches"]
|
|
383
539
|
}
|
|
384
540
|
}
|
|
385
541
|
},
|
|
@@ -388,8 +544,19 @@ const listenToEditor = fromCallback(({
|
|
|
388
544
|
"patch emitted": {
|
|
389
545
|
target: "local write"
|
|
390
546
|
},
|
|
547
|
+
"mutation flushed": {
|
|
548
|
+
actions: ["push to remote"]
|
|
549
|
+
},
|
|
550
|
+
// No repair on the push acknowledgment: the editor snapshot can
|
|
551
|
+
// lag the live document while the user keeps typing, so a diff
|
|
552
|
+
// against the store here resurrects deleted text and duplicates
|
|
553
|
+
// in-flight keystrokes. Once truly idle, the store change or the
|
|
554
|
+
// quiescent delay runs the repair with a caught-up snapshot.
|
|
391
555
|
"remote value changed": {
|
|
392
556
|
target: "idle"
|
|
557
|
+
},
|
|
558
|
+
"remote patches received": {
|
|
559
|
+
actions: ["apply remote patches"]
|
|
393
560
|
}
|
|
394
561
|
}
|
|
395
562
|
},
|
|
@@ -398,9 +565,12 @@ const listenToEditor = fromCallback(({
|
|
|
398
565
|
"patch emitted": {},
|
|
399
566
|
"mutation flushed": {
|
|
400
567
|
target: "pushing to remote",
|
|
401
|
-
actions: ["push to remote"
|
|
568
|
+
actions: ["push to remote"]
|
|
402
569
|
},
|
|
403
|
-
"remote value changed": {}
|
|
570
|
+
"remote value changed": {},
|
|
571
|
+
"remote patches received": {
|
|
572
|
+
actions: ["apply remote patches"]
|
|
573
|
+
}
|
|
404
574
|
}
|
|
405
575
|
}
|
|
406
576
|
}
|
|
@@ -479,11 +649,16 @@ function ValueSyncPlugin(props) {
|
|
|
479
649
|
if (event.type === "mutation flushed") {
|
|
480
650
|
if (pushPatches && event.patches.length > 0)
|
|
481
651
|
try {
|
|
482
|
-
|
|
652
|
+
const mergeable = toMergeableMarkDefsPatches(event.patches, context.getRemoteValue);
|
|
653
|
+
syncDebug("push-patches", () => ({
|
|
654
|
+
patches: mergeable
|
|
655
|
+
})), pushPatches(mergeable);
|
|
483
656
|
return;
|
|
484
657
|
} catch {
|
|
485
658
|
}
|
|
486
|
-
|
|
659
|
+
syncDebug("push-whole-value", () => ({
|
|
660
|
+
text: debugTextOf(event.value ?? context.editor.getSnapshot().context.value)
|
|
661
|
+
})), pushValue(event.value ?? context.editor.getSnapshot().context.value);
|
|
487
662
|
}
|
|
488
663
|
}
|
|
489
664
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/plugin.sdk-value.tsx"],"sourcesContent":["import {\n useEditor,\n type Editor,\n type PortableTextBlock,\n type Patch as PtePatch,\n} from '@portabletext/editor'\nimport type {\n JSONValue,\n Path,\n PathSegment,\n InsertPatch as PteInsertPatch,\n} from '@portabletext/patches'\nimport {diffValue, type SanityPatchOperations} from '@sanity/diff-patch'\nimport {\n parsePath,\n type ExprNode,\n type PathNode,\n type SegmentNode,\n type ThisNode,\n} from '@sanity/json-match'\nimport {\n editDocument,\n getDocumentState,\n subscribeDocumentEvents,\n useApplyDocumentActions,\n useEditDocument,\n useSanityInstance,\n type DocumentHandle,\n type EditDocumentAction,\n} from '@sanity/sdk-react'\nimport {useActorRef} from '@xstate/react'\nimport {useCallback} from 'react'\nimport {fromCallback, setup, type AnyEventObject} from 'xstate'\n\ntype InsertPatch = Required<Pick<SanityPatchOperations, 'insert'>>\n\nfunction* getSegments(\n node: PathNode,\n): Generator<Exclude<SegmentNode, ThisNode>> {\n if (node.base) {\n yield* getSegments(node.base)\n }\n if (node.segment.type !== 'This') {\n yield node.segment\n }\n}\n\nfunction isKeyPath(node: ExprNode): node is PathNode {\n if (node.type !== 'Path') {\n return false\n }\n if (node.base) {\n return false\n }\n if (node.recursive) {\n return false\n }\n if (node.segment.type !== 'Identifier') {\n return false\n }\n return node.segment.name === '_key'\n}\n\n/**\n * Converts a `diffValue` path expression (e.g. `[_key==\"a\"].children[0]`) into\n * a keyed Portable Text Editor path.\n *\n * Returns `null` – rather than throwing – for any expression that can't be\n * represented as a keyed PTE path. `diffValue` can emit such expressions in\n * practice: removing several non-keyed array items at once (e.g. clearing\n * multiple span `marks`) produces an array slice like `...marks[1:]`. Throwing\n * here would escape the synchronous `applySync` and break syncing entirely, so\n * we signal failure via `null` and let the caller skip the offending patch and\n * recover.\n */\nexport function arrayifyPath(pathExpr: string): Path | null {\n let node: ExprNode | undefined\n try {\n node = parsePath(pathExpr)\n } catch {\n // `parsePath` throws on malformed input such as an empty expression.\n return null\n }\n if (!node) {\n return null\n }\n if (node.type !== 'Path') {\n return null\n }\n\n const path: Path = []\n for (const segment of getSegments(node)) {\n if (segment.type === 'Identifier') {\n path.push(segment.name)\n continue\n }\n if (segment.type !== 'Subscript') {\n return null\n }\n if (segment.elements.length !== 1) {\n return null\n }\n\n const [element] = segment.elements\n if (element.type === 'Number') {\n path.push(element.value)\n continue\n }\n if (element.type !== 'Comparison') {\n // e.g. an array slice (`Slice`) that `diffValue` emits when removing\n // multiple non-keyed items at once.\n return null\n }\n if (element.operator !== '==') {\n return null\n }\n const keyPathNode = [element.left, element.right].find(isKeyPath)\n if (!keyPathNode) {\n return null\n }\n const other = element.left === keyPathNode ? element.right : element.left\n if (other.type !== 'String') {\n return null\n }\n path.push({_key: other.value})\n }\n\n return path\n}\n\n/**\n * Converts a batch of `diffValue` patch operations into PTE patches.\n *\n * `incomplete` is `true` when one or more operations had to be dropped because\n * their path couldn't be converted (see `arrayifyPath`). The caller uses this\n * to fall back to an authoritative full value update instead of persisting a\n * partial diff.\n */\nexport function convertPatches(patches: SanityPatchOperations[]): {\n patches: PtePatch[]\n incomplete: boolean\n} {\n let incomplete = false\n\n const converted = patches.flatMap((operation) => {\n return Object.entries(operation).flatMap(([type, values]): PtePatch[] => {\n const origin = 'remote'\n\n switch (type) {\n case 'set':\n case 'setIfMissing':\n case 'diffMatchPatch':\n case 'inc':\n case 'dec': {\n return Object.entries(values).flatMap(([pathExpr, value]) => {\n const path = arrayifyPath(pathExpr)\n if (!path) {\n incomplete = true\n return []\n }\n return [{type, value, origin, path} as PtePatch]\n })\n }\n case 'unset': {\n if (!Array.isArray(values)) {\n return []\n }\n return values.flatMap((pathExpr) => {\n const path = arrayifyPath(pathExpr)\n if (!path) {\n incomplete = true\n return []\n }\n return [{type, origin, path} as PtePatch]\n })\n }\n case 'insert': {\n const {items, ...rest} = values as InsertPatch['insert']\n type InsertPosition = PteInsertPatch['position']\n const position = Object.keys(rest).at(0) as InsertPosition | undefined\n\n if (!position) {\n return []\n }\n const pathExpr = (rest as {[K in InsertPosition]: string})[position]\n const path = arrayifyPath(pathExpr)\n if (!path) {\n incomplete = true\n return []\n }\n const insertPatch: PteInsertPatch = {\n type,\n origin,\n position,\n path,\n items: items as JSONValue[],\n }\n\n return [insertPatch]\n }\n\n default: {\n return []\n }\n }\n })\n })\n\n return {patches: converted, incomplete}\n}\n\nconst STRINGIFY_ERROR_MESSAGE =\n 'Unable to convert an editor patch path to a Sanity path expression.'\n\n/**\n * Converts a Portable Text Editor patch path (an array of segments) into a\n * Sanity json-match path expression. The inverse of `arrayifyPath`.\n *\n * @internal\n */\nexport function stringifyPatchPath(path: Path): string {\n let result = ''\n for (const segment of path) {\n if (typeof segment === 'string') {\n result = result === '' ? segment : `${result}.${segment}`\n } else if (typeof segment === 'number') {\n result = `${result}[${segment}]`\n } else if (\n typeof segment === 'object' &&\n segment !== null &&\n '_key' in segment\n ) {\n result = `${result}[_key==\"${segment._key}\"]`\n } else {\n throw new Error(STRINGIFY_ERROR_MESSAGE)\n }\n }\n return result\n}\n\nfunction prefixPathExpression(prefix: string, expression: string): string {\n if (expression === '') {\n return prefix\n }\n return expression.startsWith('[')\n ? `${prefix}${expression}`\n : `${prefix}.${expression}`\n}\n\n/**\n * `SanityPatchOperations` from `@sanity/diff-patch` only covers the\n * operations `diffValue` emits; the editor can additionally produce these.\n */\ntype SanityPatchOperationsWithExtras = SanityPatchOperations & {\n setIfMissing?: {[path: string]: unknown}\n inc?: {[path: string]: number}\n dec?: {[path: string]: number}\n}\n\n/**\n * Converts Portable Text Editor patches into Sanity patch operations rooted\n * at the given document field path. Throws if a patch cannot be converted;\n * callers should fall back to pushing the whole value.\n *\n * @internal\n */\nexport function convertPatchesToSanity(\n patches: PtePatch[],\n options: {prefix: string},\n): SanityPatchOperationsWithExtras[] {\n return patches.map((patch): SanityPatchOperationsWithExtras => {\n const pathExpression = prefixPathExpression(\n options.prefix,\n stringifyPatchPath(patch.path),\n )\n\n switch (patch.type) {\n case 'set':\n return {set: {[pathExpression]: patch.value}}\n case 'setIfMissing':\n return {setIfMissing: {[pathExpression]: patch.value}}\n case 'diffMatchPatch':\n return {diffMatchPatch: {[pathExpression]: patch.value}}\n case 'inc':\n return {inc: {[pathExpression]: patch.value as number}}\n case 'dec':\n return {dec: {[pathExpression]: patch.value as number}}\n case 'unset':\n return {unset: [pathExpression]}\n case 'insert':\n return {\n insert: {\n [patch.position]: pathExpression,\n items: patch.items,\n } as SanityPatchOperations['insert'],\n }\n default:\n throw new Error(STRINGIFY_ERROR_MESSAGE)\n }\n })\n}\n\nfunction segmentsEqual(a: PathSegment, b: PathSegment): boolean {\n if (typeof a === 'string' || typeof a === 'number') {\n return a === b\n }\n if (typeof b === 'string' || typeof b === 'number') {\n return false\n }\n if (Array.isArray(a) || Array.isArray(b)) {\n return false\n }\n return a._key === b._key\n}\n\n/**\n * Scopes document-rooted Sanity patches to the given field path, returning\n * field-relative Portable Text Editor patches. Patches outside the field are\n * dropped. Returns `null` when the field (or an ancestor of it) is replaced\n * wholesale, when the field path itself can't be converted, or when any patch\n * op can't be converted to a keyed editor path — in all of which the caller\n * should fall back to a full value sync rather than apply a partial batch.\n *\n * @internal\n */\nexport function scopeRemotePatches(\n patches: SanityPatchOperations[],\n fieldPath: string,\n): PtePatch[] | null {\n const prefix = arrayifyPath(fieldPath)\n if (!prefix) {\n return null\n }\n const {patches: converted, incomplete} = convertPatches(patches)\n if (incomplete) {\n // a patch op couldn't be converted to a keyed editor path; applying the\n // rest would leave the field partially updated, so fall back to full sync\n return null\n }\n const scoped: PtePatch[] = []\n\n for (const patch of converted) {\n const overlap = Math.min(patch.path.length, prefix.length)\n let touchesField = true\n for (let index = 0; index < overlap; index++) {\n if (!segmentsEqual(patch.path[index], prefix[index])) {\n touchesField = false\n break\n }\n }\n if (!touchesField) {\n continue\n }\n if (patch.path.length <= prefix.length) {\n // the patch targets the field itself or an ancestor of it, which\n // cannot be expressed as a field-relative operation\n return null\n }\n scoped.push({...patch, path: patch.path.slice(prefix.length)})\n }\n\n return scoped\n}\n\nfunction applySync({\n editor,\n getRemoteValue,\n}: {\n editor: Editor\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n}) {\n const remoteValue = getRemoteValue()\n\n if (!remoteValue) {\n return\n }\n\n const snapshot = editor.getSnapshot().context.value\n const {patches, incomplete} = convertPatches(diffValue(snapshot, remoteValue))\n\n // Recover with an authoritative full value update when the diff can't be\n // applied faithfully. Either a patch was dropped – replaying the rest would\n // leave the editor in a partial/garbled state – or the editor moved on from\n // `snapshot` while we were diffing, so the patches were computed against a\n // value the editor no longer holds and can't be reconciled safely.\n if (incomplete || editor.getSnapshot().context.value !== snapshot) {\n updateValueFromRemote({editor, getRemoteValue})\n return\n }\n\n if (patches.length) {\n editor.send({type: 'patches', patches, snapshot})\n }\n}\n\nfunction updateValueFromRemote({\n editor,\n getRemoteValue,\n}: {\n editor: Editor\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n}) {\n editor.send({type: 'update value', value: getRemoteValue() ?? []})\n}\n\nconst listenToEditor = fromCallback<AnyEventObject, {editor: Editor}>(\n ({sendBack, input}) => {\n const patchSubscription = input.editor.on('patch', () => {\n sendBack({type: 'patch emitted'})\n })\n\n const mutationSubscription = input.editor.on('mutation', (event) => {\n sendBack({\n type: 'mutation flushed',\n value: event.value,\n patches: event.patches,\n })\n })\n\n return () => {\n patchSubscription.unsubscribe()\n mutationSubscription.unsubscribe()\n }\n },\n)\n\nconst listenToRemote = fromCallback<\n AnyEventObject,\n {onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']}\n>(({sendBack, input}) => {\n return input.onRemoteValueChange(() => {\n sendBack({type: 'remote value changed'})\n })\n})\n\nconst listenToRemotePatches = fromCallback<\n AnyEventObject,\n {onRemotePatches: ValueSyncConfig['onRemotePatches']}\n>(({sendBack, input}) => {\n return input.onRemotePatches?.((patches) => {\n sendBack({type: 'remote patches received', patches})\n })\n})\n\nconst valueSyncMachine = setup({\n types: {\n context: {} as {\n editor: Editor\n getRemoteValue: ValueSyncConfig['getRemoteValue']\n onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']\n onRemotePatches: ValueSyncConfig['onRemotePatches']\n },\n input: {} as {\n editor: Editor\n getRemoteValue: ValueSyncConfig['getRemoteValue']\n onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']\n onRemotePatches: ValueSyncConfig['onRemotePatches']\n },\n events: {} as\n | {type: 'patch emitted'}\n | {\n type: 'mutation flushed'\n value: PortableTextBlock[] | undefined\n patches: PtePatch[]\n }\n | {type: 'remote value changed'}\n | {type: 'remote patches received'; patches: PtePatch[]},\n },\n actions: {\n 'send initial value': ({context}) => {\n updateValueFromRemote({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n },\n 'push to remote': () => {\n throw new Error('push to remote must be provided via .provide()')\n },\n 'apply sync': ({context}) => {\n applySync({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n },\n 'defer then apply sync': ({context}) => {\n queueMicrotask(() => {\n applySync({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n })\n },\n 'apply remote patches': ({context, event}) => {\n if (event.type !== 'remote patches received') {\n return\n }\n if (event.patches.length === 0) {\n return\n }\n context.editor.send({\n type: 'patches',\n patches: event.patches,\n snapshot: context.editor.getSnapshot().context.value,\n })\n },\n },\n actors: {\n 'listen to editor': listenToEditor,\n 'listen to remote': listenToRemote,\n 'listen to remote patches': listenToRemotePatches,\n },\n}).createMachine({\n id: 'value sync',\n context: ({input}) => ({\n editor: input.editor,\n getRemoteValue: input.getRemoteValue,\n onRemoteValueChange: input.onRemoteValueChange,\n onRemotePatches: input.onRemotePatches,\n }),\n entry: ['send initial value'],\n invoke: [\n {\n src: 'listen to editor',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'listen to remote',\n input: ({context}) => ({\n onRemoteValueChange: context.onRemoteValueChange,\n }),\n },\n {\n src: 'listen to remote patches',\n input: ({context}) => ({\n onRemotePatches: context.onRemotePatches,\n }),\n },\n ],\n // operational patches from other clients apply immediately in every state;\n // the editor merges them with any in-flight local changes\n on: {\n 'remote patches received': {\n actions: ['apply remote patches'],\n },\n },\n initial: 'idle',\n states: {\n 'idle': {\n on: {\n 'patch emitted': {\n target: 'local write',\n },\n 'remote value changed': {\n actions: ['apply sync'],\n },\n },\n },\n 'local write': {\n on: {\n 'patch emitted': {},\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote'],\n },\n 'remote value changed': {\n target: 'pending sync',\n },\n },\n },\n 'pushing to remote': {\n on: {\n 'patch emitted': {\n target: 'local write',\n },\n 'remote value changed': {\n target: 'idle',\n },\n },\n },\n 'pending sync': {\n on: {\n 'patch emitted': {},\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote', 'defer then apply sync'],\n },\n 'remote value changed': {},\n },\n },\n },\n})\n\ninterface SDKValuePluginProps extends DocumentHandle {\n path: string\n}\n\n/**\n * The shape of the `remote-patches` document event emitted by\n * `@sanity/sdk` >= 2.17. Declared structurally so the plugin stays\n * compatible with older SDK typings until its dependency is bumped.\n */\ntype RemotePatchesDocumentEvent = {\n type: 'remote-patches'\n documentId: string\n transactionId: string\n timestamp: string\n previousRev?: string\n patches: SanityPatchOperations[]\n origin: 'local' | 'remote'\n}\n\nfunction isRemotePatchesEvent(event: {\n type: string\n}): event is RemotePatchesDocumentEvent {\n return event.type === 'remote-patches'\n}\n\nfunction getPublishedDocumentId(id: string): string {\n if (id.startsWith('drafts.')) {\n return id.slice('drafts.'.length)\n }\n if (id.startsWith('versions.')) {\n return id.split('.').slice(2).join('.')\n }\n return id\n}\n\n/**\n * @public\n */\nexport function SDKValuePlugin(props: SDKValuePluginProps) {\n const {documentId, documentType, path} = props\n const setSdkValue = useEditDocument(props)\n const instance = useSanityInstance(props)\n const applyActions = useApplyDocumentActions()\n\n const handle = {documentId, documentType, path}\n const {getCurrent, subscribe} = getDocumentState<PortableTextBlock[]>(\n instance,\n handle,\n )\n\n const onRemotePatches = useCallback(\n (callback: (patches: PtePatch[]) => void) => {\n return subscribeDocumentEvents(instance, {\n eventHandler: (event) => {\n // widen before narrowing: `remote-patches` is not part of the\n // `DocumentEvent` union in older SDK typings\n const candidate: {type: string} = event\n if (!isRemotePatchesEvent(candidate)) {\n return\n }\n // our own transactions are already reflected in the editor\n if (candidate.origin !== 'remote') {\n return\n }\n if (\n getPublishedDocumentId(candidate.documentId) !==\n getPublishedDocumentId(documentId)\n ) {\n return\n }\n\n let patches: PtePatch[] | null\n try {\n patches = scopeRemotePatches(candidate.patches, path)\n } catch {\n // unconvertible patch shapes fall back to the whole-value sync\n // driven by `onRemoteValueChange`\n return\n }\n if (patches && patches.length > 0) {\n callback(patches)\n }\n },\n })\n },\n [instance, documentId, path],\n )\n\n const pushPatches = useCallback(\n (patches: PtePatch[]) => {\n const sanityPatches = convertPatchesToSanity(patches, {prefix: path})\n // `preserveOperations` ships in @sanity/sdk >= 2.17; the intersection\n // type keeps the plugin compatible with older SDK typings\n const action: EditDocumentAction & {preserveOperations?: boolean} = {\n ...editDocument(\n {documentId, documentType},\n sanityPatches as Parameters<typeof editDocument>[1],\n ),\n preserveOperations: true,\n }\n applyActions(action)\n },\n [applyActions, documentId, documentType, path],\n )\n\n return (\n <ValueSyncPlugin\n getRemoteValue={getCurrent}\n pushValue={setSdkValue}\n onRemoteValueChange={subscribe}\n onRemotePatches={onRemotePatches}\n pushPatches={pushPatches}\n />\n )\n}\n\n/**\n * @internal\n */\ntype ValueSyncConfig = {\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n pushValue: (value: PortableTextBlock[]) => void\n onRemoteValueChange: (callback: () => void) => () => void\n /**\n * Optional patch channel. When provided, operational patches from other\n * clients are applied directly to the editor (in every state) instead of\n * waiting for a whole-value diff, and local editor patches are pushed\n * through `pushPatches`. The whole-value sync remains as a fallback for\n * anything the patch channel cannot express.\n */\n onRemotePatches?: (\n callback: (patches: PtePatch[]) => void,\n ) => (() => void) | undefined\n /**\n * Pushes the editor's own operational patches to the remote store. May\n * throw when a patch cannot be converted, in which case the plugin falls\n * back to pushing the whole value.\n */\n pushPatches?: (patches: PtePatch[]) => void\n}\n\n/**\n * NOTE: You are probably looking for SDKValuePlugin instead of this.\n * This is a lower-level plugin that only handles syncing the value\n * between the editor and a remote source. It does not know anything\n * about Sanity documents or how to fetch/update them.\n *\n * May be removed in the future, do not rely on this directly.\n *\n * @internal\n */\nexport function ValueSyncPlugin(props: ValueSyncConfig) {\n const {\n getRemoteValue,\n pushValue,\n onRemoteValueChange,\n onRemotePatches,\n pushPatches,\n } = props\n const editor = useEditor()\n\n useActorRef(\n valueSyncMachine.provide({\n actions: {\n 'push to remote': ({context, event}) => {\n if (event.type !== 'mutation flushed') {\n return\n }\n\n if (pushPatches && event.patches.length > 0) {\n try {\n pushPatches(event.patches)\n return\n } catch {\n // fall back to pushing the whole value below\n }\n }\n\n pushValue(event.value ?? context.editor.getSnapshot().context.value)\n },\n },\n }),\n {\n input: {\n editor,\n getRemoteValue,\n onRemoteValueChange,\n onRemotePatches,\n },\n },\n )\n\n return null\n}\n"],"names":["getSegments","node","base","segment","type","isKeyPath","recursive","name","arrayifyPath","pathExpr","parsePath","path","push","elements","length","element","value","operator","keyPathNode","left","right","find","other","_key","convertPatches","patches","incomplete","flatMap","operation","Object","entries","values","origin","Array","isArray","items","rest","position","keys","at","STRINGIFY_ERROR_MESSAGE","stringifyPatchPath","result","Error","prefixPathExpression","prefix","expression","startsWith","convertPatchesToSanity","options","map","patch","pathExpression","set","setIfMissing","diffMatchPatch","inc","dec","unset","insert","segmentsEqual","a","b","scopeRemotePatches","fieldPath","converted","scoped","overlap","Math","min","touchesField","index","slice","applySync","editor","getRemoteValue","remoteValue","snapshot","getSnapshot","context","diffValue","updateValueFromRemote","send","listenToEditor","fromCallback","sendBack","input","patchSubscription","on","mutationSubscription","event","unsubscribe","listenToRemote","onRemoteValueChange","listenToRemotePatches","onRemotePatches","valueSyncMachine","setup","types","events","actions","send initial value","push to remote","apply sync","defer then apply sync","queueMicrotask","apply remote patches","actors","createMachine","id","entry","invoke","src","initial","states","target","isRemotePatchesEvent","getPublishedDocumentId","split","join","SDKValuePlugin","props","$","_c","documentId","documentType","setSdkValue","useEditDocument","instance","useSanityInstance","applyActions","useApplyDocumentActions","t0","getDocumentState","getCurrent","subscribe","t1","callback","subscribeDocumentEvents","eventHandler","candidate","t2","patches_0","sanityPatches","action","editDocument","preserveOperations","pushPatches","t3","ValueSyncPlugin","pushValue","useEditor","provide","useActorRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/plugin.sdk-value.tsx"],"sourcesContent":["import {\n useEditor,\n type Editor,\n type PortableTextBlock,\n type Patch as PtePatch,\n} from '@portabletext/editor'\nimport type {\n JSONValue,\n Path,\n PathSegment,\n InsertPatch as PteInsertPatch,\n} from '@portabletext/patches'\nimport {diffValue, type SanityPatchOperations} from '@sanity/diff-patch'\nimport {\n parsePath,\n type ExprNode,\n type PathNode,\n type SegmentNode,\n type ThisNode,\n} from '@sanity/json-match'\nimport {\n editDocument,\n getDocumentState,\n subscribeDocumentEvents,\n useApplyDocumentActions,\n useEditDocument,\n useSanityInstance,\n type DocumentHandle,\n type EditDocumentAction,\n} from '@sanity/sdk-react'\nimport {useActorRef} from '@xstate/react'\nimport {useCallback} from 'react'\nimport {fromCallback, setup, type AnyEventObject} from 'xstate'\n\ntype InsertPatch = Required<Pick<SanityPatchOperations, 'insert'>>\n\nconst ARRAYIFY_ERROR_MESSAGE =\n 'Unexpected path format from diffValue output. Please report this issue.'\n\nfunction* getSegments(\n node: PathNode,\n): Generator<Exclude<SegmentNode, ThisNode>> {\n if (node.base) {\n yield* getSegments(node.base)\n }\n if (node.segment.type !== 'This') {\n yield node.segment\n }\n}\n\nfunction isKeyPath(node: ExprNode): node is PathNode {\n if (node.type !== 'Path') {\n return false\n }\n if (node.base) {\n return false\n }\n if (node.recursive) {\n return false\n }\n if (node.segment.type !== 'Identifier') {\n return false\n }\n return node.segment.name === '_key'\n}\n\nexport function arrayifyPath(pathExpr: string): Path {\n const node = parsePath(pathExpr)\n if (!node) {\n return []\n }\n if (node.type !== 'Path') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n\n return Array.from(getSegments(node)).map((segment): PathSegment => {\n if (segment.type === 'Identifier') {\n return segment.name\n }\n if (segment.type !== 'Subscript') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n if (segment.elements.length !== 1) {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n\n const [element] = segment.elements\n if (element.type === 'Number') {\n return element.value\n }\n\n if (element.type !== 'Comparison') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n if (element.operator !== '==') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n const keyPathNode = [element.left, element.right].find(isKeyPath)\n if (!keyPathNode) {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n const other = element.left === keyPathNode ? element.right : element.left\n if (other.type !== 'String') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n return {_key: other.value}\n })\n}\n\nexport function convertPatches(patches: SanityPatchOperations[]): PtePatch[] {\n return patches.flatMap((p) => {\n return Object.entries(p).flatMap(([type, values]): PtePatch[] => {\n const origin = 'remote'\n\n switch (type) {\n case 'set':\n case 'setIfMissing':\n case 'diffMatchPatch':\n case 'inc':\n case 'dec': {\n return Object.entries(values).map(\n ([pathExpr, value]) =>\n ({type, value, origin, path: arrayifyPath(pathExpr)}) as PtePatch,\n )\n }\n case 'unset': {\n if (!Array.isArray(values)) {\n return []\n }\n return values.map(arrayifyPath).map((path) => ({type, origin, path}))\n }\n case 'insert': {\n const {items, ...rest} = values as InsertPatch['insert']\n type InsertPosition = PteInsertPatch['position']\n const position = Object.keys(rest).at(0) as InsertPosition | undefined\n\n if (!position) {\n return []\n }\n const pathExpr = (rest as {[K in InsertPosition]: string})[position]\n const insertPatch: PteInsertPatch = {\n type,\n origin,\n position,\n path: arrayifyPath(pathExpr),\n items: items as JSONValue[],\n }\n\n return [insertPatch]\n }\n\n default: {\n return []\n }\n }\n })\n })\n}\n\nconst STRINGIFY_ERROR_MESSAGE =\n 'Unable to convert an editor patch path to a Sanity path expression.'\n\n/**\n * Converts a Portable Text Editor patch path (an array of segments) into a\n * Sanity json-match path expression. The inverse of `arrayifyPath`.\n *\n * @internal\n */\nexport function stringifyPatchPath(path: Path): string {\n let result = ''\n for (const segment of path) {\n if (typeof segment === 'string') {\n result = result === '' ? segment : `${result}.${segment}`\n } else if (typeof segment === 'number') {\n result = `${result}[${segment}]`\n } else if (\n typeof segment === 'object' &&\n segment !== null &&\n '_key' in segment\n ) {\n result = `${result}[_key==\"${segment._key}\"]`\n } else {\n throw new Error(STRINGIFY_ERROR_MESSAGE)\n }\n }\n return result\n}\n\nfunction prefixPathExpression(prefix: string, expression: string): string {\n if (expression === '') {\n return prefix\n }\n return expression.startsWith('[')\n ? `${prefix}${expression}`\n : `${prefix}.${expression}`\n}\n\n/**\n * `SanityPatchOperations` from `@sanity/diff-patch` only covers the\n * operations `diffValue` emits; the editor can additionally produce these.\n */\ntype SanityPatchOperationsWithExtras = SanityPatchOperations & {\n setIfMissing?: {[path: string]: unknown}\n inc?: {[path: string]: number}\n dec?: {[path: string]: number}\n}\n\n/**\n * Converts Portable Text Editor patches into Sanity patch operations rooted\n * at the given document field path. Throws if a patch cannot be converted;\n * callers should fall back to pushing the whole value.\n *\n * @internal\n */\nexport function convertPatchesToSanity(\n patches: PtePatch[],\n options: {prefix: string},\n): SanityPatchOperationsWithExtras[] {\n return patches.map((patch): SanityPatchOperationsWithExtras => {\n const pathExpression = prefixPathExpression(\n options.prefix,\n stringifyPatchPath(patch.path),\n )\n\n switch (patch.type) {\n case 'set':\n return {set: {[pathExpression]: patch.value}}\n case 'setIfMissing':\n return {setIfMissing: {[pathExpression]: patch.value}}\n case 'unset':\n // The editor unsets the whole field when it becomes empty. Write an\n // empty array instead: unsetting the field would leave other clients\n // unable to reconcile against it (their remote value disappears).\n if (patch.path.length === 0) {\n return {set: {[pathExpression]: []}}\n }\n return {unset: [pathExpression]}\n case 'diffMatchPatch':\n return {diffMatchPatch: {[pathExpression]: patch.value}}\n case 'inc':\n return {inc: {[pathExpression]: patch.value as number}}\n case 'dec':\n return {dec: {[pathExpression]: patch.value as number}}\n case 'insert':\n return {\n insert: {\n [patch.position]: pathExpression,\n items: patch.items,\n } as SanityPatchOperations['insert'],\n }\n default:\n throw new Error(STRINGIFY_ERROR_MESSAGE)\n }\n })\n}\n\nfunction segmentsEqual(a: PathSegment, b: PathSegment): boolean {\n if (typeof a === 'string' || typeof a === 'number') {\n return a === b\n }\n if (typeof b === 'string' || typeof b === 'number') {\n return false\n }\n if (Array.isArray(a) || Array.isArray(b)) {\n return false\n }\n return a._key === b._key\n}\n\nfunction pathsEqual(a: Path, b: Path): boolean {\n return (\n a.length === b.length &&\n a.every((segment, index) => segmentsEqual(segment, b[index]))\n )\n}\n\n/**\n * The editor engine can only resolve keyed/indexed segments against the\n * root block array and (possibly nested) `children` arrays. Operations\n * that address items of any other array, e.g. a block's `markDefs` or a\n * span's `marks`, misapply. When a patch path enters such a sidecar\n * array, this returns the path of the array itself so callers can fall\n * back to replacing the whole property; returns `null` for paths the\n * engine can apply.\n *\n * @internal\n */\nexport function findSidecarArrayPath(path: Path): Path | null {\n // a keyed/numeric segment is only resolvable first (root block array)\n // or directly after a `children` property\n let expectNode = true\n for (let index = 0; index < path.length; index++) {\n const segment = path[index]\n if (typeof segment === 'string') {\n expectNode = segment === 'children'\n } else {\n if (!expectNode) {\n return path.slice(0, index)\n }\n expectNode = false\n }\n }\n return null\n}\n\nfunction getValueAtPath(value: JSONValue, path: Path): JSONValue | undefined {\n let current: JSONValue | undefined = value\n for (const segment of path) {\n if (current === null || current === undefined) {\n return undefined\n }\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) {\n return undefined\n }\n current = current[segment < 0 ? current.length + segment : segment]\n } else if (typeof segment === 'string') {\n if (typeof current !== 'object' || Array.isArray(current)) {\n return undefined\n }\n current = (current as {[key: string]: JSONValue})[segment]\n } else if (Array.isArray(segment)) {\n // index tuples address ranges, not single values\n return undefined\n } else {\n if (!Array.isArray(current)) {\n return undefined\n }\n current = current.find(\n (item) =>\n typeof item === 'object' &&\n item !== null &&\n !Array.isArray(item) &&\n (item as {_key?: unknown})._key === segment._key,\n )\n }\n }\n return current\n}\n\n/**\n * Converts a target-value diff into patches the editor engine can apply.\n * Patches addressing items inside sidecar arrays are coalesced into whole\n * `set`s (or `unset`s) of the owning property, taken from the target\n * value.\n *\n * @internal\n */\nexport function toEngineSafePatches(\n patches: PtePatch[],\n targetValue: PortableTextBlock[],\n): PtePatch[] {\n const safe: PtePatch[] = []\n const sidecarPaths: Path[] = []\n\n for (const patch of patches) {\n const sidecarPath = findSidecarArrayPath(patch.path)\n if (!sidecarPath) {\n safe.push(patch)\n continue\n }\n if (!sidecarPaths.some((existing) => pathsEqual(existing, sidecarPath))) {\n sidecarPaths.push(sidecarPath)\n }\n }\n\n for (const sidecarPath of sidecarPaths) {\n const value = getValueAtPath(\n targetValue as unknown as JSONValue,\n sidecarPath,\n )\n safe.push(\n value === undefined\n ? {type: 'unset', path: sidecarPath, origin: 'remote'}\n : {type: 'set', path: sidecarPath, value, origin: 'remote'},\n )\n }\n\n return safe\n}\n\n/**\n * The editor writes `markDefs` as whole-array `set`s. Two clients\n * formatting the same block concurrently then overwrite each other's\n * arrays at the server (last writer wins) while both clients' span\n * `marks` references survive, stranding marks without definitions.\n * Outgoing `markDefs` sets are therefore decomposed into item-level\n * operations against the store (server truth): new definitions insert,\n * changed definitions set by key, and removed definitions unset by key,\n * except definitions the store's own spans still reference (a diverged\n * client's normalizer prunes those spuriously; a later, converged flush\n * removes them for real). Item-keyed operations merge at the server\n * instead of overwriting.\n *\n * @internal\n */\nexport function toMergeableMarkDefsPatches(\n patches: PtePatch[],\n getCurrentValue: () => PortableTextBlock[] | null | undefined,\n): PtePatch[] {\n return patches.flatMap((patch): PtePatch[] => {\n if (\n patch.type !== 'set' ||\n patch.path.at(-1) !== 'markDefs' ||\n !Array.isArray(patch.value)\n ) {\n return [patch]\n }\n const currentValue = getCurrentValue()\n if (!currentValue) {\n return [patch]\n }\n const root = currentValue as unknown as JSONValue\n const storeMarkDefs = getValueAtPath(root, patch.path)\n const storeBlock = getValueAtPath(root, patch.path.slice(0, -1))\n if (\n !Array.isArray(storeMarkDefs) ||\n typeof storeBlock !== 'object' ||\n storeBlock === null\n ) {\n return [patch]\n }\n\n const local = patch.value as Array<{_key?: string}>\n const store = storeMarkDefs as Array<{_key?: string}>\n if (local.some((item) => item._key === undefined)) {\n return [patch]\n }\n\n const referencedKeys = new Set(\n (\n (storeBlock as {children?: Array<{marks?: string[]}>}).children ?? []\n ).flatMap((child) => child.marks ?? []),\n )\n const storeByKey = new Map(store.map((item) => [item._key, item]))\n const localKeys = new Set(local.map((item) => item._key))\n const origin = patch.origin\n\n const ops: PtePatch[] = []\n\n const inserted = local.filter((item) => !storeByKey.has(item._key))\n if (inserted.length > 0) {\n ops.push({\n type: 'insert',\n origin,\n position: 'after',\n path: [...patch.path, -1],\n items: inserted as JSONValue[],\n })\n }\n\n for (const item of local) {\n const existing = storeByKey.get(item._key)\n if (existing && JSON.stringify(existing) !== JSON.stringify(item)) {\n ops.push({\n type: 'set',\n origin,\n path: [...patch.path, {_key: item._key as string}],\n value: item as JSONValue,\n })\n }\n }\n\n for (const item of store) {\n if (\n item._key !== undefined &&\n !localKeys.has(item._key) &&\n !referencedKeys.has(item._key)\n ) {\n ops.push({\n type: 'unset',\n origin,\n path: [...patch.path, {_key: item._key}],\n })\n }\n }\n\n return ops\n })\n}\n\n/**\n * Whether a remote patch can resolve against the given editor value.\n * Concurrent edits routinely produce operations addressing nodes another\n * client has already removed or not yet created; sending those into the\n * engine fails loudly (console errors) before being skipped. Callers drop\n * unresolvable patches up front and rely on the follow-up repair sync to\n * converge instead.\n *\n * @internal\n */\nexport function canApplyToValue(\n patch: PtePatch,\n value: PortableTextBlock[] | undefined,\n): boolean {\n if (!value) {\n return true\n }\n const root = value as unknown as JSONValue\n switch (patch.type) {\n // unset needs the node itself; insert needs the sibling at `path`;\n // diffMatchPatch needs the existing string\n case 'unset':\n case 'insert':\n case 'diffMatchPatch':\n return getValueAtPath(root, patch.path) !== undefined\n // set creates its target property, so only the parent must resolve\n case 'set':\n return (\n patch.path.length === 0 ||\n getValueAtPath(root, patch.path.slice(0, -1)) !== undefined\n )\n default:\n return true\n }\n}\n\n/**\n * Scopes document-rooted Sanity patches to the given field path, returning\n * field-relative Portable Text Editor patches. Patches outside the field are\n * dropped. Returns `null` when the field (or an ancestor of it) is replaced\n * wholesale, in which case the caller should fall back to a full value sync.\n * Throws when a path expression cannot be converted.\n *\n * @internal\n */\nexport function scopeRemotePatches(\n patches: SanityPatchOperations[],\n fieldPath: string,\n): PtePatch[] | null {\n const prefix = arrayifyPath(fieldPath)\n const converted = convertPatches(patches)\n const scoped: PtePatch[] = []\n\n for (const patch of converted) {\n const overlap = Math.min(patch.path.length, prefix.length)\n let touchesField = true\n for (let index = 0; index < overlap; index++) {\n if (!segmentsEqual(patch.path[index], prefix[index])) {\n touchesField = false\n break\n }\n }\n if (!touchesField) {\n continue\n }\n if (patch.path.length <= prefix.length) {\n // the patch targets the field itself or an ancestor of it, which\n // cannot be expressed as a field-relative operation\n return null\n }\n scoped.push({...patch, path: patch.path.slice(prefix.length)})\n }\n\n return scoped\n}\n\n// Sync diagnostics, disabled unless `globalThis.__PTE_SYNC_DEBUG = true`\n// is set before load. Callers pass a thunk so detail computation is free\n// when the flag is off.\nfunction syncDebugEnabled(): boolean {\n return (globalThis as {__PTE_SYNC_DEBUG?: boolean}).__PTE_SYNC_DEBUG === true\n}\n\nfunction syncDebug(kind: string, detail: () => Record<string, unknown>) {\n if (syncDebugEnabled()) {\n // biome-ignore lint/suspicious/noConsole: opt-in diagnostics channel\n console.debug(`[pte-sync] ${kind} ${JSON.stringify(detail())}`)\n }\n}\n\nfunction debugTextOf(value: unknown): string {\n if (!Array.isArray(value)) {\n return ''\n }\n return value\n .map((block) =>\n Array.isArray((block as {children?: unknown}).children)\n ? ((block as {children: Array<{text?: string}>}).children ?? [])\n .map((child) => child.text ?? '')\n .join('')\n : '',\n )\n .join('\\n')\n}\n\nfunction applySync({\n editor,\n getRemoteValue,\n}: {\n editor: Editor\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n}) {\n const remoteValue = getRemoteValue()\n\n if (!remoteValue) {\n return\n }\n\n const snapshot = editor.getSnapshot().context.value\n if (syncDebugEnabled()) {\n const editorText = debugTextOf(snapshot)\n const remoteText = debugTextOf(remoteValue)\n if (editorText !== remoteText) {\n syncDebug('applySync:texts-differ', () => ({editorText, remoteText}))\n }\n }\n\n let patches: PtePatch[]\n try {\n patches = toEngineSafePatches(\n convertPatches(diffValue(snapshot, remoteValue)),\n remoteValue,\n )\n } catch {\n // diffValue can emit path shapes the converter does not understand\n // (e.g. array slices when multiple items are dropped). Fall back to\n // the full value sync machinery rather than leaving the editor\n // diverged.\n editor.send({type: 'update value', value: remoteValue})\n return\n }\n\n if (patches.length) {\n syncDebug('applySync:repair-patches', () => ({patches}))\n editor.send({type: 'patches', patches, snapshot})\n\n // Patch application is best-effort: the editor skips operations it\n // cannot resolve against its current tree, and concurrent edits to the\n // same range produce keyed operations whose targets no longer exist\n // locally. When the editor is still diverged after the diff-based\n // repair, escalate to the full value sync machinery, which reconciles\n // arbitrary divergence block by block.\n const valueAfterPatches = editor.getSnapshot().context.value\n if (diffValue(valueAfterPatches, remoteValue).length > 0) {\n syncDebug('applySync:escalate-update-value', () => ({\n editorText: debugTextOf(valueAfterPatches),\n remoteText: debugTextOf(remoteValue),\n }))\n editor.send({type: 'update value', value: remoteValue})\n }\n }\n}\n\nconst listenToEditor = fromCallback<AnyEventObject, {editor: Editor}>(\n ({sendBack, input}) => {\n const patchSubscription = input.editor.on('patch', () => {\n sendBack({type: 'patch emitted'})\n })\n\n const mutationSubscription = input.editor.on('mutation', (event) => {\n syncDebug('event:mutation-flushed', () => ({\n flushText: debugTextOf(event.value),\n snapshotText: debugTextOf(input.editor.getSnapshot().context.value),\n }))\n sendBack({\n type: 'mutation flushed',\n value: event.value,\n patches: event.patches,\n })\n })\n\n return () => {\n patchSubscription.unsubscribe()\n mutationSubscription.unsubscribe()\n }\n },\n)\n\nconst listenToRemote = fromCallback<\n AnyEventObject,\n {onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']}\n>(({sendBack, input}) => {\n return input.onRemoteValueChange(() => {\n sendBack({type: 'remote value changed'})\n })\n})\n\nconst listenToRemotePatches = fromCallback<\n AnyEventObject,\n {onRemotePatches: ValueSyncConfig['onRemotePatches']}\n>(({sendBack, input}) => {\n return input.onRemotePatches?.((patches) => {\n sendBack({type: 'remote patches received', patches})\n })\n})\n\n/**\n * How long the machine must sit in 'idle' (no local keystrokes, no store\n * events) before the one-shot whole-value repair runs. Long enough for the\n * editor's external value snapshot to catch up after the last flush; short\n * enough that residual divergence from concurrent editing heals promptly.\n */\nconst QUIESCENT_REPAIR_DELAY = 500\n\nconst valueSyncMachine = setup({\n types: {\n context: {} as {\n editor: Editor\n getRemoteValue: ValueSyncConfig['getRemoteValue']\n onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']\n onRemotePatches: ValueSyncConfig['onRemotePatches']\n },\n input: {} as {\n editor: Editor\n getRemoteValue: ValueSyncConfig['getRemoteValue']\n onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']\n onRemotePatches: ValueSyncConfig['onRemotePatches']\n },\n events: {} as\n | {type: 'patch emitted'}\n | {\n type: 'mutation flushed'\n value: PortableTextBlock[] | undefined\n patches: PtePatch[]\n }\n | {type: 'remote value changed'}\n | {type: 'remote patches received'; patches: PtePatch[]},\n },\n actions: {\n 'send initial value': ({context}) => {\n context.editor.send({\n type: 'update value',\n value: context.getRemoteValue() ?? [],\n })\n },\n 'push to remote': () => {\n throw new Error('push to remote must be provided via .provide()')\n },\n 'apply sync': ({context}) => {\n applySync({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n },\n 'apply remote patches': ({context, event}) => {\n if (event.type !== 'remote patches received') {\n return\n }\n syncDebug('apply-remote-patches', () => ({patches: event.patches}))\n const snapshot = context.editor.getSnapshot().context.value\n // The store already reflects this transaction, so it can serve as\n // the target for coalescing sidecar-array item operations (which\n // the engine misroutes) into whole-property sets.\n const remoteValue = context.getRemoteValue()\n const coalesced = remoteValue\n ? toEngineSafePatches(event.patches, remoteValue)\n : event.patches\n const patches = coalesced.filter((patch) =>\n canApplyToValue(patch, snapshot),\n )\n if (patches.length === 0) {\n return\n }\n context.editor.send({type: 'patches', patches, snapshot})\n },\n },\n actors: {\n 'listen to editor': listenToEditor,\n 'listen to remote': listenToRemote,\n 'listen to remote patches': listenToRemotePatches,\n },\n}).createMachine({\n id: 'value sync',\n context: ({input}) => ({\n editor: input.editor,\n getRemoteValue: input.getRemoteValue,\n onRemoteValueChange: input.onRemoteValueChange,\n onRemotePatches: input.onRemotePatches,\n }),\n entry: ['send initial value'],\n invoke: [\n {\n src: 'listen to editor',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'listen to remote',\n input: ({context}) => ({\n onRemoteValueChange: context.onRemoteValueChange,\n }),\n },\n {\n src: 'listen to remote patches',\n input: ({context}) => ({\n onRemotePatches: context.onRemotePatches,\n }),\n },\n ],\n // Two invariants, learned the hard way:\n //\n // 1. EVERY 'mutation flushed' event must be pushed, in every state. The\n // editor emits mutation events in bursts (one per input batch, e.g.\n // each backspace of a quick delete), and any state without a handler\n // silently drops the flush. A dropped flush permanently diverges the\n // store from the editor, and the whole-value repair then \"heals\" the\n // editor backwards, resurrecting deleted text.\n // 2. The whole-value repair must only run when no local edits can be in\n // flight (quiescent 'idle'). Running it mid-typing diffs the editor\n // against a store that lags the user's keystrokes and stomps them.\n //\n // Operational patches from other clients still apply immediately in\n // every state; the editor merges them with in-flight local changes.\n initial: 'idle',\n states: {\n 'idle': {\n // One-shot repair after a quiet period. Covers divergence left by\n // best-effort patch application while local edits were in flight\n // (those states never repair; see below) when no further store\n // event arrives to trigger the on-change repair.\n after: {\n [QUIESCENT_REPAIR_DELAY]: {\n actions: ['apply sync'],\n },\n },\n on: {\n 'patch emitted': {\n target: 'local write',\n },\n // Mutation events arrive in bursts (one per input batch), so a\n // flush can land after a sibling flush already advanced the state.\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote'],\n },\n 'remote value changed': {\n actions: ['apply sync'],\n },\n // No immediate repair here: every remote patch batch also updates\n // the store value, so the accompanying 'remote value changed'\n // event runs the whole-value repair right after.\n 'remote patches received': {\n actions: ['apply remote patches'],\n },\n },\n },\n 'local write': {\n on: {\n 'patch emitted': {},\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote'],\n },\n 'remote value changed': {\n target: 'pending sync',\n },\n 'remote patches received': {\n target: 'pending sync',\n actions: ['apply remote patches'],\n },\n },\n },\n 'pushing to remote': {\n on: {\n 'patch emitted': {\n target: 'local write',\n },\n 'mutation flushed': {\n actions: ['push to remote'],\n },\n // No repair on the push acknowledgment: the editor snapshot can\n // lag the live document while the user keeps typing, so a diff\n // against the store here resurrects deleted text and duplicates\n // in-flight keystrokes. Once truly idle, the store change or the\n // quiescent delay runs the repair with a caught-up snapshot.\n 'remote value changed': {\n target: 'idle',\n },\n 'remote patches received': {\n actions: ['apply remote patches'],\n },\n },\n },\n 'pending sync': {\n on: {\n 'patch emitted': {},\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote'],\n },\n 'remote value changed': {},\n 'remote patches received': {\n actions: ['apply remote patches'],\n },\n },\n },\n },\n})\n\ninterface SDKValuePluginProps extends DocumentHandle {\n path: string\n}\n\n/**\n * The shape of the `remote-patches` document event emitted by\n * `@sanity/sdk` >= 2.17. Declared structurally so the plugin stays\n * compatible with older SDK typings until its dependency is bumped.\n */\ntype RemotePatchesDocumentEvent = {\n type: 'remote-patches'\n documentId: string\n transactionId: string\n timestamp: string\n previousRev?: string\n patches: SanityPatchOperations[]\n origin: 'local' | 'remote'\n}\n\nfunction isRemotePatchesEvent(event: {\n type: string\n}): event is RemotePatchesDocumentEvent {\n return event.type === 'remote-patches'\n}\n\nfunction getPublishedDocumentId(id: string): string {\n if (id.startsWith('drafts.')) {\n return id.slice('drafts.'.length)\n }\n if (id.startsWith('versions.')) {\n return id.split('.').slice(2).join('.')\n }\n return id\n}\n\n/**\n * @public\n */\nexport function SDKValuePlugin(props: SDKValuePluginProps) {\n const {documentId, documentType, path} = props\n const setSdkValue = useEditDocument(props)\n const instance = useSanityInstance(props)\n const applyActions = useApplyDocumentActions()\n\n const handle = {documentId, documentType, path}\n const {getCurrent, subscribe} = getDocumentState<PortableTextBlock[]>(\n instance,\n handle,\n )\n\n const onRemotePatches = useCallback(\n (callback: (patches: PtePatch[]) => void) => {\n return subscribeDocumentEvents(instance, {\n eventHandler: (event) => {\n // widen before narrowing: `remote-patches` is not part of the\n // `DocumentEvent` union in older SDK typings\n const candidate: {type: string} = event\n if (!isRemotePatchesEvent(candidate)) {\n return\n }\n // our own transactions are already reflected in the editor\n if (candidate.origin !== 'remote') {\n return\n }\n if (\n getPublishedDocumentId(candidate.documentId) !==\n getPublishedDocumentId(documentId)\n ) {\n return\n }\n\n let patches: PtePatch[] | null\n try {\n patches = scopeRemotePatches(candidate.patches, path)\n } catch {\n // unconvertible patch shapes fall back to the whole-value sync\n // driven by `onRemoteValueChange`\n return\n }\n if (patches && patches.length > 0) {\n callback(patches)\n }\n },\n })\n },\n [instance, documentId, path],\n )\n\n const pushPatches = useCallback(\n (patches: PtePatch[]) => {\n const sanityPatches = convertPatchesToSanity(patches, {prefix: path})\n // `preserveOperations` ships in @sanity/sdk >= 2.17; the intersection\n // type keeps the plugin compatible with older SDK typings\n const action: EditDocumentAction & {preserveOperations?: boolean} = {\n ...editDocument(\n {documentId, documentType},\n sanityPatches as Parameters<typeof editDocument>[1],\n ),\n preserveOperations: true,\n }\n applyActions(action)\n },\n [applyActions, documentId, documentType, path],\n )\n\n return (\n <ValueSyncPlugin\n getRemoteValue={getCurrent}\n pushValue={setSdkValue}\n onRemoteValueChange={subscribe}\n onRemotePatches={onRemotePatches}\n pushPatches={pushPatches}\n />\n )\n}\n\n/**\n * @internal\n */\ntype ValueSyncConfig = {\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n pushValue: (value: PortableTextBlock[]) => void\n onRemoteValueChange: (callback: () => void) => () => void\n /**\n * Optional patch channel. When provided, operational patches from other\n * clients are applied directly to the editor (in every state) instead of\n * waiting for a whole-value diff, and local editor patches are pushed\n * through `pushPatches`. The whole-value sync remains as a fallback for\n * anything the patch channel cannot express.\n */\n onRemotePatches?: (\n callback: (patches: PtePatch[]) => void,\n ) => (() => void) | undefined\n /**\n * Pushes the editor's own operational patches to the remote store. May\n * throw when a patch cannot be converted, in which case the plugin falls\n * back to pushing the whole value.\n */\n pushPatches?: (patches: PtePatch[]) => void\n}\n\n/**\n * NOTE: You are probably looking for SDKValuePlugin instead of this.\n * This is a lower-level plugin that only handles syncing the value\n * between the editor and a remote source. It does not know anything\n * about Sanity documents or how to fetch/update them.\n *\n * May be removed in the future, do not rely on this directly.\n *\n * @internal\n */\nexport function ValueSyncPlugin(props: ValueSyncConfig) {\n const {\n getRemoteValue,\n pushValue,\n onRemoteValueChange,\n onRemotePatches,\n pushPatches,\n } = props\n const editor = useEditor()\n\n useActorRef(\n valueSyncMachine.provide({\n actions: {\n 'push to remote': ({context, event}) => {\n if (event.type !== 'mutation flushed') {\n return\n }\n\n if (pushPatches && event.patches.length > 0) {\n try {\n const mergeable = toMergeableMarkDefsPatches(\n event.patches,\n context.getRemoteValue,\n )\n syncDebug('push-patches', () => ({patches: mergeable}))\n pushPatches(mergeable)\n return\n } catch {\n // fall back to pushing the whole value below\n }\n }\n\n syncDebug('push-whole-value', () => ({\n text: debugTextOf(\n event.value ?? context.editor.getSnapshot().context.value,\n ),\n }))\n pushValue(event.value ?? context.editor.getSnapshot().context.value)\n },\n },\n }),\n {\n input: {\n editor,\n getRemoteValue,\n onRemoteValueChange,\n onRemotePatches,\n },\n },\n )\n\n return null\n}\n"],"names":["ARRAYIFY_ERROR_MESSAGE","getSegments","node","base","segment","type","isKeyPath","recursive","name","arrayifyPath","pathExpr","parsePath","Error","Array","from","map","elements","length","element","value","operator","keyPathNode","left","right","find","other","_key","convertPatches","patches","flatMap","p","Object","entries","values","origin","path","isArray","items","rest","position","keys","at","STRINGIFY_ERROR_MESSAGE","stringifyPatchPath","result","prefixPathExpression","prefix","expression","startsWith","convertPatchesToSanity","options","patch","pathExpression","set","setIfMissing","unset","diffMatchPatch","inc","dec","insert","segmentsEqual","a","b","pathsEqual","every","index","findSidecarArrayPath","expectNode","slice","getValueAtPath","current","item","toEngineSafePatches","targetValue","safe","sidecarPaths","sidecarPath","push","some","existing","undefined","toMergeableMarkDefsPatches","getCurrentValue","currentValue","root","storeMarkDefs","storeBlock","local","store","referencedKeys","Set","children","child","marks","storeByKey","Map","localKeys","ops","inserted","filter","has","get","JSON","stringify","canApplyToValue","scopeRemotePatches","fieldPath","converted","scoped","overlap","Math","min","touchesField","syncDebugEnabled","globalThis","__PTE_SYNC_DEBUG","syncDebug","kind","detail","console","debug","debugTextOf","block","text","join","applySync","editor","getRemoteValue","remoteValue","snapshot","getSnapshot","context","editorText","remoteText","diffValue","send","valueAfterPatches","listenToEditor","fromCallback","sendBack","input","patchSubscription","on","mutationSubscription","event","flushText","snapshotText","unsubscribe","listenToRemote","onRemoteValueChange","listenToRemotePatches","onRemotePatches","QUIESCENT_REPAIR_DELAY","valueSyncMachine","setup","types","events","actions","send initial value","push to remote","apply sync","apply remote patches","actors","createMachine","id","entry","invoke","src","initial","states","after","target","isRemotePatchesEvent","getPublishedDocumentId","split","SDKValuePlugin","props","$","_c","documentId","documentType","setSdkValue","useEditDocument","instance","useSanityInstance","applyActions","useApplyDocumentActions","t0","getDocumentState","getCurrent","subscribe","t1","callback","subscribeDocumentEvents","eventHandler","candidate","t2","patches_0","sanityPatches","action","editDocument","preserveOperations","pushPatches","t3","ValueSyncPlugin","pushValue","useEditor","provide","mergeable","useActorRef"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/plugin-sdk-value",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.1",
|
|
4
4
|
"description": "Connect a Portable Text Editor with a Sanity document using the SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"@sanity/sdk",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"xstate": "^5.32.4"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
+
"@sanity/diff-match-patch": "^3.2.0",
|
|
43
44
|
"@sanity/pkg-utils": "^10.8.2",
|
|
44
45
|
"@sanity/sdk-react": "^2.13.0",
|
|
45
46
|
"@sanity/tsconfig": "^2.1.0",
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
"typescript-eslint": "^8.62.0",
|
|
59
60
|
"vitest": "^4.1.10",
|
|
60
61
|
"vitest-browser-react": "^2.2.0",
|
|
61
|
-
"@portabletext/editor": "^7.10.
|
|
62
|
+
"@portabletext/editor": "^7.10.9",
|
|
62
63
|
"@portabletext/patches": "^2.0.5",
|
|
63
64
|
"@portabletext/schema": "^2.2.3",
|
|
64
65
|
"@portabletext/test": "^1.0.4"
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
"@sanity/sdk-react": "^2.1.2",
|
|
68
69
|
"react": "^19.2",
|
|
69
70
|
"react-dom": "^19.2",
|
|
70
|
-
"@portabletext/editor": "^7.10.
|
|
71
|
+
"@portabletext/editor": "^7.10.9"
|
|
71
72
|
},
|
|
72
73
|
"engines": {
|
|
73
74
|
"node": ">=20.19 <22 || >=22.12"
|