@portabletext/plugin-sdk-value 7.0.36-crx.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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
- let node;
18
- try {
19
- node = parsePath(pathExpr);
20
- } catch {
21
- return null;
22
- }
23
- if (!node || node.type !== "Path")
24
- return null;
25
- const path = [];
26
- for (const segment of getSegments(node)) {
27
- if (segment.type === "Identifier") {
28
- path.push(segment.name);
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
- path.push(element.value);
36
- continue;
37
- }
38
- if (element.type !== "Comparison" || element.operator !== "==")
39
- return null;
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
- return null;
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
- return null;
46
- path.push({
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
- let incomplete = !1;
54
- return {
55
- patches: patches.flatMap((operation) => Object.entries(operation).flatMap(([type, values]) => {
56
- const origin = "remote";
57
- switch (type) {
58
- case "set":
59
- case "setIfMissing":
60
- case "diffMatchPatch":
61
- case "inc":
62
- case "dec":
63
- return Object.entries(values).flatMap(([pathExpr, value]) => {
64
- const path = arrayifyPath(pathExpr);
65
- return path ? [{
66
- type,
67
- value,
68
- origin,
69
- path
70
- }] : (incomplete = !0, []);
71
- });
72
- case "unset":
73
- return Array.isArray(values) ? values.flatMap((pathExpr) => {
74
- const path = arrayifyPath(pathExpr);
75
- return path ? [{
76
- type,
77
- origin,
78
- path
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
- incomplete
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;
@@ -208,31 +313,29 @@ function applySync({
208
313
  const remoteValue = getRemoteValue();
209
314
  if (!remoteValue)
210
315
  return;
211
- const snapshot = editor.getSnapshot().context.value, {
212
- patches,
213
- incomplete
214
- } = convertPatches(diffValue(snapshot, remoteValue));
215
- if (incomplete || editor.getSnapshot().context.value !== snapshot) {
216
- updateValueFromRemote({
217
- editor,
218
- getRemoteValue
316
+ const snapshot = editor.getSnapshot().context.value;
317
+ let patches;
318
+ try {
319
+ patches = toEngineSafePatches(convertPatches(diffValue(snapshot, remoteValue)), remoteValue);
320
+ } catch {
321
+ editor.send({
322
+ type: "update value",
323
+ value: remoteValue
219
324
  });
220
325
  return;
221
326
  }
222
- patches.length && editor.send({
223
- type: "patches",
224
- patches,
225
- snapshot
226
- });
227
- }
228
- function updateValueFromRemote({
229
- editor,
230
- getRemoteValue
231
- }) {
232
- editor.send({
233
- type: "update value",
234
- value: getRemoteValue() ?? []
235
- });
327
+ if (patches.length) {
328
+ editor.send({
329
+ type: "patches",
330
+ patches,
331
+ snapshot
332
+ });
333
+ const valueAfterPatches = editor.getSnapshot().context.value;
334
+ diffValue(valueAfterPatches, remoteValue).length > 0 && editor.send({
335
+ type: "update value",
336
+ value: remoteValue
337
+ });
338
+ }
236
339
  }
237
340
  const listenToEditor = fromCallback(({
238
341
  sendBack,
@@ -277,9 +380,9 @@ const listenToEditor = fromCallback(({
277
380
  "send initial value": ({
278
381
  context
279
382
  }) => {
280
- updateValueFromRemote({
281
- editor: context.editor,
282
- getRemoteValue: context.getRemoteValue
383
+ context.editor.send({
384
+ type: "update value",
385
+ value: context.getRemoteValue() ?? []
283
386
  });
284
387
  },
285
388
  "push to remote": () => {
@@ -307,10 +410,13 @@ const listenToEditor = fromCallback(({
307
410
  context,
308
411
  event
309
412
  }) => {
310
- event.type === "remote patches received" && event.patches.length !== 0 && context.editor.send({
413
+ if (event.type !== "remote patches received")
414
+ return;
415
+ const snapshot = context.editor.getSnapshot().context.value, remoteValue = context.getRemoteValue(), patches = (remoteValue ? toEngineSafePatches(event.patches, remoteValue) : event.patches).filter((patch) => canApplyToValue(patch, snapshot));
416
+ patches.length !== 0 && context.editor.send({
311
417
  type: "patches",
312
- patches: event.patches,
313
- snapshot: context.editor.getSnapshot().context.value
418
+ patches,
419
+ snapshot
314
420
  });
315
421
  }
316
422
  },
@@ -352,13 +458,11 @@ const listenToEditor = fromCallback(({
352
458
  onRemotePatches: context.onRemotePatches
353
459
  })
354
460
  }],
355
- // operational patches from other clients apply immediately in every state;
356
- // the editor merges them with any in-flight local changes
357
- on: {
358
- "remote patches received": {
359
- actions: ["apply remote patches"]
360
- }
361
- },
461
+ // Operational patches from other clients apply immediately in every
462
+ // state; the editor merges them with any in-flight local changes.
463
+ // Application is best-effort, so each state also arranges a follow-up
464
+ // whole-value repair: immediately (deferred a microtask) when no local
465
+ // edits are in flight, or after the next mutation flush when they are.
362
466
  initial: "idle",
363
467
  states: {
364
468
  idle: {
@@ -368,6 +472,9 @@ const listenToEditor = fromCallback(({
368
472
  },
369
473
  "remote value changed": {
370
474
  actions: ["apply sync"]
475
+ },
476
+ "remote patches received": {
477
+ actions: ["apply remote patches", "defer then apply sync"]
371
478
  }
372
479
  }
373
480
  },
@@ -380,6 +487,10 @@ const listenToEditor = fromCallback(({
380
487
  },
381
488
  "remote value changed": {
382
489
  target: "pending sync"
490
+ },
491
+ "remote patches received": {
492
+ target: "pending sync",
493
+ actions: ["apply remote patches"]
383
494
  }
384
495
  }
385
496
  },
@@ -390,6 +501,9 @@ const listenToEditor = fromCallback(({
390
501
  },
391
502
  "remote value changed": {
392
503
  target: "idle"
504
+ },
505
+ "remote patches received": {
506
+ actions: ["apply remote patches", "defer then apply sync"]
393
507
  }
394
508
  }
395
509
  },
@@ -400,7 +514,10 @@ const listenToEditor = fromCallback(({
400
514
  target: "pushing to remote",
401
515
  actions: ["push to remote", "defer then apply sync"]
402
516
  },
403
- "remote value changed": {}
517
+ "remote value changed": {},
518
+ "remote patches received": {
519
+ actions: ["apply remote patches"]
520
+ }
404
521
  }
405
522
  }
406
523
  }
@@ -479,7 +596,7 @@ function ValueSyncPlugin(props) {
479
596
  if (event.type === "mutation flushed") {
480
597
  if (pushPatches && event.patches.length > 0)
481
598
  try {
482
- pushPatches(event.patches);
599
+ pushPatches(toMergeableMarkDefsPatches(event.patches, context.getRemoteValue));
483
600
  return;
484
601
  } catch {
485
602
  }
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\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\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 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 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 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 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 '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 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 // Operational patches from other clients apply immediately in every\n // state; the editor merges them with any in-flight local changes.\n // Application is best-effort, so each state also arranges a follow-up\n // whole-value repair: immediately (deferred a microtask) when no local\n // edits are in flight, or after the next mutation flush when they are.\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 'remote patches received': {\n actions: ['apply remote patches', 'defer then 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 '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 'remote value changed': {\n target: 'idle',\n },\n 'remote patches received': {\n actions: ['apply remote patches', 'defer then apply sync'],\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 '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 pushPatches(\n toMergeableMarkDefsPatches(\n event.patches,\n context.getRemoteValue,\n ),\n )\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":["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","applySync","editor","getRemoteValue","remoteValue","snapshot","getSnapshot","context","diffValue","send","valueAfterPatches","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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/plugin-sdk-value",
3
- "version": "7.0.36-crx.0",
3
+ "version": "7.1.0",
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,16 +59,16 @@
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.8-crx.0",
62
- "@portabletext/patches": "^2.0.5",
62
+ "@portabletext/editor": "^7.10.8",
63
63
  "@portabletext/schema": "^2.2.3",
64
+ "@portabletext/patches": "^2.0.5",
64
65
  "@portabletext/test": "^1.0.4"
65
66
  },
66
67
  "peerDependencies": {
67
68
  "@sanity/sdk-react": "^2.1.2",
68
69
  "react": "^19.2",
69
70
  "react-dom": "^19.2",
70
- "@portabletext/editor": "^7.10.8-crx.0"
71
+ "@portabletext/editor": "^7.10.8"
71
72
  },
72
73
  "engines": {
73
74
  "node": ">=20.19 <22 || >=22.12"