@sanity/agent-mutations 0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/buildPatchTransaction.ts","../src/convertArrayIndices.ts","../src/filterInvalidArrayItems.ts","../src/generateKey.ts","../src/keyMapping.ts","../src/normalizeInternationalizedArrays.ts","../src/normalizeReferences.ts","../src/normalizePatchOperations.ts","../src/portableTextCompat.ts","../src/prepareOperations.ts","../src/validatePatchOperations.ts"],"sourcesContent":["/**\n * Builds a Sanity transaction from normalized patch operations.\n *\n * Array context grouping helpers for patch operations\n *\n * Sanity's patch API has these constraints:\n * 1. SET operations: Can modify multiple array items in ONE request\n * 2. APPEND operations: Only ONE insertion point per array path per request\n *\n * This means we need to group operations strategically:\n * - All SET and UNSET operations can go together (even if targeting different array items)\n * - APPEND operations must be separated by array path (one append per array per request)\n */\n\nimport type { InsertOperation } from '@sanity/agent-schema'\nimport type { SanityClient, Transaction } from '@sanity/client'\n\n/** Patch operations structure */\ninterface PatchOperations {\n set?: Array<{ path: string; value?: unknown }>\n unset?: string[]\n append?: Array<{ path: string; items: unknown[] }>\n insertBefore?: InsertOperation[]\n insertAfter?: InsertOperation[]\n}\n\ninterface PatchGroup {\n context: string\n operations: {\n set: Array<{ path: string; value?: unknown }>\n unset: string[]\n append: Array<{ path: string; items: unknown[] }>\n insertBefore: InsertOperation[]\n insertAfter: InsertOperation[]\n }\n}\n\ninterface BuildTransactionOptions {\n client: SanityClient\n documentId: string\n operations: PatchOperations\n setIfMissing: Record<string, unknown>\n}\n\n/**\n * Extract the array path (without _key selector) from a field path.\n * This identifies which array the operation targets, regardless of which item.\n *\n * @param path - A field path that may contain array selectors\n * @returns The array path (e.g., \"content\" or \"content.items\"), or the full path if no arrays\n *\n * @example\n * extractArrayPath(\"content[_key=='abc'].title\") // Returns: \"content\"\n * extractArrayPath(\"content[_key=='abc'].items[_key=='xyz'].name\") // Returns: \"content.items\"\n * extractArrayPath(\"content\") // Returns: \"content\"\n */\nfunction extractArrayPath(path: string): string {\n const arrayFields: string[] = []\n const currentPath = path\n let offset = 0\n\n while (offset < currentPath.length) {\n // Find the next array selector [_key==...] (supports both single and double quotes)\n const selectorMatch = currentPath.slice(offset).match(/^([^.[]+)(\\[_key==[\"'][^\"']+[\"']\\])/)\n\n if (selectorMatch) {\n arrayFields.push(selectorMatch[1])\n offset += selectorMatch[0].length\n\n // Skip the dot after the selector if present\n if (currentPath[offset] === '.') {\n offset++\n }\n } else {\n // No more array selectors - check if there's a trailing field name\n const remainingMatch = currentPath.slice(offset).match(/^([^.[]+)/)\n if (remainingMatch && arrayFields.length > 0) {\n arrayFields.push(remainingMatch[1])\n }\n break\n }\n }\n\n if (arrayFields.length > 0) {\n return arrayFields.join('.')\n }\n\n // No array selectors found - extract just the first field name\n const firstFieldMatch = path.match(/^([^.[]+)/)\n return firstFieldMatch ? firstFieldMatch[1] : path\n}\n\n/**\n * Group operations by Sanity's actual API constraints for optimal performance.\n *\n * STRATEGY:\n * - Group 1: ALL SET, UNSET, insertBefore, and insertAfter operations\n * (can be executed in one request, order handled by buildPatchTransaction)\n * - Groups 2+: One group per array path for APPEND operations (one append per array per request)\n */\nfunction groupOperationsByArrayContext(params: PatchOperations): PatchGroup[] {\n const groups: PatchGroup[] = []\n\n // GROUP 1: All SET, UNSET, insertBefore, and insertAfter operations go together\n const hasMainOperations =\n (params.set && params.set.length > 0) ||\n (params.unset && params.unset.length > 0) ||\n (params.insertBefore && params.insertBefore.length > 0) ||\n (params.insertAfter && params.insertAfter.length > 0)\n\n if (hasMainOperations) {\n groups.push({\n context: 'main',\n operations: {\n set: params.set || [],\n unset: params.unset || [],\n append: [],\n insertBefore: params.insertBefore || [],\n insertAfter: params.insertAfter || [],\n },\n })\n }\n\n // GROUPS 2+: One group per array path for APPEND operations\n if (params.append && params.append.length > 0) {\n const appendsByArrayPath = new Map<string, Array<{ path: string; items: unknown[] }>>()\n\n for (const appendOp of params.append) {\n const arrayPath = extractArrayPath(appendOp.path)\n\n if (!appendsByArrayPath.has(arrayPath)) {\n appendsByArrayPath.set(arrayPath, [])\n }\n appendsByArrayPath.get(arrayPath)!.push(appendOp)\n }\n\n // Create one group per array path\n for (const [arrayPath, appendOps] of appendsByArrayPath.entries()) {\n if (appendOps.length > 1) {\n // Multiple appends to same array - split into separate groups\n for (let i = 0; i < appendOps.length; i++) {\n groups.push({\n context: `append:${arrayPath}:${i}`,\n operations: {\n set: [],\n unset: [],\n append: [appendOps[i]],\n insertBefore: [],\n insertAfter: [],\n },\n })\n }\n } else {\n groups.push({\n context: `append:${arrayPath}`,\n operations: {\n set: [],\n unset: [],\n append: appendOps,\n insertBefore: [],\n insertAfter: [],\n },\n })\n }\n }\n }\n\n return groups\n}\n\n/**\n * Builds a Sanity transaction from patch operations and setIfMissing patches.\n *\n * The order of operations follows Sanity's recommended sequence:\n * 1. setIfMissing - ensure parent paths exist\n * 2. insertBefore/insertAfter - array shape changes (native insert semantics)\n * 3. set - replace values at paths\n * 4. unset - remove values at paths\n * 5. append - insert items after the specified path (using insert: { after })\n *\n * This order ensures that:\n * - Arrays exist before inserting into them\n * - Insert operations don't conflict with set operations on the same array\n *\n * @param options - The transaction building options\n * @returns A Sanity transaction ready to be committed\n */\nexport function buildPatchTransaction(options: BuildTransactionOptions): Transaction {\n const { client, documentId, operations, setIfMissing } = options\n const transaction = client.transaction()\n\n // Group operations by API constraints\n const groups = groupOperationsByArrayContext(operations)\n\n // 1. setIfMissing first - ensure parent paths exist before setting nested values\n for (const [path, value] of Object.entries(setIfMissing)) {\n transaction.patch(documentId, { setIfMissing: { [path]: value } })\n }\n\n // 2. Process each group's operations\n for (const group of groups) {\n // insertBefore operations - use native insert: { before } semantics\n // MUST run before set operations to avoid conflicts\n for (const op of group.operations.insertBefore) {\n const path = `${op.arrayPath}[_key==\"${op.key}\"]`\n transaction.patch(documentId, { insert: { before: path, items: op.items } })\n }\n\n // insertAfter operations - use native insert: { after } semantics\n // MUST run before set operations to avoid conflicts\n for (const op of group.operations.insertAfter) {\n const path = `${op.arrayPath}[_key==\"${op.key}\"]`\n transaction.patch(documentId, { insert: { after: path, items: op.items } })\n }\n\n // set operations\n for (const op of group.operations.set) {\n if (op.value !== undefined) {\n transaction.patch(documentId, { set: { [op.path]: op.value } })\n }\n }\n\n // unset operations\n for (const path of group.operations.unset) {\n transaction.patch(documentId, { unset: [path] })\n }\n\n // append operations - use insert: { after } for reliable ordering\n for (const op of group.operations.append) {\n transaction.patch(documentId, { insert: { after: op.path, items: op.items } })\n }\n }\n\n return transaction\n}\n","/**\n * Array index converter - converts numeric array indices to proper format\n * - Object arrays: [0] → [_key==\"actualKey\"]\n * - Primitive arrays: arr[0] = value → arr = [value, item2, ...]\n */\n\nimport type { ManifestField, ManifestSchemaType } from '@sanity/agent-schema'\n\n/**\n * Primitive types for array item checking.\n * Does not include 'block' or 'reference' as those are object-like.\n */\nconst PRIMITIVE_TYPES = [\n 'string',\n 'number',\n 'boolean',\n 'date',\n 'datetime',\n 'text',\n 'url',\n 'email',\n 'slug',\n]\n\n/**\n * Check if an array field contains only primitive types\n */\nexport function isPrimitiveArray(field: ManifestField | undefined): boolean {\n if (!field || field.type !== 'array' || !field.of || field.of.length === 0) {\n return false\n }\n\n return field.of.every((item) => {\n const itemType = item.type || (typeof item === 'string' ? item : '')\n if (!itemType || typeof itemType !== 'string') return false\n return PRIMITIVE_TYPES.includes(itemType)\n })\n}\n\n/**\n * Check if a path contains numeric array index notation like [0], [1], etc.\n */\nexport function hasNumericIndex(path: string): boolean {\n return /\\[\\d+\\]/.test(path)\n}\n\n/**\n * Parse a path with numeric index to extract components\n * Finds the FIRST numeric index in the path, even if there's _key notation before it\n * Example: \"sections[0].bodyParagraphs[1]\" → {basePath: \"sections\", index: 0, restPath: \".bodyParagraphs[1]\"}\n * Example: \"sections[_key==\"x\"].bodyParagraphs[0]\" → {basePath: \"sections[_key==\"x\"].bodyParagraphs\", index: 0, restPath: \"\"}\n */\nexport function parseArrayIndex(path: string): {\n basePath: string\n index: number\n restPath: string\n} | null {\n // Find the first numeric index in the path\n const match = path.match(/^(.*?)\\[(\\d+)\\](.*)$/)\n if (!match) return null\n\n return {\n basePath: match[1],\n index: parseInt(match[2], 10),\n restPath: match[3],\n }\n}\n\n/**\n * Navigate to an array in the document using a dot-notation path\n * Example: \"sections.bodyParagraphs\" in document {sections: {bodyParagraphs: [...]}}\n */\nexport function getArrayAtPath(document: Record<string, unknown>, path: string): unknown[] | null {\n // Split on dots that are NOT inside brackets\n const parts = path.split(/\\.(?![^[]*\\])/)\n let current: unknown = document\n\n for (const part of parts) {\n // Handle _key notation in path parts\n const keyMatch = part.match(/^([^[]+)\\[_key==\"([^\"]+)\"\\]$/)\n if (keyMatch) {\n const [, fieldName, keyValue] = keyMatch\n const currentObj = current as Record<string, unknown>\n if (!currentObj[fieldName] || !Array.isArray(currentObj[fieldName])) {\n return null\n }\n const arr = currentObj[fieldName] as Array<Record<string, unknown>>\n current = arr.find((item) => item._key === keyValue)\n if (!current) return null\n continue\n }\n\n // Regular field access\n if (!current || typeof current !== 'object') {\n return null\n }\n current = (current as Record<string, unknown>)[part]\n }\n\n return Array.isArray(current) ? current : null\n}\n\n/**\n * Get the _key value at a specific index in an object array\n * Returns null if the item doesn't have a _key or index is out of bounds\n */\nexport function getKeyAtIndex(array: unknown[], index: number): string | null {\n if (index < 0 || index >= array.length) {\n return null\n }\n\n const item = array[index]\n if (!item || typeof item !== 'object') {\n return null\n }\n\n const key = (item as Record<string, unknown>)._key\n return typeof key === 'string' ? key : null\n}\n\n/**\n * Built-in Sanity types that may not appear in allSchemas but have known structure\n */\nconst BUILT_IN_BLOCK_SCHEMA: ManifestSchemaType = {\n name: 'block',\n type: 'object',\n fields: [\n { name: 'style', type: 'string' },\n { name: 'children', type: 'array', of: [{ type: 'span' }] },\n { name: 'markDefs', type: 'array', of: [{ type: 'object' }] },\n { name: 'listItem', type: 'string' },\n { name: 'level', type: 'number' },\n ],\n}\n\nconst BUILT_IN_SPAN_SCHEMA: ManifestSchemaType = {\n name: 'span',\n type: 'object',\n fields: [\n { name: 'text', type: 'string' },\n { name: 'marks', type: 'array', of: [{ type: 'string' }] },\n ],\n}\n\nconst BUILT_IN_SCHEMAS: Record<string, ManifestSchemaType> = {\n block: BUILT_IN_BLOCK_SCHEMA,\n span: BUILT_IN_SPAN_SCHEMA,\n}\n\n/**\n * Navigate to an item in the document using a path with potential _key selectors\n * Returns the item at the path, or null if not found\n */\nfunction getDocumentItemAtPath(\n document: Record<string, unknown>,\n pathParts: string[],\n upToIndex: number,\n): unknown | null {\n let current: unknown = document\n\n for (let i = 0; i <= upToIndex; i++) {\n const part = pathParts[i]\n if (current === null || current === undefined || typeof current !== 'object') {\n return null\n }\n\n // Handle _key notation\n const keyMatch = part.match(/^([^[]+)\\[_key==\"([^\"]+)\"\\]$/)\n if (keyMatch) {\n const [, fieldName, keyValue] = keyMatch\n const arr = (current as Record<string, unknown>)[fieldName]\n if (!Array.isArray(arr)) return null\n current = arr.find((item: unknown) => {\n if (item && typeof item === 'object') {\n return (item as Record<string, unknown>)._key === keyValue\n }\n return false\n })\n continue\n }\n\n // Handle numeric index notation\n const indexMatch = part.match(/^([^[]+)\\[(\\d+)\\]$/)\n if (indexMatch) {\n const [, fieldName, indexStr] = indexMatch\n const arr = (current as Record<string, unknown>)[fieldName]\n if (!Array.isArray(arr)) return null\n const index = parseInt(indexStr, 10)\n if (index < 0 || index >= arr.length) return null\n current = arr[index]\n continue\n }\n\n // Regular field access\n current = (current as Record<string, unknown>)[part]\n }\n\n return current\n}\n\n/**\n * Get a field definition from the schema by traversing a path\n * Handles both _key notation and numeric indices in paths\n * Uses document to determine actual types for polymorphic arrays\n */\nfunction getFieldAtPath(\n path: string,\n typeSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n document?: Record<string, unknown>,\n): ManifestField | null {\n // Split on dots that are NOT inside brackets\n const parts = path.split(/\\.(?![^[]*\\])/)\n let currentSchema = typeSchema\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]\n\n // Handle _key notation or numeric index\n const keyMatch = part.match(/^([^[]+)\\[_key==\"([^\"]+)\"\\]$/)\n const indexMatch = part.match(/^([^[]+)\\[(\\d+)\\]$/)\n const fieldName = keyMatch ? keyMatch[1] : indexMatch ? indexMatch[1] : part\n\n const field = currentSchema.fields?.find((f) => f.name === fieldName)\n if (!field) return null\n\n // If this is the last part, return the field\n if (i === parts.length - 1) {\n return field\n }\n\n // Check if field.type is a custom type alias (like 'blockContent') that we need to resolve\n let resolvedField = field\n if (\n field.type !== 'array' &&\n field.type !== 'object' &&\n field.type !== 'string' &&\n field.type !== 'number' &&\n field.type !== 'boolean'\n ) {\n // Look up the type in allSchemas to see if it's a type alias\n const aliasSchema = allSchemas.find((s) => s.name === field.type)\n if (aliasSchema && aliasSchema.type === 'array' && aliasSchema.of) {\n // It's an array type alias - use its definition\n resolvedField = { ...field, type: 'array', of: aliasSchema.of }\n }\n }\n\n // Traverse deeper into arrays or objects\n if (resolvedField.type === 'array' && resolvedField.of && resolvedField.of.length > 0) {\n let itemSchema: ManifestSchemaType | undefined\n\n // FIRST: Try to get actual _type from document if we have _key or index selector\n if (document && (keyMatch || indexMatch)) {\n const docItem = getDocumentItemAtPath(document, parts, i)\n\n if (docItem && typeof docItem === 'object' && '_type' in docItem) {\n const actualType = (docItem as { _type: string })._type\n\n // First try allSchemas, then built-in schemas\n itemSchema = allSchemas.find((s) => s.name === actualType) || BUILT_IN_SCHEMAS[actualType]\n\n // If not found, check if it's an inline type defined in the 'of' array\n if (!itemSchema) {\n for (const itemTypeRef of resolvedField.of!) {\n if (typeof itemTypeRef === 'object' && itemTypeRef.name === actualType) {\n // Found an inline type definition - use it as the schema\n itemSchema = itemTypeRef as ManifestSchemaType\n break\n }\n }\n }\n }\n }\n\n // FALLBACK: If document lookup didn't work, try to find ANY matching schema from 'of' types\n if (!itemSchema) {\n for (const itemTypeRef of resolvedField.of) {\n const itemTypeName =\n typeof itemTypeRef === 'string' ? itemTypeRef : (itemTypeRef.type as string | undefined)\n if (!itemTypeName) continue\n // Try to find schema in allSchemas first, then fall back to built-in schemas\n itemSchema =\n allSchemas.find((s) => s.name === itemTypeName) || BUILT_IN_SCHEMAS[itemTypeName]\n if (itemSchema) {\n break\n }\n }\n }\n\n if (!itemSchema) {\n return null\n }\n currentSchema = itemSchema\n } else if (resolvedField.type === 'object' && resolvedField.fields) {\n // Traverse into the object's fields\n currentSchema = resolvedField as ManifestSchemaType\n } else {\n return null\n }\n }\n\n return null\n}\n\n/**\n * Collected operations for a single primitive array that will be merged\n */\ninterface PrimitiveArrayOps {\n sets: Array<{ index: number; value: unknown }>\n unsets: number[]\n}\n\n/** Insert operation structure for insertBefore/insertAfter */\ninterface InsertOperation {\n arrayPath: string\n key: string\n items: unknown[]\n}\n\n/**\n * Convert array index operations to proper format\n * - Object arrays: [0] → [_key==\"actualKey\"]\n * - Primitive arrays: All operations on same array are merged into single SET\n */\nexport function convertArrayIndexOperations(\n operations: {\n set?: Array<{ path: string; value?: unknown }>\n unset?: string[]\n append?: Array<{ path: string; items: unknown[] }>\n insertBefore?: InsertOperation[]\n insertAfter?: InsertOperation[]\n },\n typeSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n document: Record<string, unknown>,\n): {\n set?: Array<{ path: string; value?: unknown }>\n unset?: string[]\n append?: Array<{ path: string; items: unknown[] }>\n insertBefore?: InsertOperation[]\n insertAfter?: InsertOperation[]\n} {\n // Collect primitive array operations for merging (keyed by base path)\n const primitiveArrayOps = new Map<string, PrimitiveArrayOps>()\n\n // Pass-through operations that don't need merging\n const passThroughSets: Array<{ path: string; value?: unknown }> = []\n const passThroughUnsets: string[] = []\n\n // Process SET operations\n if (operations.set && operations.set.length > 0) {\n for (const op of operations.set) {\n if (!hasNumericIndex(op.path)) {\n passThroughSets.push(op)\n continue\n }\n\n const parsed = parseArrayIndex(op.path)\n if (!parsed) {\n passThroughSets.push(op)\n continue\n }\n\n const { basePath, index, restPath } = parsed\n const field = getFieldAtPath(basePath, typeSchema, allSchemas, document)\n\n if (!field) {\n throw new Error(\n `Field validation failed:\\n - ${op.path}: Field \"${basePath}\" does not exist in schema \"${typeSchema.name}\"\\n\\nPlease correct the invalid field paths and try again.`,\n )\n }\n\n if (field.type !== 'array') {\n throw new Error(\n `Field validation failed:\\n - ${op.path}: Field \"${basePath}\" is not an array (type: ${field.type})\\n\\nPlease correct the invalid field paths and try again.`,\n )\n }\n\n if (isPrimitiveArray(field)) {\n // Primitive array - collect for merging\n if (restPath) {\n throw new Error(\n `Field validation failed:\\n - ${op.path}: Cannot access nested path \"${restPath}\" on primitive array item at \"${basePath}[${index}]\"\\n\\nPrimitive arrays (strings, numbers, etc.) don't have nested fields.`,\n )\n }\n\n const group = primitiveArrayOps.get(basePath) || { sets: [], unsets: [] }\n group.sets.push({ index, value: op.value })\n primitiveArrayOps.set(basePath, group)\n } else {\n // Object array - convert to _key notation\n const converted = convertObjectArraySetOperation(\n op,\n basePath,\n index,\n restPath,\n typeSchema,\n allSchemas,\n document,\n )\n passThroughSets.push(...converted)\n }\n }\n }\n\n // Process UNSET operations\n if (operations.unset && operations.unset.length > 0) {\n for (const path of operations.unset) {\n if (!hasNumericIndex(path)) {\n passThroughUnsets.push(path)\n continue\n }\n\n const parsed = parseArrayIndex(path)\n if (!parsed) {\n passThroughUnsets.push(path)\n continue\n }\n\n const { basePath, index, restPath } = parsed\n const field = getFieldAtPath(basePath, typeSchema, allSchemas, document)\n\n if (!field) {\n throw new Error(\n `Field validation failed:\\n - ${path}: Field \"${basePath}\" does not exist in schema \"${typeSchema.name}\"\\n\\nPlease correct the invalid field paths and try again.`,\n )\n }\n\n if (field.type !== 'array') {\n throw new Error(\n `Field validation failed:\\n - ${path}: Field \"${basePath}\" is not an array (type: ${field.type})\\n\\nPlease correct the invalid field paths and try again.`,\n )\n }\n\n if (isPrimitiveArray(field)) {\n // Primitive array - collect for merging\n if (restPath) {\n throw new Error(\n `Field validation failed:\\n - ${path}: Cannot access nested path \"${restPath}\" on primitive array item at \"${basePath}[${index}]\"\\n\\nPrimitive arrays (strings, numbers, etc.) don't have nested fields.`,\n )\n }\n\n const group = primitiveArrayOps.get(basePath) || { sets: [], unsets: [] }\n group.unsets.push(index)\n primitiveArrayOps.set(basePath, group)\n } else {\n // Object array - must use _key notation\n throw new Error(\n `Unsetting object array items by index is not supported. Path: ${path}\\n\\nTo remove an item from an object array, use the unset operation with _key notation: items[_key==\"...\"]`,\n )\n }\n }\n }\n\n // Collect append operations for primitive arrays that need merging\n const appendsToMerge = new Map<string, unknown[]>()\n const passThroughAppends: Array<{ path: string; items: unknown[] }> = []\n\n if (operations.append) {\n for (const appendOp of operations.append) {\n // If this append targets a primitive array that also has set/unset operations,\n // we need to merge the append into the SET operation\n if (primitiveArrayOps.has(appendOp.path)) {\n const existingItems = appendsToMerge.get(appendOp.path) ?? []\n appendsToMerge.set(appendOp.path, [...existingItems, ...appendOp.items])\n } else {\n passThroughAppends.push(appendOp)\n }\n }\n }\n\n // Merge primitive array operations into single SET operations\n const mergedSets = mergePrimitiveArrayOperations(primitiveArrayOps, appendsToMerge, document)\n\n // Build result\n const result: typeof operations = {}\n\n const allSets = [...passThroughSets, ...mergedSets]\n if (allSets.length > 0) {\n result.set = allSets\n }\n\n if (passThroughUnsets.length > 0) {\n result.unset = passThroughUnsets\n }\n\n if (passThroughAppends.length > 0) {\n result.append = passThroughAppends\n }\n\n // Pass through insertBefore/insertAfter unchanged\n if (operations.insertBefore && operations.insertBefore.length > 0) {\n result.insertBefore = operations.insertBefore\n }\n\n if (operations.insertAfter && operations.insertAfter.length > 0) {\n result.insertAfter = operations.insertAfter\n }\n\n return result\n}\n\n/**\n * Merge all collected primitive array operations into single SET operations\n */\nfunction mergePrimitiveArrayOperations(\n primitiveArrayOps: Map<string, PrimitiveArrayOps>,\n appendsToMerge: Map<string, unknown[]>,\n document: Record<string, unknown>,\n): Array<{ path: string; value: unknown }> {\n const mergedSets: Array<{ path: string; value: unknown }> = []\n\n for (const [basePath, ops] of primitiveArrayOps) {\n const currentArray = getArrayAtPath(document, basePath)\n if (!currentArray) {\n throw new Error(\n `Field validation failed:\\n - ${basePath}: Array \"${basePath}\" not found in document or is empty\\n\\nPlease ensure the array exists before modifying items by index.`,\n )\n }\n\n // Validate all indices are in bounds\n const maxIndex = currentArray.length - 1\n for (const { index } of ops.sets) {\n if (index < 0 || index > maxIndex) {\n throw new Error(\n `Field validation failed:\\n - ${basePath}[${index}]: Index ${index} is out of bounds for array \"${basePath}\" (length: ${currentArray.length})\\n\\nPlease use a valid index between 0 and ${maxIndex}.`,\n )\n }\n }\n for (const index of ops.unsets) {\n if (index < 0 || index > maxIndex) {\n throw new Error(\n `Field validation failed:\\n - ${basePath}[${index}]: Index ${index} is out of bounds for array \"${basePath}\" (length: ${currentArray.length})\\n\\nPlease use a valid index between 0 and ${maxIndex}.`,\n )\n }\n }\n\n // Start with a copy of the current array\n const newArray = [...currentArray]\n\n // Apply SETs first (order doesn't matter for sets as they target specific indices)\n for (const { index, value } of ops.sets) {\n newArray[index] = value\n }\n\n // Apply UNSETs in descending order to avoid index shifting issues\n // Deduplicate indices first to prevent double-removal\n const uniqueUnsets = [...new Set(ops.unsets)].sort((a, b) => b - a)\n for (const index of uniqueUnsets) {\n newArray.splice(index, 1)\n }\n\n // Apply APPENDs last - add items to end of array\n const itemsToAppend = appendsToMerge.get(basePath)\n if (itemsToAppend) {\n newArray.push(...itemsToAppend)\n }\n\n mergedSets.push({ path: basePath, value: newArray })\n }\n\n return mergedSets\n}\n\n/**\n * Convert a SET operation on an object array from numeric index to _key notation\n * Called after we've already determined this is an object array (not primitive)\n */\nfunction convertObjectArraySetOperation(\n op: { path: string; value?: unknown },\n basePath: string,\n index: number,\n restPath: string,\n typeSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n document: Record<string, unknown>,\n): Array<{ path: string; value?: unknown }> {\n // Get the current array value from document\n const currentArray = getArrayAtPath(document, basePath)\n if (!currentArray) {\n throw new Error(\n `Field validation failed:\\n - ${op.path}: Array \"${basePath}\" not found in document or is empty\\n\\nPlease ensure the array exists before modifying items by index.`,\n )\n }\n\n if (index < 0 || index >= currentArray.length) {\n throw new Error(\n `Field validation failed:\\n - ${op.path}: Index ${index} is out of bounds for array \"${basePath}\" (length: ${currentArray.length})\\n\\nPlease use a valid index between 0 and ${currentArray.length - 1}.`,\n )\n }\n\n // OBJECT ARRAY: Convert [N] to [_key==\"...\"]\n const key = getKeyAtIndex(currentArray, index)\n if (!key) {\n throw new Error(\n `Field validation failed:\\n - ${op.path}: Array item at \"${basePath}[${index}]\" does not have a _key field\\n\\nObject arrays require _key fields for addressing. Please ensure all array items have _key fields.`,\n )\n }\n\n // Convert path: arr[0].nested → arr[_key==\"abc\"].nested\n const newPath = `${basePath}[_key==\"${key}\"]${restPath}`\n\n // If there's a restPath with more numeric indices, we need to recursively handle it\n if (restPath && hasNumericIndex(restPath)) {\n // Parse the next numeric index in restPath\n const nestedParsed = parseArrayIndex(newPath)\n if (nestedParsed) {\n const nestedField = getFieldAtPath(nestedParsed.basePath, typeSchema, allSchemas, document)\n if (nestedField && nestedField.type === 'array') {\n if (isPrimitiveArray(nestedField)) {\n // Nested primitive array - this case should be collected for merging\n // but since we're in the object array path, we need to handle it here\n const nestedArray = getArrayAtPath(document, nestedParsed.basePath)\n if (!nestedArray) {\n throw new Error(\n `Field validation failed:\\n - ${op.path}: Array \"${nestedParsed.basePath}\" not found in document\\n\\nPlease ensure the array exists before modifying items by index.`,\n )\n }\n const newArray = [...nestedArray]\n newArray[nestedParsed.index] = op.value\n return [{ path: nestedParsed.basePath, value: newArray }]\n } else {\n // Nested object array - recurse\n return convertObjectArraySetOperation(\n { path: newPath, value: op.value },\n nestedParsed.basePath,\n nestedParsed.index,\n nestedParsed.restPath,\n typeSchema,\n allSchemas,\n document,\n )\n }\n }\n }\n }\n\n return [\n {\n path: newPath,\n value: op.value,\n },\n ]\n}\n","/**\n * Partial array write support.\n *\n * When a patch operation contains array items that fail validation,\n * this module separates per-item errors (filterable) from structural\n * errors (not filterable). If only per-item errors exist, it filters\n * out the invalid items so the valid ones can be written. The caller\n * then throws after the write succeeds, forcing the agent to retry\n * only the missing items.\n */\n\nimport type { InsertOperation, ValidationError } from '@sanity/agent-schema'\n\ninterface SkippedItem {\n arrayPath: string\n index: number\n type: string | undefined\n reason: string\n}\n\ninterface FilterResult {\n /** Whether any errors are structural (not per-item) — if true, caller should throw all errors */\n hasStructuralErrors: boolean\n /** Items that were filtered out */\n skippedItems: SkippedItem[]\n /** Cleaned SET operations (invalid items removed from array values) */\n set?: Array<{ path: string; value?: unknown }>\n /** Cleaned APPEND operations */\n append?: Array<{ path: string; items: unknown[] }>\n /** Cleaned INSERT operations */\n insertBefore?: InsertOperation[]\n insertAfter?: InsertOperation[]\n}\n\n/**\n * Classify validation errors and filter invalid array items from operations.\n *\n * Errors with `itemIndex` and `arrayPath` are per-item — the invalid item can\n * be removed and the rest of the array written successfully.\n *\n * Errors without these fields are structural — wrong path, not an array, etc.\n * These cannot be fixed by filtering items.\n */\nexport function filterInvalidArrayItems(\n ops: {\n set?: Array<{ path: string; value?: unknown }>\n append?: Array<{ path: string; items: unknown[] }>\n insertBefore?: InsertOperation[]\n insertAfter?: InsertOperation[]\n },\n errors: ValidationError[],\n): FilterResult {\n const perItemErrors: ValidationError[] = []\n const structuralErrors: ValidationError[] = []\n\n for (const error of errors) {\n if (error.itemIndex !== undefined && error.arrayPath !== undefined) {\n perItemErrors.push(error)\n } else {\n structuralErrors.push(error)\n }\n }\n\n if (structuralErrors.length > 0) {\n return { hasStructuralErrors: true, skippedItems: [] }\n }\n\n if (perItemErrors.length === 0) {\n return { hasStructuralErrors: false, skippedItems: [] }\n }\n\n // Group invalid indices by arrayPath\n const invalidByPath = new Map<string, Set<number>>()\n for (const error of perItemErrors) {\n const existing = invalidByPath.get(error.arrayPath!) ?? new Set()\n existing.add(error.itemIndex!)\n invalidByPath.set(error.arrayPath!, existing)\n }\n\n const skippedItems: SkippedItem[] = []\n\n // Build skipped items list from the first error per (arrayPath, itemIndex)\n const seen = new Set<string>()\n for (const error of perItemErrors) {\n const key = `${error.arrayPath}:${error.itemIndex}`\n if (seen.has(key)) continue\n seen.add(key)\n skippedItems.push({\n arrayPath: error.arrayPath!,\n index: error.itemIndex!,\n type: undefined, // filled below from the actual item\n reason: error.message,\n })\n }\n\n // Filter SET operations — remove invalid items from array values\n const cleanedSet = ops.set?.map((op) => {\n const invalidIndices = invalidByPath.get(op.path)\n if (!invalidIndices || !Array.isArray(op.value)) return op\n\n // Tag skipped items with their _type from the actual value\n for (const idx of invalidIndices) {\n const item = (op.value as Array<Record<string, unknown>>)[idx]\n const skipped = skippedItems.find((s) => s.arrayPath === op.path && s.index === idx)\n if (skipped && item) {\n skipped.type = item._type as string | undefined\n }\n }\n\n const filtered = (op.value as unknown[]).filter((_, idx) => !invalidIndices.has(idx))\n return { ...op, value: filtered }\n })\n\n // Filter APPEND operations\n const cleanedAppend = ops.append?.map((op) => {\n const invalidIndices = invalidByPath.get(op.path)\n if (!invalidIndices) return op\n\n for (const idx of invalidIndices) {\n const item = op.items[idx] as Record<string, unknown> | undefined\n const skipped = skippedItems.find((s) => s.arrayPath === op.path && s.index === idx)\n if (skipped && item) {\n skipped.type = item._type as string | undefined\n }\n }\n\n const filtered = op.items.filter((_, idx) => !invalidIndices.has(idx))\n return { ...op, items: filtered }\n })\n\n // Filter INSERT operations (insertBefore and insertAfter)\n const filterInsert = (\n insertOps: InsertOperation[] | undefined,\n ): InsertOperation[] | undefined => {\n return insertOps?.map((op) => {\n const invalidIndices = invalidByPath.get(op.arrayPath)\n if (!invalidIndices) return op\n\n for (const idx of invalidIndices) {\n const item = op.items[idx] as Record<string, unknown> | undefined\n const skipped = skippedItems.find((s) => s.arrayPath === op.arrayPath && s.index === idx)\n if (skipped && item) {\n skipped.type = item._type as string | undefined\n }\n }\n\n const filtered = op.items.filter((_, idx) => !invalidIndices.has(idx))\n return { ...op, items: filtered }\n })\n }\n\n return {\n hasStructuralErrors: false,\n skippedItems,\n set: cleanedSet,\n append: cleanedAppend,\n insertBefore: filterInsert(ops.insertBefore),\n insertAfter: filterInsert(ops.insertAfter),\n }\n}\n\n/**\n * Format a partial write error message that tells the agent exactly\n * what was written and what needs to be fixed via insertAfter.\n */\nexport function formatPartialWriteError(\n skippedItems: SkippedItem[],\n totalItemsByPath: Map<string, number>,\n): string {\n const lines: string[] = []\n\n // Group skipped items by array path\n const byPath = new Map<string, SkippedItem[]>()\n for (const item of skippedItems) {\n const existing = byPath.get(item.arrayPath) ?? []\n existing.push(item)\n byPath.set(item.arrayPath, existing)\n }\n\n for (const [arrayPath, items] of byPath) {\n const total = totalItemsByPath.get(arrayPath) ?? 0\n const written = total - items.length\n const details = items\n .map((s) => `${s.type ?? 'unknown'} at index ${s.index} (${s.reason})`)\n .join('; ')\n lines.push(\n `Partial write to \"${arrayPath}\": wrote ${written}/${total} items. ` +\n `Skipped ${items.length}: ${details}.`,\n )\n }\n\n lines.push('Read the document and use insertAfter to add the missing items.')\n return lines.join('\\n')\n}\n","/**\n * Generate a random 12-character key for Sanity array items\n * Uses lowercase letters and numbers only\n */\nexport function generateKey(): string {\n const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'\n let key = ''\n for (let i = 0; i < 12; i++) {\n key += chars.charAt(Math.floor(Math.random() * chars.length))\n }\n return key\n}\n\n/**\n * Recursively add missing _key fields to all objects in arrays\n * This ensures Sanity array items have proper keys for tracking and updates\n *\n * @param value - The value to process (can be any type)\n * @param options - Optional configuration\n * @param options.ensureRootKey - If true, ensure the top-level object has a _key (for array item replacements)\n * @returns The same value with _key fields added to array items where missing\n */\nexport function addMissingKeys(value: unknown, options?: { ensureRootKey?: boolean }): unknown {\n // Handle null/undefined\n if (value === null || value === undefined) {\n return value\n }\n\n // Handle arrays - add keys to objects within arrays\n if (Array.isArray(value)) {\n return value.map((item) => {\n // If the item is an object, ensure it has a _key and recursively process it\n if (item && typeof item === 'object' && !Array.isArray(item)) {\n const obj = item as Record<string, unknown>\n\n // Recursively process all properties first\n const processedObj: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(obj)) {\n processedObj[key] = addMissingKeys(val)\n }\n\n // Add _key if missing\n if (!processedObj._key) {\n return {\n _key: generateKey(),\n ...processedObj,\n }\n }\n\n return processedObj\n }\n // For non-objects, just recursively process\n return addMissingKeys(item)\n })\n }\n\n // Handle objects - recursively process all properties\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>\n const result: Record<string, unknown> = {}\n\n for (const [key, val] of Object.entries(obj)) {\n result[key] = addMissingKeys(val)\n }\n\n // If ensureRootKey is true and the object doesn't have a _key, add one\n if (options?.ensureRootKey && !result._key) {\n return {\n _key: generateKey(),\n ...result,\n }\n }\n\n return result\n }\n\n // Primitives - return as-is\n return value\n}\n\n/**\n * Result of duplicate key regeneration\n */\ninterface RegenerateDuplicateKeysResult {\n value: unknown\n keyMapping: Map<string, string>\n duplicatesFound: number\n}\n\n/**\n * Collect all _key values and their paths from a document\n */\nfunction collectKeys(value: unknown, currentPath: string, keys: Map<string, string[]>): void {\n if (value === null || value === undefined) {\n return\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n if (item && typeof item === 'object' && !Array.isArray(item)) {\n const obj = item as Record<string, unknown>\n const itemPath = currentPath ? `${currentPath}.${index}` : `${index}`\n\n if (typeof obj._key === 'string') {\n const existing = keys.get(obj._key) || []\n existing.push(itemPath)\n keys.set(obj._key, existing)\n }\n\n // Recursively collect from nested properties\n for (const [key, val] of Object.entries(obj)) {\n if (key !== '_key') {\n collectKeys(val, `${itemPath}.${key}`, keys)\n }\n }\n } else {\n // Non-object array items\n const itemPath = currentPath ? `${currentPath}.${index}` : `${index}`\n collectKeys(item, itemPath, keys)\n }\n })\n } else if (typeof value === 'object') {\n const obj = value as Record<string, unknown>\n for (const [key, val] of Object.entries(obj)) {\n const nestedPath = currentPath ? `${currentPath}.${key}` : key\n collectKeys(val, nestedPath, keys)\n }\n }\n}\n\n/**\n * Regenerate duplicate keys in a document (second pass)\n */\nfunction regenerateDuplicatesInternal(\n value: unknown,\n currentPath: string,\n duplicateKeys: Set<string>,\n seenKeys: Set<string>,\n keyMapping: Map<string, string>,\n): unknown {\n if (value === null || value === undefined) {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map((item, index) => {\n if (item && typeof item === 'object' && !Array.isArray(item)) {\n const obj = item as Record<string, unknown>\n const itemPath = currentPath ? `${currentPath}.${index}` : `${index}`\n const oldKey = obj._key as string | undefined\n\n let newKey = oldKey\n\n // If this key is a duplicate and we've already seen it, regenerate\n if (oldKey && duplicateKeys.has(oldKey)) {\n if (seenKeys.has(oldKey)) {\n // This is a duplicate occurrence - regenerate\n newKey = generateKey()\n\n // Build key mapping for path transformation\n const oldKeyPath =\n `${itemPath.split('.').slice(0, -1).join('.')}[_key==\"${oldKey}\"]`.replace(/^\\./, '')\n const newKeyPath =\n `${itemPath.split('.').slice(0, -1).join('.')}[_key==\"${newKey}\"]`.replace(/^\\./, '')\n\n // Map index-based path to new key-based path\n keyMapping.set(itemPath, newKeyPath || `[_key==\"${newKey}\"]`)\n\n // Map old key-based path to new key-based path\n if (oldKeyPath) {\n keyMapping.set(oldKeyPath, newKeyPath || `[_key==\"${newKey}\"]`)\n }\n } else {\n // First occurrence - mark as seen but keep the key\n seenKeys.add(oldKey)\n }\n }\n\n // Recursively process nested properties\n const processedObj: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(obj)) {\n if (key !== '_key') {\n processedObj[key] = regenerateDuplicatesInternal(\n val,\n `${itemPath}.${key}`,\n duplicateKeys,\n seenKeys,\n keyMapping,\n )\n }\n }\n\n return {\n _key: newKey,\n ...processedObj,\n }\n }\n\n // Non-object items\n const itemPath = currentPath ? `${currentPath}.${index}` : `${index}`\n return regenerateDuplicatesInternal(item, itemPath, duplicateKeys, seenKeys, keyMapping)\n })\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>\n const result: Record<string, unknown> = {}\n\n for (const [key, val] of Object.entries(obj)) {\n const nestedPath = currentPath ? `${currentPath}.${key}` : key\n result[key] = regenerateDuplicatesInternal(\n val,\n nestedPath,\n duplicateKeys,\n seenKeys,\n keyMapping,\n )\n }\n\n return result\n }\n\n return value\n}\n\n/**\n * Regenerate only duplicate _key fields in a document\n * This preserves unique keys and only regenerates keys that appear more than once.\n * The first occurrence of a duplicate key is kept, subsequent occurrences are regenerated.\n *\n * @param value - The value to process (can be any type)\n * @returns Object containing the transformed value, key mapping, and count of duplicates found\n */\nexport function regenerateDuplicateKeys(value: unknown): RegenerateDuplicateKeysResult {\n // First pass: collect all keys and their paths\n const keyPaths = new Map<string, string[]>()\n collectKeys(value, '', keyPaths)\n\n // Find duplicate keys (keys that appear more than once)\n const duplicateKeys = new Set<string>()\n let duplicatesFound = 0\n for (const [key, paths] of keyPaths) {\n if (paths.length > 1) {\n duplicateKeys.add(key)\n duplicatesFound += paths.length - 1 // Count extra occurrences\n }\n }\n\n // If no duplicates, return as-is\n if (duplicateKeys.size === 0) {\n return {\n value,\n keyMapping: new Map(),\n duplicatesFound: 0,\n }\n }\n\n // Second pass: regenerate duplicate keys\n const keyMapping = new Map<string, string>()\n const seenKeys = new Set<string>()\n const transformedValue = regenerateDuplicatesInternal(\n value,\n '',\n duplicateKeys,\n seenKeys,\n keyMapping,\n )\n\n return {\n value: transformedValue,\n keyMapping,\n duplicatesFound,\n }\n}\n","/**\n * Key mapping utilities for mutation tools.\n * Handles transformation of paths and keys after key regeneration.\n */\n\n/**\n * Normalize _key selector quote style from single quotes to double quotes.\n * This ensures consistent path format across the codebase.\n *\n * @param path - The path to normalize\n * @returns The path with single quotes converted to double quotes in _key selectors\n *\n * @example\n * normalizeKeyQuotes(\"body[_key=='abc']\") // \"body[_key=\\\"abc\\\"]\"\n * normalizeKeyQuotes(\"body[_key==\\\"abc\\\"]\") // \"body[_key=\\\"abc\\\"]\" (unchanged)\n */\nexport function normalizeKeyQuotes(path: string): string {\n // Replace [_key=='value'] with [_key==\"value\"]\n return path.replace(/\\[_key=='([^']+)'\\]/g, '[_key==\"$1\"]')\n}\n\n/**\n * Normalize array bracket notation to dot notation for consistent matching.\n * Converts [0], [1], etc. to .0, .1, etc.\n * Does NOT convert [_key==\"...\"] bracket notation.\n *\n * @param path - The path to normalize\n * @returns The path with array indices normalized to dot notation\n *\n * @example\n * normalizeArrayIndices(\"content[0].media[1]\") // \"content.0.media.1\"\n * normalizeArrayIndices(\"content[_key==\"abc\"]\") // \"content[_key==\"abc\"]\" (unchanged)\n */\nfunction normalizeArrayIndices(path: string): string {\n // Replace [0], [1], [2], etc. with .0, .1, .2, etc.\n // But do NOT replace [_key==\"...\"] bracket notation\n return path.replace(/\\[(\\d+)\\]/g, '.$1')\n}\n\n/**\n * Apply a single transformation pass to a path using key mapping.\n * Finds the longest matching prefix and replaces it.\n *\n * @param path - The path to transform\n * @param keyMapping - Map of old paths to new paths\n * @returns Object with the transformed path and whether a transformation occurred\n */\nfunction applySingleTransformation(\n path: string,\n keyMapping: Map<string, string>,\n): { path: string; transformed: boolean } {\n // Try exact match first\n if (keyMapping.has(path)) {\n return { path: keyMapping.get(path)!, transformed: true }\n }\n\n // Try prefix matching - find the longest matching prefix\n let longestMatch = ''\n let longestMatchValue = ''\n\n for (const [oldPath, newPath] of keyMapping.entries()) {\n // Check if the path starts with this mapping key\n // We need to ensure we match complete path segments, not partial ones\n if (path === oldPath || path.startsWith(`${oldPath}.`) || path.startsWith(`${oldPath}[`)) {\n if (oldPath.length > longestMatch.length) {\n longestMatch = oldPath\n longestMatchValue = newPath\n }\n }\n }\n\n // If we found a prefix match, replace it\n if (longestMatch) {\n // Replace the prefix and keep the rest of the path\n const remainder = path.slice(longestMatch.length)\n return { path: longestMatchValue + remainder, transformed: true }\n }\n\n // No match found\n return { path, transformed: false }\n}\n\n/**\n * Transform a path string by replacing old key references with new ones based on the key mapping.\n * This is used after key regeneration to ensure paths reference the correct regenerated keys.\n *\n * The function applies transformations iteratively until no more matches are found.\n * This handles cases where multiple nested keys need to be replaced.\n *\n * The function tries multiple matching strategies per iteration:\n * 1. Direct exact match of the full path\n * 2. Longest prefix match - replaces the longest matching prefix with its mapped value\n *\n * @param path - The path string to transform (e.g., \"content[_key=='oldKey'].image\" or \"content.0.image\")\n * @param keyMapping - Map of old paths to new paths from key regeneration\n * @returns The transformed path with updated key references\n *\n * @example\n * const keyMapping = new Map([\n * [\"content.0\", \"content[_key=='abc123']\"],\n * [\"content[_key=='oldKey']\", \"content[_key=='abc123']\"]\n * ])\n * transformPathWithKeyMapping(\"content.0.image\", keyMapping)\n * // Returns: \"content[_key=='abc123'].image\"\n *\n * transformPathWithKeyMapping(\"content[_key=='oldKey'].image\", keyMapping)\n * // Returns: \"content[_key=='abc123'].image\"\n *\n * // Multiple nested transformations:\n * transformPathWithKeyMapping(\"content[_key=='old1'].media[_key=='old2'].asset\", keyMapping)\n * // Applies transformations iteratively until fully transformed\n */\nexport function transformPathWithKeyMapping(\n path: string,\n keyMapping?: Map<string, string>,\n): string {\n // If no mapping provided, return path as-is\n if (!keyMapping || keyMapping.size === 0) {\n return path\n }\n\n // Normalize array bracket notation [0] to dot notation .0 for consistent matching\n let currentPath = normalizeArrayIndices(path)\n let iterations = 0\n const maxIterations = 10 // Safety limit to prevent infinite loops\n\n // Keep applying transformations until the path stops changing or max iterations reached\n while (iterations < maxIterations) {\n const result = applySingleTransformation(currentPath, keyMapping)\n\n // If no transformation occurred, we're done\n if (!result.transformed) {\n break\n }\n\n currentPath = result.path\n iterations++\n }\n\n return currentPath\n}\n\n/**\n * Map a single key through a key mapping.\n * Used for transforming anchor keys in insertBefore/insertAfter operations.\n *\n * @param key - The key to map\n * @param keyMapping - The key mapping (Record<string, string> or unknown)\n * @returns The mapped key, or the original key if no mapping exists\n */\nexport function mapKeyThroughKeyMapping(key: string, keyMapping: unknown): string {\n if (!keyMapping || typeof keyMapping !== 'object') return key\n const map = keyMapping as Record<string, string>\n return map[key] ?? key\n}\n","/**\n * Normalizes internationalized array items in patch operations to match the\n * schema's expected format (v4 or v5).\n *\n * - v4: `_key` is the language code (e.g. `{ _key: \"en\", value: \"hello\" }`)\n * - v5: `_key` is a random ID, language in `language` field\n * (e.g. `{ _key: \"abc123\", language: \"en\", value: \"hello\" }`)\n *\n * LLMs may generate v4-style items for v5 schemas (or vice versa) because\n * they don't know which plugin version the project uses. This function\n * detects the mismatch and normalizes the items to match the schema.\n */\n\nimport type { ManifestSchemaType } from '@sanity/agent-schema'\nimport {\n isInternationalizedArrayField,\n isV5InternationalizedArray,\n} from '@sanity/agent-schema/validation'\nimport { generateKey } from './generateKey'\n\n/** Patch operations structure (matches prepareOperations) */\ninterface PatchOperations {\n set?: Array<{ path: string; value?: unknown }>\n unset?: string[]\n append?: Array<{ path: string; items: unknown[] }>\n insertBefore?: Array<{ arrayPath: string; key: string; items: unknown[] }>\n insertAfter?: Array<{ arrayPath: string; key: string; items: unknown[] }>\n}\n\ninterface NormalizeOptions {\n typeSchema: ManifestSchemaType\n allSchemas: ManifestSchemaType[]\n}\n\ntype ItemObj = Record<string, unknown>\n\n/**\n * Resolve the field schema for a top-level field path on a document type.\n * Returns undefined if the field is not found.\n */\nfunction resolveTopLevelFieldSchema(\n path: string,\n typeSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): ManifestSchemaType | undefined {\n // Extract the top-level field name (before any dots or brackets)\n const topField = path.split('.')[0].split('[')[0]\n const field = typeSchema.fields?.find((f) => f.name === topField)\n if (!field) return undefined\n\n // If the field type is a named type, resolve it from allSchemas\n const resolved = allSchemas.find((s) => s.name === field.type)\n return resolved ?? (field as unknown as ManifestSchemaType)\n}\n\n/**\n * Resolve the configured language IDs for an internationalized array field.\n */\nfunction resolveLanguageIds(\n fieldSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): Set<string> {\n const options = fieldSchema.options as Record<string, unknown> | undefined\n let languages = options?.languages as Array<{ id: string }> | undefined\n\n if (!languages?.length) {\n const resolved = allSchemas.find((s) => s.name === fieldSchema.type)\n const resolvedOptions = resolved?.options as Record<string, unknown> | undefined\n languages = resolvedOptions?.languages as Array<{ id: string }> | undefined\n }\n\n if (!languages?.length) return new Set()\n return new Set(languages.map((l) => l.id))\n}\n\n/**\n * Check if an item looks like v4 format: _key is a known language ID and\n * there is no `language` field.\n */\nfunction isV4PatternItem(item: ItemObj, languageIds: Set<string>): boolean {\n const key = item._key\n return typeof key === 'string' && languageIds.has(key) && !('language' in item)\n}\n\n/**\n * Check if an item looks like v5 format: has a `language` field.\n */\nfunction isV5PatternItem(item: ItemObj): boolean {\n return 'language' in item && typeof item.language === 'string'\n}\n\n/**\n * Normalize a single array item from v4 → v5 format.\n * Moves the language code from _key to the language field, regenerates _key.\n */\nfunction normalizeItemV4ToV5(item: ItemObj): ItemObj {\n const languageCode = item._key as string\n return { ...item, _key: generateKey(), language: languageCode }\n}\n\n/**\n * Normalize a single array item from v5 → v4 format.\n * Moves the language code from language to _key, removes the language field.\n */\nfunction normalizeItemV5ToV4(item: ItemObj): ItemObj {\n const { language: languageCode, ...rest } = item\n return { ...rest, _key: languageCode as string }\n}\n\n/**\n * Normalize items in an array value for an internationalized array field.\n */\nfunction normalizeItems(\n items: unknown[],\n fieldSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): unknown[] {\n const isV5 = isV5InternationalizedArray(fieldSchema, allSchemas)\n const languageIds = resolveLanguageIds(fieldSchema, allSchemas)\n\n if (languageIds.size === 0) return items\n\n return items.map((item) => {\n if (typeof item !== 'object' || item === null || Array.isArray(item)) return item\n const obj = item as ItemObj\n\n if (isV5) {\n // Schema expects v5 — check if item is in v4 format\n if (isV4PatternItem(obj, languageIds)) {\n return normalizeItemV4ToV5(obj)\n }\n } else {\n // Schema expects v4 — check if item is in v5 format\n if (isV5PatternItem(obj)) {\n return normalizeItemV5ToV4(obj)\n }\n }\n\n return item\n })\n}\n\n/**\n * Normalize internationalized array items in patch operations to match the\n * schema's expected format (v4 or v5).\n *\n * This runs as a step in the prepareOperations pipeline, after key normalization\n * and before validation. It inspects each operation's target field: if the field\n * is an internationalized array, it checks each item and converts between v4/v5\n * format as needed.\n */\nexport function normalizeInternationalizedArrays(\n operations: PatchOperations,\n options: NormalizeOptions,\n): PatchOperations {\n const { typeSchema, allSchemas } = options\n\n return {\n set: operations.set?.map((op) => {\n const fieldSchema = resolveTopLevelFieldSchema(op.path, typeSchema, allSchemas)\n if (!fieldSchema || !isInternationalizedArrayField(fieldSchema) || !Array.isArray(op.value)) {\n return op\n }\n return { ...op, value: normalizeItems(op.value, fieldSchema, allSchemas) }\n }),\n unset: operations.unset,\n append: operations.append?.map((op) => {\n const fieldSchema = resolveTopLevelFieldSchema(op.path, typeSchema, allSchemas)\n if (!fieldSchema || !isInternationalizedArrayField(fieldSchema)) {\n return op\n }\n return {\n ...op,\n items: normalizeItems(op.items, fieldSchema, allSchemas),\n }\n }),\n insertBefore: operations.insertBefore?.map((op) => {\n const fieldSchema = resolveTopLevelFieldSchema(op.arrayPath, typeSchema, allSchemas)\n if (!fieldSchema || !isInternationalizedArrayField(fieldSchema)) {\n return op\n }\n return { ...op, items: normalizeItems(op.items, fieldSchema, allSchemas) }\n }),\n insertAfter: operations.insertAfter?.map((op) => {\n const fieldSchema = resolveTopLevelFieldSchema(op.arrayPath, typeSchema, allSchemas)\n if (!fieldSchema || !isInternationalizedArrayField(fieldSchema)) {\n return op\n }\n return { ...op, items: normalizeItems(op.items, fieldSchema, allSchemas) }\n }),\n }\n}\n","/**\n * Unified reference normalization utilities.\n *\n * This module handles all reference normalization in a single pass:\n * 1. Schema-based weak reference detection\n * 2. Draft ID (drafts.*) conversion to published IDs\n * 3. Versioned ID (versions.*) conversion to published IDs\n * 4. Adding _weak: true and _strengthenOnPublish metadata\n * 5. Batch validation with error collection\n *\n * Replaces the previous three-function pipeline with a single unified approach.\n */\n\nimport type { ManifestSchemaType, ValidationError } from '@sanity/agent-schema'\nimport { resolveFieldSchema } from '@sanity/agent-schema'\nimport { createError } from '@sanity/agent-schema/validation'\nimport type { SanityClient } from '@sanity/client'\nimport {\n type DocumentId,\n getPublishedId,\n isDraftId,\n isPublishedId,\n isVersionId,\n} from '@sanity/id-utils'\nimport type { SanityDocumentLike } from '@sanity/types'\n\nexport interface SchemaFieldDefinition {\n type?: string\n name?: string\n of?: Array<{ type?: string; name?: string; to?: Array<{ type: string }>; weak?: boolean }>\n to?: Array<{ type: string }>\n weak?: boolean\n}\n\ninterface ReferenceObject {\n _type: string // Can be 'reference' or a named reference type like 'industry'\n _ref: string\n _weak?: boolean\n _strengthenOnPublish?: {\n type: string\n template: {\n id: string\n }\n }\n [key: string]: unknown\n}\n\n/**\n * Checks if a value is a reference object.\n * References can have _type: 'reference' OR a named type like 'industry'\n * (for arrays with named reference schemas: {type: \"reference\", name: \"industry\"}).\n * The key identifier is the presence of _ref field.\n */\nfunction isReferenceObject(value: unknown): value is ReferenceObject {\n return (\n value !== null &&\n typeof value === 'object' &&\n '_ref' in value &&\n typeof value._ref === 'string' &&\n '_type' in value &&\n typeof value._type === 'string'\n )\n}\n\n/**\n * Gets the reference field definition from schema, handling nested paths.\n * Uses resolveFieldSchema which has special handling for portable text\n * block.markDefs and other complex nested structures.\n */\nexport function getReferenceFieldDefinition(\n fieldPath: string,\n typeSchema: ManifestSchemaType,\n fullSchema: ManifestSchemaType[],\n): SchemaFieldDefinition | null {\n // Use resolveFieldSchema which handles:\n // - Simple paths like \"author\"\n // - Nested paths like \"seo.image\"\n // - Array paths like \"tags[0]\"\n // - Portable text paths like \"text[0].markDefs[0].target\"\n const fieldSchema = resolveFieldSchema(fieldPath, typeSchema, fullSchema)\n return fieldSchema as SchemaFieldDefinition | null\n}\n\n/**\n * Gets the schema definition for items in an array field\n * Returns null for union arrays (arrays with multiple types) to signal\n * that items need individual schema matching based on their _type\n */\nexport function getArrayItemSchema(\n arrayFieldPath: string,\n typeSchema: ManifestSchemaType,\n fullSchema: ManifestSchemaType[],\n): SchemaFieldDefinition | null {\n const field = getReferenceFieldDefinition(arrayFieldPath, typeSchema, fullSchema)\n\n if (!field || field.type !== 'array' || !field.of || field.of.length === 0) {\n return null\n }\n\n // Return null for union arrays (multiple types)\n // This signals that items need individual schema matching\n if (field.of.length > 1) {\n return null\n }\n\n // Single type array - return that type's schema\n return field.of[0] as SchemaFieldDefinition\n}\n\n/**\n * Checks if a reference field requires weak references according to schema\n */\nfunction isWeakReferenceField(fieldDefinition: SchemaFieldDefinition): boolean {\n // Direct reference with weak: true\n if (fieldDefinition.type === 'reference' && fieldDefinition.weak === true) {\n return true\n }\n\n // Array of references - check if any reference items have weak: true\n if (fieldDefinition.type === 'array' && fieldDefinition.of) {\n return fieldDefinition.of.some((item) => item.type === 'reference' && item.weak === true)\n }\n\n return false\n}\n\n/** Cached document type info */\ntype CachedDocument = { _type: string } | null\n\n/**\n * Cache for document lookups to avoid duplicate fetches\n */\nconst documentCache = new Map<string, CachedDocument>()\n\n/**\n * Clear the document cache.\n * Should be called at the start of each normalization operation.\n */\nexport function clearDocumentCache() {\n documentCache.clear()\n}\n\n/**\n * Lookup a document (draft, versioned, or published) to check existence and get type.\n * Uses cache to avoid redundant API calls.\n *\n * @param client - Sanity client\n * @param docId - The document ID to lookup\n * @returns Document object with _type, or null if doesn't exist\n */\nasync function lookupDocument(\n client: SanityClient,\n docId: string,\n): Promise<{ _type: string } | null> {\n // Check cache first\n if (documentCache.has(docId)) {\n return documentCache.get(docId)!\n }\n\n try {\n const doc = await client.getDocument(docId)\n const result = doc ? { _type: doc._type } : null\n documentCache.set(docId, result)\n return result\n } catch (_error) {\n // Document doesn't exist\n documentCache.set(docId, null)\n return null\n }\n}\n\n/**\n * Normalizes a single reference object with unified logic:\n * - Schema-based weak detection\n * - ID conversion (drafts.*, versions.* → published)\n * - Validation and error collection\n * - Adding _weak and _strengthenOnPublish metadata\n */\nasync function normalizeReferenceObject(\n client: SanityClient,\n ref: ReferenceObject,\n fieldPath: string,\n typeSchema: ManifestSchemaType | SchemaFieldDefinition,\n fullSchema: ManifestSchemaType[],\n targetDocumentId: string,\n validationErrors: ValidationError[],\n applyStrengthenOnPublish: boolean,\n parentObjectType?: string, // _type of the parent object (for global type lookup fallback)\n): Promise<ReferenceObject | null> {\n let fieldDefinition: SchemaFieldDefinition | null | undefined\n\n // Special case: If typeSchema IS a reference schema (for Type A arrays),\n // use it directly instead of looking up a field\n if (typeSchema.type === 'reference') {\n fieldDefinition = typeSchema as SchemaFieldDefinition\n } else {\n // Normal case: Get the field definition from schema\n fieldDefinition = getReferenceFieldDefinition(\n fieldPath,\n typeSchema as ManifestSchemaType,\n fullSchema,\n )\n }\n\n // Fallback: If resolveFieldSchema couldn't find the field (e.g., markDefs annotations\n // where block doesn't have marks.annotations inline), try looking up the parent object's\n // _type as a global type and find the field there\n if (!fieldDefinition && parentObjectType) {\n const globalType = fullSchema.find((s) => s.name === parentObjectType)\n if (globalType?.fields) {\n // Extract field name from path (last segment without array indices)\n const fieldName = fieldPath\n .split('.')\n .pop()\n ?.replace(/\\[\\d+\\]$/, '')\n if (fieldName) {\n const field = globalType.fields.find((f) => f.name === fieldName)\n if (field) {\n fieldDefinition = field as SchemaFieldDefinition\n }\n }\n }\n }\n\n // Handle array items: If we got an array field, extract the reference schema\n if (fieldDefinition?.type === 'array' && fieldDefinition.of) {\n const referenceSchemas = fieldDefinition.of.filter((item) => item.type === 'reference')\n if (referenceSchemas.length === 1) {\n fieldDefinition = referenceSchemas[0] as SchemaFieldDefinition\n }\n }\n\n // Check if this is a schema-defined weak reference\n // If we can't find the field definition (e.g., deeply nested in portable text annotations),\n // default to non-weak so we still normalize version IDs properly\n const isSchemaWeak = fieldDefinition ? isWeakReferenceField(fieldDefinition) : false\n\n // Determine if target document is published\n const isTargetPublished = isPublishedId(targetDocumentId as DocumentId)\n\n const originalRefId = ref._ref\n\n // Global document references (e.g. media library links) are cross-system —\n // they can't be validated against the dataset. Ensure _weak and pass through.\n if (ref._type === 'globalDocumentReference') {\n return { ...ref, _weak: true }\n }\n\n // Handle references that already have _weak: true\n if (ref._weak) {\n const publishedId =\n isVersionId(originalRefId as DocumentId) || isDraftId(originalRefId as DocumentId)\n ? getPublishedId(originalRefId as DocumentId)\n : originalRefId\n\n // Schema-weak or already has _strengthenOnPublish — just fix the ID\n if (isSchemaWeak || ref._strengthenOnPublish) {\n return { ...ref, _ref: publishedId }\n }\n\n // Worker-added _weak without _strengthenOnPublish — add it so refs\n // auto-strengthen when the target document is published.\n // No lookup needed — the ref is weak precisely because the doc may not exist yet.\n // Use schema to determine the type, or fall back to ref._type if it's a named type.\n if (applyStrengthenOnPublish && !isTargetPublished) {\n const allPossibleTypes: string[] = []\n if (fieldDefinition?.to && Array.isArray(fieldDefinition.to)) {\n allPossibleTypes.push(...fieldDefinition.to.map((t) => t.type).filter(Boolean))\n }\n const targetType =\n allPossibleTypes.length === 1\n ? allPossibleTypes[0]\n : ref._type !== 'reference'\n ? ref._type\n : allPossibleTypes[0]\n if (targetType) {\n return {\n ...ref,\n _ref: publishedId,\n _strengthenOnPublish: { type: targetType, template: { id: targetType } },\n }\n }\n }\n\n return { ...ref, _ref: publishedId }\n }\n let publishedId: string\n let needsWeakAndStrengthen = false\n let documentType: string | null = null\n\n // Handle different ID formats\n if (isVersionId(originalRefId as DocumentId)) {\n // VERSIONED ID (versions.bundle.xxx)\n\n // Check constraint: published documents can't reference versioned docs\n if (isTargetPublished) {\n validationErrors.push(\n createError(\n fieldPath,\n 'INVALID_REFERENCE',\n 'Cannot reference versioned document from published document',\n `\"${originalRefId}\" (versioned)`,\n 'Published document reference',\n 'Use a published document ID instead of a versioned one',\n ),\n )\n return null\n }\n\n // Lookup versioned document for type determination\n const versionedDoc = await lookupDocument(client, originalRefId)\n\n if (!versionedDoc) {\n validationErrors.push(\n createError(\n fieldPath,\n 'REFERENCE_NOT_FOUND',\n 'Referenced versioned document does not exist',\n `\"${originalRefId}\"`,\n 'Valid document ID',\n 'Provide a document ID that exists in the dataset',\n ),\n )\n return null\n }\n\n documentType = versionedDoc._type\n publishedId = getPublishedId(originalRefId as DocumentId)\n needsWeakAndStrengthen = true\n } else if (isDraftId(originalRefId as DocumentId)) {\n // DRAFT ID (drafts.xxx)\n\n // Check constraint: published documents can't reference drafts\n if (isTargetPublished) {\n validationErrors.push(\n createError(\n fieldPath,\n 'INVALID_REFERENCE',\n 'Cannot reference draft document from published document',\n `\"${originalRefId}\" (draft)`,\n 'Published document reference',\n 'Use a published document ID instead of a draft one',\n ),\n )\n return null\n }\n\n // Lookup draft document for type determination\n const draftDoc = await lookupDocument(client, originalRefId)\n\n if (!draftDoc) {\n validationErrors.push(\n createError(\n fieldPath,\n 'REFERENCE_NOT_FOUND',\n 'Referenced draft document does not exist',\n `\"${originalRefId}\"`,\n 'Valid document ID',\n 'Provide a document ID that exists in the dataset',\n ),\n )\n return null\n }\n\n documentType = draftDoc._type\n publishedId = getPublishedId(originalRefId as DocumentId)\n needsWeakAndStrengthen = true\n } else {\n // PUBLISHED ID (or unknown format)\n publishedId = originalRefId\n\n // Validate published document exists\n const publishedDoc = await lookupDocument(client, publishedId)\n\n if (!publishedDoc) {\n validationErrors.push(\n createError(\n fieldPath,\n 'REFERENCE_NOT_FOUND',\n 'Referenced document does not exist',\n `\"${originalRefId}\"`,\n 'Valid document ID',\n 'Provide a document ID that exists in the dataset',\n ),\n )\n return null\n }\n\n documentType = publishedDoc._type\n needsWeakAndStrengthen = false // Published refs don't need weak+strengthen\n }\n\n const normalized: ReferenceObject = {\n ...ref,\n }\n\n // Apply weak flag\n if (isSchemaWeak) {\n // Schema requires weak - always set it\n normalized._weak = true\n }\n\n if (!applyStrengthenOnPublish) {\n return normalized\n }\n\n // Get allowed types from schema (if available)\n const allPossibleTypes: string[] = []\n if (fieldDefinition?.to && Array.isArray(fieldDefinition.to)) {\n allPossibleTypes.push(...fieldDefinition.to.map((t) => t.type).filter(Boolean))\n }\n\n // Validate document type matches schema constraints (if we have schema info)\n if (allPossibleTypes.length > 0 && documentType && !allPossibleTypes.includes(documentType)) {\n validationErrors.push(\n createError(\n fieldPath,\n 'REFERENCE_WRONG_TYPE',\n 'Reference points to wrong document type',\n `\"${originalRefId}\" (type: ${documentType})`,\n `Reference to: ${allPossibleTypes.join(', ')}`,\n `Change the reference to point to a document of type ${allPossibleTypes.join(' or ')}`,\n ),\n )\n return null\n }\n\n // Add _strengthenOnPublish metadata (only for non-schema-weak refs that need it)\n if (!isSchemaWeak && needsWeakAndStrengthen && !isTargetPublished && documentType) {\n // Determine target type from field definition\n let targetType = documentType // Use the actual document type we looked up\n\n // If schema defines a single type, use that; otherwise use the looked-up type\n if (allPossibleTypes.length === 1) {\n targetType = allPossibleTypes[0]\n }\n\n normalized._ref = publishedId\n normalized._weak = true\n normalized._strengthenOnPublish = {\n type: targetType,\n template: {\n id: targetType,\n },\n }\n }\n\n return normalized\n}\n\n/**\n * Recursively traverses an object/array and normalizes all reference objects\n */\nexport async function traverseAndNormalize(\n client: SanityClient,\n value: unknown,\n currentPath: string,\n typeSchema: ManifestSchemaType | SchemaFieldDefinition,\n fullSchema: ManifestSchemaType[],\n targetDocumentId: string,\n validationErrors: ValidationError[],\n applyStrengthenOnPublish: boolean,\n parentObjectType?: string, // _type of the parent object (for global type lookup fallback)\n): Promise<unknown> {\n // Handle null/undefined\n if (value == null) {\n return value\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n const results = await Promise.all(\n value.map(async (item: unknown, index: number) => {\n const itemPath = `${currentPath}[${index}]`\n return await traverseAndNormalize(\n client,\n item,\n itemPath,\n typeSchema,\n fullSchema,\n targetDocumentId,\n validationErrors,\n applyStrengthenOnPublish,\n parentObjectType,\n )\n }),\n )\n // Filter out nulls (references that failed validation)\n return results.filter((item) => item !== null)\n }\n\n // Handle reference objects\n if (isReferenceObject(value)) {\n return await normalizeReferenceObject(\n client,\n value,\n currentPath,\n typeSchema,\n fullSchema,\n targetDocumentId,\n validationErrors,\n applyStrengthenOnPublish,\n parentObjectType,\n )\n }\n\n // Handle plain objects - recurse into properties\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>\n const normalized: Record<string, unknown> = {}\n\n // Get this object's _type for passing to children (for global type lookup fallback)\n const thisObjectType = typeof obj._type === 'string' ? obj._type : undefined\n\n for (const [key, val] of Object.entries(obj)) {\n // Skip system fields that start with _\n if (key.startsWith('_')) {\n normalized[key] = val\n continue\n }\n\n // Build the field path\n const fieldPath = currentPath ? `${currentPath}.${key}` : key\n\n // Recursively normalize nested values, passing this object's _type\n const result = await traverseAndNormalize(\n client,\n val,\n fieldPath,\n typeSchema,\n fullSchema,\n targetDocumentId,\n validationErrors,\n applyStrengthenOnPublish,\n thisObjectType,\n )\n\n // Only set the field if result is not null\n if (result !== null) {\n normalized[key] = result\n }\n }\n return normalized\n }\n\n // Primitive values - return unchanged\n return value\n}\n\n/**\n * Normalizes all reference objects in a document with unified logic.\n *\n * Performs all reference normalization in a single pass:\n * - Schema-based weak reference detection\n * - Draft/versioned ID conversion to published IDs\n * - Validation with batch error collection\n * - Adding _weak: true and _strengthenOnPublish metadata\n *\n * @param client - Sanity client for document lookups\n * @param document - The document object to normalize (must have _type and _id)\n * @param fullSchema - The full Sanity schema array\n * @returns Result object with normalized document and validation errors\n *\n * @example\n * ```typescript\n * const result = await normalizeDocumentReferences(\n * client,\n * document,\n * schema,\n * )\n *\n * if (result.validationErrors.length > 0) {\n * // Handle validation errors\n * }\n *\n * const normalizedDoc = result.normalized\n * ```\n */\nexport async function normalizeDocumentReferences(\n client: SanityClient,\n document: SanityDocumentLike,\n schema: ManifestSchemaType[],\n applyStrengthenOnPublish: boolean = true,\n) {\n // Clear cache at start of each normalization operation\n clearDocumentCache()\n\n // Validate inputs\n if (!document || !schema || schema.length === 0) {\n return {\n normalized: document,\n validationErrors: [],\n }\n }\n\n // Find the document type schema\n const typeSchema = schema.find((t) => t.name === document._type)\n\n if (!typeSchema) {\n // Can't normalize without schema - return unchanged\n return {\n normalized: document,\n validationErrors: [],\n }\n }\n\n // Collect validation errors during traversal\n const validationErrors: ValidationError[] = []\n\n // Traverse and normalize all reference objects\n const normalized = await traverseAndNormalize(\n client,\n document,\n '',\n typeSchema,\n schema,\n document._id,\n validationErrors,\n applyStrengthenOnPublish,\n )\n\n return {\n normalized: normalized as SanityDocumentLike,\n validationErrors,\n }\n}\n","/**\n * Normalizes patch operations including reference handling, append position resolution,\n * duplicate key regeneration, and setIfMissing computation.\n */\n\nimport type { InsertOperation, ManifestSchemaType, ValidationError } from '@sanity/agent-schema'\nimport { resolveFieldSchema } from '@sanity/agent-schema'\nimport { getValueAtPath } from '@sanity/agent-schema/validation'\nimport type { SanityClient } from '@sanity/client'\nimport { generateKey } from './generateKey'\nimport {\n clearDocumentCache,\n getArrayItemSchema,\n getReferenceFieldDefinition,\n type SchemaFieldDefinition,\n traverseAndNormalize,\n} from './normalizeReferences'\n\n/** Patch operations structure */\ninterface PatchOperations {\n set?: Array<{ path: string; value?: unknown }>\n unset?: string[]\n append?: Array<{ path: string; items: unknown[] }>\n insertBefore?: InsertOperation[]\n insertAfter?: InsertOperation[]\n [key: string]: unknown\n}\n\n/** Result of patch operations normalization */\ninterface PatchNormalizationResult<T = PatchOperations> {\n normalized: T\n validationErrors: ValidationError[]\n /** setIfMissing patches for parent paths (ensures nested paths exist) */\n setIfMissing: Record<string, unknown>\n}\n\ninterface NormalizePatchOptions {\n /** Whether to add _strengthenOnPublish metadata for draft/version references. Defaults to true. */\n applyStrengthenOnPublish?: boolean\n /** The existing document state, used to resolve append positions */\n existingDocument?: Record<string, unknown>\n}\n\n/**\n * Gets the last item's _key from an array value, optionally excluding certain keys.\n * @param arrayValue - The array to search\n * @param excludeKeys - Keys to skip when searching for a valid anchor\n */\nfunction getLastItemKey(arrayValue: unknown, excludeKeys?: Set<string>): string | undefined {\n if (!Array.isArray(arrayValue) || arrayValue.length === 0) return undefined\n\n // Iterate from the end to find the last valid key\n for (let i = arrayValue.length - 1; i >= 0; i--) {\n const item = arrayValue[i]\n if (item && typeof item === 'object' && '_key' in item) {\n const key = (item as Record<string, unknown>)._key as string\n // If no exclusions or key is not excluded, return it\n if (!excludeKeys || !excludeKeys.has(key)) {\n return key\n }\n }\n }\n\n return undefined\n}\n\n/**\n * Extracts _key values from unset paths that target a specific array.\n * Handles both single and double quotes in the key selector.\n * @param unsetPaths - Array of unset path strings\n * @param arrayPath - The array path to match (e.g., \"content\")\n * @returns Set of keys that will be unset from the array\n */\nfunction extractUnsetKeysForArray(unsetPaths: string[], arrayPath: string): Set<string> {\n const keys = new Set<string>()\n\n // Match paths like \"content[_key==\"block-3\"]\" or \"content[_key=='block-3']\"\n const regex = new RegExp(`^${escapeRegex(arrayPath)}\\\\[_key==[\"']([^\"']+)[\"']\\\\]$`)\n\n for (const path of unsetPaths) {\n const match = path.match(regex)\n if (match) {\n keys.add(match[1])\n }\n }\n\n return keys\n}\n\n/**\n * Escapes special regex characters in a string.\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Collects all _key values from an array (for checking conflicts with document).\n */\nfunction collectExistingKeys(arrayValue: unknown): Set<string> {\n const keys = new Set<string>()\n if (!Array.isArray(arrayValue)) return keys\n\n for (const item of arrayValue) {\n if (item && typeof item === 'object' && '_key' in item) {\n const key = (item as Record<string, unknown>)._key\n if (typeof key === 'string') {\n keys.add(key)\n }\n }\n }\n\n return keys\n}\n\n/**\n * Normalizes an array of items for insertion operations (append, insertBefore, insertAfter).\n * Handles schema matching for union arrays and reference normalization.\n */\nasync function normalizeArrayItems(\n client: SanityClient,\n items: unknown[],\n arrayPath: string,\n typeSchema: ManifestSchemaType,\n fullSchema: ManifestSchemaType[],\n targetDocumentId: string,\n validationErrors: ValidationError[],\n applyStrengthenOnPublish: boolean,\n): Promise<unknown[]> {\n const arrayItemSchema = getArrayItemSchema(arrayPath, typeSchema, fullSchema)\n const arrayFieldDef = getReferenceFieldDefinition(arrayPath, typeSchema, fullSchema)\n const normalizedItems: unknown[] = []\n\n for (const item of items) {\n let schemaForItem: ManifestSchemaType | SchemaFieldDefinition | null = arrayItemSchema\n\n // For union arrays (arrayItemSchema is null), match item._type with schema\n if (!schemaForItem && arrayFieldDef?.of) {\n const itemRecord = item as Record<string, unknown>\n const isReference = typeof itemRecord._ref === 'string'\n\n if (isReference) {\n // For reference items, find matching schema by name or type\n const matchingRefSchema = arrayFieldDef.of.find((s) => {\n if (s.type !== 'reference') return false\n return s.name === itemRecord._type || (s.type === itemRecord._type && !s.name)\n })\n\n if (matchingRefSchema) {\n schemaForItem = matchingRefSchema as SchemaFieldDefinition\n } else {\n // Fallback: check if all reference schemas have the same weak setting\n const refSchemas = arrayFieldDef.of.filter((s) => s.type === 'reference')\n if (refSchemas.length > 0) {\n const allWeak = refSchemas.every((s) => s.weak === true)\n const allStrong = refSchemas.every((s) => s.weak !== true)\n\n if (allWeak || allStrong) {\n schemaForItem = refSchemas[0] as SchemaFieldDefinition\n } else {\n // Mixed weak/strong - can't safely normalize\n normalizedItems.push(item)\n continue\n }\n }\n }\n } else {\n // For non-reference items, match by _type\n const found = arrayFieldDef.of.find((ofSchema) => {\n return ofSchema.name === itemRecord._type || ofSchema.type === itemRecord._type\n })\n schemaForItem = found ? (found as SchemaFieldDefinition) : null\n }\n }\n\n // Use the item's schema or fall back to document schema\n const effectiveSchema: ManifestSchemaType | SchemaFieldDefinition = schemaForItem || typeSchema\n\n const normalizedItem = await traverseAndNormalize(\n client,\n item,\n '',\n effectiveSchema,\n fullSchema,\n targetDocumentId,\n validationErrors,\n applyStrengthenOnPublish,\n )\n\n // Only include items that aren't null\n if (normalizedItem !== null) {\n normalizedItems.push(normalizedItem)\n }\n }\n\n return normalizedItems\n}\n\n/**\n * Recursively collects all _key values from a value (for detecting internal duplicates).\n */\nfunction collectAllKeys(value: unknown, keys: Map<string, number>): void {\n if (value === null || value === undefined) return\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && !Array.isArray(item)) {\n const obj = item as Record<string, unknown>\n if (typeof obj._key === 'string') {\n const count = keys.get(obj._key) || 0\n keys.set(obj._key, count + 1)\n }\n // Recursively collect from nested properties\n for (const val of Object.values(obj)) {\n collectAllKeys(val, keys)\n }\n } else {\n collectAllKeys(item, keys)\n }\n }\n } else if (typeof value === 'object') {\n for (const val of Object.values(value as Record<string, unknown>)) {\n collectAllKeys(val, keys)\n }\n }\n}\n\n/**\n * Recursively regenerates duplicate keys in a value.\n * @param value - The value to process\n * @param duplicateKeys - Keys that appear more than once (internal duplicates)\n * @param conflictingKeys - Keys that conflict with existing document\n * @param seenKeys - Keys we've already seen during this traversal\n */\nfunction regenerateDuplicateKeysInValue(\n value: unknown,\n duplicateKeys: Set<string>,\n conflictingKeys: Set<string>,\n seenKeys: Set<string>,\n): unknown {\n if (value === null || value === undefined) return value\n\n if (Array.isArray(value)) {\n return value.map((item) => {\n if (item && typeof item === 'object' && !Array.isArray(item)) {\n const obj = item as Record<string, unknown>\n const oldKey = obj._key as string | undefined\n\n let newKey = oldKey\n\n if (oldKey) {\n // Check if this key conflicts with document or is a duplicate\n const needsRegeneration =\n conflictingKeys.has(oldKey) || (duplicateKeys.has(oldKey) && seenKeys.has(oldKey))\n\n if (needsRegeneration) {\n newKey = generateKey()\n } else {\n // Mark this key as seen for duplicate detection\n seenKeys.add(oldKey)\n }\n }\n\n // Recursively process nested properties\n const processedObj: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(obj)) {\n if (key !== '_key') {\n processedObj[key] = regenerateDuplicateKeysInValue(\n val,\n duplicateKeys,\n conflictingKeys,\n seenKeys,\n )\n }\n }\n\n return { _key: newKey, ...processedObj }\n }\n\n return regenerateDuplicateKeysInValue(item, duplicateKeys, conflictingKeys, seenKeys)\n })\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>\n const result: Record<string, unknown> = {}\n\n for (const [key, val] of Object.entries(obj)) {\n result[key] = regenerateDuplicateKeysInValue(val, duplicateKeys, conflictingKeys, seenKeys)\n }\n\n return result\n }\n\n return value\n}\n\n/**\n * Gets all parent paths for a given path, stopping at array selectors.\n *\n * E.g., \"foo.bar.baz\" → [\"foo\", \"foo.bar\"]\n * E.g., \"tags[_key==\"abc\"].name\" → [] (path starts with array - no parent objects)\n * E.g., \"author.bio.text\" → [\"author\", \"author.bio\"]\n * E.g., \"description[_key==\"x\"].children\" → [] (path starts with array)\n * E.g., \"author.tags[_key==\"x\"].name\" → [\"author\"] (stop at array selector)\n *\n * Once we encounter an array selector, we stop - everything after is inside an array item\n * and should NOT have setIfMissing applied (the array item already exists or will be created).\n */\nfunction getParentPaths(path: string): string[] {\n const parentPaths: string[] = []\n\n // Find the position of the first array selector\n const arrayMatch = path.match(/\\[_key==[^\\]]+\\]|\\[\\d+\\]/)\n\n let pathToAnalyze: string\n if (arrayMatch && arrayMatch.index !== undefined) {\n // There's an array selector - only consider the path BEFORE it\n pathToAnalyze = path.slice(0, arrayMatch.index)\n } else {\n // No array selector - consider the whole path\n pathToAnalyze = path\n }\n\n const segments = pathToAnalyze.split('.').filter(Boolean)\n\n // Build parent paths (exclude the last segment - that's the target field or array)\n for (let i = 0; i < segments.length - 1; i++) {\n parentPaths.push(segments.slice(0, i + 1).join('.'))\n }\n\n return parentPaths\n}\n\n/**\n * Computes setIfMissing patches for all parent paths.\n * This ensures that nested paths exist before setting values on them.\n *\n * For a path like \"author.bio.text\":\n * - If \"author\" is an object type → setIfMissing[\"author\"] = { _type: \"author\" }\n * - If \"author\" is an array type → setIfMissing[\"author\"] = []\n */\nfunction computeSetIfMissing(\n paths: string[],\n typeSchema: ManifestSchemaType,\n fullSchema: ManifestSchemaType[],\n): Record<string, unknown> {\n const setIfMissing: Record<string, unknown> = {}\n\n for (const path of paths) {\n const parentPaths = getParentPaths(path)\n\n for (const parentPath of parentPaths) {\n // Skip if already computed\n if (setIfMissing[parentPath] !== undefined) continue\n\n const fieldSchema = resolveFieldSchema(parentPath, typeSchema, fullSchema)\n if (!fieldSchema) continue\n\n if (fieldSchema.type === 'array') {\n setIfMissing[parentPath] = []\n } else if (fieldSchema.type === 'object' || fieldSchema.fields) {\n // For object types, include _type if we have a name\n setIfMissing[parentPath] = fieldSchema.name ? { _type: fieldSchema.name } : {}\n }\n }\n }\n\n return setIfMissing\n}\n\n/**\n * Regenerates duplicate keys in appended items.\n * Handles both internal duplicates (within the items being appended) and\n * conflicts with keys that already exist in the document.\n */\nfunction regenerateDuplicateKeysForAppend(\n items: unknown[],\n existingArrayKeys: Set<string>,\n): unknown[] {\n // Collect all keys in the items to find internal duplicates\n const keyCounts = new Map<string, number>()\n collectAllKeys(items, keyCounts)\n\n // Find keys that appear more than once (internal duplicates)\n const duplicateKeys = new Set<string>()\n for (const [key, count] of keyCounts) {\n if (count > 1) {\n duplicateKeys.add(key)\n }\n }\n\n // If no duplicates and no conflicts, return items unchanged\n if (duplicateKeys.size === 0 && existingArrayKeys.size === 0) {\n return items\n }\n\n // Regenerate keys as needed\n const seenKeys = new Set<string>()\n return regenerateDuplicateKeysInValue(\n items,\n duplicateKeys,\n existingArrayKeys,\n seenKeys,\n ) as unknown[]\n}\n\n/**\n * Normalizes reference objects in patch operations with unified logic.\n *\n * Handles the patch tool's operation format:\n * - set: Array of {path, value} objects\n * - unset: Array of path strings (no normalization needed)\n * - append: Array of {path, items} objects\n *\n * Also resolves append paths to use the last item's _key for reliable ordering,\n * and regenerates duplicate keys.\n *\n * @param client - Sanity client for document lookups\n * @param operations - The patch operations object\n * @param documentType - The document type name\n * @param fullSchema - The full Sanity schema array\n * @param targetDocumentId - The ID of the document being patched\n * @param options - Optional configuration\n * @returns Result object with normalized operations and validation errors\n */\nexport async function normalizePatchOperations<T extends PatchOperations>(\n client: SanityClient,\n operations: T,\n documentType: string,\n fullSchema: ManifestSchemaType[],\n targetDocumentId: string,\n options: NormalizePatchOptions = {},\n): Promise<PatchNormalizationResult<T>> {\n const { applyStrengthenOnPublish = true, existingDocument } = options\n // Clear cache at start of each normalization operation\n clearDocumentCache()\n\n // Validate inputs\n if (!operations || !documentType || !fullSchema || fullSchema.length === 0) {\n return {\n normalized: operations,\n validationErrors: [],\n setIfMissing: {},\n }\n }\n\n // Find the document type schema\n const typeSchema = fullSchema.find((t) => t.name === documentType)\n\n if (!typeSchema) {\n // Can't normalize without schema - return unchanged\n return {\n normalized: operations,\n validationErrors: [],\n setIfMissing: {},\n }\n }\n\n // Collect validation errors during traversal\n const validationErrors: ValidationError[] = []\n const normalized: PatchOperations = {}\n\n // Process each operation type (set, unset, append, etc.)\n for (const [opType, opValue] of Object.entries(operations)) {\n if (opType === 'set' && Array.isArray(opValue)) {\n // Set operations: Array of {path, value}\n const normalizedSet = []\n\n for (const op of opValue) {\n const normalizedValue = await traverseAndNormalize(\n client,\n op.value,\n op.path,\n typeSchema,\n fullSchema,\n targetDocumentId,\n validationErrors,\n applyStrengthenOnPublish,\n )\n\n // Only include the set operation if the value isn't null\n if (normalizedValue !== null) {\n normalizedSet.push({\n path: op.path,\n value: normalizedValue,\n })\n }\n }\n\n normalized[opType] = normalizedSet\n } else if (opType === 'append' && Array.isArray(opValue)) {\n // Append operations: Array of {path, items}\n const normalizedAppend = []\n\n // Track the last appended key per array path for sequential appends\n const appendAfterKeyForPath: Record<string, string | undefined> = {}\n\n for (const op of opValue) {\n const normalizedItems = Array.isArray(op.items)\n ? await normalizeArrayItems(\n client,\n op.items,\n op.path,\n typeSchema,\n fullSchema,\n targetDocumentId,\n validationErrors,\n applyStrengthenOnPublish,\n )\n : []\n\n // Only include the append operation if we have items to append\n if (normalizedItems.length > 0) {\n // Resolve the append path to use the last item's _key for reliable ordering\n let resolvedPath = op.path\n\n // Get existing array keys to check for conflicts\n let existingArrayKeys = new Set<string>()\n if (existingDocument) {\n const arrayValue = getValueAtPath(existingDocument, op.path)\n existingArrayKeys = collectExistingKeys(arrayValue)\n\n // Find keys that will be unset from this array - we can't use them as anchors\n const unsetKeys = extractUnsetKeysForArray(operations.unset || [], op.path)\n\n // Check if we already have a tracked key from a previous append to this path\n let appendAfterKey = appendAfterKeyForPath[op.path]\n\n if (!appendAfterKey) {\n // Get the last item's _key from the existing array, excluding keys that will be unset\n appendAfterKey = getLastItemKey(arrayValue, unsetKeys)\n }\n\n // Convert path to use _key selector if we have a key\n if (appendAfterKey) {\n resolvedPath = `${op.path}[_key==\"${appendAfterKey}\"]`\n }\n }\n\n // Regenerate any duplicate keys (internal duplicates or conflicts with document)\n const deduplicatedItems = regenerateDuplicateKeysForAppend(\n normalizedItems,\n existingArrayKeys,\n )\n\n // Track the last appended item's _key for subsequent appends to the same array\n const lastItem = deduplicatedItems[deduplicatedItems.length - 1]\n if (lastItem && typeof lastItem === 'object' && '_key' in lastItem) {\n appendAfterKeyForPath[op.path] = (lastItem as Record<string, unknown>)._key as string\n }\n\n normalizedAppend.push({\n path: resolvedPath,\n items: deduplicatedItems,\n })\n }\n }\n\n normalized[opType] = normalizedAppend\n } else if ((opType === 'insertBefore' || opType === 'insertAfter') && Array.isArray(opValue)) {\n // Insert operations: Array of {arrayPath, key, items}\n const normalizedInserts: InsertOperation[] = []\n\n for (const op of opValue as InsertOperation[]) {\n const normalizedItems = Array.isArray(op.items)\n ? await normalizeArrayItems(\n client,\n op.items,\n op.arrayPath,\n typeSchema,\n fullSchema,\n targetDocumentId,\n validationErrors,\n applyStrengthenOnPublish,\n )\n : []\n\n // Only include the insert operation if we have items to insert\n if (normalizedItems.length > 0) {\n // Get existing array keys to check for conflicts and regenerate duplicates\n let existingArrayKeys = new Set<string>()\n if (existingDocument) {\n const arrayValue = getValueAtPath(existingDocument, op.arrayPath)\n existingArrayKeys = collectExistingKeys(arrayValue)\n }\n\n // Regenerate any duplicate keys\n const deduplicatedItems = regenerateDuplicateKeysForAppend(\n normalizedItems,\n existingArrayKeys,\n )\n\n normalizedInserts.push({\n arrayPath: op.arrayPath,\n key: op.key,\n items: deduplicatedItems,\n })\n }\n }\n\n normalized[opType] = normalizedInserts\n } else {\n // Other operations (unset, etc.) - pass through unchanged\n normalized[opType] = opValue\n }\n }\n\n // Collect all paths from set and append operations for setIfMissing computation\n const allPaths: string[] = []\n if (normalized.set && Array.isArray(normalized.set)) {\n for (const op of normalized.set) {\n allPaths.push(op.path)\n }\n }\n if (normalized.append && Array.isArray(normalized.append)) {\n for (const op of normalized.append) {\n allPaths.push(op.path)\n }\n }\n\n // Compute setIfMissing for parent paths\n const setIfMissing = computeSetIfMissing(allPaths, typeSchema, fullSchema)\n\n return {\n normalized: normalized as T,\n validationErrors,\n setIfMissing,\n }\n}\n","/**\n * Check whether a field's array schema accepts flat Portable Text blocks\n * (i.e., the output of markdownToPortableText).\n *\n * Returns true when `block` is among the array's `of` item types.\n * The array may also contain custom types (ctaBlock, image, etc.) —\n * the markdown tool just won't produce those. The worker can add\n * custom blocks separately via patch-document.\n */\n\nimport type { ManifestSchemaType } from '@sanity/agent-schema'\nimport { resolveFieldSchema } from '@sanity/agent-schema'\n\nexport function acceptsFlatPortableText(\n fieldPath: string,\n typeSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): boolean {\n const fieldSchema = resolveFieldSchema(fieldPath, typeSchema, allSchemas)\n if (!fieldSchema) return false\n return arrayAcceptsBlocks(fieldSchema, allSchemas)\n}\n\n/**\n * Stricter check: the field's array accepts ONLY block items (no custom block\n * types like tableBlock, codeBlock, image, etc.).\n *\n * This is the bar for *deterministic* markdown conversion. When an array mixes\n * `block` with custom types, markdown's tables/code fences/etc. have no faithful\n * mechanical mapping onto those custom types — so the deterministic converter\n * would silently lose them (tables → bullet lists, fences → plain paragraphs).\n * Such fields are routed to the generative path instead, where the worker has\n * the schema and a raw-Portable-Text tool to build the custom blocks correctly.\n */\nexport function acceptsOnlyFlatPortableText(\n fieldPath: string,\n typeSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): boolean {\n const fieldSchema = resolveFieldSchema(fieldPath, typeSchema, allSchemas)\n if (!fieldSchema) return false\n return arrayIsBlockOnly(fieldSchema, allSchemas)\n}\n\n/**\n * Check whether a document type has any array field that accepts block items.\n * Used to decide whether to include the markdown tool for a worker.\n */\nexport function hasAnyFlatPortableTextField(\n typeSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): boolean {\n if (!typeSchema.fields) return false\n return typeSchema.fields.some((field) => {\n const resolved = field.type ? (allSchemas.find((s) => s.name === field.type) ?? field) : field\n return arrayAcceptsBlocks(resolved, allSchemas)\n })\n}\n\n/**\n * Does this array schema include `block` (or a type that resolves to `block`)\n * among its `of` entries? Unlike the old isBlockOnlyArray, this returns true\n * even when the array also has custom types like ctaBlock or image.\n */\nfunction arrayAcceptsBlocks(\n fieldSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): boolean {\n // If the field is a named type reference (e.g. type: \"blockContent\"), resolve it\n let schema = fieldSchema\n if (!schema.of && schema.type) {\n const resolved = allSchemas.find((s) => s.name === schema.type)\n if (resolved) schema = resolved\n }\n\n const arrayOf = schema.of as ManifestSchemaType[] | undefined\n if (!arrayOf || arrayOf.length === 0) return false\n\n return arrayOf.some((item) => resolveBlockMember(item, allSchemas) !== undefined)\n}\n\n/**\n * Does this array schema contain ONLY plainly-convertible block members? Every\n * `of` entry must be a `block` (directly or via a named alias) AND declare no\n * custom mark annotations.\n *\n * Custom annotations (e.g. a `link` whose URL field is named `url`, or an\n * `internalLink` carrying a `reference`) can't be populated faithfully from\n * markdown — we'd have to guess field names across every customer's schema.\n * When a block declares its own annotations we route `convertMarkdown`\n * generative so the worker can build markDefs against the real schema. A block\n * with no declared annotations uses Sanity's implicit `link` (`href`), which\n * markdown maps onto losslessly, so it stays deterministic. Empty arrays are\n * not block-only.\n */\nfunction arrayIsBlockOnly(\n fieldSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): boolean {\n let schema = fieldSchema\n if (!schema.of && schema.type) {\n const resolved = allSchemas.find((s) => s.name === schema.type)\n if (resolved) schema = resolved\n }\n\n const arrayOf = schema.of as ManifestSchemaType[] | undefined\n if (!arrayOf || arrayOf.length === 0) return false\n\n return arrayOf.every((item) => {\n const block = resolveBlockMember(item, allSchemas)\n if (!block) return false\n const annotations = block.marks?.annotations\n return !annotations || annotations.length === 0\n })\n}\n\n/**\n * Resolve an array member to its `block` definition (following a named alias),\n * or return undefined when the member is not a block.\n */\nfunction resolveBlockMember(\n item: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): ManifestSchemaType | undefined {\n if (item.type === 'block') return item\n if (item.type) {\n const resolved = allSchemas.find((s) => s.name === item.type)\n if (resolved?.type === 'block') return resolved\n }\n return undefined\n}\n","/**\n * Prepares patch operations for execution.\n *\n * Handles:\n * - Normalizing key quote style (single to double quotes)\n * - Applying key mapping from duplicate key regeneration\n * - Converting array indices to key selectors\n * - Normalizing internationalized array items (v4 ↔ v5 format)\n * - Adding missing _key fields to array items\n */\n\nimport type { ManifestSchemaType, PatchOperations } from '@sanity/agent-schema'\nimport { getValueAtPath } from '@sanity/agent-schema/validation'\nimport { convertArrayIndexOperations } from './convertArrayIndices'\nimport { addMissingKeys } from './generateKey'\nimport {\n mapKeyThroughKeyMapping,\n normalizeKeyQuotes,\n transformPathWithKeyMapping,\n} from './keyMapping'\nimport { normalizeInternationalizedArrays } from './normalizeInternationalizedArrays'\n\n/** Options for preparing operations */\ninterface PrepareOperationsOptions {\n /** Key mapping from duplicate key regeneration */\n keyMapping?: Map<string, string>\n /** Schema for the document type */\n typeSchema: ManifestSchemaType\n /** All schemas */\n allSchemas: ManifestSchemaType[]\n /** Current document state */\n document: Record<string, unknown>\n}\n\n/**\n * Normalize all paths in operations to use double quotes in _key selectors.\n * LLMs may use single quotes which need to be converted.\n */\nfunction normalizeOperationPaths(operations: PatchOperations): PatchOperations {\n return {\n set: operations.set?.map((op) => ({\n ...op,\n path: normalizeKeyQuotes(op.path),\n })),\n unset: operations.unset?.map((path) => normalizeKeyQuotes(path)),\n append: operations.append?.map((op) => ({\n ...op,\n path: normalizeKeyQuotes(op.path),\n })),\n insertBefore: operations.insertBefore?.map((op) => ({\n ...op,\n arrayPath: normalizeKeyQuotes(op.arrayPath),\n })),\n insertAfter: operations.insertAfter?.map((op) => ({\n ...op,\n arrayPath: normalizeKeyQuotes(op.arrayPath),\n })),\n }\n}\n\n/**\n * Apply key mapping to transform old key references to new ones.\n * Used after key regeneration to ensure paths reference the correct keys.\n */\nfunction applyKeyMapping(\n operations: PatchOperations,\n keyMapping: Map<string, string>,\n): PatchOperations {\n return {\n set: operations.set?.map((op) => ({\n ...op,\n path: transformPathWithKeyMapping(op.path, keyMapping),\n })),\n unset: operations.unset?.map((path) => transformPathWithKeyMapping(path, keyMapping)),\n append: operations.append?.map((op) => ({\n ...op,\n path: transformPathWithKeyMapping(op.path, keyMapping),\n })),\n insertBefore: operations.insertBefore?.map((op) => ({\n ...op,\n arrayPath: transformPathWithKeyMapping(op.arrayPath, keyMapping),\n key: mapKeyThroughKeyMapping(op.key, keyMapping),\n })),\n insertAfter: operations.insertAfter?.map((op) => ({\n ...op,\n arrayPath: transformPathWithKeyMapping(op.arrayPath, keyMapping),\n key: mapKeyThroughKeyMapping(op.key, keyMapping),\n })),\n }\n}\n\n/**\n * Add missing _key fields to array items in operations.\n */\nfunction addMissingKeysToOperations(operations: PatchOperations): PatchOperations {\n return {\n set: operations.set?.map((op) => ({\n ...op,\n value: addMissingKeys(op.value),\n })),\n unset: operations.unset,\n append: operations.append?.map((op) => ({\n ...op,\n items: op.items.map((item) => addMissingKeys(item, { ensureRootKey: true })),\n })),\n insertBefore: operations.insertBefore?.map((op) => ({\n ...op,\n items: op.items.map((item) => addMissingKeys(item, { ensureRootKey: true })),\n })),\n insertAfter: operations.insertAfter?.map((op) => ({\n ...op,\n items: op.items.map((item) => addMissingKeys(item, { ensureRootKey: true })),\n })),\n }\n}\n\n/**\n * Convert append operations to set operations when the target array\n * does not yet exist on the document or is empty. Sanity's mutator will throw\n * \"Attempt to apply insert patch to non-array value\" if you append\n * to a field that is undefined, and insert operations on empty arrays\n * fail because there is no valid anchor element for the insert position.\n * In both cases, we convert to a set instead.\n */\nfunction convertAppendToSetForMissingArrays(\n operations: PatchOperations,\n document: Record<string, unknown>,\n): PatchOperations {\n if (!operations.append || operations.append.length === 0) {\n return operations\n }\n\n const remainingAppends: Array<{ path: string; items: unknown[] }> = []\n const convertedSets: Array<{ path: string; value: unknown }> = []\n\n for (const op of operations.append) {\n // Only convert for paths that don't traverse through array selectors.\n // Paths with _key== selectors depend on parent array items existing,\n // and are handled separately by validation.\n const isSimplePath = !op.path.includes('[')\n const existingValue = getValueAtPath(document, op.path)\n const isMissingOrEmpty =\n existingValue === undefined ||\n existingValue === null ||\n (Array.isArray(existingValue) && existingValue.length === 0)\n if (isSimplePath && isMissingOrEmpty) {\n // Array doesn't exist or is empty on document — convert to set\n convertedSets.push({ path: op.path, value: [...op.items] })\n } else {\n remainingAppends.push(op)\n }\n }\n\n if (convertedSets.length === 0) {\n return operations\n }\n\n return {\n ...operations,\n set: [...(operations.set ?? []), ...convertedSets],\n append: remainingAppends.length > 0 ? remainingAppends : undefined,\n }\n}\n\n/**\n * Prepare patch operations for execution.\n *\n * This function:\n * 1. Normalizes key quote style (single to double quotes)\n * 2. Applies key mapping (if provided) to transform regenerated keys\n * 3. Converts array indices to key selectors using document state\n * 4. Converts append to set for arrays that don't exist on the document\n * 5. Normalizes internationalized array items (v4 ↔ v5 format)\n * 6. Adds missing _key fields to array items\n *\n * @param operations - Raw operations from tool params\n * @param options - Preparation options including schema and document state\n * @returns Prepared operations ready for validation and execution\n */\nexport function prepareOperations(\n operations: PatchOperations,\n options: PrepareOperationsOptions,\n): PatchOperations {\n // Step 1: Normalize key quotes\n let prepared = normalizeOperationPaths(operations)\n\n // Step 2: Apply key mapping if provided\n if (options.keyMapping) {\n prepared = applyKeyMapping(prepared, options.keyMapping)\n }\n\n // Step 3: Convert array indices to key selectors\n prepared = convertArrayIndexOperations(\n prepared,\n options.typeSchema,\n options.allSchemas,\n options.document,\n )\n\n // Step 4: Convert append to set when the target array doesn't exist on the document\n prepared = convertAppendToSetForMissingArrays(prepared, options.document)\n\n // Step 5: Normalize internationalized array items (v4 ↔ v5 format)\n prepared = normalizeInternationalizedArrays(prepared, {\n typeSchema: options.typeSchema,\n allSchemas: options.allSchemas,\n })\n\n // Step 6: Add missing _key fields\n prepared = addMissingKeysToOperations(prepared)\n\n return prepared\n}\n","/**\n * Patch operations validation for Sanity mutations.\n *\n * Validates SET, UNSET, APPEND, and INSERT operations against the schema.\n */\n\nimport type {\n InsertOperation,\n ManifestSchemaType,\n PatchOperations,\n ValidationContext,\n ValidationError,\n ValidationResult,\n} from '@sanity/agent-schema'\nimport { isPrimitiveType, resolveFieldSchema } from '@sanity/agent-schema'\nimport {\n createError,\n getValueAtPath,\n isInternationalizedArrayField,\n resolveFieldSchemaAtPath,\n validateDocumentLanguageField,\n validateInternationalizedArrayItems,\n validateInternationalizedArraySet,\n validateUniqueItems,\n validateValue,\n} from '@sanity/agent-schema/validation'\n\n/**\n * Check if path ends with array index (numeric or _key selector).\n */\nfunction pathEndsWithArrayIndex(path: string): boolean {\n return /\\[\\d+\\]$/.test(path) || /\\[_key==[^\\]]+\\]$/.test(path)\n}\n\n/**\n * Resolve a field schema to an array schema if it's a named type reference.\n * Returns the original schema if it's already an array or not a named type.\n */\nfunction resolveToArraySchema(\n fieldSchema: ManifestSchemaType,\n allSchemas: ManifestSchemaType[],\n): ManifestSchemaType {\n if (fieldSchema.type === 'array') {\n return fieldSchema\n }\n\n if (fieldSchema.type && !isPrimitiveType(fieldSchema.type)) {\n const referencedSchema = allSchemas.find((s) => s.name === fieldSchema.type)\n if (referencedSchema) {\n return referencedSchema\n }\n }\n\n return fieldSchema\n}\n\n/**\n * Get the schema to validate a value against for a SET operation.\n * If path ends with array index, returns the appropriate item schema from the array's `of`.\n * For union arrays, finds the matching schema based on the value's `_type`.\n */\nfunction getSchemaForSetValue(\n fieldSchema: ManifestSchemaType,\n path: string,\n value: unknown,\n allSchemas: ManifestSchemaType[],\n): ManifestSchemaType {\n if (!pathEndsWithArrayIndex(path)) {\n return fieldSchema\n }\n\n const resolvedSchema = resolveToArraySchema(fieldSchema, allSchemas)\n\n if (resolvedSchema.type !== 'array' || !resolvedSchema.of?.length) {\n return fieldSchema\n }\n\n const itemSchemas = resolvedSchema.of as ManifestSchemaType[]\n\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const valueType = (value as Record<string, unknown>)._type as string | undefined\n if (valueType) {\n let matchingSchema = itemSchemas.find(\n (schema) => schema.name === valueType || schema.type === valueType,\n )\n\n if (!matchingSchema) {\n matchingSchema = allSchemas.find((s) => s.name === valueType)\n }\n\n if (matchingSchema) {\n return matchingSchema\n }\n }\n }\n\n return itemSchemas[0]\n}\n\n/**\n * Check if a schema has a uniqueItems constraint.\n */\nfunction hasUniqueConstraint(fieldSchema: ManifestSchemaType): boolean {\n return !!fieldSchema.validation?.some((group) =>\n group.rules.some((rule) => {\n const r = rule as Record<string, unknown>\n const ruleType = (r.type as string) || r.flag\n return ruleType === 'unique' || ruleType === 'uniqueItems'\n }),\n )\n}\n\n/**\n * Validate patch operations against the schema.\n */\nexport async function validatePatchOperations(\n operations: PatchOperations,\n documentType: string,\n schema: ManifestSchemaType[],\n context: ValidationContext,\n): Promise<ValidationResult> {\n const errors: ValidationError[] = []\n const warnings: ValidationError[] = []\n\n const typeSchema = schema.find((s) => s.name === documentType)\n\n if (!typeSchema) {\n errors.push(\n createError(\n '_type',\n 'FIELD_NOT_IN_SCHEMA',\n `Document type \"${documentType}\" not found in schema`,\n documentType,\n 'Valid document type',\n 'Check the schema for valid document type names',\n ),\n )\n return { valid: false, errors, warnings }\n }\n\n await validateSetOperations(operations.set, typeSchema, schema, context, errors, warnings)\n validateUnsetOperations(operations.unset, typeSchema, schema, context, errors)\n await validateAppendOperations(operations.append, typeSchema, schema, context, errors, warnings)\n await validateInsertOperations(operations, typeSchema, schema, context, errors, warnings)\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n }\n}\n\n/** Validate SET operations: path resolution, value validation, i18n, document-level language. */\nasync function validateSetOperations(\n ops: PatchOperations['set'],\n typeSchema: ManifestSchemaType,\n schema: ManifestSchemaType[],\n context: ValidationContext,\n errors: ValidationError[],\n warnings: ValidationError[],\n): Promise<void> {\n if (!ops) return\n\n for (const op of ops) {\n const resolution = resolveFieldSchemaAtPath(\n op.path,\n typeSchema,\n schema,\n context.existingDocument,\n )\n const fieldSchema = resolution.schema\n\n if (!fieldSchema) {\n errors.push(\n createError(\n op.path,\n 'FIELD_NOT_IN_SCHEMA',\n 'Path does not exist in schema',\n op.path,\n 'Valid field path',\n 'Check the schema for valid field paths',\n ),\n )\n continue\n }\n\n if (op.value !== undefined) {\n const valueSchema = getSchemaForSetValue(fieldSchema, op.path, op.value, schema)\n await validateValue(op.value, valueSchema, op.path, errors, context, schema, warnings)\n }\n\n validateInternationalizedArraySet(op.path, op.value, fieldSchema, typeSchema, schema, errors)\n\n if (context.localizationConfig?.documentLevel) {\n const { languageField, availableLanguages } = context.localizationConfig.documentLevel\n if (languageField && op.path === languageField && availableLanguages) {\n validateDocumentLanguageField(op.value, languageField, availableLanguages, op.path, errors)\n }\n }\n }\n}\n\n/** Validate UNSET operations: path existence in schema. */\nfunction validateUnsetOperations(\n ops: PatchOperations['unset'],\n typeSchema: ManifestSchemaType,\n schema: ManifestSchemaType[],\n context: ValidationContext,\n errors: ValidationError[],\n): void {\n if (!ops) return\n\n for (const path of ops) {\n const resolution = resolveFieldSchemaAtPath(path, typeSchema, schema, context.existingDocument)\n\n if (!resolution.schema) {\n errors.push(\n createError(\n path,\n 'FIELD_NOT_IN_SCHEMA',\n 'Path does not exist in schema',\n path,\n 'Valid field path',\n 'Check the schema for valid field paths',\n ),\n )\n }\n }\n}\n\n/** Validate APPEND operations: path, items, i18n, uniqueness. */\nasync function validateAppendOperations(\n ops: PatchOperations['append'],\n typeSchema: ManifestSchemaType,\n schema: ManifestSchemaType[],\n context: ValidationContext,\n errors: ValidationError[],\n warnings: ValidationError[],\n): Promise<void> {\n if (!ops) return\n\n for (const op of ops) {\n const fieldSchema = resolveFieldSchema(op.path, typeSchema, schema)\n\n if (!fieldSchema) {\n errors.push(\n createError(\n op.path,\n 'FIELD_NOT_IN_SCHEMA',\n 'Path does not exist in schema',\n op.path,\n 'Valid array field path',\n 'Check the schema for valid array field paths',\n ),\n )\n continue\n }\n\n // Verify _key== selectors exist in the document\n if (context.existingDocument && op.path.includes('[_key==')) {\n const targetArray = getValueAtPath(context.existingDocument, op.path)\n if (targetArray === undefined) {\n errors.push(\n createError(\n op.path,\n 'FIELD_NOT_IN_SCHEMA',\n 'Path does not exist in document',\n op.path,\n 'Valid array path that exists in document',\n 'Check that the path with _key selectors points to an existing location',\n ),\n )\n continue\n }\n }\n\n // Validate appended items against array schema\n const arraySchema = resolveToArraySchema(fieldSchema, schema)\n if (arraySchema.of && arraySchema.of.length > 0) {\n const errorCountBefore = errors.length\n await validateValue(op.items, arraySchema, op.path, errors, context, schema, warnings)\n // Rewrite error paths: validateValue uses \"[N]\" indices, but append errors\n // need \"[append:N]\" prefix so the patch tool can identify them as append items.\n for (let e = errorCountBefore; e < errors.length; e++) {\n errors[e].path = errors[e].path.replace(\n new RegExp(`^${op.path.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\[(\\\\d+)\\\\]`),\n `${op.path}[append:$1]`,\n )\n }\n }\n\n // Validate language keys for internationalized arrays\n if (isInternationalizedArrayField(fieldSchema)) {\n validateInternationalizedArrayItems(op.items, fieldSchema, schema, op.path, errors)\n }\n\n // Check uniqueItems constraint against existing document\n if (hasUniqueConstraint(fieldSchema) && context.existingDocument) {\n const existingArray = getValueAtPath(context.existingDocument, op.path)\n if (Array.isArray(existingArray)) {\n validateUniqueItems(op.items, existingArray, `${op.path}[append:`, errors)\n }\n }\n }\n}\n\n/** Validate INSERT operations (insertBefore/insertAfter): path, anchor key, items, i18n, uniqueness. */\nasync function validateInsertOperations(\n operations: PatchOperations,\n typeSchema: ManifestSchemaType,\n schema: ManifestSchemaType[],\n context: ValidationContext,\n errors: ValidationError[],\n warnings: ValidationError[],\n): Promise<void> {\n for (const opType of ['insertBefore', 'insertAfter'] as const) {\n const insertOps = operations[opType]\n if (!insertOps) continue\n\n for (const op of insertOps) {\n const fieldSchema = resolveFieldSchema(op.arrayPath, typeSchema, schema)\n\n if (!fieldSchema) {\n errors.push(\n createError(\n op.arrayPath,\n 'FIELD_NOT_IN_SCHEMA',\n 'Array path does not exist in schema',\n op.arrayPath,\n 'Valid array field path',\n 'Check the schema for valid array field paths',\n ),\n )\n continue\n }\n\n const resolvedSchema = resolveToArraySchema(fieldSchema, schema)\n\n if (resolvedSchema.type !== 'array' && !resolvedSchema.of) {\n errors.push(\n createError(\n op.arrayPath,\n 'TYPE_MISMATCH',\n 'Path must point to an array field',\n fieldSchema.type || 'unknown',\n 'Array field',\n 'Use an array field path for insert operations',\n ),\n )\n continue\n }\n\n const arraySchema = resolvedSchema\n\n // Verify the anchor key exists in the array\n if (context.existingDocument) {\n const existingArray = getValueAtPath(context.existingDocument, op.arrayPath)\n if (Array.isArray(existingArray)) {\n const keyExists = existingArray.some(\n (item) =>\n typeof item === 'object' &&\n item !== null &&\n (item as Record<string, unknown>)._key === op.key,\n )\n if (!keyExists) {\n errors.push(\n createError(\n `${op.arrayPath}[_key==\"${op.key}\"]`,\n 'INVALID_PATH',\n `Anchor key \"${op.key}\" not found in array`,\n op.key,\n 'Existing _key in the array',\n 'Use a _key that exists in the target array',\n ),\n )\n }\n }\n }\n\n // Validate language keys for internationalized arrays\n if (isInternationalizedArrayField(fieldSchema)) {\n validateInternationalizedArrayItems(op.items, fieldSchema, schema, op.arrayPath, errors)\n }\n\n // Validate items against the array's 'of' schema\n await validateInsertItems(op, opType, arraySchema, schema, context, errors, warnings)\n\n // Check uniqueItems constraint against existing document\n if (hasUniqueConstraint(fieldSchema) && context.existingDocument) {\n const existingArray = getValueAtPath(context.existingDocument, op.arrayPath)\n if (Array.isArray(existingArray)) {\n validateUniqueItems(op.items, existingArray, `${op.arrayPath}[${opType}:`, errors)\n }\n }\n }\n }\n}\n\n/** Validate individual items in an INSERT operation against the array's item schemas. */\nasync function validateInsertItems(\n op: InsertOperation,\n opType: 'insertBefore' | 'insertAfter',\n arraySchema: ManifestSchemaType,\n schema: ManifestSchemaType[],\n context: ValidationContext,\n errors: ValidationError[],\n warnings: ValidationError[],\n): Promise<void> {\n const itemSchemas = arraySchema.of || []\n if (itemSchemas.length === 0) return\n\n for (let i = 0; i < op.items.length; i++) {\n const item = op.items[i]\n const itemPath = `${op.arrayPath}[${opType}:${i}]`\n const errorCountBefore = errors.length\n\n const itemObj =\n typeof item === 'object' && item !== null ? (item as Record<string, unknown>) : null\n const itemType = itemObj?._type as string | undefined\n\n let matchingSchema: ManifestSchemaType | undefined\n for (const ofSchema of itemSchemas as ManifestSchemaType[]) {\n if (ofSchema.name === itemType || ofSchema.type === itemType) {\n matchingSchema = ofSchema\n break\n }\n if (!itemType && isPrimitiveType(ofSchema.type)) {\n matchingSchema = ofSchema\n break\n }\n }\n\n if (matchingSchema) {\n await validateValue(item, matchingSchema, itemPath, errors, context, schema, warnings)\n }\n\n // Tag errors from this item so the patch tool can filter invalid items\n for (let e = errorCountBefore; e < errors.length; e++) {\n errors[e].itemIndex = i\n errors[e].arrayPath = op.arrayPath\n }\n }\n}\n"],"names":["itemPath","publishedId","allPossibleTypes"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@sanity/agent-mutations",
3
+ "version": "0.1.0",
4
+ "description": "Schema-aware patch primitives for Sanity Agent mutations",
5
+ "keywords": [
6
+ "sanity",
7
+ "sanity-agent",
8
+ "mutations"
9
+ ],
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/sanity-io/sanity-agent.git",
13
+ "directory": "packages/agent-mutations"
14
+ },
15
+ "license": "MIT",
16
+ "type": "module",
17
+ "exports": {
18
+ ".": {
19
+ "default": "./dist/index.js"
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "types": "./dist/index.d.ts",
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "dependencies": {
28
+ "@sanity/id-utils": "^1.0.0",
29
+ "@sanity/agent-schema": "0.3.0"
30
+ },
31
+ "peerDependencies": {
32
+ "@sanity/client": ">=7.0.0",
33
+ "@sanity/types": ">=3.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@sanity/client": "7.14.1",
37
+ "@sanity/pkg-utils": "^10.4.1",
38
+ "@sanity/schema-descriptor-utils": "1.1.0",
39
+ "@sanity/types": "^3.89.0",
40
+ "@types/node": "^22.19.7",
41
+ "typescript": "^5.9.3",
42
+ "vitest": "^4.0.18",
43
+ "@repo/tsconfig": "0.0.0",
44
+ "@repo/package.config": "0.0.0"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "engines": {
50
+ "node": ">=18.0.0"
51
+ },
52
+ "scripts": {
53
+ "build": "pkg build --strict --check --clean",
54
+ "clean": "rm -rf dist",
55
+ "check:type-check": "tsc --noEmit",
56
+ "test": "vitest run",
57
+ "test:watch": "vitest watch"
58
+ }
59
+ }