payload-live-preview 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -18
- package/dist/adapters/astro/PreviewBoundary.astro +17 -4
- package/dist/adapters/astro/RichText.astro +13 -2
- package/dist/adapters/astro/index.d.ts +7 -7
- package/dist/adapters/astro/index.js +1 -1
- package/dist/adapters/astro/index.js.map +1 -1
- package/dist/adapters/astro/middleware-entry.d.ts +3 -3
- package/dist/adapters/astro/middleware-entry.js +1 -1
- package/dist/adapters/astro/middleware-entry.js.map +1 -1
- package/dist/adapters/nextjs/index.d.ts +2 -2
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/adapters/nextjs/index.js.map +1 -1
- package/dist/adapters/nuxt/index.d.ts +4 -4
- package/dist/adapters/nuxt/index.js +1 -1
- package/dist/adapters/nuxt/index.js.map +1 -1
- package/dist/adapters/nuxt/module.d.ts +1 -1
- package/dist/adapters/react/index.d.ts +2 -2
- package/dist/adapters/react/index.js +1 -1
- package/dist/adapters/react/index.js.map +1 -1
- package/dist/adapters/sveltekit/index.d.ts +5 -5
- package/dist/adapters/sveltekit/index.js +1 -1
- package/dist/adapters/sveltekit/index.js.map +1 -1
- package/dist/adapters/vue/index.d.ts +2 -2
- package/dist/adapters/vue/index.js +1 -1
- package/dist/adapters/vue/index.js.map +1 -1
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +15 -3
- package/dist/client.d.ts +15 -3
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/codegen-astro.js +1 -1
- package/dist/codegen-astro.js.map +1 -1
- package/dist/codegen-cli.js +1 -1
- package/dist/codegen-cli.js.map +1 -1
- package/dist/codegen.cjs +1 -1
- package/dist/codegen.cjs.map +1 -1
- package/dist/codegen.js +1 -1
- package/dist/codegen.js.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +141 -6
- package/dist/core.d.ts +141 -6
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/doctor-cli.d.ts +1 -1
- package/dist/doctor-cli.js +1 -1
- package/dist/doctor-cli.js.map +1 -1
- package/dist/doctor.d.ts +2 -2
- package/dist/doctor.js +1 -1
- package/dist/doctor.js.map +1 -1
- package/dist/{document-session-Bkd181PV.d.ts → document-session-BuYuO3ae.d.ts} +27 -2
- package/dist/{fragment-endpoint-DGGLIijM.d.ts → fragment-endpoint-CQE_7MKi.d.ts} +5 -3
- package/dist/fragment.cjs +1 -1
- package/dist/fragment.cjs.map +1 -1
- package/dist/fragment.d.cts +6 -2
- package/dist/fragment.d.ts +6 -2
- package/dist/fragment.js +1 -1
- package/dist/fragment.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -16
- package/dist/index.d.ts +79 -16
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lean.cjs +1 -1
- package/dist/lean.cjs.map +1 -1
- package/dist/lean.js +1 -1
- package/dist/lean.js.map +1 -1
- package/dist/lexical.cjs +1 -1
- package/dist/lexical.cjs.map +1 -1
- package/dist/lexical.d.cts +16 -4
- package/dist/lexical.d.ts +16 -4
- package/dist/lexical.js +1 -1
- package/dist/lexical.js.map +1 -1
- package/dist/{locals-zz2gi9dj.d.ts → locals-CyzDKfKU.d.ts} +7 -1
- package/dist/{middleware-CI-UTf6R.d.ts → middleware-Dnt6u4nF.d.ts} +2 -2
- package/dist/{options-CnYybG51.d.ts → options-DTzhFVJ4.d.ts} +13 -1
- package/dist/plugin.cjs +1 -1
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +15 -9
- package/dist/plugin.d.ts +15 -9
- package/dist/plugin.js +1 -1
- package/dist/plugin.js.map +1 -1
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.cjs.map +1 -1
- package/dist/plugins.d.cts +8 -2
- package/dist/plugins.d.ts +8 -2
- package/dist/plugins.js +1 -1
- package/dist/plugins.js.map +1 -1
- package/dist/{probe-D-IHg9dF.d.ts → probe-afwdYebU.d.ts} +6 -2
- package/dist/server.cjs +1 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +23 -3
- package/dist/server.d.ts +23 -3
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/structural.cjs +2 -2
- package/dist/structural.cjs.map +1 -1
- package/dist/structural.d.cts +2 -0
- package/dist/structural.d.ts +2 -0
- package/dist/structural.js +1 -1
- package/dist/structural.js.map +1 -1
- package/package.json +7 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["observeThenableResult","value","then","Promise","resolve","catch","noopDiagnostic","visit","state","nodes","Error","enter","depth","active","has","add","parseFieldSchema","raw","parseFields","WeakSet","Array","isArray","out","entry","parsed","parseFieldEntry","push","delete","record","name","type","length","fields","blocks","slug","Object","hasOwn","Reflect","get","includes","parseBlockSchema","result","relationTo","targets","target","optionalFieldOk","check","optionalTypeOk","isPlainObject","prototype","getPrototypeOf","NULL_AS_ABSENT_FIELDS","MAX_NODES","MAX_BODY","FORBIDDEN","Set","fail","hasControl","index","code","charCodeAt","segment","maximum","encodeURIComponent","test","id","Number","isFinite","String","own","key","put","defineProperty","writable","configurable","enumerable","stripTrailingSlashes","end","slice","copyLegacyData","characters","copy","keys","planLegacyPopulation","data","schema","serverURL","apiRoute","locale","isSafeInteger","doc","groups","Map","unique","tick","level","relation","owner","collection","selected","identity","scope","JSON","stringify","size","slots","set","fieldRelation","field","hasMany","allowed","selectedCollection","candidate","rich","walk","i","row","blockType","block","find","requests","base","URL","protocol","username","password","search","hash","startsWith","split","some","part","prefix","identities","map","slot","first","comma","chunk","url","next","proposed","query","URLSearchParams","limit","join","origin","ids","filter","async","populationBody","response","signal","current","reader","cancelled","finished","obsolete","Symbol","interrupt","interrupted","aborted","cancel","abort","addEventListener","once","body","json","bind","race","getReader","activeReader","chunks","bytes","count","pending","read","done","byteLength","Uint8Array","position","parse","TextDecoder","decode","removeEventListener","releaseLock","fillLegacyPopulation","request","safe","docs","found","isPathSegment","maxLength","character","codePoint","codePointAt","hasControlCharacter","isSafeSlug","isSafeId","DataMerger","fetchFn","log","inflight","attempt","destroyDepth","constructor","options","this","endsWith","withoutTrailingSlashes","route","diagnostic","args","canMerge","endpointOf","globalSlug","path","collectionSlug","merge","status","previous","controller","legacy","superseded","plan","fetch","AbortController","population","method","credentials","redirect","ok","endpoint","flattenLocales","headers","merged","wrongIdentity","error","destroy","MessageBus","matcher","handlers","boundListener","attachedTarget","generation","revision","queueHead","queueTail","lastAccepted","replayedGeneration","latestAcceptedAttempt","attach","window","committed","listener","event","receive","reportInvalid","resetQueue","detach","advanceGeneration","replayLastAccepted","accepted","handler","onReplay","matchesOrigin","invokeHandler","structuredClone","message","forgetLastAccepted","sendReady","origins","payload","ready","protocolVersion","postMessage","matchesSource","v","x","isLivePreviewMessage","dispatchUpdate","normalized","deleteProperty","fieldSchemaJSON","normalizeLivePreviewMessage","isDocumentEventMessage","onDocumentEvent","focusFieldOf","onFocusField","hasUpdateData","isCurrentGeneration","messageRevision","validator","validateToken","commitUpdate","verdict","enqueue","previewToken","settleValidation","approved","drainQueue","dequeue","onUpdate","snapshot","withoutToken","snapshotForReplay","reason","onInvalid","sourcePolicy","source","parent","opener","expected","LOCALHOST_PATTERN","VALID_ORIGIN_PATTERN","LOCALHOST_HANDSHAKE_PORTS","readParentOrigin","location","ancestors","ancestorOrigins","OriginDetector","explicit","additionalOrigins","normalised","normaliseOrigin","referrerOrigin","enableReferrerDetection","referrer","document","allowLocalhost","enableLocalhostMatching","forceDevMode","isDevMode","nodeEnv","process","env","readNodeEnv","host","hostname","matches","lockOrigin","unlockOrigin","lockedOrigin","enumerate","port","referrerWasAvailable","isProductionUnconfigured","isInIframe","self","top","isReferrerOnlyTrust","trimmed","trim","reasonFrom","line","label","detail","DocumentSession","merger","bus","detector","listeners","initial","lastLog","attached","initialData","allowedOrigins","handle","eventSourcePolicy","isLoading","subscribe","getSnapshot","getServerSnapshot","readyTargets","publish","SLOT","registerRouteRefresh","refresh","settle","waiting","settled","LivePreviewRouteRefresh","startTransition","useTransition","useRef","useEffect","undo","useLivePreviewDocument","session","held","useSessionFor","useSyncExternalStore"],"sources":["../../../src/core/thenable.ts","../../../src/core/diagnostics.ts","../../../src/schema/parser.ts","../../../src/core/message-guards.ts","../../../src/core/legacy-population.ts","../../../src/core/data-merger.ts","../../../src/core/message-bus.ts","../../../src/core/protocol-version.ts","../../../src/detection/origin.ts","../../../src/detection/environment.ts","../../../src/adapters/shared/document-session.ts","../../../src/core/route-refresh.ts","../../../src/adapters/react/route-refresh.ts","../../../src/adapters/react/index.ts"],"sourcesContent":["/**\n * Detect an invalid async result in a synchronous extension point.\n *\n * Rejected native Promises otherwise become unhandled after the caller falls\n * back synchronously. Assimilating the result through a handled Promise keeps\n * that contract violation observable only through the runtime's explicit\n * error channel.\n */\nexport function observeThenableResult(value: unknown): boolean {\n if ((typeof value !== 'object' || value === null) && typeof value !== 'function') return false;\n if (typeof (value as { readonly then?: unknown }).then !== 'function') return false;\n void Promise.resolve(value).catch(() => undefined);\n return true;\n}\n","import { observeThenableResult } from './thenable';\n\n/**\n * Diagnostics are observability, never control flow: a consumer logger may\n * throw or return a rejected thenable, and reporting a failure must not become\n * a second failure. Invocation stays synchronous for ordinary loggers.\n */\nexport function isolateDiagnostic(\n diagnostic: (...args: unknown[]) => unknown,\n): (...args: unknown[]) => void {\n return (...args): void => {\n try {\n observeThenableResult(diagnostic(...args));\n } catch {\n // Diagnostics must not become a second failure boundary.\n }\n };\n}\n\n/** Shared allocation-free default for disabled diagnostic channels. */\nexport function noopDiagnostic(): void {\n // Intentionally empty.\n}\n\n// Access, invocation and thenable inspection all happen inside the wrapper, so\n// a missing or hostile console cannot escape.\nexport const safeConsoleError = isolateDiagnostic((...args) =>\n (console.error as (...values: unknown[]) => unknown)(...args),\n);\n\nexport const safeConsoleWarn = isolateDiagnostic((...args) =>\n (console.warn as (...values: unknown[]) => unknown)(...args),\n);\n\nexport const safeConsoleDebug = isolateDiagnostic((...args) =>\n // eslint-disable-next-line no-console -- best-effort development diagnostics\n (console.debug as (...values: unknown[]) => unknown)(...args),\n);\n","/**\n * Validates the `fieldSchemaJSON` the admin sends. Entries that fail\n * validation are dropped, never thrown: a Payload/runtime version mismatch\n * must not take the preview down.\n */\n\nimport type { PayloadBlockSchema, PayloadFieldSchema } from '@/types/payload-protocol';\n\ninterface ParseState {\n nodes: number;\n readonly active: WeakSet<object>;\n}\nfunction visit(state: ParseState): void {\n if (++state.nodes > 10_000) throw new Error('invalid or oversized field schema');\n}\nfunction enter(value: object, state: ParseState, depth: number): void {\n visit(state);\n if (depth > 64 || state.active.has(value)) throw new Error('invalid or oversized field schema');\n state.active.add(value);\n}\n\nexport function parseFieldSchema(raw: unknown): readonly PayloadFieldSchema[] {\n try {\n return parseFields(raw, { nodes: 0, active: new WeakSet() }, 0);\n } catch {\n return [];\n }\n}\n\nfunction parseFields(\n raw: unknown,\n state: ParseState,\n depth: number,\n): readonly PayloadFieldSchema[] {\n if (!Array.isArray(raw)) return [];\n enter(raw, state, depth);\n const out: PayloadFieldSchema[] = [];\n for (const entry of raw) {\n const parsed = parseFieldEntry(entry, state, depth);\n if (parsed) out.push(parsed);\n }\n state.active.delete(raw);\n return out;\n}\n\nfunction parseFieldEntry(\n value: unknown,\n state: ParseState,\n depth: number,\n): PayloadFieldSchema | undefined {\n visit(state);\n if (typeof value !== 'object' || value === null) return undefined;\n const record = value as Record<string, unknown>;\n const name = record['name'];\n const type = record['type'];\n if (typeof name !== 'string' || name.length === 0) return undefined;\n if (typeof type !== 'string' || type.length === 0) return undefined;\n\n const fields = parseFields(record['fields'], state, depth + 1);\n const blocks = parseBlockSchema(record['blocks'], state, depth + 1);\n\n const result: Record<string, unknown> = { ...record, name, type };\n const relationTo = record['relationTo'];\n if (Array.isArray(relationTo)) {\n const targets: unknown[] = [];\n for (const target of relationTo) {\n visit(state);\n targets.push(target);\n }\n result['relationTo'] = targets;\n }\n if (fields.length > 0) result['fields'] = fields;\n else delete result['fields'];\n if (blocks.length > 0) result['blocks'] = blocks;\n else delete result['blocks'];\n\n return result as unknown as PayloadFieldSchema;\n}\n\nfunction parseBlockSchema(\n raw: unknown,\n state: ParseState,\n depth: number,\n): readonly PayloadBlockSchema[] {\n if (typeof raw === 'object' && raw !== null && !Array.isArray(raw)) {\n enter(raw, state, depth);\n const blocks: PayloadBlockSchema[] = [];\n for (const slug in raw) {\n if (!Object.hasOwn(raw, slug)) continue;\n visit(state);\n const entry: unknown = Reflect.get(raw, slug);\n if (\n typeof entry !== 'object' ||\n entry === null ||\n ['__proto__', 'constructor', 'prototype'].includes(slug)\n ) {\n continue;\n }\n blocks.push({\n ...(entry as Record<string, unknown>),\n slug,\n fields: parseFields((entry as Record<string, unknown>)['fields'], state, depth + 1),\n });\n }\n state.active.delete(raw);\n return blocks;\n }\n if (!Array.isArray(raw)) return [];\n enter(raw, state, depth);\n const out: PayloadBlockSchema[] = [];\n for (const entry of raw) {\n visit(state);\n if (typeof entry !== 'object' || entry === null) continue;\n const record = entry as Record<string, unknown>;\n const slug = record['slug'];\n if (typeof slug !== 'string' || slug.length === 0) continue;\n const fields = parseFields(record['fields'], state, depth + 1);\n out.push({ ...record, slug, fields });\n }\n state.active.delete(raw);\n return out;\n}\n","/**\n * Shape guards for the messages the bus accepts. `null` counts as absent, as\n * JSON bridges send it. The schema parser owns bounded, fail-closed normalization.\n */\n\nimport type {\n PayloadDocumentEventMessage,\n PayloadLivePreviewMessage,\n} from '@/types/payload-protocol';\nimport { parseFieldSchema } from '@schema/parser';\n\nexport function isObjectMessage(value: unknown): value is { type: string } {\n return (\n typeof value === 'object' && value !== null && 'type' in value && typeof value.type === 'string'\n );\n}\n\n/** A `payload-live-preview` message: `data` a plain object when present, scalars of the right type or absent. */\nexport function isLivePreviewMessage(value: { type: string }): value is PayloadLivePreviewMessage {\n const v = value as Record<string, unknown>;\n if (v['data'] !== undefined && v['data'] !== null && !isPlainObject(v['data'])) return false;\n return (\n optionalTypeOk(v['fieldSchemaJSON'], (x) => Array.isArray(x)) &&\n optionalTypeOk(v['globalSlug'], (x) => typeof x === 'string') &&\n optionalTypeOk(v['collectionSlug'], (x) => typeof x === 'string') &&\n optionalTypeOk(v['locale'], (x) => typeof x === 'string') &&\n optionalTypeOk(v['ready'], (x) => typeof x === 'boolean') &&\n optionalTypeOk(v['previewToken'], (x) => typeof x === 'string') &&\n optionalTypeOk(v['protocolVersion'], (x) => typeof x === 'number')\n );\n}\n\n/** The non-empty field name of a `payload-live-preview-focus` message, else `undefined`. */\nexport function focusFieldOf(value: { type: string }): string | undefined {\n const field = (value as Record<string, unknown>)['field'];\n return typeof field === 'string' && field.length > 0 ? field : undefined;\n}\n\n/** Stock Payload sends only the `type`; custom senders may add the typed fields (omitted, never `null`). */\nexport function isDocumentEventMessage(value: {\n type: string;\n}): value is PayloadDocumentEventMessage {\n const v = value as Record<string, unknown>;\n return (\n optionalFieldOk(v['action'], (x) => x === 'updated' || x === 'created' || x === 'deleted') &&\n optionalFieldOk(v['slug'], (x) => typeof x === 'string') &&\n optionalFieldOk(v['id'], (x) => typeof x === 'string' || Number.isFinite(x))\n );\n}\n\nfunction optionalFieldOk(value: unknown, check: (v: unknown) => boolean): boolean {\n return value === undefined || check(value);\n}\n\nfunction optionalTypeOk(value: unknown, check: (v: unknown) => boolean): boolean {\n return value === undefined || value === null || check(value);\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n const prototype = Object.getPrototypeOf(value) as object | null;\n return prototype === null || Object.getPrototypeOf(prototype) === null;\n}\n\nconst NULL_AS_ABSENT_FIELDS = [\n 'data',\n 'fieldSchemaJSON',\n 'globalSlug',\n 'collectionSlug',\n 'locale',\n 'ready',\n 'previewToken',\n 'protocolVersion',\n] as const satisfies readonly (keyof PayloadLivePreviewMessage)[];\n\n/**\n * Drop `null` optionals so downstream sees the strict public type, and parse\n * the field schema entry by entry (malformed entries are dropped). Unknown\n * fields stay, for protocol evolution.\n */\nexport function normalizeLivePreviewMessage(\n message: PayloadLivePreviewMessage,\n): PayloadLivePreviewMessage {\n const normalized = { ...message };\n for (const field of NULL_AS_ABSENT_FIELDS) {\n const wireValue: unknown = Reflect.get(normalized, field);\n if (wireValue === null) Reflect.deleteProperty(normalized, field);\n }\n if (!Array.isArray(normalized.fieldSchemaJSON)) return normalized;\n return {\n ...normalized,\n fieldSchemaJSON: parseFieldSchema(normalized.fieldSchemaJSON),\n };\n}\n","/**\n * Payload 2 posts raw form values and a schema, rather than a server merge target.\n * Plan collection GETs from that schema and fill an independent document only\n * after every requested identity is present; the caller owns request cancellation.\n */\nimport type { PayloadFieldSchema } from '@/types/payload-protocol';\nimport { isPlainObject } from './message-guards';\n\nconst MAX_DEPTH = 64;\nconst MAX_NODES = 10_000;\nconst MAX_IDS = 1_000;\nconst MAX_REQUESTS = 64;\nconst MAX_URL = 8_192;\nconst MAX_BODY = 1_048_576;\nconst MAX_CHUNKS = 10_000;\nconst CHUNK = 20;\nconst FORBIDDEN = new Set(['__proto__', 'constructor', 'prototype']);\ntype RecordValue = Record<string, unknown>;\ninterface Slot {\n readonly owner: RecordValue | unknown[];\n readonly key: string | number;\n readonly id: string;\n}\nexport interface LegacyRequest {\n readonly url: string;\n readonly ids: ReadonlySet<string>;\n readonly slots: readonly Slot[];\n}\nexport interface LegacyPlan {\n readonly doc: RecordValue;\n readonly requests: readonly LegacyRequest[];\n}\n\nfunction fail(): never {\n throw new Error('invalid or oversized legacy population');\n}\nfunction hasControl(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) return true;\n }\n return false;\n}\nfunction segment(value: unknown, maximum: number): value is string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > maximum ||\n value === '.' ||\n value === '..'\n ) {\n return false;\n }\n if (value.includes('/') || value.includes('\\\\') || hasControl(value)) return false;\n try {\n encodeURIComponent(value);\n return true;\n } catch {\n return false;\n }\n}\nfunction slug(value: unknown): value is string {\n return segment(value, 128) && !/[?#%]/u.test(value) && !FORBIDDEN.has(value);\n}\nfunction id(value: unknown): string {\n if (Number.isFinite(value)) return String(value);\n if (segment(value, 512)) return value;\n return fail();\n}\nfunction own(record: RecordValue | unknown[], key: string | number): unknown {\n return Object.hasOwn(record, key) ? Reflect.get(record, key) : undefined;\n}\nfunction put(record: RecordValue | unknown[], key: string | number, value: unknown): void {\n Object.defineProperty(record, key, {\n value,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n}\nfunction stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;\n return value.slice(0, end);\n}\n\n/** Copy only structured data, bounded before the planner follows any relation. */\nexport function copyLegacyData(value: unknown): unknown {\n const active = new WeakSet();\n let nodes = 0;\n let characters = 0;\n function copy(value: unknown, depth: number): unknown {\n if (++nodes > MAX_NODES || depth > MAX_DEPTH) return fail();\n if (typeof value === 'string') {\n characters += value.length;\n if (characters > MAX_BODY) fail();\n return value;\n }\n if (value === null || value === undefined || typeof value === 'boolean') return value;\n if (typeof value === 'number') return Number.isFinite(value) ? value : fail();\n if (!Array.isArray(value) && !isPlainObject(value)) return fail();\n if (Array.isArray(value)) {\n if (value.length > MAX_NODES) fail();\n for (let index = 0; index < value.length; index += 1) {\n if (!Object.hasOwn(value, index)) fail();\n }\n }\n if (active.has(value)) return fail();\n active.add(value);\n const result: RecordValue | unknown[] = Array.isArray(value) ? [] : {};\n for (const key of Object.keys(value)) {\n put(result, key, copy(Reflect.get(value, key), depth + 1));\n }\n active.delete(value);\n return result;\n }\n return copy(value, 0);\n}\n\nexport function planLegacyPopulation(\n data: RecordValue,\n schema: readonly PayloadFieldSchema[],\n serverURL: string,\n apiRoute: string,\n depth: number,\n locale?: string,\n): LegacyPlan {\n if (!Number.isSafeInteger(depth) || depth < 0 || depth > MAX_DEPTH) return fail();\n if (\n locale !== undefined &&\n (typeof locale !== 'string' || locale.length > 128 || hasControl(locale))\n ) {\n fail();\n }\n const doc = copyLegacyData(data);\n if (!isPlainObject(doc)) return fail();\n const groups = new Map<string, Slot[]>();\n const unique = new Set<string>();\n let nodes = 0;\n const active = new WeakSet();\n const tick = (level: number): void => {\n if (++nodes > MAX_NODES || level > MAX_DEPTH) fail();\n };\n\n function relation(\n owner: RecordValue | unknown[],\n key: string | number,\n collection: string,\n value: unknown,\n ): void {\n if (value === null || value === undefined || value === '') return;\n const selected = isPlainObject(value) ? own(value, 'id') : value;\n const identity = id(selected);\n if (depth === 0) {\n put(owner, key, selected);\n return;\n }\n const scope = JSON.stringify([collection, identity]);\n unique.add(scope);\n if (unique.size > MAX_IDS) fail();\n const slots = groups.get(collection) ?? [];\n slots.push({ owner, key, id: identity });\n groups.set(collection, slots);\n }\n function fieldRelation(\n owner: RecordValue | unknown[],\n key: string | number,\n field: PayloadFieldSchema,\n ): void {\n if (field.hasMany !== undefined && typeof field.hasMany !== 'boolean') fail();\n const allowed = field.relationTo;\n const value = own(owner, key);\n if (Array.isArray(allowed)) {\n if (allowed.length === 0) fail();\n const collection = isPlainObject(value) ? own(value, 'relationTo') : undefined;\n let selectedCollection: string | undefined;\n for (const candidate of allowed) {\n tick(0);\n if (!slug(candidate)) fail();\n if (candidate === collection) selectedCollection = candidate;\n }\n if (value === null || value === undefined || value === '') return;\n if (!isPlainObject(value) || selectedCollection === undefined) fail();\n relation(value, 'value', selectedCollection, own(value, 'value'));\n } else {\n if (!slug(allowed)) fail();\n relation(owner, key, allowed, value);\n }\n }\n function rich(value: unknown, level: number): void {\n tick(level);\n if (!Array.isArray(value) && !isPlainObject(value)) return;\n if (\n isPlainObject(value) &&\n Object.hasOwn(value, 'relationTo') &&\n Object.hasOwn(value, 'value')\n ) {\n const collection = own(value, 'relationTo');\n if (!slug(collection)) fail();\n relation(value, 'value', collection, own(value, 'value'));\n return;\n }\n for (const key of Object.keys(value)) rich(Reflect.get(value, key), level + 1);\n }\n function walk(fields: readonly PayloadFieldSchema[], record: RecordValue, level: number): void {\n tick(level);\n if (active.has(fields)) fail();\n active.add(fields);\n for (const field of fields) {\n tick(level);\n if (!isPlainObject(field) || !segment(field.name, 512) || FORBIDDEN.has(field.name)) fail();\n const value = own(record, field.name);\n if (field.type === 'relationship' || field.type === 'upload') {\n if (field.hasMany) {\n if (value !== null && value !== undefined && !Array.isArray(value)) fail();\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i += 1) fieldRelation(value, i, field);\n } else fieldRelation(record, field.name, field);\n } else fieldRelation(record, field.name, field);\n } else if (field.type === 'group' || field.type === 'tabs') {\n if (value != null && !isPlainObject(value)) fail();\n if (isPlainObject(value) && field.fields) walk(field.fields, value, level + 1);\n } else if (field.type === 'row' || field.type === 'collapsible') {\n if (field.fields) walk(field.fields, record, level + 1);\n } else if (field.type === 'array' || field.type === 'blocks') {\n if (value === 0) put(record, field.name, []);\n else if (value != null && !Array.isArray(value)) fail();\n if (Array.isArray(value)) {\n for (const row of value) {\n if (!isPlainObject(row)) fail();\n if (field.type === 'array' && field.fields) walk(field.fields, row, level + 1);\n else if (field.type === 'blocks') {\n const blockType = own(row, 'blockType');\n const block = field.blocks?.find((candidate) => {\n tick(level);\n return candidate.slug === blockType;\n });\n if (block === undefined) fail();\n walk(block.fields, row, level + 1);\n }\n }\n }\n } else if (field.type === 'richText') rich(value, level + 1);\n }\n active.delete(fields);\n }\n walk(schema, doc, 0);\n if (groups.size > 25) fail();\n const requests: LegacyRequest[] = [];\n if (groups.size === 0) return { doc, requests };\n const base = new URL(serverURL);\n if (\n !['http:', 'https:'].includes(base.protocol) ||\n base.username ||\n base.password ||\n base.search ||\n base.hash\n ) {\n fail();\n }\n if (\n !apiRoute.startsWith('/') ||\n apiRoute.includes('\\\\') ||\n /[%?#]/u.test(apiRoute) ||\n hasControl(apiRoute)\n ) {\n fail();\n }\n if (apiRoute.split('/').some((part) => part === '.' || part === '..')) fail();\n const prefix = `${stripTrailingSlashes(serverURL)}${stripTrailingSlashes(apiRoute)}/`;\n for (const [collection, slots] of groups) {\n const identities = [...new Set(slots.map((slot) => slot.id))];\n let index = 0;\n while (index < identities.length) {\n const first = identities[index];\n if (first === undefined) fail();\n const comma = first.includes(',');\n const chunk: string[] = [];\n let url = '';\n while (index < identities.length && chunk.length < CHUNK) {\n const next = identities[index];\n if (next === undefined || (chunk.length > 0 && (comma || next.includes(',')))) break;\n const proposed = [...chunk, next];\n const query = new URLSearchParams({\n depth: String(depth),\n limit: String(proposed.length),\n });\n if (locale !== undefined) query.set('locale', locale);\n query.set(comma ? 'where[id][equals]' : 'where[id][in]', comma ? next : proposed.join(','));\n const candidate = `${prefix}${encodeURIComponent(collection)}?${query}`;\n if (candidate.length > MAX_URL) {\n if (chunk.length === 0) fail();\n break;\n }\n if (new URL(candidate).origin !== base.origin) fail();\n chunk.push(next);\n index += 1;\n url = candidate;\n }\n if (chunk.length === 0 || requests.length >= MAX_REQUESTS) fail();\n const ids = new Set(chunk);\n requests.push({\n url,\n ids,\n slots: slots.filter((slot) => ids.has(slot.id)),\n });\n }\n }\n return { doc, requests };\n}\n\n/** Native bodies stop at byte and chunk limits; injected json-only shims still get shape limits. */\nexport async function populationBody(\n response: Response,\n signal: AbortSignal,\n current: () => boolean,\n): Promise<unknown> {\n let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let cancelled = false;\n let finished = false;\n const obsolete = Symbol();\n let interrupt: (() => void) | undefined;\n const interrupted = new Promise<typeof obsolete>((resolve) => {\n interrupt = () => {\n resolve(obsolete);\n };\n });\n const check = (): void => {\n if (!current() || signal.aborted) fail();\n };\n const cancel = (): void => {\n if (reader === undefined || cancelled) return;\n cancelled = true;\n try {\n void Promise.resolve(reader.cancel()).catch(() => {\n /* teardown remains authoritative */\n });\n } catch {\n /* teardown remains authoritative */\n }\n };\n const abort = (): void => {\n interrupt?.();\n cancel();\n };\n signal.addEventListener('abort', abort, { once: true });\n try {\n check();\n const body = response.body ?? null;\n check();\n if (body === null) {\n const json: () => Promise<unknown> = response.json.bind(response);\n check();\n const value: unknown = await Promise.race([\n Promise.resolve().then(() => {\n check();\n return json();\n }),\n interrupted,\n ]);\n check();\n if (value === obsolete) fail();\n return value;\n }\n const getReader: () => ReadableStreamDefaultReader<Uint8Array> = body.getReader.bind(body);\n check();\n const activeReader = getReader();\n reader = activeReader;\n check();\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n let count = 0;\n for (;;) {\n const pending = Promise.resolve().then(() => {\n check();\n const read = activeReader.read.bind(activeReader);\n check();\n return read();\n });\n const result = await Promise.race([pending, interrupted]);\n check();\n if (result === obsolete) fail();\n if (result.done) break;\n bytes += result.value.byteLength;\n if (++count > MAX_CHUNKS || bytes > MAX_BODY) fail();\n chunks.push(result.value);\n }\n finished = true;\n const data = new Uint8Array(bytes);\n let position = 0;\n for (const chunk of chunks) {\n data.set(chunk, position);\n position += chunk.byteLength;\n }\n try {\n return JSON.parse(new TextDecoder().decode(data));\n } catch {\n return fail();\n }\n } finally {\n signal.removeEventListener('abort', abort);\n if (!finished) cancel();\n try {\n reader?.releaseLock();\n } catch {\n /* a hostile pending read cannot own cleanup */\n }\n }\n}\n\nexport function fillLegacyPopulation(request: LegacyRequest, body: unknown): void {\n const safe = copyLegacyData(body);\n if (!isPlainObject(safe)) fail();\n const docs = own(safe, 'docs');\n if (!Array.isArray(docs) || docs.length > CHUNK) fail();\n const found = new Map<string, unknown>();\n for (const raw of docs) {\n if (!isPlainObject(raw)) fail();\n const identity = id(own(raw, 'id'));\n if (!request.ids.has(identity) || found.has(identity)) fail();\n found.set(identity, raw);\n }\n if (found.size !== request.ids.size) fail();\n for (const slot of request.slots) put(slot.owner, slot.key, found.get(slot.id));\n}\n","/**\n * Payload 3 raw form values use its REST merge with the method-override header.\n * Payload 2 sends a schema instead of a target, so it uses local values and\n * collection GETs to populate references. A newer merge aborts the one in flight,\n * and captured attempt identity drops obsolete results even when a shim ignores abort.\n */\n\nimport { isolateDiagnostic, noopDiagnostic } from './diagnostics';\nimport type { PayloadFieldSchema } from '@/types/payload-protocol';\nimport { fillLegacyPopulation, planLegacyPopulation, populationBody } from './legacy-population';\n\nexport interface DataMergerOptions {\n /** Payload server origin, e.g. `https://cms.example.com`. */\n readonly serverURL: string;\n /** REST route prefix. Defaults to `/api`. */\n readonly apiRoute?: string;\n /** Population depth requested from the server. Defaults to `1`. */\n readonly depth?: number;\n readonly fetchFn?: typeof fetch;\n readonly log?: (...args: unknown[]) => void;\n}\n\nexport interface MergeRequest {\n readonly schema?: readonly PayloadFieldSchema[] | undefined;\n readonly collectionSlug?: string | undefined;\n readonly globalSlug?: string | undefined;\n readonly data: Record<string, unknown>;\n readonly locale?: string | undefined;\n}\n\n/** `superseded`: a newer merge replaced this one. `unavailable`: fall back to the raw values. */\nexport type MergeResult =\n | { readonly status: 'merged'; readonly doc: Record<string, unknown> }\n | { readonly status: 'superseded' }\n | { readonly status: 'unavailable' };\n\ninterface MergeTarget {\n readonly path: string;\n readonly field: 'id' | 'globalType';\n readonly value: string;\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (const character of value) {\n // An iterated character always has a code point; 0 keeps the type and fails closed.\n const codePoint = character.codePointAt(0) ?? 0;\n if (codePoint <= 0x1f || codePoint === 0x7f) return true;\n }\n return false;\n}\n\n/** One path segment: non-empty, bounded, not a dot segment, without separators or control characters. */\nfunction isPathSegment(value: string, maxLength: number): boolean {\n return (\n value.length > 0 &&\n value.length <= maxLength &&\n value !== '.' &&\n value !== '..' &&\n !value.includes('/') &&\n !value.includes('\\\\') &&\n !hasControlCharacter(value)\n );\n}\n\n/** A slug is one of Payload's own names; `?` and `#` never belong in one. */\nfunction isSafeSlug(value: string): boolean {\n return isPathSegment(value, 128) && !value.includes('?') && !value.includes('#');\n}\n\n/** An id comes from the form values; a string one is encoded, so `?` and `#` may appear. */\nfunction isSafeId(value: unknown): value is string | number {\n if (typeof value === 'number') return Number.isFinite(value);\n return typeof value === 'string' && isPathSegment(value, 512);\n}\n\n/**\n * Trailing slashes off a base URL, without a regular expression: `/\\/+$/`\n * backtracks over a long run of slashes and takes quadratic time on input the\n * page supplies (CodeQL js/polynomial-redos).\n */\nfunction withoutTrailingSlashes(value: string): string {\n let end = value.length;\n while (value.endsWith('/', end)) end -= 1;\n return value.slice(0, end);\n}\n\nexport class DataMerger {\n private readonly serverURL: string;\n private readonly apiRoute: string;\n private readonly depth: number;\n private readonly fetchFn: typeof fetch | undefined;\n private readonly log: (...args: unknown[]) => void;\n private inflight: AbortController | null = null;\n private attempt = 0;\n private destroyDepth = 0;\n\n constructor(options: DataMergerOptions) {\n this.serverURL = withoutTrailingSlashes(options.serverURL);\n const route = options.apiRoute ?? '/api';\n this.apiRoute = route.startsWith('/') ? route : `/${route}`;\n this.depth = options.depth ?? 1;\n this.fetchFn = options.fetchFn;\n this.log = isolateDiagnostic(options.log ?? noopDiagnostic);\n }\n\n /** A v2 schema plans local values and GETs; a v3 target needs its document identity. */\n canMerge(request: MergeRequest): boolean {\n try {\n const schema = request.schema;\n if (schema !== undefined) {\n planLegacyPopulation(\n request.data,\n schema,\n this.serverURL,\n this.apiRoute,\n this.depth,\n request.locale,\n );\n return true;\n }\n return this.endpointOf(request) !== null;\n } catch {\n return false;\n }\n }\n\n /**\n * The path and its response identity, or `null` when no safe one exists. A request\n * accessor that throws counts as none, and so does a lone surrogate, which\n * `encodeURIComponent` refuses with a `URIError`.\n */\n private endpointOf(request: MergeRequest): MergeTarget | null {\n try {\n // An empty global slug means \"collection document\" on the wire.\n const globalSlug = request.globalSlug;\n if (globalSlug) {\n return isSafeSlug(globalSlug)\n ? {\n path: `globals/${encodeURIComponent(globalSlug)}`,\n field: 'globalType',\n value: globalSlug,\n }\n : null;\n }\n const collectionSlug = request.collectionSlug ?? '';\n const id: unknown = request.data['id'];\n if (!isSafeSlug(collectionSlug) || !isSafeId(id)) return null;\n return {\n path: `${encodeURIComponent(collectionSlug)}/${encodeURIComponent(String(id))}`,\n field: 'id',\n value: String(id),\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Fulfills merged, superseded or unavailable. Supported request, fetch and\n * response failures are outcomes; isolated diagnostics cannot reject the merge.\n */\n async merge(request: MergeRequest): Promise<MergeResult> {\n if (this.destroyDepth > 0) return { status: 'superseded' };\n // Claim the attempt before aborting: abort listeners and fetch shims are\n // reentrant, and a newer merge they start must win. Nothing but this class\n // aborts the signal, and only after the counter moved, so the counter\n // alone decides who was superseded.\n const attempt = (this.attempt += 1);\n const previous = this.inflight;\n this.inflight = null;\n let controller: AbortController | null = null;\n let legacy = false;\n const superseded = (): boolean => this.attempt !== attempt;\n try {\n previous?.abort();\n if (superseded()) return { status: 'superseded' };\n const schema = request.schema;\n legacy = schema !== undefined;\n if (schema !== undefined) {\n const plan = planLegacyPopulation(\n request.data,\n schema,\n this.serverURL,\n this.apiRoute,\n this.depth,\n request.locale,\n );\n if (superseded()) return { status: 'superseded' };\n if (plan.requests.length === 0) return { status: 'merged', doc: plan.doc };\n const fetchFn = this.fetchFn ?? (typeof fetch === 'function' ? fetch : undefined);\n if (superseded()) return { status: 'superseded' };\n if (fetchFn === undefined) return { status: 'unavailable' };\n controller = new AbortController();\n this.inflight = controller;\n for (const population of plan.requests) {\n const response = await fetchFn(population.url, {\n method: 'GET',\n credentials: 'include',\n redirect: 'error',\n signal: controller.signal,\n });\n if (superseded()) return { status: 'superseded' };\n const ok = response.ok;\n if (superseded()) return { status: 'superseded' };\n if (!ok) {\n const status = response.status;\n if (superseded()) return { status: 'superseded' };\n controller.abort();\n if (superseded()) return { status: 'superseded' };\n this.log('merge HTTP', status);\n return superseded() ? { status: 'superseded' } : { status: 'unavailable' };\n }\n const body = await populationBody(response, controller.signal, () => !superseded());\n if (superseded()) return { status: 'superseded' };\n fillLegacyPopulation(population, body);\n if (superseded()) return { status: 'superseded' };\n }\n return { status: 'merged', doc: plan.doc };\n }\n // The endpoint reads the request's own values, which may be consumer\n // getters that start a newer merge before throwing.\n const endpoint = this.endpointOf(request);\n if (superseded()) return { status: 'superseded' };\n if (endpoint === null) return { status: 'unavailable' };\n const fetchFn = this.fetchFn ?? (typeof fetch === 'function' ? fetch : undefined);\n if (superseded()) return { status: 'superseded' };\n if (fetchFn === undefined) return { status: 'unavailable' };\n // Serialize before publishing the controller: accessors may accept newer work.\n const body = JSON.stringify({\n data: request.data,\n depth: this.depth,\n flattenLocales: false,\n locale: request.locale,\n });\n if (superseded()) return { status: 'superseded' };\n controller = new AbortController();\n this.inflight = controller;\n const url = `${this.serverURL}${this.apiRoute}/${endpoint.path}`;\n const response = await fetchFn(url, {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Payload-HTTP-Method-Override': 'GET',\n },\n // The admin already flattens locales before posting; an absent locale\n // is left out of the JSON.\n body,\n signal: controller.signal,\n });\n // A fetch shim may ignore the signal; the attempt is authoritative.\n if (superseded()) return { status: 'superseded' };\n const ok = response.ok;\n if (superseded()) return { status: 'superseded' };\n if (!ok) {\n const status = response.status;\n if (superseded()) return { status: 'superseded' };\n this.log('merge HTTP', status, url);\n return superseded() ? { status: 'superseded' } : { status: 'unavailable' };\n }\n const json: () => Promise<unknown> = response.json.bind(response);\n if (superseded()) return { status: 'superseded' };\n const merged: unknown = await json();\n if (superseded()) return { status: 'superseded' };\n if (merged === null || typeof merged !== 'object' || Array.isArray(merged)) {\n this.log('merge invalid', url);\n return superseded() ? { status: 'superseded' } : { status: 'unavailable' };\n }\n const doc = merged as Record<string, unknown>;\n // Missing IDs remain compatible with projected responses. An explicit\n // identity must match the dispatched target, never mutable request data.\n const identity = doc[endpoint.field];\n const wrongIdentity =\n Object.hasOwn(doc, endpoint.field) &&\n (endpoint.field === 'id'\n ? !isSafeId(identity) || String(identity) !== endpoint.value\n : identity !== endpoint.value);\n if (superseded()) return { status: 'superseded' };\n if (wrongIdentity) {\n this.log('merge invalid', url);\n return superseded() ? { status: 'superseded' } : { status: 'unavailable' };\n }\n return { status: 'merged', doc };\n } catch (error) {\n if (superseded()) return { status: 'superseded' };\n if (legacy) {\n controller?.abort();\n if (superseded()) return { status: 'superseded' };\n }\n this.log(\n 'merge exception',\n legacy ? new Error('legacy population could not be resolved') : error,\n );\n if (superseded()) return { status: 'superseded' };\n return { status: 'unavailable' };\n } finally {\n // Only the newest attempt's controller is ever in flight: a superseded\n // attempt's is gone already, and its successor's is left alone.\n if (this.inflight === controller) this.inflight = null;\n }\n }\n\n /** Abort any in-flight merge. The merger stays usable across a stop/start cycle. */\n destroy(): void {\n this.attempt += 1;\n const inflight = this.inflight;\n this.inflight = null;\n this.destroyDepth += 1;\n try {\n inflight?.abort();\n } finally {\n this.destroyDepth -= 1;\n }\n }\n}\n","/**\n * postMessage ingress: origin and source checks, per-type shape guards, the\n * ordered preview-token validation queue, and the `ready` handshake. The bus\n * never throws; a rejected message is dropped or reported via `onInvalid`.\n * Consumer callbacks may detach or re-attach the bus synchronously, so\n * anything that runs after one re-checks the generation it started in.\n * See ADR 0004.\n */\n\nimport type {\n PayloadDocumentEventMessage,\n PayloadLivePreviewMessage,\n} from '@/types/payload-protocol';\nimport {\n focusFieldOf,\n isDocumentEventMessage,\n isLivePreviewMessage,\n isObjectMessage,\n isPlainObject,\n normalizeLivePreviewMessage,\n} from './message-guards';\nimport { LIBRARY_PROTOCOL_VERSION } from './protocol-version';\nimport { observeThenableResult } from './thenable';\n\nexport type OriginMatcher = (origin: string) => boolean;\n\n/** Identity of a data-bearing update: `revision` is monotonic, `generation` names the listener attachment. */\nexport interface MessageRevision {\n readonly revision: number;\n readonly generation: number;\n}\nexport function sameRevision(a: MessageRevision, b: MessageRevision): boolean {\n return a.generation === b.generation && a.revision === b.revision;\n}\n\nexport type InvalidReason = 'origin' | 'shape' | 'type' | 'token' | 'source';\n\nexport interface MessageHandlers {\n /** A validated update; data-bearing ones carry their revision, ready handshakes do not. */\n readonly onUpdate: (\n msg: PayloadLivePreviewMessage,\n origin: string,\n messageRevision?: MessageRevision,\n ) => void;\n /** A locally retained, previously accepted update replayed in a new lifecycle generation. */\n readonly onReplay?: (\n msg: PayloadLivePreviewMessage,\n origin: string,\n messageRevision: MessageRevision,\n ) => void;\n readonly onDocumentEvent: (msg: PayloadDocumentEventMessage, origin: string) => void;\n /** The admin reports the cursor moved into a field (reveal tier 2). */\n readonly onFocusField?: (field: string, origin: string) => void;\n readonly onInvalid?: (reason: InvalidReason, origin: string) => void;\n /** `'parent-or-opener'` refuses every window but the framing/opening one, even from an allowed origin. */\n readonly sourcePolicy?: 'any' | 'parent-or-opener';\n /**\n * Gate for data-bearing updates. Verdicts commit in arrival order, so an\n * earlier update is dispatched before a later one even when its validation\n * resolves later; an error counts as rejection.\n */\n readonly validateToken?: (\n token: string | undefined,\n origin: string,\n ) => boolean | Promise<boolean>;\n}\n\n/** One entry of the validation queue: a singly linked list in arrival order. */\ninterface PendingValidation {\n readonly generation: number;\n readonly message: PayloadLivePreviewMessage;\n readonly origin: string;\n readonly messageRevision: MessageRevision | undefined;\n /** `undefined` until the validator settled; only literal `true` approves. */\n verdict: boolean | undefined;\n next: PendingValidation | undefined;\n}\n\ninterface AcceptedUpdate {\n readonly generation: number;\n readonly message: PayloadLivePreviewMessage;\n readonly origin: string;\n}\n\n/** Keep consumer callbacks from mutating the snapshot reserved for navigation replay. */\nfunction snapshotForReplay(message: PayloadLivePreviewMessage): PayloadLivePreviewMessage | null {\n const withoutToken = { ...message };\n delete withoutToken.previewToken;\n try {\n return structuredClone(withoutToken);\n } catch {\n // A real postMessage payload is cloneable. A synthetic non-cloneable one\n // may still be processed once, but retaining it would make replay mutable.\n return null;\n }\n}\n\nexport class MessageBus {\n private readonly matcher: OriginMatcher;\n private readonly handlers: MessageHandlers;\n private boundListener: ((event: MessageEvent) => void) | undefined = undefined;\n private attachedTarget: Window | undefined = undefined;\n private generation = 0;\n private revision = 0;\n private queueHead: PendingValidation | undefined = undefined;\n private queueTail: PendingValidation | undefined = undefined;\n private lastAccepted: AcceptedUpdate | undefined = undefined;\n private replayedGeneration = 0;\n /** Identity of the newest accepted data commit, including one still crossing the clone boundary. */\n private latestAcceptedAttempt: object | undefined = undefined;\n\n constructor(matcher: OriginMatcher, handlers: MessageHandlers) {\n this.matcher = matcher;\n this.handlers = handlers;\n }\n\n /** Start listening on `target`. Idempotent. */\n attach(target: Window = window): void {\n if (this.attachedTarget !== undefined) return;\n let committed = false;\n const listener = (event: MessageEvent): void => {\n // Each attachment owns its listener; a stale one must not borrow the new generation.\n if (!committed || this.boundListener !== listener) return;\n const generation = this.generation;\n try {\n this.receive(event, generation, target);\n } catch {\n // A synthetic event can carry throwing accessors; that is a shape failure.\n let origin: string;\n try {\n origin = event.origin;\n } catch {\n origin = '';\n }\n this.reportInvalid('shape', origin, generation);\n }\n };\n this.generation += 1;\n this.resetQueue();\n this.attachedTarget = target;\n this.boundListener = listener;\n try {\n target.addEventListener('message', listener);\n } catch (error) {\n // Invalidate before rollback: a hook may already have attached a newer generation.\n if (this.boundListener === listener) {\n this.attachedTarget = undefined;\n this.boundListener = undefined;\n this.resetQueue();\n }\n try {\n target.removeEventListener('message', listener);\n } catch {\n // Keep the original failure.\n }\n throw error;\n }\n if (this.boundListener === listener) {\n committed = true;\n } else {\n try {\n target.removeEventListener('message', listener);\n } catch {\n // The listener is identity-gated above even if removal fails.\n }\n }\n }\n\n /** Stop listening. Idempotent. */\n detach(): void {\n const target = this.attachedTarget;\n const listener = this.boundListener;\n if (target === undefined || listener === undefined) return;\n // Invalidate first so a listener already on the stack sees an obsolete generation.\n this.attachedTarget = undefined;\n this.boundListener = undefined;\n this.resetQueue();\n target.removeEventListener('message', listener);\n }\n\n /** Invalidate pending validations while staying attached (heartbeat expiry). */\n advanceGeneration(): boolean {\n if (this.attachedTarget === undefined) return false;\n this.generation += 1;\n this.resetQueue();\n return true;\n }\n\n /**\n * Re-dispatch the last data-bearing update under the current generation.\n * Only an update already accepted in an older generation is eligible; its\n * preview token is never retained or replayed. @internal\n */\n replayLastAccepted(): boolean {\n const accepted = this.lastAccepted;\n const generation = this.generation;\n const handler = this.handlers.onReplay;\n if (\n handler === undefined ||\n accepted === undefined ||\n accepted.generation >= generation ||\n this.replayedGeneration === generation\n ) {\n return false;\n }\n // Origin matching fails closed outside the attached generation it ran in,\n // and it is consumer code that may accept a newer message reentrantly.\n // Never let the older snapshot run after it.\n if (!this.matchesOrigin(accepted.origin, generation) || this.lastAccepted !== accepted) {\n return false;\n }\n this.replayedGeneration = generation;\n const revision = { generation, revision: (this.revision += 1) };\n // Clone for every replay: hooks may mutate what they receive, but the\n // retained copy is the baseline for later navigations too. It came out\n // of structuredClone, so cloning it again cannot throw.\n this.invokeHandler(\n generation,\n handler,\n structuredClone(accepted.message),\n accepted.origin,\n revision,\n );\n return true;\n }\n\n /** Forget retained document data when the connection expires or the owner is destroyed. @internal */\n forgetLastAccepted(): void {\n this.lastAccepted = undefined;\n this.replayedGeneration = 0;\n this.latestAcceptedAttempt = undefined;\n }\n\n /** Post the `ready` handshake to every target for every origin. */\n static sendReady(targets: readonly Window[], origins: readonly string[]): void {\n const payload: PayloadLivePreviewMessage = {\n type: 'payload-live-preview',\n ready: true,\n protocolVersion: LIBRARY_PROTOCOL_VERSION,\n };\n for (const target of targets) {\n for (const origin of origins) {\n try {\n target.postMessage(payload, origin);\n } catch {\n // A malformed origin is the consumer's configuration problem.\n }\n }\n }\n }\n\n private receive(event: MessageEvent, generation: number, target: Window): void {\n const origin = event.origin;\n if (!this.matchesOrigin(origin, generation)) {\n this.reportInvalid('origin', origin, generation);\n return;\n }\n if (!this.matchesSource(event, target)) {\n this.reportInvalid('source', origin, generation);\n return;\n }\n const data: unknown = event.data;\n if (!isObjectMessage(data)) {\n this.reportInvalid('shape', origin, generation);\n return;\n }\n switch (data.type) {\n case 'payload-live-preview':\n if (!isLivePreviewMessage(data)) {\n this.reportInvalid('shape', origin, generation);\n return;\n }\n this.dispatchUpdate(normalizeLivePreviewMessage(data), origin, generation);\n return;\n case 'payload-document-event':\n if (!isDocumentEventMessage(data)) {\n this.reportInvalid('shape', origin, generation);\n return;\n }\n this.invokeHandler(generation, this.handlers.onDocumentEvent, data, origin);\n return;\n case 'payload-live-preview-focus': {\n const field = focusFieldOf(data);\n if (field === undefined) {\n this.reportInvalid('shape', origin, generation);\n return;\n }\n this.invokeHandler(generation, this.handlers.onFocusField, field, origin);\n return;\n }\n default:\n this.reportInvalid('type', origin, generation);\n }\n }\n\n private dispatchUpdate(\n message: PayloadLivePreviewMessage,\n origin: string,\n generation: number,\n ): void {\n const hasUpdateData = isPlainObject(message.data);\n if (!this.isCurrentGeneration(generation)) return;\n // A shape-valid data update consumes its revision before validation; a rejected token leaves a gap.\n const messageRevision = hasUpdateData\n ? { generation, revision: (this.revision += 1) }\n : undefined;\n const validator = this.handlers.validateToken;\n if (!this.isCurrentGeneration(generation)) return;\n if (validator === undefined) {\n this.commitUpdate(message, origin, generation, messageRevision);\n return;\n }\n // The data-less ready handshake carries no token and passes, so the admin learns we listen.\n if (message.ready === true && message.data === undefined) {\n this.commitUpdate(message, origin, generation, undefined);\n return;\n }\n const pending: PendingValidation = {\n generation,\n message,\n origin,\n messageRevision,\n verdict: undefined,\n next: undefined,\n };\n this.enqueue(pending);\n let verdict: unknown;\n try {\n // Invoked eagerly; only the commit waits for earlier queue entries.\n verdict = validator(message.previewToken, origin);\n } catch {\n this.settleValidation(pending, false);\n return;\n }\n if (typeof verdict === 'boolean') {\n this.settleValidation(pending, verdict);\n return;\n }\n // Assimilate any thenable; only literal `true` approves.\n void Promise.resolve(verdict).then(\n (approved) => {\n this.settleValidation(pending, approved === true);\n },\n () => {\n this.settleValidation(pending, false);\n },\n );\n }\n\n private settleValidation(pending: PendingValidation, approved: boolean): void {\n pending.verdict = approved;\n this.drainQueue(pending.generation);\n }\n\n private drainQueue(generation: number): void {\n while (this.isCurrentGeneration(generation)) {\n const pending = this.queueHead;\n if (pending === undefined) return;\n // The matcher may have narrowed since ingress (origin lock); an obsolete\n // origin must not hold the queue head and block the locked origin's work.\n if (!this.matchesOrigin(pending.origin, generation)) {\n if (!this.dequeue(pending)) continue;\n this.reportInvalid('origin', pending.origin, pending.generation);\n continue;\n }\n if (pending.verdict === undefined) return;\n if (!this.dequeue(pending)) continue;\n if (pending.verdict) {\n this.commitUpdate(\n pending.message,\n pending.origin,\n pending.generation,\n pending.messageRevision,\n );\n } else {\n this.reportInvalid('token', pending.origin, pending.generation);\n }\n }\n }\n\n private commitUpdate(\n message: PayloadLivePreviewMessage,\n origin: string,\n generation: number,\n messageRevision: MessageRevision | undefined,\n ): void {\n if (messageRevision === undefined) {\n this.invokeHandler(generation, this.handlers.onUpdate, message, origin);\n } else {\n const attempt = {};\n this.latestAcceptedAttempt = attempt;\n const snapshot = snapshotForReplay(message);\n // Cloning synthetic input can run accessors. If one accepted a newer\n // message reentrantly, the older commit must not overwrite or follow it.\n if (this.latestAcceptedAttempt !== attempt || !this.isCurrentGeneration(generation)) return;\n this.lastAccepted = snapshot === null ? undefined : { generation, message: snapshot, origin };\n this.invokeHandler(generation, this.handlers.onUpdate, message, origin, messageRevision);\n }\n }\n\n private reportInvalid(reason: InvalidReason, origin: string, generation: number): void {\n this.invokeHandler(generation, this.handlers.onInvalid, reason, origin);\n }\n\n /** Under `'parent-or-opener'`, whether the event came from the attached window's parent or opener. */\n private matchesSource(event: MessageEvent, target: Window): boolean {\n if (this.handlers.sourcePolicy !== 'parent-or-opener') return true;\n try {\n // Only a window is a source: a missing one matches nothing, not even a missing opener.\n const source: unknown = event.source;\n if (typeof source !== 'object' || source === null) return false;\n const parent = target.parent;\n if (parent !== target && source === parent) return true;\n const opener: unknown = target.opener;\n return source === opener;\n } catch {\n return false;\n }\n }\n\n /** Fail-closed: only literal `true` from the matcher, and only within the generation it ran in. */\n private matchesOrigin(origin: string, generation: number): boolean {\n try {\n const approved: unknown = this.isCurrentGeneration(generation) && this.matcher(origin);\n return approved === true && this.isCurrentGeneration(generation);\n } catch {\n return false;\n }\n }\n\n /** Callbacks run only in a current generation and must not unwind the listener or the drain. */\n private invokeHandler<TArgs extends unknown[]>(\n generation: number,\n handler: ((...args: TArgs) => unknown) | undefined,\n ...args: TArgs\n ): void {\n if (handler === undefined || !this.isCurrentGeneration(generation)) return;\n try {\n observeThenableResult(handler(...args));\n } catch {\n // Isolated by contract.\n }\n }\n\n private isCurrentGeneration(generation: number): boolean {\n return this.attachedTarget !== undefined && this.generation === generation;\n }\n\n private enqueue(pending: PendingValidation): void {\n if (this.queueTail === undefined) this.queueHead = pending;\n else this.queueTail.next = pending;\n this.queueTail = pending;\n }\n\n /** Advance the head past `expected`, unless a matcher reset the queue meanwhile. */\n private dequeue(expected: PendingValidation): boolean {\n if (this.queueHead !== expected) return false;\n this.queueHead = expected.next;\n if (this.queueHead === undefined) this.queueTail = undefined;\n return true;\n }\n\n private resetQueue(): void {\n this.queueHead = undefined;\n this.queueTail = undefined;\n }\n}\n","/**\n * Protocol negotiation. A capability is granted either by the version a peer\n * announces or by observation, since the stock Payload admin announces none:\n * what it can do is read off the messages it sends. See ADR 0010.\n */\n\n/** Bumped only when this library's understanding of the wire format changes. @internal */\nexport const LIBRARY_PROTOCOL_VERSION = 4;\n\n/** How a capability becomes active. @internal */\nexport type CapabilitySource = 'version' | 'observed';\n\n/** @internal */\nexport interface CapabilityDeclaration {\n /** Enabled once the negotiated version reaches this (for announced peers). */\n readonly since: number;\n /** The wire signal that grants this capability to a peer announcing no version. */\n readonly observed?:\n 'schema' | 'locale' | 'preview-token' | 'document-event' | 'relationship-event';\n}\n\n/** What activates each capability; the prose lives in `CAPABILITY_DOCUMENTATION`. */\nexport const CAPABILITY_DECLARATIONS = {\n basic: { since: 1 },\n 'schema-json': { since: 2, observed: 'schema' },\n locale: { since: 2, observed: 'locale' },\n 'preview-token': { since: 3, observed: 'preview-token' },\n 'nested-arrays': { since: 4 },\n 'recursive-diffs': { since: 4 },\n 'document-events': { since: 4, observed: 'document-event' },\n 'relationship-events': { since: 4, observed: 'relationship-event' },\n} as const satisfies Record<string, CapabilityDeclaration>;\n\nexport type ProtocolCapability = keyof typeof CAPABILITY_DECLARATIONS;\n\n/** Every declared capability, in declaration order. @internal */\nexport const PROTOCOL_CAPABILITIES = Object.keys(\n CAPABILITY_DECLARATIONS,\n) as readonly ProtocolCapability[];\n\nexport interface ProtocolNegotiation {\n /** This library's protocol version. */\n readonly ours: number;\n /** The remote party's version, when it announced one. */\n readonly theirs: number | undefined;\n /** `min(ours, theirs ?? 1)` — the version both sides actually share. */\n readonly negotiated: number;\n /** Capabilities active at the negotiated version or seen on the wire. */\n readonly capabilities: ReadonlySet<ProtocolCapability>;\n /** The subset that was observed on the wire rather than granted by version. */\n readonly observed: ReadonlySet<ProtocolCapability>;\n}\n\n/** Deterministic; the runtime re-runs it whenever either input changes. */\nexport function negotiateProtocol(\n theirs: number | undefined,\n observed: Iterable<ProtocolCapability> = [],\n): ProtocolNegotiation {\n const sanitisedTheirs =\n typeof theirs === 'number' && Number.isFinite(theirs) && theirs >= 1\n ? Math.floor(theirs)\n : undefined;\n const effectiveTheirs = sanitisedTheirs ?? 1;\n const negotiated = Math.min(LIBRARY_PROTOCOL_VERSION, effectiveTheirs);\n const seen = new Set<ProtocolCapability>(observed);\n const capabilities = new Set<ProtocolCapability>();\n for (const capability of PROTOCOL_CAPABILITIES) {\n if (negotiated >= CAPABILITY_DECLARATIONS[capability].since || seen.has(capability)) {\n capabilities.add(capability);\n }\n }\n return {\n ours: LIBRARY_PROTOCOL_VERSION,\n ...(sanitisedTheirs !== undefined ? { theirs: sanitisedTheirs } : { theirs: undefined }),\n negotiated,\n capabilities,\n observed: seen,\n };\n}\n\n/** @internal */\nexport function hasCapability(\n negotiation: ProtocolNegotiation,\n capability: ProtocolCapability,\n): boolean {\n return negotiation.capabilities.has(capability);\n}\n\n/** The capabilities a single message demonstrates, by its shape alone. */\nexport function observeCapabilities(message: {\n readonly fieldSchemaJSON?: unknown;\n readonly locale?: unknown;\n readonly previewToken?: unknown;\n readonly externallyUpdatedRelationship?: unknown;\n}): readonly ProtocolCapability[] {\n const seen: ProtocolCapability[] = [];\n if (Array.isArray(message.fieldSchemaJSON)) seen.push('schema-json');\n if (typeof message.locale === 'string') seen.push('locale');\n if (typeof message.previewToken === 'string') seen.push('preview-token');\n if (\n typeof message.externallyUpdatedRelationship === 'object' &&\n message.externallyUpdatedRelationship !== null\n ) {\n seen.push('relationship-events');\n }\n return seen;\n}\n","/**\n * Which admin origins the runtime trusts: explicit ones always, the\n * `document.referrer` origin only when none is configured, any localhost port\n * in development. See docs/security.md §1. The handshake goes to the trusted\n * origins, and to guessed localhost ports only while the browser names no parent.\n */\n\nimport { isDevMode, isInIframe } from './environment';\n\nconst LOCALHOST_PATTERN = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(?::\\d+)?$/i;\nconst VALID_ORIGIN_PATTERN = /^https?:\\/\\/[^/?#\\s]+$/i;\n\n/** Ports the handshake broadcasts to when the localhost pattern is on; matching itself is unrestricted. */\nconst LOCALHOST_HANDSHAKE_PORTS: readonly number[] = [\n 3000, 3001, 3333, 4000, 4321, 5000, 5173, 5174, 8000, 8080, 8888, 9000,\n];\n\nexport interface OriginDetectorOptions {\n /** Explicit origins to trust. Always allowed. */\n readonly additionalOrigins?: readonly string[];\n /** Set to `false` to ignore `document.referrer`. */\n readonly enableReferrerDetection?: boolean;\n /** Set to `false` to ignore the localhost pattern even in development. */\n readonly enableLocalhostMatching?: boolean;\n /** Override dev-mode detection. */\n readonly forceDevMode?: boolean;\n /** Override `document.referrer` for tests. */\n readonly referrer?: string;\n}\n\nconst enum OriginSlot {\n ExplicitOrigins,\n ReferrerOrigin,\n AllowLocalhost,\n ReferrerWasAvailable,\n LockedOrigin,\n ParentOrigin,\n}\n\ntype OriginState = [\n explicitOrigins: ReadonlySet<string>,\n referrerOrigin: string | undefined,\n allowLocalhost: boolean,\n referrerWasAvailable: boolean,\n lockedOrigin: string | undefined,\n parentOrigin: string | undefined,\n];\n\n/**\n * The framing parent's origin, where the browser names it: Chromium and WebKit\n * do (`location.ancestorOrigins`), Firefox does not. Never a trust source, only\n * where the handshake is worth sending.\n */\nfunction readParentOrigin(): string | undefined {\n if (typeof location === 'undefined') return undefined;\n const ancestors = (location as { readonly ancestorOrigins?: ArrayLike<string> }).ancestorOrigins;\n return ancestors?.[0];\n}\n\n/** The trusted-origin policy: the union of the candidate sources, narrowed to one by `lockOrigin()`. */\nexport class OriginDetector {\n readonly #state: OriginState;\n\n constructor(options: OriginDetectorOptions = {}) {\n const explicit = new Set<string>();\n for (const origin of options.additionalOrigins ?? []) {\n const normalised = normaliseOrigin(origin);\n if (normalised !== undefined) explicit.add(normalised);\n }\n let referrerOrigin: string | undefined;\n if (options.enableReferrerDetection ?? true) {\n const referrer =\n options.referrer ?? (typeof document !== 'undefined' ? document.referrer : '');\n if (referrer.length > 0) {\n try {\n const origin = new URL(referrer).origin;\n if (origin && origin !== 'null') referrerOrigin = origin;\n } catch {\n // opaque referrer\n }\n }\n }\n const allowLocalhost =\n (options.enableLocalhostMatching ?? true) && (options.forceDevMode ?? isDevMode());\n this.#state = [\n explicit,\n referrerOrigin,\n allowLocalhost,\n referrerOrigin !== undefined,\n undefined,\n readParentOrigin(),\n ];\n }\n\n /** Whether `origin` is trusted: the locked origin alone once locked, otherwise the policy above. */\n matches(origin: string): boolean {\n if (origin.length === 0 || origin === 'null') return false;\n if (this.#state[OriginSlot.LockedOrigin] !== undefined) {\n return origin === this.#state[OriginSlot.LockedOrigin];\n }\n if (this.#state[OriginSlot.ExplicitOrigins].has(origin)) return true;\n // The referrer is a fallback, not a union member: any embedder lands there.\n if (\n this.#state[OriginSlot.ExplicitOrigins].size === 0 &&\n this.#state[OriginSlot.ReferrerOrigin] !== undefined &&\n origin === this.#state[OriginSlot.ReferrerOrigin]\n ) {\n return true;\n }\n if (this.#state[OriginSlot.AllowLocalhost] && LOCALHOST_PATTERN.test(origin)) return true;\n return false;\n }\n\n /** Narrow trust to `origin`; refused (`false`) when it is not currently trusted. */\n lockOrigin(origin: string): boolean {\n if (!this.matches(origin)) return false;\n this.#state[OriginSlot.LockedOrigin] = origin;\n return true;\n }\n\n /** Release the lock (heartbeat timeout) so another allow-listed origin may reconnect. Returns the previous lock. */\n unlockOrigin(): string | undefined {\n const previous = this.#state[OriginSlot.LockedOrigin];\n this.#state[OriginSlot.LockedOrigin] = undefined;\n return previous;\n }\n\n get lockedOrigin(): string | undefined {\n return this.#state[OriginSlot.LockedOrigin];\n }\n\n /**\n * Every origin the `ready` handshake is broadcast to. The localhost pattern\n * expands to the common dev ports, a guess that costs a console error per\n * wrong port, so a parent the browser names replaces it: that origin when the\n * pattern trusts it, none when it is not on localhost.\n */\n enumerate(): string[] {\n if (this.#state[OriginSlot.LockedOrigin] !== undefined) {\n return [this.#state[OriginSlot.LockedOrigin]];\n }\n const result = new Set<string>(this.#state[OriginSlot.ExplicitOrigins]);\n if (\n this.#state[OriginSlot.ExplicitOrigins].size === 0 &&\n this.#state[OriginSlot.ReferrerOrigin] !== undefined\n ) {\n result.add(this.#state[OriginSlot.ReferrerOrigin]);\n }\n const parent = this.#state[OriginSlot.ParentOrigin];\n if (this.#state[OriginSlot.AllowLocalhost] && parent !== undefined) {\n if (LOCALHOST_PATTERN.test(parent)) result.add(parent);\n } else if (this.#state[OriginSlot.AllowLocalhost]) {\n for (const port of LOCALHOST_HANDSHAKE_PORTS) {\n result.add(`http://localhost:${String(port)}`);\n result.add(`http://127.0.0.1:${String(port)}`);\n }\n }\n return [...result];\n }\n\n /** Whether `document.referrer` contributed an origin (absent under `Referrer-Policy: no-referrer`). */\n get referrerWasAvailable(): boolean {\n return this.#state[OriginSlot.ReferrerWasAvailable];\n }\n\n /** Framed, outside development, with no trusted origin at all: the host should warn (LP0101). */\n get isProductionUnconfigured(): boolean {\n if (!isInIframe()) return false;\n if (this.#state[OriginSlot.ExplicitOrigins].size > 0) return false;\n if (this.#state[OriginSlot.AllowLocalhost]) return false;\n if (this.#state[OriginSlot.ReferrerOrigin] !== undefined) return false;\n return true;\n }\n\n /** The referrer is the only trust source, so any framing site may drive the preview (LP0102). */\n get isReferrerOnlyTrust(): boolean {\n if (this.#state[OriginSlot.ExplicitOrigins].size > 0) return false;\n if (this.#state[OriginSlot.AllowLocalhost]) return false;\n return this.#state[OriginSlot.ReferrerOrigin] !== undefined;\n }\n}\n\n/** The canonical `http(s)://host[:port]` form of `value`, or `undefined` when it is not one. */\nexport function normaliseOrigin(value: string): string | undefined {\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n try {\n const url = new URL(trimmed);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return undefined;\n if (!VALID_ORIGIN_PATTERN.test(url.origin)) return undefined;\n return url.origin;\n } catch {\n return undefined;\n }\n}\n","/**\n * Where the runtime is running: framed, opened, or on a developer's machine.\n * Nothing reads bundler-injected variables; a Vite consumer passes\n * `import.meta.env.X` explicitly (docs/astro.md).\n * @internal\n */\n\nexport function isInIframe(): boolean {\n if (typeof window === 'undefined') return false;\n try {\n return window.self !== window.top;\n } catch {\n // A cross-origin parent throws on the comparison; that is an iframe.\n return true;\n }\n}\n\n/** @internal */\nexport function isInPopup(): boolean {\n if (typeof window === 'undefined') return false;\n return window.opener != null;\n}\n\n/** An iframe or a popup; top-level navigation never starts the preview. @internal */\nexport function isInPreviewContext(): boolean {\n return isInIframe() || isInPopup();\n}\n\n/** Under Node, `NODE_ENV !== 'production'`; in a browser the hostname, which is the only signal a bundle has. @internal */\nexport function isDevMode(): boolean {\n const nodeEnv = readNodeEnv();\n if (nodeEnv !== undefined) return nodeEnv !== 'production';\n if (typeof window !== 'undefined') {\n const host = window.location.hostname;\n return host === 'localhost' || host === '127.0.0.1';\n }\n return false;\n}\n\nfunction readNodeEnv(): string | undefined {\n if (typeof process === 'undefined') return undefined;\n const value = process.env['NODE_ENV'];\n return typeof value === 'string' ? value : undefined;\n}\n","/**\n * The document a framework hook exposes, kept outside any framework: the\n * message bus decides which windows may speak, `DataMerger` turns the admin's\n * raw form values back into a populated document, and this class holds the one\n * snapshot a `useSyncExternalStore`-shaped API reads.\n *\n * It touches no DOM. A hook that re-renders a component tree needs the data,\n * not the bindings — everything about elements lives in the runtime instead.\n *\n * The session is per instance (ADR 0002): two hooks on one page have two\n * mergers, two revisions and two snapshots, so a request or an error in one\n * never reaches the other. Both follow the document the admin sends: a session\n * merges every message the bus lets through, whichever document it started from.\n */\n\nimport { DataMerger } from '@core/data-merger';\nimport { MessageBus } from '@core/message-bus';\nimport { OriginDetector } from '@detection/origin';\nimport type { PayloadFieldSchema, PayloadLivePreviewMessage } from '@/types/payload-protocol';\n\n/**\n * `idle` — connected, nothing received yet. `live` — the newest update was\n * merged and is in `data`. `unavailable` — it could not be, and `data` is the\n * last good document rather than a half-merged one.\n */\nexport type DocumentStatus = 'idle' | 'live' | 'unavailable';\n\nexport interface DocumentSnapshot<T> {\n /** The newest document that merged; never a partially applied one. */\n readonly data: T;\n /** No update has settled yet, or a merge is in flight. */\n readonly isLoading: boolean;\n readonly status: DocumentStatus;\n /** Why the last update did not merge; `undefined` while `status` is not `unavailable`. */\n readonly error: Error | undefined;\n /**\n * Which of this session's messages `data` came from: `0` for the initial\n * data, and unchanged when a merge fails. The framework paints `data` in its\n * own commit; a component that must know it was painted compares this in an\n * effect (ADR 0023).\n */\n readonly revision: number;\n}\n\nexport interface DocumentSessionOptions {\n /** Payload server origin the update is re-fetched from. */\n readonly serverURL: string;\n /** REST route prefix. Default `/api`. */\n readonly apiRoute?: string;\n /** Population depth for the merge. Default `1`, as Payload's own hook. */\n readonly depth?: number;\n /**\n * Admin origins allowed to post updates. Without one the session falls back\n * to the localhost matcher in development and trusts nothing in production.\n */\n readonly allowedOrigins?: readonly string[];\n /** `'parent-or-opener'` (default) refuses every window but the framing or opening one. */\n readonly eventSourcePolicy?: 'any' | 'parent-or-opener';\n /** Trust `document.referrer` as an origin source. Default `false`. */\n readonly enableReferrerDetection?: boolean;\n /** Match `localhost` origins in development. Default `true`. */\n readonly enableLocalhostMatching?: boolean;\n /** Injected for tests. */\n readonly fetchFn?: typeof fetch;\n /** Window to listen on. Default the global one. */\n readonly target?: Window;\n}\n\ntype Listener = () => void;\n\n/** What the merger logged for the attempt that failed, turned into one sentence. */\nfunction reasonFrom(line: readonly unknown[]): string {\n const [label, detail] = line;\n if (label === 'merge HTTP') return `the server answered ${String(detail)}`;\n if (label === 'merge invalid') return 'the server answered with something other than a document';\n if (label === 'merge exception') {\n return detail instanceof Error ? detail.message : 'the request failed';\n }\n return 'the update could not be merged';\n}\n\nexport class DocumentSession<T> {\n readonly #merger: DataMerger;\n readonly #bus: MessageBus;\n readonly #detector: OriginDetector;\n readonly #target: Window | undefined;\n readonly #listeners = new Set<Listener>();\n readonly #initial: DocumentSnapshot<T>;\n #snapshot: DocumentSnapshot<T>;\n /** Newest handled message; an older merge that settles later is ignored. */\n #revision = 0;\n #lastLog: readonly unknown[] = [];\n #attached = false;\n #schema: readonly PayloadFieldSchema[] | undefined;\n #locale: string | undefined;\n\n constructor(initialData: T, options: DocumentSessionOptions) {\n this.#detector = new OriginDetector({\n ...(options.allowedOrigins !== undefined\n ? { additionalOrigins: options.allowedOrigins }\n : {}),\n enableReferrerDetection: options.enableReferrerDetection ?? false,\n ...(options.enableLocalhostMatching !== undefined\n ? { enableLocalhostMatching: options.enableLocalhostMatching }\n : {}),\n });\n this.#merger = new DataMerger({\n serverURL: options.serverURL,\n ...(options.apiRoute !== undefined ? { apiRoute: options.apiRoute } : {}),\n ...(options.depth !== undefined ? { depth: options.depth } : {}),\n ...(options.fetchFn !== undefined ? { fetchFn: options.fetchFn } : {}),\n log: (...args: unknown[]) => {\n this.#lastLog = args;\n },\n });\n this.#bus = new MessageBus((origin) => this.#detector.matches(origin), {\n onUpdate: (message) => {\n void this.#handle(message);\n },\n onDocumentEvent: () => {\n // A save is the admin's business; the document itself arrives as an\n // update like any other.\n },\n sourcePolicy: options.eventSourcePolicy ?? 'parent-or-opener',\n });\n this.#target = options.target;\n this.#initial = {\n data: initialData,\n isLoading: true,\n status: 'idle',\n error: undefined,\n revision: 0,\n };\n this.#snapshot = this.#initial;\n }\n\n /**\n * Attach on the first subscriber and detach with the last, so a component\n * that mounts twice (React's strict mode) listens once and a page that\n * unmounts the hook stops listening at all.\n */\n subscribe = (listener: Listener): (() => void) => {\n this.#listeners.add(listener);\n if (!this.#attached) this.#attach();\n return () => {\n this.#listeners.delete(listener);\n if (this.#listeners.size === 0) this.#detach();\n };\n };\n\n getSnapshot = (): DocumentSnapshot<T> => this.#snapshot;\n\n /** Server rendering has no window and no messages: the initial snapshot a client render starts from. */\n getServerSnapshot = (): DocumentSnapshot<T> => this.#initial;\n\n #attach(): void {\n if (typeof window === 'undefined' && this.#target === undefined) return;\n this.#attached = true;\n this.#bus.attach(this.#target ?? window);\n MessageBus.sendReady(this.#readyTargets(), this.#detector.enumerate());\n }\n\n #detach(): void {\n if (!this.#attached) return;\n this.#attached = false;\n this.#revision += 1;\n this.#bus.detach();\n this.#merger.destroy();\n }\n\n #readyTargets(): Window[] {\n const host = this.#target ?? (typeof window === 'undefined' ? undefined : window);\n if (host === undefined) return [];\n const targets: Window[] = [];\n if (host.parent !== host) targets.push(host.parent);\n const opener: unknown = host.opener;\n if (opener !== null && opener !== undefined && opener !== host) targets.push(opener as Window);\n return targets;\n }\n\n #current(revision: number): boolean {\n return this.#attached && revision === this.#revision;\n }\n\n async #handle(message: PayloadLivePreviewMessage): Promise<void> {\n const data = message.data;\n if (data === undefined) return;\n const revision = (this.#revision += 1);\n if (message.fieldSchemaJSON !== undefined) this.#schema = message.fieldSchemaJSON;\n const schema = this.#schema;\n if (message.locale !== undefined) this.#locale = message.locale;\n const locale = schema === undefined ? message.locale : this.#locale;\n this.#publish({ ...this.#snapshot, isLoading: true });\n if (!this.#current(revision)) return;\n this.#lastLog = [];\n const result = await this.#merger.merge({\n data,\n ...(schema === undefined ? {} : { schema }),\n ...(message.collectionSlug !== undefined ? { collectionSlug: message.collectionSlug } : {}),\n ...(message.globalSlug !== undefined ? { globalSlug: message.globalSlug } : {}),\n ...(locale !== undefined ? { locale } : {}),\n });\n // A newer message owns the state now, whatever this one turned out to be.\n if (!this.#current(revision)) return;\n if (result.status === 'superseded') return;\n if (result.status === 'unavailable') {\n this.#publish({\n ...this.#snapshot,\n isLoading: false,\n status: 'unavailable',\n error: new Error(`live preview: ${reasonFrom(this.#lastLog)}`),\n });\n return;\n }\n // The server decides the document's shape; `T` is what the caller says it is.\n this.#publish({\n data: result.doc as T,\n isLoading: false,\n status: 'live',\n error: undefined,\n revision,\n });\n }\n\n #publish(next: DocumentSnapshot<T>): void {\n const current = this.#snapshot;\n if (\n current.data === next.data &&\n current.isLoading === next.isLoading &&\n current.status === next.status &&\n current.error === next.error &&\n current.revision === next.revision\n ) {\n return;\n }\n this.#snapshot = next;\n for (const listener of [...this.#listeners]) listener();\n }\n}\n","/**\n * The seam between a host framework's own router and the route strategy.\n *\n * The route strategy answers a revision by fetching the route and morphing it\n * into the living page. On a page whose DOM belongs to a reconciler that is\n * working against the framework, and it was seen to break once: `removeChild`\n * on `null` inside React's commit phase, over markup this package had patched.\n * A host that re-renders the route itself does the same job without the morph\n * and without the second HTML request, so it is given the chance to.\n *\n * Why a named slot on `window` and not a reference: the runtime is an inline\n * script that builds its strategy before any application code has hydrated, so\n * there is nothing to hand a component; `window.__livePreview`, the only other\n * public surface, is created later and not at all outside a preview; and the\n * two richer extension points — plugins and events — are reachable only through\n * the programmatic client, which a page using an adapter does not have. One\n * slot, written by whoever mounts and read at the moment of a refresh, is the\n * smallest thing that survives both orders of arrival.\n */\n\n/**\n * A host's own route refresh. It must settle once the fresh markup is\n * committed: the runtime re-applies the revision on top of it, and doing that\n * against the markup being replaced would write into nodes about to be dropped.\n * A function that returns nothing is taken as already committed; the route\n * strategy says once that it could not wait (LP0810), and 3.0 requires the\n * promise (ADR 0028).\n */\nexport type RouteRefresh = () => void | Promise<void>;\n\n/** Read late, so it does not matter whether the runtime or the component came first. */\nconst SLOT = '__livePreviewRouteRefresh';\n\ntype WindowSlot = Record<string, RouteRefresh | undefined>;\n\nfunction slot(): WindowSlot | undefined {\n return typeof window === 'undefined' ? undefined : (window as unknown as WindowSlot);\n}\n\n/**\n * Lend the runtime the host's route refresh; the return value undoes it, for a\n * component's cleanup. A later registration wins, and undoing one that has\n * already been replaced does nothing — two components on one page would\n * otherwise take the slot from each other on unmount.\n */\nexport function registerRouteRefresh(refresh: RouteRefresh): () => void {\n const target = slot();\n if (target === undefined) return () => undefined;\n target[SLOT] = refresh;\n return () => {\n // Cleared rather than deleted: the slot is read through `?.` anyway, and\n // removing the key buys nothing a lint rule would not have to be argued out of.\n if (target[SLOT] === refresh) target[SLOT] = undefined;\n };\n}\n\n/** The registered refresh, or `undefined` on a page that registered none. */\nexport function readRouteRefresh(): RouteRefresh | undefined {\n return slot()?.[SLOT];\n}\n","/**\n * `<LivePreviewRouteRefresh />` — lends the runtime the host router's own\n * refresh, so a route update is a re-render the framework performs rather than\n * fresh HTML this package morphs over the reconciler's nodes (see\n * `src/core/route-refresh.ts` for why that is worth avoiding).\n *\n * It takes the refresh as a prop instead of reaching for `next/navigation`,\n * because `next` is not a dependency of this package and must not become one\n * for a component this small. In Next's App Router that is one client\n * component:\n *\n * ```tsx\n * 'use client';\n * import { useRouter } from 'next/navigation';\n * import { LivePreviewRouteRefresh } from 'payload-live-preview/react';\n *\n * export function LivePreviewRefresh() {\n * return <LivePreviewRouteRefresh refresh={useRouter().refresh} />;\n * }\n * ```\n *\n * The same component serves any router with a refresh of that shape.\n */\n\nimport { useEffect, useRef, useTransition } from 'react';\nimport { registerRouteRefresh } from '@core/route-refresh';\n\nexport interface LivePreviewRouteRefreshProps {\n /** The host router's refresh — `useRouter().refresh` in Next's App Router. */\n readonly refresh: () => void;\n}\n\n/** Resolve everyone waiting on the transition that has just finished. */\nfunction settle(waiting: { current: (() => void)[] }): void {\n const settled = waiting.current;\n waiting.current = [];\n for (const resolve of settled) resolve();\n}\n\n/**\n * Renders nothing. Mount it once inside the preview tree; a second one takes\n * the registration from the first, and unmounting gives it back.\n */\nexport function LivePreviewRouteRefresh({ refresh }: LivePreviewRouteRefreshProps): null {\n const [pending, startTransition] = useTransition();\n const waiting = useRef<(() => void)[]>([]);\n\n // The runtime re-applies the revision on top of the fresh markup, so the\n // refresh it is given may not resolve before that markup is committed. The\n // transition is what makes that observable: it is pending until React has\n // rendered the new server output, and this effect runs on the commit after.\n useEffect(() => {\n if (!pending) settle(waiting);\n });\n\n useEffect(() => {\n const undo = registerRouteRefresh(\n () =>\n new Promise<void>((resolve) => {\n waiting.current.push(resolve);\n startTransition(() => {\n refresh();\n });\n }),\n );\n // A tree that unmounts mid-refresh will never commit one, so the waiting\n // runtime is released here rather than left holding a promise for good.\n return () => {\n undo();\n settle(waiting);\n };\n }, [refresh, startTransition]);\n\n return null;\n}\n","/**\n * The React hook: Payload's `useLivePreview` shape, with this package's merge\n * underneath — one request per accepted update, a newer one aborting the one in\n * flight, an HTTP error refused instead of becoming the document, and a session\n * that belongs to this hook alone (ADR 0002).\n *\n * It re-renders your component tree, so conditional sections and derived values\n * follow the merged document. React preserves component and DOM state while\n * type, key and position stay stable; a remount or replaced node loses the\n * state it held. The DOM runtime uses direct writes and a keyed morph instead\n * (docs/react.md).\n *\n * `react` is an optional peer. This entry imports it at module scope; `./nextjs`\n * loads it, and `react-dom/server`, only at the first render that needs them.\n *\n * The published file starts with `'use client'`. It is not written here because\n * esbuild drops a module directive when it bundles, and a banner with it; the\n * build writes it back through terser's `preamble` (`DIRECTIVE_ENTRIES` in\n * scripts/package-entries.ts, applied in scripts/build-dist.ts).\n */\n\nimport { useRef, useSyncExternalStore } from 'react';\nimport {\n DocumentSession,\n type DocumentSessionOptions,\n type DocumentSnapshot,\n type DocumentStatus,\n} from '@adapters/shared/document-session';\n\nexport type { DocumentSessionOptions, DocumentSnapshot, DocumentStatus };\n\nexport { LivePreviewRouteRefresh, type LivePreviewRouteRefreshProps } from './route-refresh';\nexport { registerRouteRefresh, type RouteRefresh } from '@core/route-refresh';\n\nexport interface UseLivePreviewDocumentOptions<T> extends DocumentSessionOptions {\n /** The document this session starts from; create a new hook instance to switch documents. */\n readonly initialData: T;\n}\n\n/**\n * Subscribe to the admin's updates and return the merged document.\n *\n * ```tsx\n * const { data, status } = useLivePreviewDocument<Page>({\n * serverURL: process.env.NEXT_PUBLIC_PAYLOAD_URL!,\n * allowedOrigins: [process.env.NEXT_PUBLIC_PAYLOAD_ADMIN_ORIGIN!],\n * initialData: page,\n * depth: 1,\n * });\n * ```\n *\n * Returns `{ data, isLoading }` as Payload's hook does, plus `status` and\n * `error`: a merge that fails keeps the last good document instead of leaving\n * the page on a stale one with no way to tell.\n */\nexport function useLivePreviewDocument<T>(\n options: UseLivePreviewDocumentOptions<T>,\n): DocumentSnapshot<T> {\n const session = useSessionFor(options);\n return useSyncExternalStore(session.subscribe, session.getSnapshot, session.getServerSnapshot);\n}\n\n/**\n * One session per hook instance, rebuilt only when a connection option changes.\n * `initialData` is deliberately not one of them: a re-render with a fresh object\n * identity must not throw away a document that already merged.\n */\nfunction useSessionFor<T>(options: UseLivePreviewDocumentOptions<T>): DocumentSession<T> {\n const {\n initialData,\n serverURL,\n apiRoute,\n depth,\n allowedOrigins,\n eventSourcePolicy,\n enableReferrerDetection,\n enableLocalhostMatching,\n fetchFn,\n target,\n } = options;\n const key = [\n serverURL,\n apiRoute ?? '',\n String(depth ?? ''),\n (allowedOrigins ?? []).join(' '),\n eventSourcePolicy ?? '',\n String(enableReferrerDetection ?? ''),\n String(enableLocalhostMatching ?? ''),\n // A separator no origin, route prefix or policy name can contain.\n ].join(' | ');\n const held = useRef<{\n key: string;\n target: Window | undefined;\n session: DocumentSession<T>;\n } | null>(null);\n if (held.current?.key !== key || held.current.target !== target) {\n held.current = {\n key,\n target,\n session: new DocumentSession<T>(initialData, {\n serverURL,\n ...(apiRoute !== undefined ? { apiRoute } : {}),\n ...(depth !== undefined ? { depth } : {}),\n ...(allowedOrigins !== undefined ? { allowedOrigins } : {}),\n ...(eventSourcePolicy !== undefined ? { eventSourcePolicy } : {}),\n ...(enableReferrerDetection !== undefined ? { enableReferrerDetection } : {}),\n ...(enableLocalhostMatching !== undefined ? { enableLocalhostMatching } : {}),\n ...(fetchFn !== undefined ? { fetchFn } : {}),\n ...(target !== undefined ? { target } : {}),\n }),\n };\n }\n return held.current.session;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["observeThenableResult","value","then","Promise","resolve","catch","noopDiagnostic","visit","state","nodes","Error","enter","depth","active","has","add","parseFieldSchema","raw","parseFields","WeakSet","Array","isArray","out","entry","parsed","parseFieldEntry","push","delete","record","name","type","length","fields","blocks","slug","Object","hasOwn","Reflect","get","includes","parseBlockSchema","result","relationTo","targets","target","optionalFieldOk","check","optionalTypeOk","isPlainObject","prototype","getPrototypeOf","NULL_AS_ABSENT_FIELDS","MAX_NODES","MAX_BODY","FORBIDDEN","Set","fail","hasControl","index","code","charCodeAt","segment","maximum","encodeURIComponent","test","id","Number","isFinite","String","own","key","put","defineProperty","writable","configurable","enumerable","stripTrailingSlashes","end","slice","copyLegacyData","characters","copy","keys","planLegacyPopulation","data","schema","serverURL","apiRoute","locale","isSafeInteger","doc","groups","Map","unique","tick","level","relation","owner","collection","selected","identity","scope","JSON","stringify","size","slots","set","fieldRelation","field","hasMany","allowed","selectedCollection","candidate","rich","walk","i","row","blockType","block","find","requests","base","URL","protocol","username","password","search","hash","startsWith","split","some","part","prefix","identities","map","slot","first","comma","chunk","url","next","proposed","query","URLSearchParams","limit","join","origin","ids","filter","async","populationBody","response","signal","current","reader","cancelled","finished","obsolete","Symbol","interrupt","interrupted","aborted","cancel","abort","addEventListener","once","body","json","bind","race","getReader","activeReader","chunks","bytes","count","pending","read","done","byteLength","Uint8Array","position","parse","TextDecoder","decode","removeEventListener","releaseLock","fillLegacyPopulation","request","safe","docs","found","isPathSegment","maxLength","character","codePoint","codePointAt","hasControlCharacter","isSafeSlug","isSafeId","TIMED_OUT","DataMerger","fetchFn","log","timeoutMs","inflight","attempt","destroyDepth","constructor","options","this","endsWith","withoutTrailingSlashes","route","diagnostic","args","POSITIVE_INFINITY","canMerge","endpointOf","globalSlug","path","collectionSlug","merge","status","previous","controller","legacy","superseded","timer","deadline","within","work","owned","_resolve","reject","setTimeout","plan","fetch","AbortController","population","method","credentials","redirect","ok","endpoint","flattenLocales","headers","merged","wrongIdentity","error","clearTimeout","destroy","MessageBus","matcher","handlers","boundListener","attachedTarget","generation","revision","queueHead","queueTail","lastAccepted","replayedGeneration","latestAcceptedAttempt","attach","window","committed","listener","event","receive","reportInvalid","resetQueue","detach","advanceGeneration","replayLastAccepted","accepted","handler","onReplay","matchesOrigin","invokeHandler","structuredClone","message","forgetLastAccepted","sendReady","origins","payload","ready","protocolVersion","postMessage","matchesSource","v","x","isLivePreviewMessage","dispatchUpdate","normalized","deleteProperty","fieldSchemaJSON","normalizeLivePreviewMessage","isDocumentEventMessage","onDocumentEvent","focusFieldOf","onFocusField","hasUpdateData","isCurrentGeneration","messageRevision","validator","validateToken","commitUpdate","verdict","enqueue","previewToken","settleValidation","approved","drainQueue","dequeue","onUpdate","snapshot","withoutToken","snapshotForReplay","reason","onInvalid","sourcePolicy","source","parent","opener","expected","isDevMode","nodeEnv","process","env","readNodeEnv","host","location","hostname","LOCALHOST_PATTERN","VALID_ORIGIN_PATTERN","LOCALHOST_HANDSHAKE_PORTS","readParentOrigin","ancestors","ancestorOrigins","OriginDetector","explicit","additionalOrigins","normalised","normaliseOrigin","referrerOrigin","enableReferrerDetection","referrer","document","allowLocalhost","enableLocalhostMatching","forceDevMode","matches","lockOrigin","unlockOrigin","lockedOrigin","enumerate","port","referrerWasAvailable","isProductionUnconfigured","isInIframe","self","top","isReferrerOnlyTrust","trimmed","trim","reasonFrom","line","label","detail","DocumentSession","merger","bus","detector","listeners","initial","lastLog","attached","warnedUnproven","warnedPayload2","initialData","allowedOrigins","handle","eventSourcePolicy","isLoading","subscribe","getSnapshot","getServerSnapshot","readyTargets","accepts","global","readDocumentId","warnUnproven","named","console","warn","publish","SLOT","registerRouteRefresh","refresh","settle","waiting","settled","LivePreviewRouteRefresh","startTransition","useTransition","useRef","useEffect","undo","useLivePreviewDocument","session","held","useSessionFor","useSyncExternalStore"],"sources":["../../../src/core/thenable.ts","../../../src/core/diagnostics.ts","../../../src/schema/parser.ts","../../../src/core/message-guards.ts","../../../src/core/legacy-population.ts","../../../src/core/data-merger.ts","../../../src/core/message-bus.ts","../../../src/core/protocol-version.ts","../../../src/detection/environment.ts","../../../src/detection/origin.ts","../../../src/adapters/shared/document-session.ts","../../../src/core/binding-owner.ts","../../../src/core/route-refresh.ts","../../../src/adapters/react/route-refresh.ts","../../../src/adapters/react/index.ts"],"sourcesContent":["/**\n * Detect an invalid async result in a synchronous extension point.\n *\n * Rejected native Promises otherwise become unhandled after the caller falls\n * back synchronously. Assimilating the result through a handled Promise keeps\n * that contract violation observable only through the runtime's explicit\n * error channel.\n */\nexport function observeThenableResult(value: unknown): boolean {\n if ((typeof value !== 'object' || value === null) && typeof value !== 'function') return false;\n if (typeof (value as { readonly then?: unknown }).then !== 'function') return false;\n void Promise.resolve(value).catch(() => undefined);\n return true;\n}\n","import { observeThenableResult } from './thenable';\n\n/**\n * Diagnostics are observability, never control flow: a consumer logger may\n * throw or return a rejected thenable, and reporting a failure must not become\n * a second failure. Invocation stays synchronous for ordinary loggers.\n */\nexport function isolateDiagnostic(\n diagnostic: (...args: unknown[]) => unknown,\n): (...args: unknown[]) => void {\n return (...args): void => {\n try {\n observeThenableResult(diagnostic(...args));\n } catch {\n // Diagnostics must not become a second failure boundary.\n }\n };\n}\n\n/** Shared allocation-free default for disabled diagnostic channels. */\nexport function noopDiagnostic(): void {\n // Intentionally empty.\n}\n\n// Access, invocation and thenable inspection all happen inside the wrapper, so\n// a missing or hostile console cannot escape.\nexport const safeConsoleError = isolateDiagnostic((...args) =>\n (console.error as (...values: unknown[]) => unknown)(...args),\n);\n\nexport const safeConsoleWarn = isolateDiagnostic((...args) =>\n (console.warn as (...values: unknown[]) => unknown)(...args),\n);\n\nexport const safeConsoleDebug = isolateDiagnostic((...args) =>\n // eslint-disable-next-line no-console -- best-effort development diagnostics\n (console.debug as (...values: unknown[]) => unknown)(...args),\n);\n","/**\n * Validates the `fieldSchemaJSON` the admin sends. Entries that fail\n * validation are dropped, never thrown: a Payload/runtime version mismatch\n * must not take the preview down.\n */\n\nimport type { PayloadBlockSchema, PayloadFieldSchema } from '@/types/payload-protocol';\n\ninterface ParseState {\n nodes: number;\n readonly active: WeakSet<object>;\n}\nfunction visit(state: ParseState): void {\n if (++state.nodes > 10_000) throw new Error('invalid or oversized field schema');\n}\nfunction enter(value: object, state: ParseState, depth: number): void {\n visit(state);\n if (depth > 64 || state.active.has(value)) throw new Error('invalid or oversized field schema');\n state.active.add(value);\n}\n\nexport function parseFieldSchema(raw: unknown): readonly PayloadFieldSchema[] {\n try {\n return parseFields(raw, { nodes: 0, active: new WeakSet() }, 0);\n } catch {\n return [];\n }\n}\n\nfunction parseFields(\n raw: unknown,\n state: ParseState,\n depth: number,\n): readonly PayloadFieldSchema[] {\n if (!Array.isArray(raw)) return [];\n enter(raw, state, depth);\n const out: PayloadFieldSchema[] = [];\n for (const entry of raw) {\n const parsed = parseFieldEntry(entry, state, depth);\n if (parsed) out.push(parsed);\n }\n state.active.delete(raw);\n return out;\n}\n\nfunction parseFieldEntry(\n value: unknown,\n state: ParseState,\n depth: number,\n): PayloadFieldSchema | undefined {\n visit(state);\n if (typeof value !== 'object' || value === null) return undefined;\n const record = value as Record<string, unknown>;\n const name = record['name'];\n const type = record['type'];\n if (typeof name !== 'string' || name.length === 0) return undefined;\n if (typeof type !== 'string' || type.length === 0) return undefined;\n\n const fields = parseFields(record['fields'], state, depth + 1);\n const blocks = parseBlockSchema(record['blocks'], state, depth + 1);\n\n const result: Record<string, unknown> = { ...record, name, type };\n const relationTo = record['relationTo'];\n if (Array.isArray(relationTo)) {\n const targets: unknown[] = [];\n for (const target of relationTo) {\n visit(state);\n targets.push(target);\n }\n result['relationTo'] = targets;\n }\n if (fields.length > 0) result['fields'] = fields;\n else delete result['fields'];\n if (blocks.length > 0) result['blocks'] = blocks;\n else delete result['blocks'];\n\n return result as unknown as PayloadFieldSchema;\n}\n\nfunction parseBlockSchema(\n raw: unknown,\n state: ParseState,\n depth: number,\n): readonly PayloadBlockSchema[] {\n if (typeof raw === 'object' && raw !== null && !Array.isArray(raw)) {\n enter(raw, state, depth);\n const blocks: PayloadBlockSchema[] = [];\n for (const slug in raw) {\n if (!Object.hasOwn(raw, slug)) continue;\n visit(state);\n const entry: unknown = Reflect.get(raw, slug);\n if (\n typeof entry !== 'object' ||\n entry === null ||\n ['__proto__', 'constructor', 'prototype'].includes(slug)\n ) {\n continue;\n }\n blocks.push({\n ...(entry as Record<string, unknown>),\n slug,\n fields: parseFields((entry as Record<string, unknown>)['fields'], state, depth + 1),\n });\n }\n state.active.delete(raw);\n return blocks;\n }\n if (!Array.isArray(raw)) return [];\n enter(raw, state, depth);\n const out: PayloadBlockSchema[] = [];\n for (const entry of raw) {\n visit(state);\n if (typeof entry !== 'object' || entry === null) continue;\n const record = entry as Record<string, unknown>;\n const slug = record['slug'];\n if (typeof slug !== 'string' || slug.length === 0) continue;\n const fields = parseFields(record['fields'], state, depth + 1);\n out.push({ ...record, slug, fields });\n }\n state.active.delete(raw);\n return out;\n}\n","/**\n * Shape guards for the messages the bus accepts. `null` counts as absent, as\n * JSON bridges send it. The schema parser owns bounded, fail-closed normalization.\n */\n\nimport type {\n PayloadDocumentEventMessage,\n PayloadLivePreviewMessage,\n} from '@/types/payload-protocol';\nimport { parseFieldSchema } from '@schema/parser';\n\nexport function isObjectMessage(value: unknown): value is { type: string } {\n return (\n typeof value === 'object' && value !== null && 'type' in value && typeof value.type === 'string'\n );\n}\n\n/** A `payload-live-preview` message: `data` a plain object when present, scalars of the right type or absent. */\nexport function isLivePreviewMessage(value: { type: string }): value is PayloadLivePreviewMessage {\n const v = value as Record<string, unknown>;\n if (v['data'] !== undefined && v['data'] !== null && !isPlainObject(v['data'])) return false;\n return (\n optionalTypeOk(v['fieldSchemaJSON'], (x) => Array.isArray(x)) &&\n optionalTypeOk(v['globalSlug'], (x) => typeof x === 'string') &&\n optionalTypeOk(v['collectionSlug'], (x) => typeof x === 'string') &&\n optionalTypeOk(v['locale'], (x) => typeof x === 'string') &&\n optionalTypeOk(v['ready'], (x) => typeof x === 'boolean') &&\n optionalTypeOk(v['previewToken'], (x) => typeof x === 'string') &&\n optionalTypeOk(v['protocolVersion'], (x) => typeof x === 'number')\n );\n}\n\n/** The non-empty field name of a `payload-live-preview-focus` message, else `undefined`. */\nexport function focusFieldOf(value: { type: string }): string | undefined {\n const field = (value as Record<string, unknown>)['field'];\n return typeof field === 'string' && field.length > 0 ? field : undefined;\n}\n\n/** Stock Payload sends only the `type`; custom senders may add the typed fields (omitted, never `null`). */\nexport function isDocumentEventMessage(value: {\n type: string;\n}): value is PayloadDocumentEventMessage {\n const v = value as Record<string, unknown>;\n return (\n optionalFieldOk(v['action'], (x) => x === 'updated' || x === 'created' || x === 'deleted') &&\n optionalFieldOk(v['slug'], (x) => typeof x === 'string') &&\n optionalFieldOk(v['id'], (x) => typeof x === 'string' || Number.isFinite(x))\n );\n}\n\nfunction optionalFieldOk(value: unknown, check: (v: unknown) => boolean): boolean {\n return value === undefined || check(value);\n}\n\nfunction optionalTypeOk(value: unknown, check: (v: unknown) => boolean): boolean {\n return value === undefined || value === null || check(value);\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n const prototype = Object.getPrototypeOf(value) as object | null;\n return prototype === null || Object.getPrototypeOf(prototype) === null;\n}\n\nconst NULL_AS_ABSENT_FIELDS = [\n 'data',\n 'fieldSchemaJSON',\n 'globalSlug',\n 'collectionSlug',\n 'locale',\n 'ready',\n 'previewToken',\n 'protocolVersion',\n] as const satisfies readonly (keyof PayloadLivePreviewMessage)[];\n\n/**\n * Drop `null` optionals so downstream sees the strict public type, and parse\n * the field schema entry by entry (malformed entries are dropped). Unknown\n * fields stay, for protocol evolution.\n */\nexport function normalizeLivePreviewMessage(\n message: PayloadLivePreviewMessage,\n): PayloadLivePreviewMessage {\n const normalized = { ...message };\n for (const field of NULL_AS_ABSENT_FIELDS) {\n const wireValue: unknown = Reflect.get(normalized, field);\n if (wireValue === null) Reflect.deleteProperty(normalized, field);\n }\n if (!Array.isArray(normalized.fieldSchemaJSON)) return normalized;\n return {\n ...normalized,\n fieldSchemaJSON: parseFieldSchema(normalized.fieldSchemaJSON),\n };\n}\n","/**\n * Payload 2 posts raw form values and a schema, rather than a server merge target.\n * Plan collection GETs from that schema and fill an independent document only\n * after every requested identity is present; the caller owns request cancellation.\n */\nimport type { PayloadFieldSchema } from '@/types/payload-protocol';\nimport { isPlainObject } from './message-guards';\n\nconst MAX_DEPTH = 64;\nconst MAX_NODES = 10_000;\nconst MAX_IDS = 1_000;\nconst MAX_REQUESTS = 64;\nconst MAX_URL = 8_192;\nconst MAX_BODY = 1_048_576;\nconst MAX_CHUNKS = 10_000;\nconst CHUNK = 20;\nconst FORBIDDEN = new Set(['__proto__', 'constructor', 'prototype']);\ntype RecordValue = Record<string, unknown>;\ninterface Slot {\n readonly owner: RecordValue | unknown[];\n readonly key: string | number;\n readonly id: string;\n}\nexport interface LegacyRequest {\n readonly url: string;\n readonly ids: ReadonlySet<string>;\n readonly slots: readonly Slot[];\n}\nexport interface LegacyPlan {\n readonly doc: RecordValue;\n readonly requests: readonly LegacyRequest[];\n}\n\nfunction fail(): never {\n throw new Error('invalid or oversized legacy population');\n}\nfunction hasControl(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) return true;\n }\n return false;\n}\nfunction segment(value: unknown, maximum: number): value is string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > maximum ||\n value === '.' ||\n value === '..'\n ) {\n return false;\n }\n if (value.includes('/') || value.includes('\\\\') || hasControl(value)) return false;\n try {\n encodeURIComponent(value);\n return true;\n } catch {\n return false;\n }\n}\nfunction slug(value: unknown): value is string {\n return segment(value, 128) && !/[?#%]/u.test(value) && !FORBIDDEN.has(value);\n}\nfunction id(value: unknown): string {\n if (Number.isFinite(value)) return String(value);\n if (segment(value, 512)) return value;\n return fail();\n}\nfunction own(record: RecordValue | unknown[], key: string | number): unknown {\n return Object.hasOwn(record, key) ? Reflect.get(record, key) : undefined;\n}\nfunction put(record: RecordValue | unknown[], key: string | number, value: unknown): void {\n Object.defineProperty(record, key, {\n value,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n}\nfunction stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;\n return value.slice(0, end);\n}\n\n/** Copy only structured data, bounded before the planner follows any relation. */\nexport function copyLegacyData(value: unknown): unknown {\n const active = new WeakSet();\n let nodes = 0;\n let characters = 0;\n function copy(value: unknown, depth: number): unknown {\n if (++nodes > MAX_NODES || depth > MAX_DEPTH) return fail();\n if (typeof value === 'string') {\n characters += value.length;\n if (characters > MAX_BODY) fail();\n return value;\n }\n if (value === null || value === undefined || typeof value === 'boolean') return value;\n if (typeof value === 'number') return Number.isFinite(value) ? value : fail();\n if (!Array.isArray(value) && !isPlainObject(value)) return fail();\n if (Array.isArray(value)) {\n if (value.length > MAX_NODES) fail();\n for (let index = 0; index < value.length; index += 1) {\n if (!Object.hasOwn(value, index)) fail();\n }\n }\n if (active.has(value)) return fail();\n active.add(value);\n const result: RecordValue | unknown[] = Array.isArray(value) ? [] : {};\n for (const key of Object.keys(value)) {\n put(result, key, copy(Reflect.get(value, key), depth + 1));\n }\n active.delete(value);\n return result;\n }\n return copy(value, 0);\n}\n\nexport function planLegacyPopulation(\n data: RecordValue,\n schema: readonly PayloadFieldSchema[],\n serverURL: string,\n apiRoute: string,\n depth: number,\n locale?: string,\n): LegacyPlan {\n if (!Number.isSafeInteger(depth) || depth < 0 || depth > MAX_DEPTH) return fail();\n if (\n locale !== undefined &&\n (typeof locale !== 'string' || locale.length > 128 || hasControl(locale))\n ) {\n fail();\n }\n const doc = copyLegacyData(data);\n if (!isPlainObject(doc)) return fail();\n const groups = new Map<string, Slot[]>();\n const unique = new Set<string>();\n let nodes = 0;\n const active = new WeakSet();\n const tick = (level: number): void => {\n if (++nodes > MAX_NODES || level > MAX_DEPTH) fail();\n };\n\n function relation(\n owner: RecordValue | unknown[],\n key: string | number,\n collection: string,\n value: unknown,\n ): void {\n if (value === null || value === undefined || value === '') return;\n const selected = isPlainObject(value) ? own(value, 'id') : value;\n const identity = id(selected);\n if (depth === 0) {\n put(owner, key, selected);\n return;\n }\n const scope = JSON.stringify([collection, identity]);\n unique.add(scope);\n if (unique.size > MAX_IDS) fail();\n const slots = groups.get(collection) ?? [];\n slots.push({ owner, key, id: identity });\n groups.set(collection, slots);\n }\n function fieldRelation(\n owner: RecordValue | unknown[],\n key: string | number,\n field: PayloadFieldSchema,\n ): void {\n if (field.hasMany !== undefined && typeof field.hasMany !== 'boolean') fail();\n const allowed = field.relationTo;\n const value = own(owner, key);\n if (Array.isArray(allowed)) {\n if (allowed.length === 0) fail();\n const collection = isPlainObject(value) ? own(value, 'relationTo') : undefined;\n let selectedCollection: string | undefined;\n for (const candidate of allowed) {\n tick(0);\n if (!slug(candidate)) fail();\n if (candidate === collection) selectedCollection = candidate;\n }\n if (value === null || value === undefined || value === '') return;\n if (!isPlainObject(value) || selectedCollection === undefined) fail();\n relation(value, 'value', selectedCollection, own(value, 'value'));\n } else {\n if (!slug(allowed)) fail();\n relation(owner, key, allowed, value);\n }\n }\n function rich(value: unknown, level: number): void {\n tick(level);\n if (!Array.isArray(value) && !isPlainObject(value)) return;\n if (\n isPlainObject(value) &&\n Object.hasOwn(value, 'relationTo') &&\n Object.hasOwn(value, 'value')\n ) {\n const collection = own(value, 'relationTo');\n if (!slug(collection)) fail();\n relation(value, 'value', collection, own(value, 'value'));\n return;\n }\n for (const key of Object.keys(value)) rich(Reflect.get(value, key), level + 1);\n }\n function walk(fields: readonly PayloadFieldSchema[], record: RecordValue, level: number): void {\n tick(level);\n if (active.has(fields)) fail();\n active.add(fields);\n for (const field of fields) {\n tick(level);\n if (!isPlainObject(field) || !segment(field.name, 512) || FORBIDDEN.has(field.name)) fail();\n const value = own(record, field.name);\n if (field.type === 'relationship' || field.type === 'upload') {\n if (field.hasMany) {\n if (value !== null && value !== undefined && !Array.isArray(value)) fail();\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i += 1) fieldRelation(value, i, field);\n } else fieldRelation(record, field.name, field);\n } else fieldRelation(record, field.name, field);\n } else if (field.type === 'group' || field.type === 'tabs') {\n if (value != null && !isPlainObject(value)) fail();\n if (isPlainObject(value) && field.fields) walk(field.fields, value, level + 1);\n } else if (field.type === 'row' || field.type === 'collapsible') {\n if (field.fields) walk(field.fields, record, level + 1);\n } else if (field.type === 'array' || field.type === 'blocks') {\n if (value === 0) put(record, field.name, []);\n else if (value != null && !Array.isArray(value)) fail();\n if (Array.isArray(value)) {\n for (const row of value) {\n if (!isPlainObject(row)) fail();\n if (field.type === 'array' && field.fields) walk(field.fields, row, level + 1);\n else if (field.type === 'blocks') {\n const blockType = own(row, 'blockType');\n const block = field.blocks?.find((candidate) => {\n tick(level);\n return candidate.slug === blockType;\n });\n if (block === undefined) fail();\n walk(block.fields, row, level + 1);\n }\n }\n }\n } else if (field.type === 'richText') rich(value, level + 1);\n }\n active.delete(fields);\n }\n walk(schema, doc, 0);\n if (groups.size > 25) fail();\n const requests: LegacyRequest[] = [];\n if (groups.size === 0) return { doc, requests };\n const base = new URL(serverURL);\n if (\n !['http:', 'https:'].includes(base.protocol) ||\n base.username ||\n base.password ||\n base.search ||\n base.hash\n ) {\n fail();\n }\n if (\n !apiRoute.startsWith('/') ||\n apiRoute.includes('\\\\') ||\n /[%?#]/u.test(apiRoute) ||\n hasControl(apiRoute)\n ) {\n fail();\n }\n if (apiRoute.split('/').some((part) => part === '.' || part === '..')) fail();\n const prefix = `${stripTrailingSlashes(serverURL)}${stripTrailingSlashes(apiRoute)}/`;\n for (const [collection, slots] of groups) {\n const identities = [...new Set(slots.map((slot) => slot.id))];\n let index = 0;\n while (index < identities.length) {\n const first = identities[index];\n if (first === undefined) fail();\n const comma = first.includes(',');\n const chunk: string[] = [];\n let url = '';\n while (index < identities.length && chunk.length < CHUNK) {\n const next = identities[index];\n if (next === undefined || (chunk.length > 0 && (comma || next.includes(',')))) break;\n const proposed = [...chunk, next];\n const query = new URLSearchParams({\n depth: String(depth),\n limit: String(proposed.length),\n });\n if (locale !== undefined) query.set('locale', locale);\n query.set(comma ? 'where[id][equals]' : 'where[id][in]', comma ? next : proposed.join(','));\n const candidate = `${prefix}${encodeURIComponent(collection)}?${query}`;\n if (candidate.length > MAX_URL) {\n if (chunk.length === 0) fail();\n break;\n }\n if (new URL(candidate).origin !== base.origin) fail();\n chunk.push(next);\n index += 1;\n url = candidate;\n }\n if (chunk.length === 0 || requests.length >= MAX_REQUESTS) fail();\n const ids = new Set(chunk);\n requests.push({\n url,\n ids,\n slots: slots.filter((slot) => ids.has(slot.id)),\n });\n }\n }\n return { doc, requests };\n}\n\n/** Native bodies stop at byte and chunk limits; injected json-only shims still get shape limits. */\nexport async function populationBody(\n response: Response,\n signal: AbortSignal,\n current: () => boolean,\n): Promise<unknown> {\n let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let cancelled = false;\n let finished = false;\n const obsolete = Symbol();\n let interrupt: (() => void) | undefined;\n const interrupted = new Promise<typeof obsolete>((resolve) => {\n interrupt = () => {\n resolve(obsolete);\n };\n });\n const check = (): void => {\n if (!current() || signal.aborted) fail();\n };\n const cancel = (): void => {\n if (reader === undefined || cancelled) return;\n cancelled = true;\n try {\n void Promise.resolve(reader.cancel()).catch(() => {\n /* teardown remains authoritative */\n });\n } catch {\n /* teardown remains authoritative */\n }\n };\n const abort = (): void => {\n interrupt?.();\n cancel();\n };\n signal.addEventListener('abort', abort, { once: true });\n try {\n check();\n const body = response.body ?? null;\n check();\n if (body === null) {\n const json: () => Promise<unknown> = response.json.bind(response);\n check();\n const value: unknown = await Promise.race([\n Promise.resolve().then(() => {\n check();\n return json();\n }),\n interrupted,\n ]);\n check();\n if (value === obsolete) fail();\n return value;\n }\n const getReader: () => ReadableStreamDefaultReader<Uint8Array> = body.getReader.bind(body);\n check();\n const activeReader = getReader();\n reader = activeReader;\n check();\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n let count = 0;\n for (;;) {\n const pending = Promise.resolve().then(() => {\n check();\n const read = activeReader.read.bind(activeReader);\n check();\n return read();\n });\n const result = await Promise.race([pending, interrupted]);\n check();\n if (result === obsolete) fail();\n if (result.done) break;\n bytes += result.value.byteLength;\n if (++count > MAX_CHUNKS || bytes > MAX_BODY) fail();\n chunks.push(result.value);\n }\n finished = true;\n const data = new Uint8Array(bytes);\n let position = 0;\n for (const chunk of chunks) {\n data.set(chunk, position);\n position += chunk.byteLength;\n }\n try {\n return JSON.parse(new TextDecoder().decode(data));\n } catch {\n return fail();\n }\n } finally {\n signal.removeEventListener('abort', abort);\n if (!finished) cancel();\n try {\n reader?.releaseLock();\n } catch {\n /* a hostile pending read cannot own cleanup */\n }\n }\n}\n\nexport function fillLegacyPopulation(request: LegacyRequest, body: unknown): void {\n const safe = copyLegacyData(body);\n if (!isPlainObject(safe)) fail();\n const docs = own(safe, 'docs');\n if (!Array.isArray(docs) || docs.length > CHUNK) fail();\n const found = new Map<string, unknown>();\n for (const raw of docs) {\n if (!isPlainObject(raw)) fail();\n const identity = id(own(raw, 'id'));\n if (!request.ids.has(identity) || found.has(identity)) fail();\n found.set(identity, raw);\n }\n if (found.size !== request.ids.size) fail();\n for (const slot of request.slots) put(slot.owner, slot.key, found.get(slot.id));\n}\n","/**\n * Payload 3 raw form values use its REST merge with the method-override header.\n * Payload 2 sends a schema instead of a target, so it uses local values and\n * collection GETs to populate references. A newer merge aborts the one in flight,\n * and captured attempt identity drops obsolete results even when a shim ignores abort.\n * An optional deadline aborts a merge that has not answered in time.\n */\n\nimport { isolateDiagnostic, noopDiagnostic } from './diagnostics';\nimport type { PayloadFieldSchema } from '@/types/payload-protocol';\nimport { fillLegacyPopulation, planLegacyPopulation, populationBody } from './legacy-population';\n\nexport interface DataMergerOptions {\n /** Payload server origin, e.g. `https://cms.example.com`. */\n readonly serverURL: string;\n /** REST route prefix. Defaults to `/api`. */\n readonly apiRoute?: string;\n /** Population depth requested from the server. Defaults to `1`. */\n readonly depth?: number;\n readonly fetchFn?: typeof fetch;\n readonly log?: (...args: unknown[]) => void;\n /**\n * Milliseconds a merge may wait for the server before it is aborted and reported\n * `unavailable`. Off unless a positive finite number.\n */\n readonly timeoutMs?: number;\n}\n\nexport interface MergeRequest {\n readonly schema?: readonly PayloadFieldSchema[] | undefined;\n readonly collectionSlug?: string | undefined;\n readonly globalSlug?: string | undefined;\n readonly data: Record<string, unknown>;\n readonly locale?: string | undefined;\n}\n\n/** `superseded`: a newer merge replaced this one. `unavailable`: fall back to the raw values. */\nexport type MergeResult =\n | { readonly status: 'merged'; readonly doc: Record<string, unknown> }\n | { readonly status: 'superseded' }\n | { readonly status: 'unavailable' };\n\ninterface MergeTarget {\n readonly path: string;\n readonly field: 'id' | 'globalType';\n readonly value: string;\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (const character of value) {\n // An iterated character always has a code point; 0 keeps the type and fails closed.\n const codePoint = character.codePointAt(0) ?? 0;\n if (codePoint <= 0x1f || codePoint === 0x7f) return true;\n }\n return false;\n}\n\n/** One path segment: non-empty, bounded, not a dot segment, without separators or control characters. */\nfunction isPathSegment(value: string, maxLength: number): boolean {\n return (\n value.length > 0 &&\n value.length <= maxLength &&\n value !== '.' &&\n value !== '..' &&\n !value.includes('/') &&\n !value.includes('\\\\') &&\n !hasControlCharacter(value)\n );\n}\n\n/** A slug is one of Payload's own names; `?` and `#` never belong in one. */\nfunction isSafeSlug(value: string): boolean {\n return isPathSegment(value, 128) && !value.includes('?') && !value.includes('#');\n}\n\n/** An id comes from the form values; a string one is encoded, so `?` and `#` may appear. */\nfunction isSafeId(value: unknown): value is string | number {\n if (typeof value === 'number') return Number.isFinite(value);\n return typeof value === 'string' && isPathSegment(value, 512);\n}\n\n/**\n * Trailing slashes off a base URL, without a regular expression: `/\\/+$/`\n * backtracks over a long run of slashes and takes quadratic time on input the\n * page supplies (CodeQL js/polynomial-redos).\n */\n/** What the deadline rejects with: no fetch, body or shim rejects with this object. */\nconst TIMED_OUT = new Error();\n\nfunction withoutTrailingSlashes(value: string): string {\n let end = value.length;\n while (value.endsWith('/', end)) end -= 1;\n return value.slice(0, end);\n}\n\nexport class DataMerger {\n private readonly serverURL: string;\n private readonly apiRoute: string;\n private readonly depth: number;\n private readonly fetchFn: typeof fetch | undefined;\n private readonly log: (...args: unknown[]) => void;\n private readonly timeoutMs: number | undefined;\n private inflight: AbortController | null = null;\n private attempt = 0;\n private destroyDepth = 0;\n\n constructor(options: DataMergerOptions) {\n this.serverURL = withoutTrailingSlashes(options.serverURL);\n const route = options.apiRoute ?? '/api';\n this.apiRoute = route.startsWith('/') ? route : `/${route}`;\n this.depth = options.depth ?? 1;\n this.fetchFn = options.fetchFn;\n this.log = isolateDiagnostic(options.log ?? noopDiagnostic);\n const timeoutMs = options.timeoutMs ?? 0;\n this.timeoutMs = timeoutMs > 0 && timeoutMs < Number.POSITIVE_INFINITY ? timeoutMs : undefined;\n }\n\n /** A v2 schema plans local values and GETs; a v3 target needs its document identity. */\n canMerge(request: MergeRequest): boolean {\n try {\n const schema = request.schema;\n if (schema !== undefined) {\n planLegacyPopulation(\n request.data,\n schema,\n this.serverURL,\n this.apiRoute,\n this.depth,\n request.locale,\n );\n return true;\n }\n return this.endpointOf(request) !== null;\n } catch {\n return false;\n }\n }\n\n /**\n * The path and its response identity, or `null` when no safe one exists. A request\n * accessor that throws counts as none, and so does a lone surrogate, which\n * `encodeURIComponent` refuses with a `URIError`.\n */\n private endpointOf(request: MergeRequest): MergeTarget | null {\n try {\n // An empty global slug means \"collection document\" on the wire.\n const globalSlug = request.globalSlug;\n if (globalSlug) {\n return isSafeSlug(globalSlug)\n ? {\n path: `globals/${encodeURIComponent(globalSlug)}`,\n field: 'globalType',\n value: globalSlug,\n }\n : null;\n }\n const collectionSlug = request.collectionSlug ?? '';\n const id: unknown = request.data['id'];\n if (!isSafeSlug(collectionSlug) || !isSafeId(id)) return null;\n return {\n path: `${encodeURIComponent(collectionSlug)}/${encodeURIComponent(String(id))}`,\n field: 'id',\n value: String(id),\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Fulfills merged, superseded or unavailable. Supported request, fetch and\n * response failures are outcomes; isolated diagnostics cannot reject the merge.\n */\n async merge(request: MergeRequest): Promise<MergeResult> {\n if (this.destroyDepth > 0) return { status: 'superseded' };\n // Claim the attempt before aborting: abort listeners and fetch shims are\n // reentrant, and a newer merge they start must win. Nothing but this class\n // aborts the signal, and only after the counter moved, so the counter\n // alone decides who was superseded.\n const attempt = (this.attempt += 1);\n const previous = this.inflight;\n this.inflight = null;\n let controller: AbortController | null = null;\n let legacy = false;\n const superseded = (): boolean => this.attempt !== attempt;\n // Every wait on the server races one deadline, armed with the attempt's controller at its\n // first request; a shim that ignores the abort cannot hold the merge past it, and what it\n // answers later is never read.\n const timeoutMs = this.timeoutMs;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let deadline: Promise<never> | undefined;\n const within = <T>(work: Promise<T>, owned: AbortController): Promise<T> => {\n if (timeoutMs === undefined) return work;\n if (deadline === undefined) {\n deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n owned.abort();\n reject(TIMED_OUT);\n }, timeoutMs);\n });\n deadline.catch(() => undefined);\n }\n return Promise.race([work, deadline]);\n };\n try {\n previous?.abort();\n if (superseded()) return { status: 'superseded' };\n const schema = request.schema;\n legacy = schema !== undefined;\n if (schema !== undefined) {\n const plan = planLegacyPopulation(\n request.data,\n schema,\n this.serverURL,\n this.apiRoute,\n this.depth,\n request.locale,\n );\n if (superseded()) return { status: 'superseded' };\n if (plan.requests.length === 0) return { status: 'merged', doc: plan.doc };\n const fetchFn = this.fetchFn ?? (typeof fetch === 'function' ? fetch : undefined);\n if (superseded()) return { status: 'superseded' };\n if (fetchFn === undefined) return { status: 'unavailable' };\n controller = new AbortController();\n this.inflight = controller;\n for (const population of plan.requests) {\n const response = await within(\n fetchFn(population.url, {\n method: 'GET',\n credentials: 'include',\n redirect: 'error',\n signal: controller.signal,\n }),\n controller,\n );\n if (superseded()) return { status: 'superseded' };\n const ok = response.ok;\n if (superseded()) return { status: 'superseded' };\n if (!ok) {\n const status = response.status;\n if (superseded()) return { status: 'superseded' };\n controller.abort();\n if (superseded()) return { status: 'superseded' };\n this.log('merge HTTP', status);\n return superseded() ? { status: 'superseded' } : { status: 'unavailable' };\n }\n const body = await within(\n populationBody(response, controller.signal, () => !superseded()),\n controller,\n );\n if (superseded()) return { status: 'superseded' };\n fillLegacyPopulation(population, body);\n if (superseded()) return { status: 'superseded' };\n }\n return { status: 'merged', doc: plan.doc };\n }\n // The endpoint reads the request's own values, which may be consumer\n // getters that start a newer merge before throwing.\n const endpoint = this.endpointOf(request);\n if (superseded()) return { status: 'superseded' };\n if (endpoint === null) return { status: 'unavailable' };\n const fetchFn = this.fetchFn ?? (typeof fetch === 'function' ? fetch : undefined);\n if (superseded()) return { status: 'superseded' };\n if (fetchFn === undefined) return { status: 'unavailable' };\n // Serialize before publishing the controller: accessors may accept newer work.\n const body = JSON.stringify({\n data: request.data,\n depth: this.depth,\n flattenLocales: false,\n locale: request.locale,\n });\n if (superseded()) return { status: 'superseded' };\n controller = new AbortController();\n this.inflight = controller;\n const url = `${this.serverURL}${this.apiRoute}/${endpoint.path}`;\n const response = await within(\n fetchFn(url, {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Payload-HTTP-Method-Override': 'GET',\n },\n // The admin already flattens locales before posting; an absent locale\n // is left out of the JSON.\n body,\n signal: controller.signal,\n }),\n controller,\n );\n // A fetch shim may ignore the signal; the attempt is authoritative.\n if (superseded()) return { status: 'superseded' };\n const ok = response.ok;\n if (superseded()) return { status: 'superseded' };\n if (!ok) {\n const status = response.status;\n if (superseded()) return { status: 'superseded' };\n this.log('merge HTTP', status, url);\n return superseded() ? { status: 'superseded' } : { status: 'unavailable' };\n }\n const json: () => Promise<unknown> = response.json.bind(response);\n if (superseded()) return { status: 'superseded' };\n const merged: unknown = await within(json(), controller);\n if (superseded()) return { status: 'superseded' };\n if (merged === null || typeof merged !== 'object' || Array.isArray(merged)) {\n this.log('merge invalid', url);\n return superseded() ? { status: 'superseded' } : { status: 'unavailable' };\n }\n const doc = merged as Record<string, unknown>;\n // Missing IDs remain compatible with projected responses. An explicit\n // identity must match the dispatched target, never mutable request data.\n const identity = doc[endpoint.field];\n const wrongIdentity =\n Object.hasOwn(doc, endpoint.field) &&\n (endpoint.field === 'id'\n ? !isSafeId(identity) || String(identity) !== endpoint.value\n : identity !== endpoint.value);\n if (superseded()) return { status: 'superseded' };\n if (wrongIdentity) {\n this.log('merge invalid', url);\n return superseded() ? { status: 'superseded' } : { status: 'unavailable' };\n }\n return { status: 'merged', doc };\n } catch (error) {\n if (superseded()) return { status: 'superseded' };\n if (error === TIMED_OUT) {\n this.log('merge timeout', timeoutMs);\n return { status: 'unavailable' };\n }\n if (legacy) {\n controller?.abort();\n if (superseded()) return { status: 'superseded' };\n }\n this.log(\n 'merge exception',\n legacy ? new Error('legacy population could not be resolved') : error,\n );\n if (superseded()) return { status: 'superseded' };\n return { status: 'unavailable' };\n } finally {\n clearTimeout(timer);\n // Only the newest attempt's controller is ever in flight: a superseded\n // attempt's is gone already, and its successor's is left alone.\n if (this.inflight === controller) this.inflight = null;\n }\n }\n\n /** Abort any in-flight merge. The merger stays usable across a stop/start cycle. */\n destroy(): void {\n this.attempt += 1;\n const inflight = this.inflight;\n this.inflight = null;\n this.destroyDepth += 1;\n try {\n inflight?.abort();\n } finally {\n this.destroyDepth -= 1;\n }\n }\n}\n","/**\n * postMessage ingress: origin and source checks, per-type shape guards, the\n * ordered preview-token validation queue, and the `ready` handshake. The bus\n * never throws; a rejected message is dropped or reported via `onInvalid`.\n * Consumer callbacks may detach or re-attach the bus synchronously, so\n * anything that runs after one re-checks the generation it started in.\n * See ADR 0004.\n */\n\nimport type {\n PayloadDocumentEventMessage,\n PayloadLivePreviewMessage,\n} from '@/types/payload-protocol';\nimport {\n focusFieldOf,\n isDocumentEventMessage,\n isLivePreviewMessage,\n isObjectMessage,\n isPlainObject,\n normalizeLivePreviewMessage,\n} from './message-guards';\nimport { LIBRARY_PROTOCOL_VERSION } from './protocol-version';\nimport { observeThenableResult } from './thenable';\n\nexport type OriginMatcher = (origin: string) => boolean;\n\n/** Identity of a data-bearing update: `revision` is monotonic, `generation` names the listener attachment. */\nexport interface MessageRevision {\n readonly revision: number;\n readonly generation: number;\n}\nexport function sameRevision(a: MessageRevision, b: MessageRevision): boolean {\n return a.generation === b.generation && a.revision === b.revision;\n}\n\nexport type InvalidReason = 'origin' | 'shape' | 'type' | 'token' | 'source';\n\nexport interface MessageHandlers {\n /** A validated update; data-bearing ones carry their revision, ready handshakes do not. */\n readonly onUpdate: (\n msg: PayloadLivePreviewMessage,\n origin: string,\n messageRevision?: MessageRevision,\n ) => void;\n /** A locally retained, previously accepted update replayed in a new lifecycle generation. */\n readonly onReplay?: (\n msg: PayloadLivePreviewMessage,\n origin: string,\n messageRevision: MessageRevision,\n ) => void;\n readonly onDocumentEvent: (msg: PayloadDocumentEventMessage, origin: string) => void;\n /** The admin reports the cursor moved into a field (reveal tier 2). */\n readonly onFocusField?: (field: string, origin: string) => void;\n readonly onInvalid?: (reason: InvalidReason, origin: string) => void;\n /** `'parent-or-opener'` refuses every window but the framing/opening one, even from an allowed origin. */\n readonly sourcePolicy?: 'any' | 'parent-or-opener';\n /**\n * Gate for data-bearing updates. Verdicts commit in arrival order, so an\n * earlier update is dispatched before a later one even when its validation\n * resolves later; an error counts as rejection.\n */\n readonly validateToken?: (\n token: string | undefined,\n origin: string,\n ) => boolean | Promise<boolean>;\n}\n\n/** One entry of the validation queue: a singly linked list in arrival order. */\ninterface PendingValidation {\n readonly generation: number;\n readonly message: PayloadLivePreviewMessage;\n readonly origin: string;\n readonly messageRevision: MessageRevision | undefined;\n /** `undefined` until the validator settled; only literal `true` approves. */\n verdict: boolean | undefined;\n next: PendingValidation | undefined;\n}\n\ninterface AcceptedUpdate {\n readonly generation: number;\n readonly message: PayloadLivePreviewMessage;\n readonly origin: string;\n}\n\n/** Keep consumer callbacks from mutating the snapshot reserved for navigation replay. */\nfunction snapshotForReplay(message: PayloadLivePreviewMessage): PayloadLivePreviewMessage | null {\n const withoutToken = { ...message };\n delete withoutToken.previewToken;\n try {\n return structuredClone(withoutToken);\n } catch {\n // A real postMessage payload is cloneable. A synthetic non-cloneable one\n // may still be processed once, but retaining it would make replay mutable.\n return null;\n }\n}\n\nexport class MessageBus {\n private readonly matcher: OriginMatcher;\n private readonly handlers: MessageHandlers;\n private boundListener: ((event: MessageEvent) => void) | undefined = undefined;\n private attachedTarget: Window | undefined = undefined;\n private generation = 0;\n private revision = 0;\n private queueHead: PendingValidation | undefined = undefined;\n private queueTail: PendingValidation | undefined = undefined;\n private lastAccepted: AcceptedUpdate | undefined = undefined;\n private replayedGeneration = 0;\n /** Identity of the newest accepted data commit, including one still crossing the clone boundary. */\n private latestAcceptedAttempt: object | undefined = undefined;\n\n constructor(matcher: OriginMatcher, handlers: MessageHandlers) {\n this.matcher = matcher;\n this.handlers = handlers;\n }\n\n /** Start listening on `target`. Idempotent. */\n attach(target: Window = window): void {\n if (this.attachedTarget !== undefined) return;\n let committed = false;\n const listener = (event: MessageEvent): void => {\n // Each attachment owns its listener; a stale one must not borrow the new generation.\n if (!committed || this.boundListener !== listener) return;\n const generation = this.generation;\n try {\n this.receive(event, generation, target);\n } catch {\n // A synthetic event can carry throwing accessors; that is a shape failure.\n let origin: string;\n try {\n origin = event.origin;\n } catch {\n origin = '';\n }\n this.reportInvalid('shape', origin, generation);\n }\n };\n this.generation += 1;\n this.resetQueue();\n this.attachedTarget = target;\n this.boundListener = listener;\n try {\n target.addEventListener('message', listener);\n } catch (error) {\n // Invalidate before rollback: a hook may already have attached a newer generation.\n if (this.boundListener === listener) {\n this.attachedTarget = undefined;\n this.boundListener = undefined;\n this.resetQueue();\n }\n try {\n target.removeEventListener('message', listener);\n } catch {\n // Keep the original failure.\n }\n throw error;\n }\n if (this.boundListener === listener) {\n committed = true;\n } else {\n try {\n target.removeEventListener('message', listener);\n } catch {\n // The listener is identity-gated above even if removal fails.\n }\n }\n }\n\n /** Stop listening. Idempotent. */\n detach(): void {\n const target = this.attachedTarget;\n const listener = this.boundListener;\n if (target === undefined || listener === undefined) return;\n // Invalidate first so a listener already on the stack sees an obsolete generation.\n this.attachedTarget = undefined;\n this.boundListener = undefined;\n this.resetQueue();\n target.removeEventListener('message', listener);\n }\n\n /** Invalidate pending validations while staying attached (heartbeat expiry). */\n advanceGeneration(): boolean {\n if (this.attachedTarget === undefined) return false;\n this.generation += 1;\n this.resetQueue();\n return true;\n }\n\n /**\n * Re-dispatch the last data-bearing update under the current generation.\n * Only an update already accepted in an older generation is eligible; its\n * preview token is never retained or replayed. @internal\n */\n replayLastAccepted(): boolean {\n const accepted = this.lastAccepted;\n const generation = this.generation;\n const handler = this.handlers.onReplay;\n if (\n handler === undefined ||\n accepted === undefined ||\n accepted.generation >= generation ||\n this.replayedGeneration === generation\n ) {\n return false;\n }\n // Origin matching fails closed outside the attached generation it ran in,\n // and it is consumer code that may accept a newer message reentrantly.\n // Never let the older snapshot run after it.\n if (!this.matchesOrigin(accepted.origin, generation) || this.lastAccepted !== accepted) {\n return false;\n }\n this.replayedGeneration = generation;\n const revision = { generation, revision: (this.revision += 1) };\n // Clone for every replay: hooks may mutate what they receive, but the\n // retained copy is the baseline for later navigations too. It came out\n // of structuredClone, so cloning it again cannot throw.\n this.invokeHandler(\n generation,\n handler,\n structuredClone(accepted.message),\n accepted.origin,\n revision,\n );\n return true;\n }\n\n /** Forget retained document data when the connection expires or the owner is destroyed. @internal */\n forgetLastAccepted(): void {\n this.lastAccepted = undefined;\n this.replayedGeneration = 0;\n this.latestAcceptedAttempt = undefined;\n }\n\n /** Post the `ready` handshake to every target for every origin. */\n static sendReady(targets: readonly Window[], origins: readonly string[]): void {\n const payload: PayloadLivePreviewMessage = {\n type: 'payload-live-preview',\n ready: true,\n protocolVersion: LIBRARY_PROTOCOL_VERSION,\n };\n for (const target of targets) {\n for (const origin of origins) {\n try {\n target.postMessage(payload, origin);\n } catch {\n // A malformed origin is the consumer's configuration problem.\n }\n }\n }\n }\n\n private receive(event: MessageEvent, generation: number, target: Window): void {\n const origin = event.origin;\n if (!this.matchesOrigin(origin, generation)) {\n this.reportInvalid('origin', origin, generation);\n return;\n }\n if (!this.matchesSource(event, target)) {\n this.reportInvalid('source', origin, generation);\n return;\n }\n const data: unknown = event.data;\n if (!isObjectMessage(data)) {\n this.reportInvalid('shape', origin, generation);\n return;\n }\n switch (data.type) {\n case 'payload-live-preview':\n if (!isLivePreviewMessage(data)) {\n this.reportInvalid('shape', origin, generation);\n return;\n }\n this.dispatchUpdate(normalizeLivePreviewMessage(data), origin, generation);\n return;\n case 'payload-document-event':\n if (!isDocumentEventMessage(data)) {\n this.reportInvalid('shape', origin, generation);\n return;\n }\n this.invokeHandler(generation, this.handlers.onDocumentEvent, data, origin);\n return;\n case 'payload-live-preview-focus': {\n const field = focusFieldOf(data);\n if (field === undefined) {\n this.reportInvalid('shape', origin, generation);\n return;\n }\n this.invokeHandler(generation, this.handlers.onFocusField, field, origin);\n return;\n }\n default:\n this.reportInvalid('type', origin, generation);\n }\n }\n\n private dispatchUpdate(\n message: PayloadLivePreviewMessage,\n origin: string,\n generation: number,\n ): void {\n const hasUpdateData = isPlainObject(message.data);\n if (!this.isCurrentGeneration(generation)) return;\n // A shape-valid data update consumes its revision before validation; a rejected token leaves a gap.\n const messageRevision = hasUpdateData\n ? { generation, revision: (this.revision += 1) }\n : undefined;\n const validator = this.handlers.validateToken;\n if (!this.isCurrentGeneration(generation)) return;\n if (validator === undefined) {\n this.commitUpdate(message, origin, generation, messageRevision);\n return;\n }\n // The data-less ready handshake carries no token and passes, so the admin learns we listen.\n if (message.ready === true && message.data === undefined) {\n this.commitUpdate(message, origin, generation, undefined);\n return;\n }\n const pending: PendingValidation = {\n generation,\n message,\n origin,\n messageRevision,\n verdict: undefined,\n next: undefined,\n };\n this.enqueue(pending);\n let verdict: unknown;\n try {\n // Invoked eagerly; only the commit waits for earlier queue entries.\n verdict = validator(message.previewToken, origin);\n } catch {\n this.settleValidation(pending, false);\n return;\n }\n if (typeof verdict === 'boolean') {\n this.settleValidation(pending, verdict);\n return;\n }\n // Assimilate any thenable; only literal `true` approves.\n void Promise.resolve(verdict).then(\n (approved) => {\n this.settleValidation(pending, approved === true);\n },\n () => {\n this.settleValidation(pending, false);\n },\n );\n }\n\n private settleValidation(pending: PendingValidation, approved: boolean): void {\n pending.verdict = approved;\n this.drainQueue(pending.generation);\n }\n\n private drainQueue(generation: number): void {\n while (this.isCurrentGeneration(generation)) {\n const pending = this.queueHead;\n if (pending === undefined) return;\n // The matcher may have narrowed since ingress (origin lock); an obsolete\n // origin must not hold the queue head and block the locked origin's work.\n if (!this.matchesOrigin(pending.origin, generation)) {\n if (!this.dequeue(pending)) continue;\n this.reportInvalid('origin', pending.origin, pending.generation);\n continue;\n }\n if (pending.verdict === undefined) return;\n if (!this.dequeue(pending)) continue;\n if (pending.verdict) {\n this.commitUpdate(\n pending.message,\n pending.origin,\n pending.generation,\n pending.messageRevision,\n );\n } else {\n this.reportInvalid('token', pending.origin, pending.generation);\n }\n }\n }\n\n private commitUpdate(\n message: PayloadLivePreviewMessage,\n origin: string,\n generation: number,\n messageRevision: MessageRevision | undefined,\n ): void {\n if (messageRevision === undefined) {\n this.invokeHandler(generation, this.handlers.onUpdate, message, origin);\n } else {\n const attempt = {};\n this.latestAcceptedAttempt = attempt;\n const snapshot = snapshotForReplay(message);\n // Cloning synthetic input can run accessors. If one accepted a newer\n // message reentrantly, the older commit must not overwrite or follow it.\n if (this.latestAcceptedAttempt !== attempt || !this.isCurrentGeneration(generation)) return;\n this.lastAccepted = snapshot === null ? undefined : { generation, message: snapshot, origin };\n this.invokeHandler(generation, this.handlers.onUpdate, message, origin, messageRevision);\n }\n }\n\n private reportInvalid(reason: InvalidReason, origin: string, generation: number): void {\n this.invokeHandler(generation, this.handlers.onInvalid, reason, origin);\n }\n\n /** Under `'parent-or-opener'`, whether the event came from the attached window's parent or opener. */\n private matchesSource(event: MessageEvent, target: Window): boolean {\n if (this.handlers.sourcePolicy !== 'parent-or-opener') return true;\n try {\n // Only a window is a source: a missing one matches nothing, not even a missing opener.\n const source: unknown = event.source;\n if (typeof source !== 'object' || source === null) return false;\n const parent = target.parent;\n if (parent !== target && source === parent) return true;\n const opener: unknown = target.opener;\n return source === opener;\n } catch {\n return false;\n }\n }\n\n /** Fail-closed: only literal `true` from the matcher, and only within the generation it ran in. */\n private matchesOrigin(origin: string, generation: number): boolean {\n try {\n const approved: unknown = this.isCurrentGeneration(generation) && this.matcher(origin);\n return approved === true && this.isCurrentGeneration(generation);\n } catch {\n return false;\n }\n }\n\n /** Callbacks run only in a current generation and must not unwind the listener or the drain. */\n private invokeHandler<TArgs extends unknown[]>(\n generation: number,\n handler: ((...args: TArgs) => unknown) | undefined,\n ...args: TArgs\n ): void {\n if (handler === undefined || !this.isCurrentGeneration(generation)) return;\n try {\n observeThenableResult(handler(...args));\n } catch {\n // Isolated by contract.\n }\n }\n\n private isCurrentGeneration(generation: number): boolean {\n return this.attachedTarget !== undefined && this.generation === generation;\n }\n\n private enqueue(pending: PendingValidation): void {\n if (this.queueTail === undefined) this.queueHead = pending;\n else this.queueTail.next = pending;\n this.queueTail = pending;\n }\n\n /** Advance the head past `expected`, unless a matcher reset the queue meanwhile. */\n private dequeue(expected: PendingValidation): boolean {\n if (this.queueHead !== expected) return false;\n this.queueHead = expected.next;\n if (this.queueHead === undefined) this.queueTail = undefined;\n return true;\n }\n\n private resetQueue(): void {\n this.queueHead = undefined;\n this.queueTail = undefined;\n }\n}\n","/**\n * Protocol negotiation. A capability is granted either by the version a peer\n * announces or by observation, since the stock Payload admin announces none:\n * what it can do is read off the messages it sends. See ADR 0010.\n */\n\n/** Bumped only when this library's understanding of the wire format changes. @internal */\nexport const LIBRARY_PROTOCOL_VERSION = 4;\n\n/** How a capability becomes active. @internal */\nexport type CapabilitySource = 'version' | 'observed';\n\n/** @internal */\nexport interface CapabilityDeclaration {\n /** Enabled once the negotiated version reaches this (for announced peers). */\n readonly since: number;\n /** The wire signal that grants this capability to a peer announcing no version. */\n readonly observed?:\n 'schema' | 'locale' | 'preview-token' | 'document-event' | 'relationship-event';\n}\n\n/** What activates each capability; the prose lives in `CAPABILITY_DOCUMENTATION`. */\nexport const CAPABILITY_DECLARATIONS = {\n basic: { since: 1 },\n 'schema-json': { since: 2, observed: 'schema' },\n locale: { since: 2, observed: 'locale' },\n 'preview-token': { since: 3, observed: 'preview-token' },\n 'nested-arrays': { since: 4 },\n 'recursive-diffs': { since: 4 },\n 'document-events': { since: 4, observed: 'document-event' },\n 'relationship-events': { since: 4, observed: 'relationship-event' },\n} as const satisfies Record<string, CapabilityDeclaration>;\n\nexport type ProtocolCapability = keyof typeof CAPABILITY_DECLARATIONS;\n\n/** Every declared capability, in declaration order. @internal */\nexport const PROTOCOL_CAPABILITIES = Object.keys(\n CAPABILITY_DECLARATIONS,\n) as readonly ProtocolCapability[];\n\nexport interface ProtocolNegotiation {\n /** This library's protocol version. */\n readonly ours: number;\n /** The remote party's version, when it announced one. */\n readonly theirs: number | undefined;\n /** `min(ours, theirs ?? 1)` — the version both sides actually share. */\n readonly negotiated: number;\n /** Capabilities active at the negotiated version or seen on the wire. */\n readonly capabilities: ReadonlySet<ProtocolCapability>;\n /** The subset that was observed on the wire rather than granted by version. */\n readonly observed: ReadonlySet<ProtocolCapability>;\n}\n\n/** Deterministic; the runtime re-runs it whenever either input changes. */\nexport function negotiateProtocol(\n theirs: number | undefined,\n observed: Iterable<ProtocolCapability> = [],\n): ProtocolNegotiation {\n const sanitisedTheirs =\n typeof theirs === 'number' && Number.isFinite(theirs) && theirs >= 1\n ? Math.floor(theirs)\n : undefined;\n const effectiveTheirs = sanitisedTheirs ?? 1;\n const negotiated = Math.min(LIBRARY_PROTOCOL_VERSION, effectiveTheirs);\n const seen = new Set<ProtocolCapability>(observed);\n const capabilities = new Set<ProtocolCapability>();\n for (const capability of PROTOCOL_CAPABILITIES) {\n if (negotiated >= CAPABILITY_DECLARATIONS[capability].since || seen.has(capability)) {\n capabilities.add(capability);\n }\n }\n return {\n ours: LIBRARY_PROTOCOL_VERSION,\n ...(sanitisedTheirs !== undefined ? { theirs: sanitisedTheirs } : { theirs: undefined }),\n negotiated,\n capabilities,\n observed: seen,\n };\n}\n\n/** @internal */\nexport function hasCapability(\n negotiation: ProtocolNegotiation,\n capability: ProtocolCapability,\n): boolean {\n return negotiation.capabilities.has(capability);\n}\n\n/** What a project on Payload 2 hears in development, from the runtime and from a hook. @internal */\nexport const PAYLOAD_2_HINT =\n '[payload-live-preview] This admin sends fieldSchemaJSON, which only Payload 2 does. ' +\n 'Every 2.x release of this package supports Payload 2; 3.0 supports Payload 3 and 4.';\n\n/** The capabilities a single message demonstrates, by its shape alone. */\nexport function observeCapabilities(message: {\n readonly fieldSchemaJSON?: unknown;\n readonly locale?: unknown;\n readonly previewToken?: unknown;\n readonly externallyUpdatedRelationship?: unknown;\n}): readonly ProtocolCapability[] {\n const seen: ProtocolCapability[] = [];\n if (Array.isArray(message.fieldSchemaJSON)) seen.push('schema-json');\n if (typeof message.locale === 'string') seen.push('locale');\n if (typeof message.previewToken === 'string') seen.push('preview-token');\n if (\n typeof message.externallyUpdatedRelationship === 'object' &&\n message.externallyUpdatedRelationship !== null\n ) {\n seen.push('relationship-events');\n }\n return seen;\n}\n","/**\n * Where the runtime is running: framed, opened, or on a developer's machine.\n * Nothing reads bundler-injected variables; a Vite consumer passes\n * `import.meta.env.X` explicitly (docs/astro.md).\n * @internal\n */\n\nexport function isInIframe(): boolean {\n if (typeof window === 'undefined') return false;\n try {\n return window.self !== window.top;\n } catch {\n // A cross-origin parent throws on the comparison; that is an iframe.\n return true;\n }\n}\n\n/** @internal */\nexport function isInPopup(): boolean {\n if (typeof window === 'undefined') return false;\n return window.opener != null;\n}\n\n/** An iframe or a popup; top-level navigation never starts the preview. @internal */\nexport function isInPreviewContext(): boolean {\n return isInIframe() || isInPopup();\n}\n\n/** Under Node, `NODE_ENV !== 'production'`; in a browser the hostname, which is the only signal a bundle has. @internal */\nexport function isDevMode(): boolean {\n const nodeEnv = readNodeEnv();\n if (nodeEnv !== undefined) return nodeEnv !== 'production';\n if (typeof window !== 'undefined') {\n const host = window.location.hostname;\n return host === 'localhost' || host === '127.0.0.1';\n }\n return false;\n}\n\nfunction readNodeEnv(): string | undefined {\n if (typeof process === 'undefined') return undefined;\n const value = process.env['NODE_ENV'];\n return typeof value === 'string' ? value : undefined;\n}\n","/**\n * Which admin origins the runtime trusts: explicit ones always, the\n * `document.referrer` origin only when none is configured, any localhost port\n * in development. See docs/security.md §1. The handshake goes to the trusted\n * origins, and to guessed localhost ports only while the browser names no parent.\n */\n\nimport { isDevMode, isInIframe } from './environment';\n\nconst LOCALHOST_PATTERN = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(?::\\d+)?$/i;\nconst VALID_ORIGIN_PATTERN = /^https?:\\/\\/[^/?#\\s]+$/i;\n\n/** Ports the handshake broadcasts to when the localhost pattern is on; matching itself is unrestricted. */\nconst LOCALHOST_HANDSHAKE_PORTS: readonly number[] = [\n 3000, 3001, 3333, 4000, 4321, 5000, 5173, 5174, 8000, 8080, 8888, 9000,\n];\n\nexport interface OriginDetectorOptions {\n /** Explicit origins to trust. Always allowed. */\n readonly additionalOrigins?: readonly string[];\n /** Set to `false` to ignore `document.referrer`. */\n readonly enableReferrerDetection?: boolean;\n /** Set to `false` to ignore the localhost pattern even in development. */\n readonly enableLocalhostMatching?: boolean;\n /** Override dev-mode detection. */\n readonly forceDevMode?: boolean;\n /** Override `document.referrer` for tests. */\n readonly referrer?: string;\n}\n\nconst enum OriginSlot {\n ExplicitOrigins,\n ReferrerOrigin,\n AllowLocalhost,\n ReferrerWasAvailable,\n LockedOrigin,\n ParentOrigin,\n}\n\ntype OriginState = [\n explicitOrigins: ReadonlySet<string>,\n referrerOrigin: string | undefined,\n allowLocalhost: boolean,\n referrerWasAvailable: boolean,\n lockedOrigin: string | undefined,\n parentOrigin: string | undefined,\n];\n\n/**\n * The framing parent's origin, where the browser names it: Chromium and WebKit\n * do (`location.ancestorOrigins`), Firefox does not. Never a trust source, only\n * where the handshake is worth sending.\n */\nfunction readParentOrigin(): string | undefined {\n if (typeof location === 'undefined') return undefined;\n const ancestors = (location as { readonly ancestorOrigins?: ArrayLike<string> }).ancestorOrigins;\n return ancestors?.[0];\n}\n\n/** The trusted-origin policy: the union of the candidate sources, narrowed to one by `lockOrigin()`. */\nexport class OriginDetector {\n readonly #state: OriginState;\n\n constructor(options: OriginDetectorOptions = {}) {\n const explicit = new Set<string>();\n for (const origin of options.additionalOrigins ?? []) {\n const normalised = normaliseOrigin(origin);\n if (normalised !== undefined) explicit.add(normalised);\n }\n let referrerOrigin: string | undefined;\n if (options.enableReferrerDetection ?? true) {\n const referrer =\n options.referrer ?? (typeof document !== 'undefined' ? document.referrer : '');\n if (referrer.length > 0) {\n try {\n const origin = new URL(referrer).origin;\n if (origin && origin !== 'null') referrerOrigin = origin;\n } catch {\n // opaque referrer\n }\n }\n }\n const allowLocalhost =\n (options.enableLocalhostMatching ?? true) && (options.forceDevMode ?? isDevMode());\n this.#state = [\n explicit,\n referrerOrigin,\n allowLocalhost,\n referrerOrigin !== undefined,\n undefined,\n readParentOrigin(),\n ];\n }\n\n /** Whether `origin` is trusted: the locked origin alone once locked, otherwise the policy above. */\n matches(origin: string): boolean {\n if (origin.length === 0 || origin === 'null') return false;\n if (this.#state[OriginSlot.LockedOrigin] !== undefined) {\n return origin === this.#state[OriginSlot.LockedOrigin];\n }\n if (this.#state[OriginSlot.ExplicitOrigins].has(origin)) return true;\n // The referrer is a fallback, not a union member: any embedder lands there.\n if (\n this.#state[OriginSlot.ExplicitOrigins].size === 0 &&\n this.#state[OriginSlot.ReferrerOrigin] !== undefined &&\n origin === this.#state[OriginSlot.ReferrerOrigin]\n ) {\n return true;\n }\n if (this.#state[OriginSlot.AllowLocalhost] && LOCALHOST_PATTERN.test(origin)) return true;\n return false;\n }\n\n /** Narrow trust to `origin`; refused (`false`) when it is not currently trusted. */\n lockOrigin(origin: string): boolean {\n if (!this.matches(origin)) return false;\n this.#state[OriginSlot.LockedOrigin] = origin;\n return true;\n }\n\n /** Release the lock (heartbeat timeout) so another allow-listed origin may reconnect. Returns the previous lock. */\n unlockOrigin(): string | undefined {\n const previous = this.#state[OriginSlot.LockedOrigin];\n this.#state[OriginSlot.LockedOrigin] = undefined;\n return previous;\n }\n\n get lockedOrigin(): string | undefined {\n return this.#state[OriginSlot.LockedOrigin];\n }\n\n /**\n * Every origin the `ready` handshake is broadcast to. The localhost pattern\n * expands to the common dev ports, a guess that costs a console error per\n * wrong port, so a parent the browser names replaces it: that origin when the\n * pattern trusts it, none when it is not on localhost.\n */\n enumerate(): string[] {\n if (this.#state[OriginSlot.LockedOrigin] !== undefined) {\n return [this.#state[OriginSlot.LockedOrigin]];\n }\n const result = new Set<string>(this.#state[OriginSlot.ExplicitOrigins]);\n if (\n this.#state[OriginSlot.ExplicitOrigins].size === 0 &&\n this.#state[OriginSlot.ReferrerOrigin] !== undefined\n ) {\n result.add(this.#state[OriginSlot.ReferrerOrigin]);\n }\n const parent = this.#state[OriginSlot.ParentOrigin];\n if (this.#state[OriginSlot.AllowLocalhost] && parent !== undefined) {\n if (LOCALHOST_PATTERN.test(parent)) result.add(parent);\n } else if (this.#state[OriginSlot.AllowLocalhost]) {\n for (const port of LOCALHOST_HANDSHAKE_PORTS) {\n result.add(`http://localhost:${String(port)}`);\n result.add(`http://127.0.0.1:${String(port)}`);\n }\n }\n return [...result];\n }\n\n /** Whether `document.referrer` contributed an origin (absent under `Referrer-Policy: no-referrer`). */\n get referrerWasAvailable(): boolean {\n return this.#state[OriginSlot.ReferrerWasAvailable];\n }\n\n /** Framed, outside development, with no trusted origin at all: the host should warn (LP0101). */\n get isProductionUnconfigured(): boolean {\n if (!isInIframe()) return false;\n if (this.#state[OriginSlot.ExplicitOrigins].size > 0) return false;\n if (this.#state[OriginSlot.AllowLocalhost]) return false;\n if (this.#state[OriginSlot.ReferrerOrigin] !== undefined) return false;\n return true;\n }\n\n /** The referrer is the only trust source, so any framing site may drive the preview (LP0102). */\n get isReferrerOnlyTrust(): boolean {\n if (this.#state[OriginSlot.ExplicitOrigins].size > 0) return false;\n if (this.#state[OriginSlot.AllowLocalhost]) return false;\n return this.#state[OriginSlot.ReferrerOrigin] !== undefined;\n }\n}\n\n/** The canonical `http(s)://host[:port]` form of `value`, or `undefined` when it is not one. */\nexport function normaliseOrigin(value: string): string | undefined {\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n try {\n const url = new URL(trimmed);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return undefined;\n if (!VALID_ORIGIN_PATTERN.test(url.origin)) return undefined;\n return url.origin;\n } catch {\n return undefined;\n }\n}\n","/**\n * The document a framework hook exposes, kept outside any framework: the\n * message bus decides which windows may speak, `DataMerger` turns the admin's\n * raw form values back into a populated document, and this class holds the one\n * snapshot a `useSyncExternalStore`-shaped API reads.\n *\n * It touches no DOM. A hook that re-renders a component tree needs the data,\n * not the bindings — everything about elements lives in the runtime instead.\n *\n * The session is per instance (ADR 0002): two hooks on one page have two\n * mergers, two revisions and two snapshots, so a request or an error in one\n * never reaches the other. A session given a `document` merges only the\n * messages for that document; without one it follows the document the admin\n * sends, whichever document it started from.\n */\n\nimport { readDocumentId } from '@core/binding-owner';\nimport { DataMerger } from '@core/data-merger';\nimport { MessageBus } from '@core/message-bus';\nimport { PAYLOAD_2_HINT } from '@core/protocol-version';\nimport { isDevMode } from '@detection/environment';\nimport { OriginDetector } from '@detection/origin';\nimport type { PayloadFieldSchema, PayloadLivePreviewMessage } from '@/types/payload-protocol';\n\n/**\n * `idle` — connected, nothing received yet. `live` — the newest update was\n * merged and is in `data`. `unavailable` — it could not be, and `data` is the\n * last good document rather than a half-merged one.\n */\nexport type DocumentStatus = 'idle' | 'live' | 'unavailable';\n\nexport interface DocumentSnapshot<T> {\n /** The newest document that merged; never a partially applied one. */\n readonly data: T;\n /** No update has settled yet, or a merge is in flight. */\n readonly isLoading: boolean;\n readonly status: DocumentStatus;\n /** Why the last update did not merge; `undefined` while `status` is not `unavailable`. */\n readonly error: Error | undefined;\n /**\n * Which of this session's messages `data` came from: `0` for the initial\n * data, and unchanged when a merge fails. The framework paints `data` in its\n * own commit; a component that must know it was painted compares this in an\n * effect (ADR 0023).\n */\n readonly revision: number;\n}\n\n/**\n * The document a session previews: a collection document by its id, or a global by its slug.\n * `locale` narrows it to the updates the admin sends for that locale.\n */\nexport type PreviewDocument =\n | { readonly collection: string; readonly id: string | number; readonly locale?: string }\n | { readonly global: string; readonly locale?: string };\n\nexport interface DocumentSessionOptions {\n /** Payload server origin the update is re-fetched from. */\n readonly serverURL: string;\n /** REST route prefix. Default `/api`. */\n readonly apiRoute?: string;\n /** Population depth for the merge. Default `1`, as Payload's own hook. */\n readonly depth?: number;\n /**\n * Milliseconds a merge may wait for the server; after that the update is `unavailable`\n * and `data` stays the last good document. Off by default: a merge waits as long as the\n * server takes.\n */\n readonly timeoutMs?: number;\n /**\n * Admin origins allowed to post updates. Without one the session falls back\n * to the localhost matcher in development and trusts nothing in production.\n */\n readonly allowedOrigins?: readonly string[];\n /** `'parent-or-opener'` (default) refuses every window but the framing or opening one. */\n readonly eventSourcePolicy?: 'any' | 'parent-or-opener';\n /** Trust `document.referrer` as an origin source. Default `false`. */\n readonly enableReferrerDetection?: boolean;\n /** Match `localhost` origins in development. Default `true`. */\n readonly enableLocalhostMatching?: boolean;\n /**\n * The document this session previews. An update for another document is ignored, and so is\n * one that does not say which document it is for: Payload 2 sends no collection or global\n * slug, and a create screen has no id yet. Without it the session merges every update.\n */\n readonly document?: PreviewDocument;\n /** Injected for tests. */\n readonly fetchFn?: typeof fetch;\n /** Window to listen on. Default the global one. */\n readonly target?: Window;\n}\n\ntype Listener = () => void;\n\n/** What the merger logged for the attempt that failed, turned into one sentence. */\nfunction reasonFrom(line: readonly unknown[]): string {\n const [label, detail] = line;\n if (label === 'merge HTTP') return `the server answered ${String(detail)}`;\n if (label === 'merge timeout') return `the server did not answer within ${String(detail)} ms`;\n if (label === 'merge invalid') return 'the server answered with something other than a document';\n if (label === 'merge exception') {\n return detail instanceof Error ? detail.message : 'the request failed';\n }\n return 'the update could not be merged';\n}\n\nexport class DocumentSession<T> {\n readonly #merger: DataMerger;\n readonly #bus: MessageBus;\n readonly #detector: OriginDetector;\n readonly #target: Window | undefined;\n readonly #listeners = new Set<Listener>();\n readonly #initial: DocumentSnapshot<T>;\n #snapshot: DocumentSnapshot<T>;\n /** Newest handled message; an older merge that settles later is ignored. */\n #revision = 0;\n #lastLog: readonly unknown[] = [];\n #attached = false;\n #schema: readonly PayloadFieldSchema[] | undefined;\n #locale: string | undefined;\n readonly #document: PreviewDocument | undefined;\n #warnedUnproven = false;\n #warnedPayload2 = false;\n\n constructor(initialData: T, options: DocumentSessionOptions) {\n this.#detector = new OriginDetector({\n ...(options.allowedOrigins !== undefined\n ? { additionalOrigins: options.allowedOrigins }\n : {}),\n enableReferrerDetection: options.enableReferrerDetection ?? false,\n ...(options.enableLocalhostMatching !== undefined\n ? { enableLocalhostMatching: options.enableLocalhostMatching }\n : {}),\n });\n this.#merger = new DataMerger({\n serverURL: options.serverURL,\n ...(options.apiRoute !== undefined ? { apiRoute: options.apiRoute } : {}),\n ...(options.depth !== undefined ? { depth: options.depth } : {}),\n ...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),\n ...(options.fetchFn !== undefined ? { fetchFn: options.fetchFn } : {}),\n log: (...args: unknown[]) => {\n this.#lastLog = args;\n },\n });\n this.#bus = new MessageBus((origin) => this.#detector.matches(origin), {\n onUpdate: (message) => {\n void this.#handle(message);\n },\n onDocumentEvent: () => {\n // A save is the admin's business; the document itself arrives as an\n // update like any other.\n },\n sourcePolicy: options.eventSourcePolicy ?? 'parent-or-opener',\n });\n this.#target = options.target;\n this.#document = options.document;\n this.#initial = {\n data: initialData,\n isLoading: true,\n status: 'idle',\n error: undefined,\n revision: 0,\n };\n this.#snapshot = this.#initial;\n }\n\n /**\n * Attach on the first subscriber and detach with the last, so a component\n * that mounts twice (React's strict mode) listens once and a page that\n * unmounts the hook stops listening at all.\n */\n subscribe = (listener: Listener): (() => void) => {\n this.#listeners.add(listener);\n if (!this.#attached) this.#attach();\n return () => {\n this.#listeners.delete(listener);\n if (this.#listeners.size === 0) this.#detach();\n };\n };\n\n getSnapshot = (): DocumentSnapshot<T> => this.#snapshot;\n\n /** Server rendering has no window and no messages: the initial snapshot a client render starts from. */\n getServerSnapshot = (): DocumentSnapshot<T> => this.#initial;\n\n #attach(): void {\n if (typeof window === 'undefined' && this.#target === undefined) return;\n this.#attached = true;\n this.#bus.attach(this.#target ?? window);\n MessageBus.sendReady(this.#readyTargets(), this.#detector.enumerate());\n }\n\n #detach(): void {\n if (!this.#attached) return;\n this.#attached = false;\n this.#revision += 1;\n this.#bus.detach();\n this.#merger.destroy();\n }\n\n #readyTargets(): Window[] {\n const host = this.#target ?? (typeof window === 'undefined' ? undefined : window);\n if (host === undefined) return [];\n const targets: Window[] = [];\n if (host.parent !== host) targets.push(host.parent);\n const opener: unknown = host.opener;\n if (opener !== null && opener !== undefined && opener !== host) targets.push(opener as Window);\n return targets;\n }\n\n #current(revision: number): boolean {\n return this.#attached && revision === this.#revision;\n }\n\n /** Whether the update is for the document this session previews; any update is without one. */\n #accepts(message: PayloadLivePreviewMessage, data: Record<string, unknown>): boolean {\n const target = this.#document;\n if (target === undefined) return true;\n const { locale, globalSlug, collectionSlug } = message;\n if (target.locale !== undefined && locale !== undefined && locale !== target.locale) {\n return false;\n }\n if ('global' in target) {\n if (globalSlug !== undefined) return globalSlug === target.global;\n if (collectionSlug !== undefined) return false;\n } else {\n if (globalSlug !== undefined) return false;\n if (collectionSlug !== undefined && collectionSlug !== target.collection) return false;\n const id = collectionSlug === undefined ? undefined : readDocumentId(data);\n if (id !== undefined) return id === String(target.id);\n }\n this.#warnUnproven(target);\n return false;\n }\n\n #warnUnproven(target: PreviewDocument): void {\n if (this.#warnedUnproven || !isDevMode()) return;\n this.#warnedUnproven = true;\n const named =\n 'global' in target\n ? `global \"${target.global}\"`\n : `collection \"${target.collection}\", id \"${String(target.id)}\"`;\n console.warn(\n `[payload-live-preview] This hook previews ${named} and ignored an update that does not ` +\n 'say which document it is for: Payload 2 sends no collection or global slug, and a ' +\n 'create screen has no id yet.',\n );\n }\n\n async #handle(message: PayloadLivePreviewMessage): Promise<void> {\n const data = message.data;\n if (data === undefined) return;\n if (message.fieldSchemaJSON !== undefined && !this.#warnedPayload2 && isDevMode()) {\n this.#warnedPayload2 = true;\n console.warn(PAYLOAD_2_HINT);\n }\n // Before the revision moves: an update for another document must not abort this one's merge.\n if (!this.#accepts(message, data)) return;\n const revision = (this.#revision += 1);\n if (message.fieldSchemaJSON !== undefined) this.#schema = message.fieldSchemaJSON;\n const schema = this.#schema;\n if (message.locale !== undefined) this.#locale = message.locale;\n const locale = schema === undefined ? message.locale : this.#locale;\n this.#publish({ ...this.#snapshot, isLoading: true });\n if (!this.#current(revision)) return;\n this.#lastLog = [];\n const result = await this.#merger.merge({\n data,\n ...(schema === undefined ? {} : { schema }),\n ...(message.collectionSlug !== undefined ? { collectionSlug: message.collectionSlug } : {}),\n ...(message.globalSlug !== undefined ? { globalSlug: message.globalSlug } : {}),\n ...(locale !== undefined ? { locale } : {}),\n });\n // A newer message owns the state now, whatever this one turned out to be.\n if (!this.#current(revision)) return;\n if (result.status === 'superseded') return;\n if (result.status === 'unavailable') {\n this.#publish({\n ...this.#snapshot,\n isLoading: false,\n status: 'unavailable',\n error: new Error(`live preview: ${reasonFrom(this.#lastLog)}`),\n });\n return;\n }\n // The server decides the document's shape; `T` is what the caller says it is.\n this.#publish({\n data: result.doc as T,\n isLoading: false,\n status: 'live',\n error: undefined,\n revision,\n });\n }\n\n #publish(next: DocumentSnapshot<T>): void {\n const current = this.#snapshot;\n if (\n current.data === next.data &&\n current.isLoading === next.isLoading &&\n current.status === next.status &&\n current.error === next.error &&\n current.revision === next.revision\n ) {\n return;\n }\n this.#snapshot = next;\n for (const listener of [...this.#listeners]) listener();\n }\n}\n\n/**\n * One preview document, with no framework around it: `subscribe` and `getSnapshot`\n * fit a `useSyncExternalStore` or a Svelte store.\n * @beta\n */\nexport function createDocumentSession<T extends Record<string, unknown>>(\n initialData: T,\n options: DocumentSessionOptions,\n): DocumentSession<T> {\n return new DocumentSession<T>(initialData, options);\n}\n","/**\n * Document ownership for bindings. A field name alone cannot identify a\n * binding on a page that previews several documents — `title` may belong to a\n * global, to shared SEO metadata and to every card at once. An owner marker\n * names the document a subtree belongs to, as a plain comparable string:\n * `global:<slug>`, `collection:<slug>`, `collection:<slug>:<id>`.\n */\n\n/** Identity of the document an incoming message describes. */\nexport interface MessageDocumentIdentity {\n readonly globalSlug?: string | undefined;\n readonly collectionSlug?: string | undefined;\n /** Primary key of the edited document, when the payload carries one. */\n readonly documentId?: string | undefined;\n}\n\n/** Owner key naming one Payload global. */\nexport function globalOwnerKey(slug: string): string {\n return `global:${slug}`;\n}\n\n/** Owner key for a collection; without an id it claims every document of it. */\nexport function collectionOwnerKey(slug: string, documentId?: string): string {\n return documentId === undefined || documentId === ''\n ? `collection:${slug}`\n : `collection:${slug}:${documentId}`;\n}\n\nfunction nonEmpty(value: string | undefined): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\n/**\n * Owner keys this message may address, or `null` when it carries no usable\n * identity — the runtime treats that as fail-closed rather than guessing. A\n * marker naming an id stays unreachable while the id is unknown: an unproven\n * identity must not satisfy an exact claim.\n */\nexport function messageOwnerKeys(identity: MessageDocumentIdentity): readonly string[] | null {\n if (nonEmpty(identity.globalSlug)) return [globalOwnerKey(identity.globalSlug)];\n if (!nonEmpty(identity.collectionSlug)) return null;\n const collectionKey = collectionOwnerKey(identity.collectionSlug);\n return nonEmpty(identity.documentId)\n ? [collectionKey, collectionOwnerKey(identity.collectionSlug, identity.documentId)]\n : [collectionKey];\n}\n\n/** Whether a binding may receive an update addressed to `keys`; an unowned binding never may. */\nexport function isBindingInScope(\n owner: string | undefined,\n keys: readonly string[] | null,\n): boolean {\n if (keys === null || owner === undefined) return false;\n return keys.includes(owner);\n}\n\n/** The document id Payload sends alongside the edited values; only scalars prove an identity. */\nexport function readDocumentId(fields: Record<string, unknown>): string | undefined {\n const id: unknown = fields['id'];\n if (typeof id === 'string' && id.length > 0) return id;\n if (typeof id === 'number' && Number.isFinite(id)) return String(id);\n return undefined;\n}\n","/**\n * The seam between a host framework's own router and the route strategy.\n *\n * The route strategy answers a revision by fetching the route and morphing it\n * into the living page. On a page whose DOM belongs to a reconciler that is\n * working against the framework, and it was seen to break once: `removeChild`\n * on `null` inside React's commit phase, over markup this package had patched.\n * A host that re-renders the route itself does the same job without the morph\n * and without the second HTML request, so it is given the chance to.\n *\n * Why a named slot on `window` and not a reference: the runtime is an inline\n * script that builds its strategy before any application code has hydrated, so\n * there is nothing to hand a component; `window.__livePreview`, the only other\n * public surface, is created later and not at all outside a preview; and the\n * two richer extension points — plugins and events — are reachable only through\n * the programmatic client, which a page using an adapter does not have. One\n * slot, written by whoever mounts and read at the moment of a refresh, is the\n * smallest thing that survives both orders of arrival.\n */\n\n/**\n * A host's own route refresh. It must settle once the fresh markup is\n * committed: the runtime re-applies the revision on top of it, and doing that\n * against the markup being replaced would write into nodes about to be dropped.\n * A function that returns nothing is taken as already committed; the route\n * strategy says once that it could not wait (LP0810), and 3.0 requires the\n * promise (ADR 0028).\n */\nexport type RouteRefresh = () => void | Promise<void>;\n\n/** Read late, so it does not matter whether the runtime or the component came first. */\nconst SLOT = '__livePreviewRouteRefresh';\n\ntype WindowSlot = Record<string, RouteRefresh | undefined>;\n\nfunction slot(): WindowSlot | undefined {\n return typeof window === 'undefined' ? undefined : (window as unknown as WindowSlot);\n}\n\n/**\n * Lend the runtime the host's route refresh; the return value undoes it, for a\n * component's cleanup. A later registration wins, and undoing one that has\n * already been replaced does nothing — two components on one page would\n * otherwise take the slot from each other on unmount.\n */\nexport function registerRouteRefresh(refresh: RouteRefresh): () => void {\n const target = slot();\n if (target === undefined) return () => undefined;\n target[SLOT] = refresh;\n return () => {\n // Cleared rather than deleted: the slot is read through `?.` anyway, and\n // removing the key buys nothing a lint rule would not have to be argued out of.\n if (target[SLOT] === refresh) target[SLOT] = undefined;\n };\n}\n\n/** The registered refresh, or `undefined` on a page that registered none. */\nexport function readRouteRefresh(): RouteRefresh | undefined {\n return slot()?.[SLOT];\n}\n","/**\n * `<LivePreviewRouteRefresh />` — lends the runtime the host router's own\n * refresh, so a route update is a re-render the framework performs rather than\n * fresh HTML this package morphs over the reconciler's nodes (see\n * `src/core/route-refresh.ts` for why that is worth avoiding).\n *\n * It takes the refresh as a prop instead of reaching for `next/navigation`,\n * because `next` is not a dependency of this package and must not become one\n * for a component this small. In Next's App Router that is one client\n * component:\n *\n * ```tsx\n * 'use client';\n * import { useRouter } from 'next/navigation';\n * import { LivePreviewRouteRefresh } from 'payload-live-preview/react';\n *\n * export function LivePreviewRefresh() {\n * return <LivePreviewRouteRefresh refresh={useRouter().refresh} />;\n * }\n * ```\n *\n * The same component serves any router with a refresh of that shape.\n */\n\nimport { useEffect, useRef, useTransition } from 'react';\nimport { registerRouteRefresh } from '@core/route-refresh';\n\nexport interface LivePreviewRouteRefreshProps {\n /** The host router's refresh — `useRouter().refresh` in Next's App Router. */\n readonly refresh: () => void;\n}\n\n/** Resolve everyone waiting on the transition that has just finished. */\nfunction settle(waiting: { current: (() => void)[] }): void {\n const settled = waiting.current;\n waiting.current = [];\n for (const resolve of settled) resolve();\n}\n\n/**\n * Renders nothing. Mount it once inside the preview tree; a second one takes\n * the registration from the first, and unmounting gives it back.\n */\nexport function LivePreviewRouteRefresh({ refresh }: LivePreviewRouteRefreshProps): null {\n const [pending, startTransition] = useTransition();\n const waiting = useRef<(() => void)[]>([]);\n\n // The runtime re-applies the revision on top of the fresh markup, so the\n // refresh it is given may not resolve before that markup is committed. The\n // transition is what makes that observable: it is pending until React has\n // rendered the new server output, and this effect runs on the commit after.\n useEffect(() => {\n if (!pending) settle(waiting);\n });\n\n useEffect(() => {\n const undo = registerRouteRefresh(\n () =>\n new Promise<void>((resolve) => {\n waiting.current.push(resolve);\n startTransition(() => {\n refresh();\n });\n }),\n );\n // A tree that unmounts mid-refresh will never commit one, so the waiting\n // runtime is released here rather than left holding a promise for good.\n return () => {\n undo();\n settle(waiting);\n };\n }, [refresh, startTransition]);\n\n return null;\n}\n","/**\n * The React hook: Payload's `useLivePreview` shape, with this package's merge\n * underneath — one request per accepted update, a newer one aborting the one in\n * flight, an HTTP error refused instead of becoming the document, and a session\n * that belongs to this hook alone (ADR 0002).\n *\n * It re-renders your component tree, so conditional sections and derived values\n * follow the merged document. React preserves component and DOM state while\n * type, key and position stay stable; a remount or replaced node loses the\n * state it held. The DOM runtime uses direct writes and a keyed morph instead\n * (docs/react.md).\n *\n * `react` is an optional peer. This entry imports it at module scope; `./nextjs`\n * loads it, and `react-dom/server`, only at the first render that needs them.\n *\n * The published file starts with `'use client'`. It is not written here because\n * esbuild drops a module directive when it bundles, and a banner with it; the\n * build writes it back through terser's `preamble` (`DIRECTIVE_ENTRIES` in\n * scripts/package-entries.ts, applied in scripts/build-dist.ts).\n */\n\nimport { useRef, useSyncExternalStore } from 'react';\nimport {\n DocumentSession,\n type DocumentSessionOptions,\n type DocumentSnapshot,\n type DocumentStatus,\n} from '@adapters/shared/document-session';\n\nexport type { DocumentSessionOptions, DocumentSnapshot, DocumentStatus };\n\nexport { LivePreviewRouteRefresh, type LivePreviewRouteRefreshProps } from './route-refresh';\nexport { registerRouteRefresh, type RouteRefresh } from '@core/route-refresh';\n\nexport interface UseLivePreviewDocumentOptions<T> extends DocumentSessionOptions {\n /** The document this session starts from; create a new hook instance to switch documents. */\n readonly initialData: T;\n}\n\n/**\n * Subscribe to the admin's updates and return the merged document.\n *\n * ```tsx\n * const { data, status } = useLivePreviewDocument<Page>({\n * serverURL: process.env.NEXT_PUBLIC_PAYLOAD_URL!,\n * allowedOrigins: [process.env.NEXT_PUBLIC_PAYLOAD_ADMIN_ORIGIN!],\n * initialData: page,\n * depth: 1,\n * });\n * ```\n *\n * Returns `{ data, isLoading }` as Payload's hook does, plus `status` and\n * `error`: a merge that fails keeps the last good document instead of leaving\n * the page on a stale one with no way to tell.\n */\nexport function useLivePreviewDocument<T>(\n options: UseLivePreviewDocumentOptions<T>,\n): DocumentSnapshot<T> {\n const session = useSessionFor(options);\n return useSyncExternalStore(session.subscribe, session.getSnapshot, session.getServerSnapshot);\n}\n\n/**\n * One session per hook instance, rebuilt only when a connection option changes.\n * `initialData` is deliberately not one of them: a re-render with a fresh object\n * identity must not throw away a document that already merged.\n */\nfunction useSessionFor<T>(options: UseLivePreviewDocumentOptions<T>): DocumentSession<T> {\n const {\n initialData,\n serverURL,\n apiRoute,\n depth,\n timeoutMs,\n allowedOrigins,\n eventSourcePolicy,\n enableReferrerDetection,\n enableLocalhostMatching,\n document,\n fetchFn,\n target,\n } = options;\n const key = [\n serverURL,\n apiRoute ?? '',\n String(depth ?? ''),\n String(timeoutMs ?? ''),\n (allowedOrigins ?? []).join(' '),\n eventSourcePolicy ?? '',\n String(enableReferrerDetection ?? ''),\n String(enableLocalhostMatching ?? ''),\n document === undefined\n ? ''\n : 'global' in document\n ? `global ${document.global} ${document.locale ?? ''}`\n : `collection ${document.collection} ${String(document.id)} ${document.locale ?? ''}`,\n // A separator no origin, route prefix or policy name can contain.\n ].join(' | ');\n const held = useRef<{\n key: string;\n target: Window | undefined;\n session: DocumentSession<T>;\n } | null>(null);\n if (held.current?.key !== key || held.current.target !== target) {\n held.current = {\n key,\n target,\n session: new DocumentSession<T>(initialData, {\n serverURL,\n ...(apiRoute !== undefined ? { apiRoute } : {}),\n ...(depth !== undefined ? { depth } : {}),\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(allowedOrigins !== undefined ? { allowedOrigins } : {}),\n ...(eventSourcePolicy !== undefined ? { eventSourcePolicy } : {}),\n ...(enableReferrerDetection !== undefined ? { enableReferrerDetection } : {}),\n ...(enableLocalhostMatching !== undefined ? { enableLocalhostMatching } : {}),\n ...(document !== undefined ? { document } : {}),\n ...(fetchFn !== undefined ? { fetchFn } : {}),\n ...(target !== undefined ? { target } : {}),\n }),\n };\n }\n return held.current.session;\n}\n"],"mappings":"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","ignoreList":[]}
|