@portabletext/plugin-sdk-value 7.1.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 CHANGED
@@ -306,6 +306,16 @@ function scopeRemotePatches(patches, fieldPath) {
306
306
  }
307
307
  return scoped;
308
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
+ }
309
319
  function applySync({
310
320
  editor,
311
321
  getRemoteValue
@@ -314,6 +324,13 @@ function applySync({
314
324
  if (!remoteValue)
315
325
  return;
316
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
+ }
317
334
  let patches;
318
335
  try {
319
336
  patches = toEngineSafePatches(convertPatches(diffValue(snapshot, remoteValue)), remoteValue);
@@ -325,16 +342,21 @@ function applySync({
325
342
  return;
326
343
  }
327
344
  if (patches.length) {
328
- editor.send({
345
+ syncDebug("applySync:repair-patches", () => ({
346
+ patches
347
+ })), editor.send({
329
348
  type: "patches",
330
349
  patches,
331
350
  snapshot
332
351
  });
333
352
  const valueAfterPatches = editor.getSnapshot().context.value;
334
- diffValue(valueAfterPatches, remoteValue).length > 0 && editor.send({
353
+ diffValue(valueAfterPatches, remoteValue).length > 0 && (syncDebug("applySync:escalate-update-value", () => ({
354
+ editorText: debugTextOf(valueAfterPatches),
355
+ remoteText: debugTextOf(remoteValue)
356
+ })), editor.send({
335
357
  type: "update value",
336
358
  value: remoteValue
337
- });
359
+ }));
338
360
  }
339
361
  }
340
362
  const listenToEditor = fromCallback(({
@@ -346,7 +368,10 @@ const listenToEditor = fromCallback(({
346
368
  type: "patch emitted"
347
369
  });
348
370
  }), mutationSubscription = input.editor.on("mutation", (event) => {
349
- sendBack({
371
+ syncDebug("event:mutation-flushed", () => ({
372
+ flushText: debugTextOf(event.value),
373
+ snapshotText: debugTextOf(input.editor.getSnapshot().context.value)
374
+ })), sendBack({
350
375
  type: "mutation flushed",
351
376
  value: event.value,
352
377
  patches: event.patches
@@ -370,7 +395,7 @@ const listenToEditor = fromCallback(({
370
395
  type: "remote patches received",
371
396
  patches
372
397
  });
373
- })), valueSyncMachine = setup({
398
+ })), QUIESCENT_REPAIR_DELAY = 500, valueSyncMachine = setup({
374
399
  types: {
375
400
  context: {},
376
401
  input: {},
@@ -396,22 +421,15 @@ const listenToEditor = fromCallback(({
396
421
  getRemoteValue: context.getRemoteValue
397
422
  });
398
423
  },
399
- "defer then apply sync": ({
400
- context
401
- }) => {
402
- queueMicrotask(() => {
403
- applySync({
404
- editor: context.editor,
405
- getRemoteValue: context.getRemoteValue
406
- });
407
- });
408
- },
409
424
  "apply remote patches": ({
410
425
  context,
411
426
  event
412
427
  }) => {
413
428
  if (event.type !== "remote patches received")
414
429
  return;
430
+ syncDebug("apply-remote-patches", () => ({
431
+ patches: event.patches
432
+ }));
415
433
  const snapshot = context.editor.getSnapshot().context.value, remoteValue = context.getRemoteValue(), patches = (remoteValue ? toEngineSafePatches(event.patches, remoteValue) : event.patches).filter((patch) => canApplyToValue(patch, snapshot));
416
434
  patches.length !== 0 && context.editor.send({
417
435
  type: "patches",
@@ -458,23 +476,50 @@ const listenToEditor = fromCallback(({
458
476
  onRemotePatches: context.onRemotePatches
459
477
  })
460
478
  }],
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.
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.
466
493
  initial: "idle",
467
494
  states: {
468
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
+ },
469
505
  on: {
470
506
  "patch emitted": {
471
507
  target: "local write"
472
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
+ },
473
515
  "remote value changed": {
474
516
  actions: ["apply sync"]
475
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.
476
521
  "remote patches received": {
477
- actions: ["apply remote patches", "defer then apply sync"]
522
+ actions: ["apply remote patches"]
478
523
  }
479
524
  }
480
525
  },
@@ -499,11 +544,19 @@ const listenToEditor = fromCallback(({
499
544
  "patch emitted": {
500
545
  target: "local write"
501
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.
502
555
  "remote value changed": {
503
556
  target: "idle"
504
557
  },
505
558
  "remote patches received": {
506
- actions: ["apply remote patches", "defer then apply sync"]
559
+ actions: ["apply remote patches"]
507
560
  }
508
561
  }
509
562
  },
@@ -512,7 +565,7 @@ const listenToEditor = fromCallback(({
512
565
  "patch emitted": {},
513
566
  "mutation flushed": {
514
567
  target: "pushing to remote",
515
- actions: ["push to remote", "defer then apply sync"]
568
+ actions: ["push to remote"]
516
569
  },
517
570
  "remote value changed": {},
518
571
  "remote patches received": {
@@ -596,11 +649,16 @@ function ValueSyncPlugin(props) {
596
649
  if (event.type === "mutation flushed") {
597
650
  if (pushPatches && event.patches.length > 0)
598
651
  try {
599
- pushPatches(toMergeableMarkDefsPatches(event.patches, context.getRemoteValue));
652
+ const mergeable = toMergeableMarkDefsPatches(event.patches, context.getRemoteValue);
653
+ syncDebug("push-patches", () => ({
654
+ patches: mergeable
655
+ })), pushPatches(mergeable);
600
656
  return;
601
657
  } catch {
602
658
  }
603
- pushValue(event.value ?? context.editor.getSnapshot().context.value);
659
+ syncDebug("push-whole-value", () => ({
660
+ text: debugTextOf(event.value ?? context.editor.getSnapshot().context.value)
661
+ })), pushValue(event.value ?? context.editor.getSnapshot().context.value);
604
662
  }
605
663
  }
606
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\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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"}
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.1.0",
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",
@@ -59,16 +59,16 @@
59
59
  "typescript-eslint": "^8.62.0",
60
60
  "vitest": "^4.1.10",
61
61
  "vitest-browser-react": "^2.2.0",
62
- "@portabletext/editor": "^7.10.8",
63
- "@portabletext/schema": "^2.2.3",
62
+ "@portabletext/editor": "^7.10.9",
64
63
  "@portabletext/patches": "^2.0.5",
64
+ "@portabletext/schema": "^2.2.3",
65
65
  "@portabletext/test": "^1.0.4"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "@sanity/sdk-react": "^2.1.2",
69
69
  "react": "^19.2",
70
70
  "react-dom": "^19.2",
71
- "@portabletext/editor": "^7.10.8"
71
+ "@portabletext/editor": "^7.10.9"
72
72
  },
73
73
  "engines": {
74
74
  "node": ">=20.19 <22 || >=22.12"