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.
Files changed (104) hide show
  1. package/README.md +21 -18
  2. package/dist/adapters/astro/PreviewBoundary.astro +17 -4
  3. package/dist/adapters/astro/RichText.astro +13 -2
  4. package/dist/adapters/astro/index.d.ts +7 -7
  5. package/dist/adapters/astro/index.js +1 -1
  6. package/dist/adapters/astro/index.js.map +1 -1
  7. package/dist/adapters/astro/middleware-entry.d.ts +3 -3
  8. package/dist/adapters/astro/middleware-entry.js +1 -1
  9. package/dist/adapters/astro/middleware-entry.js.map +1 -1
  10. package/dist/adapters/nextjs/index.d.ts +2 -2
  11. package/dist/adapters/nextjs/index.js +1 -1
  12. package/dist/adapters/nextjs/index.js.map +1 -1
  13. package/dist/adapters/nuxt/index.d.ts +4 -4
  14. package/dist/adapters/nuxt/index.js +1 -1
  15. package/dist/adapters/nuxt/index.js.map +1 -1
  16. package/dist/adapters/nuxt/module.d.ts +1 -1
  17. package/dist/adapters/react/index.d.ts +2 -2
  18. package/dist/adapters/react/index.js +1 -1
  19. package/dist/adapters/react/index.js.map +1 -1
  20. package/dist/adapters/sveltekit/index.d.ts +5 -5
  21. package/dist/adapters/sveltekit/index.js +1 -1
  22. package/dist/adapters/sveltekit/index.js.map +1 -1
  23. package/dist/adapters/vue/index.d.ts +2 -2
  24. package/dist/adapters/vue/index.js +1 -1
  25. package/dist/adapters/vue/index.js.map +1 -1
  26. package/dist/client.cjs +1 -1
  27. package/dist/client.cjs.map +1 -1
  28. package/dist/client.d.cts +15 -3
  29. package/dist/client.d.ts +15 -3
  30. package/dist/client.js +1 -1
  31. package/dist/client.js.map +1 -1
  32. package/dist/codegen-astro.js +1 -1
  33. package/dist/codegen-astro.js.map +1 -1
  34. package/dist/codegen-cli.js +1 -1
  35. package/dist/codegen-cli.js.map +1 -1
  36. package/dist/codegen.cjs +1 -1
  37. package/dist/codegen.cjs.map +1 -1
  38. package/dist/codegen.js +1 -1
  39. package/dist/codegen.js.map +1 -1
  40. package/dist/core.cjs +1 -1
  41. package/dist/core.cjs.map +1 -1
  42. package/dist/core.d.cts +141 -6
  43. package/dist/core.d.ts +141 -6
  44. package/dist/core.js +1 -1
  45. package/dist/core.js.map +1 -1
  46. package/dist/doctor-cli.d.ts +1 -1
  47. package/dist/doctor-cli.js +1 -1
  48. package/dist/doctor-cli.js.map +1 -1
  49. package/dist/doctor.d.ts +2 -2
  50. package/dist/doctor.js +1 -1
  51. package/dist/doctor.js.map +1 -1
  52. package/dist/{document-session-Bkd181PV.d.ts → document-session-BuYuO3ae.d.ts} +27 -2
  53. package/dist/{fragment-endpoint-DGGLIijM.d.ts → fragment-endpoint-CQE_7MKi.d.ts} +5 -3
  54. package/dist/fragment.cjs +1 -1
  55. package/dist/fragment.cjs.map +1 -1
  56. package/dist/fragment.d.cts +6 -2
  57. package/dist/fragment.d.ts +6 -2
  58. package/dist/fragment.js +1 -1
  59. package/dist/fragment.js.map +1 -1
  60. package/dist/index.cjs +1 -1
  61. package/dist/index.cjs.map +1 -1
  62. package/dist/index.d.cts +79 -16
  63. package/dist/index.d.ts +79 -16
  64. package/dist/index.js +1 -1
  65. package/dist/index.js.map +1 -1
  66. package/dist/lean.cjs +1 -1
  67. package/dist/lean.cjs.map +1 -1
  68. package/dist/lean.js +1 -1
  69. package/dist/lean.js.map +1 -1
  70. package/dist/lexical.cjs +1 -1
  71. package/dist/lexical.cjs.map +1 -1
  72. package/dist/lexical.d.cts +16 -4
  73. package/dist/lexical.d.ts +16 -4
  74. package/dist/lexical.js +1 -1
  75. package/dist/lexical.js.map +1 -1
  76. package/dist/{locals-zz2gi9dj.d.ts → locals-CyzDKfKU.d.ts} +7 -1
  77. package/dist/{middleware-CI-UTf6R.d.ts → middleware-Dnt6u4nF.d.ts} +2 -2
  78. package/dist/{options-CnYybG51.d.ts → options-DTzhFVJ4.d.ts} +13 -1
  79. package/dist/plugin.cjs +1 -1
  80. package/dist/plugin.cjs.map +1 -1
  81. package/dist/plugin.d.cts +15 -9
  82. package/dist/plugin.d.ts +15 -9
  83. package/dist/plugin.js +1 -1
  84. package/dist/plugin.js.map +1 -1
  85. package/dist/plugins.cjs +1 -1
  86. package/dist/plugins.cjs.map +1 -1
  87. package/dist/plugins.d.cts +8 -2
  88. package/dist/plugins.d.ts +8 -2
  89. package/dist/plugins.js +1 -1
  90. package/dist/plugins.js.map +1 -1
  91. package/dist/{probe-D-IHg9dF.d.ts → probe-afwdYebU.d.ts} +6 -2
  92. package/dist/server.cjs +1 -1
  93. package/dist/server.cjs.map +1 -1
  94. package/dist/server.d.cts +23 -3
  95. package/dist/server.d.ts +23 -3
  96. package/dist/server.js +1 -1
  97. package/dist/server.js.map +1 -1
  98. package/dist/structural.cjs +2 -2
  99. package/dist/structural.cjs.map +1 -1
  100. package/dist/structural.d.cts +2 -0
  101. package/dist/structural.d.ts +2 -0
  102. package/dist/structural.js +1 -1
  103. package/dist/structural.js.map +1 -1
  104. package/package.json +7 -4
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-cli.js","names":["tsMorph","project","PACKAGE_NAME","loadTsMorph","createRequire","url","error","Error","cause","parseScript","text","kind","morph","Project","useInMemoryFileSystem","skipLoadingLibFiles","skipFileDependencyResolution","compilerOptions","allowJs","noLib","createSourceFile","overwrite","isPackageSpecifier","specifier","startsWith","packageReexports","script","out","declaration","getExportDeclarations","getModuleSpecifierValue","spec","getNamedExports","push","imported","getName","importedNode","getNameNode","alias","getAliasNode","getText","line","getStartLineNumber","packageBindings","Node","SyntaxKind","getImportDeclarations","getNamedImports","localNode","local","aliased","symbol","getSymbol","getDescendantsOfKind","VariableDeclaration","requiredSpecifier","getInitializer","pattern","isObjectBindingPattern","element","getElements","nameNode","isIdentifier","propertyName","getPropertyNameNode","literalName","initializer","call","isAwaitExpression","getExpression","isCallExpression","callee","getKind","ImportKeyword","argument","getArguments","isStringLiteral","getLiteralText","node","isNoSubstitutionTemplateLiteral","propertyKey","property","isSpreadAssignment","isComputedPropertyName","referencesTo","binding","target","compilerSymbol","checker","getProject","getTypeChecker","Identifier","isInside","parent","getParent","isShorthandPropertyAssignment","getShorthandAssignmentValueSymbol","isExportSpecifier","getLocalTargetSymbol","ancestor","getFirstAncestor","candidate","declaresName","name","except","bindsIdentifier","some","skip","isVariableDeclaration","isBindingElement","isFunctionDeclaration","isClassDeclaration","isParameterDeclaration","isEnumDeclaration","isImportSpecifier","isImportClause","getDefaultImport","isNamespaceImport","replaceNode","start","getStart","end","getEnd","applyTextEdits","edits","ordered","sort","left","right","output","floor","Number","POSITIVE_INFINITY","edit","slice","ADAPTER_ENTRIES","Set","map","entry","optionLiterals","found","Map","record","literal","use","uses","get","known","outer","at","set","visit","getProperties","forEach","shared","constLiteral","has","reference","isNewExpression","inner","unwrap","isObjectLiteralExpression","packageJsxAttributes","tags","JsxAttribute","filter","attribute","isJsxOpeningElement","isJsxSelfClosingElement","getTagNameNode","memberNamed","key","find","VariableDeclarationKind","getDeclarations","getVariableStatement","getDeclarationKind","Const","current","isParenthesizedExpression","isAsExpression","isSatisfiesExpression","isTypeAssertion","ID","KEY","RUNTIME_ROWS","q","ROWS","adapter","join","runtime","ROW_KEYS","BY_HAND","expandDefaultsV1","id","summary","ledgerEntry","notice","apply","conflicts","conflict","reason","codemod","value","isPropertyAssignment","refusal","refuse","expansion","charAt","size","properties","index","findIndex","member","overridden","quote","present","composed","part","opaque","rows","source","getSourceFile","getFullText","length","next","lineStart","lastIndexOf","lead","separator","test","SERVER_SPECIFIER","METHOD","fetchPreviewDocument","fetchPreviewGlobal","SERVER_OPTIONS","DROPPED_OPTIONS","SHARED_READ_OPTIONS","READ_OPTIONS","rewriteCall","options","server","read","dropped","keys","add","accepted","unplaceable","includes","typeArguments","getTypeArguments","generic","method","droppedNote","done","advice","importLine","names","moveFetchPreviewHelpers","bindings","reexports","reexport","blocking","notes","rewritten","serverDeclaration","foreign","declarations","isImportDeclaration","serverImport","isTypeOnly","hasDefinePreview","serverLine","getModuleSpecifier","getQuoteKind","defaultImport","clauses","remaining","clause","typeOnly","kept","trailingNewline","rewriteImports","plan","CALLEE","OLD_KEY","NEW_KEY","renameAdminOriginsOption","BOOLEAN_REFUSED","renameBindingsAuthorizedOption","isFalseLiteral","OLD_NAME","NEW_NAME","renameBinding","getParentOrThrow","renameIsPreviewRequest","existing","isPropertyAccessExpression","memberAccesses","RENAMED","route","ignore","renameOnUnboundChange","renamed","WHOLE_FILE","COMPONENT_EXTENSIONS","FRONTMATTER","SCRIPT_TAG","PACKAGE_REFERENCE","IMPLEMENTATIONS","CODEMODS","lineNumberAt","offset","lineEdits","before","after","firstLine","oldLines","split","newLines","prefix","suffix","oldMiddle","newMiddle","changed","Math","max","migrateSource","chosen","only","importsThisPackage","byCodemod","cursor","block","fileName","extension","extname","toLowerCase","blocks","frontmatter","exec","indexOf","match","matchAll","body","trim","scriptBlocks","item","lines","count","SOURCE_EXTENSIONS","DECLARATION_FILE","SKIP_DIRECTORIES","isSourceFile","async","collectFiles","root","stat","isDirectory","walk","directory","readdir","withFileTypes","path","relativeTo","file","rel","relative","MIGRATE_HELP","describe","String","LEVEL_LABEL","warning","info","DIAGNOSTIC_CODES","Object","freeze","NoTrustedOrigin","ReferrerOnlyTrust","PluginIncompatible","ProfileFeatureOmitted","OrphanField","UnattributableUpdate","UnboundField","VisibilityGateDeferred","UnsafeAttributeWrite","TextTargetHasChildren","MissingArrayTemplate","StructuralItemUnkeyed","StructuralDuplicateKey","StructuralUnstableKeys","UnsupportedStrategy","UnknownValueFormat","SanitizerDroppedAttribute","UnrenderedBlockKept","UnfaithfulPatch","ServerFormatReplaced","UnrenderedBlockLost","MessageRejected","TokenRejected","ProtocolShapeUnknown","HandlerThrew","TransformThrew","RendererThrew","StartupFailed","ReadyFailed","HydrationWaitTimedOut","AuditRuntimeMissing","AuditNoFrameAncestors","AuditFrameOptionsBlocks","AuditBindingsExposed","AuditGateThresholdExceeded","AuditUnownedBindings","AuditNoBindings","AuditNotAPage","FragmentRequestFailed","FragmentResponseInvalid","FragmentUnauthorized","FragmentSuperseded","RouteRefreshLoop","FragmentStrategyUnavailable","UnboundChangeRefresh","EscalationUnavailable","IslandStartUnavailable","RouteRefreshUnconfirmed","V2ReadinessGap","RuntimeOnPublicPage","DEFAULT_PORT","http","https","ws","wss","SCHEME_SOURCE","HOST_SOURCE","schemeOf","protocol","portOf","port","schemeMatches","expression","actual","isSelf","admin","page","hostname","adminScheme","pageScheme","sourceMatches","scheme","host","expressionScheme","expressionHost","expressionPort","wanted","replace","endsWith","hostMatches","INLINE_CONFIG_KEYS","V2_RUNTIME_DEFAULTS","disableReferrerDetection","eventSourcePolicy","skipUnchanged","sanitizerPolicy","V1_RUNTIME_DEFAULTS","CONFIG_NAME","CONFIG_MARKER","COMMENT_OR_SCRIPT","CONFIG_ID","JSON_TYPE","title","effect","condition","ORIGIN_DETAIL","profile","explicit","unmarked","UNREADABLE","code","level","detail","remedy","UNMARKED","readServedConfig","scripts","attributes","servedScripts","inline","tuple","from","depth","inString","previous","json","char","JSON","parse","Array","isArray","readInlineConfig","named","readConfigElement","hasOwn","stringify","remedyFor","origin","row","gap","unknownGeneration","marker","RUNTIME_MARKER","START_TAG","TAG_ATTRIBUTE","LEVEL_ORDER","NON_MARKUP","visibleMarkup","markup","stripped","markupAttributes","tag","assigned","double","single","bare","tryUrl","URL","analyzeProbe","probe","context","publicResponse","pub","previewResponse","preview","notAPage","status","location","headers","contentType","describeNonPage","findings","errors","warnings","runtimeInPreview","credentials","adminOrigin","sameOrigin","frameAncestors","csp","directive","trimmed","frameAncestorsOf","admitted","sources","frameAncestorsAdmits","frameOptions","judged","framingFindings","previewMarkup","publicMarkup","gate","previewBindings","publicBindings","owners","boundaries","boundary","threshold","configured","unowned","firstOwner","unownedBindingsBeforeFirstOwner","bindingFindings","config","servedGate","v2","generation","fallback","flatMap","slot","analyzeV2Readiness","a","b","finding","DEFAULT_INTENT_PARAMS","splitUrl","hashAt","hash","beforeHash","queryAt","base","parts","decodePart","decode","decodeURIComponent","TOKEN_PARAM","redactToken","tokenParam","shown","carriesToken","lowercaseHeaders","readBody","response","limit","reader","getReader","decoder","TextDecoder","received","byteLength","cancel","stream","previewReferer","href","PARAM_NAME","HEADER_LINE","addHeader","parsed","isAbsoluteUrl","given","usageError","addParam","params","setTokenParam","HELP_TEXT","run","argv","fetchImpl","subcommand","rest","process","stdout","write","args","unknown","help","ids","token","parseArgs","stderr","result","io","readFile","content","writeFile","list","results","files","changedCount","conflictCount","runMigrate","message","conflicted","where","runMigrateCommand","showHelp","i","report","timeoutMs","maxBodyBytes","init","fetchFn","globalThis","fetch","redirect","signal","AbortSignal","timeout","createDefaultFetch","previewQueryParams","tokenQueryParam","visitorUrl","Accept","probeHeaders","Referer","sent","own","taken","fromEntries","entries","callerHeaders","previewHeaders","isIntentValue","query","joiner","intent","encodeURIComponent","previewUrl","runDoctor","describeFailure","formatReport","isCliInvocation","pop","then","exit"],"sources":["../src/migrate/ast.ts","../src/migrate/option-literals.ts","../src/migrate/codemods/expand-defaults-v1.ts","../src/migrate/codemods/move-fetch-preview-helpers.ts","../src/migrate/codemods/rename-admin-origins-option.ts","../src/migrate/codemods/rename-bindings-authorized-option.ts","../src/migrate/codemods/rename-is-preview-request.ts","../src/migrate/codemods/rename-on-unbound-change.ts","../src/migrate/script-blocks.ts","../src/migrate/index.ts","../src/migrate/runner.ts","../src/migrate/cli.ts","../src/doctor/format.ts","../src/core/diagnostic-codes.ts","../src/doctor/csp.ts","../src/types/inline-config.ts","../src/types/defaults-profile.ts","../src/doctor/readiness.ts","../src/doctor/analyze.ts","../src/doctor/probe.ts","../src/doctor/cli.ts"],"sourcesContent":["/**\n * ts-morph access for the codemods: parsing, the package's bindings in a\n * script and the references those bindings have. ts-morph is loaded on first\n * use so the entry stays importable without the optional peer.\n */\nimport { createRequire } from 'node:module';\nimport type * as TsMorphModule from 'ts-morph';\nimport type {\n Identifier,\n Node,\n ObjectLiteralElementLike,\n Project,\n SourceFile,\n Symbol as TsSymbol,\n} from 'ts-morph';\nimport type { TextEdit } from './types';\n\ntype TsMorph = typeof TsMorphModule;\n\nexport type ScriptKind = 'ts' | 'tsx' | 'js' | 'jsx';\n\nexport const PACKAGE_NAME = 'payload-live-preview';\n\nlet tsMorph: TsMorph | undefined;\nlet project: Project | undefined;\n\nexport function loadTsMorph(): TsMorph {\n if (tsMorph === undefined) {\n try {\n tsMorph = createRequire(import.meta.url)('ts-morph') as TsMorph;\n } catch (error) {\n throw new Error('pll migrate needs ts-morph: npm install --save-dev ts-morph', {\n cause: error,\n });\n }\n }\n return tsMorph;\n}\n\n/** Parse one script into a throwaway in-memory project; the previous script is discarded. */\nexport function parseScript(text: string, kind: ScriptKind): SourceFile {\n const morph = loadTsMorph();\n project ??= new morph.Project({\n useInMemoryFileSystem: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: { allowJs: true, noLib: true },\n });\n return project.createSourceFile(`/script.${kind}`, text, { overwrite: true });\n}\n\nexport function isPackageSpecifier(specifier: string): boolean {\n return specifier === PACKAGE_NAME || specifier.startsWith(`${PACKAGE_NAME}/`);\n}\n\n/** A name the script binds from the package, by `import` or by destructuring `require()`/`import()`. */\nexport interface PackageBinding {\n /** The exported name, as the package spells it. */\n readonly imported: string;\n /** The name the script uses; equals `imported` unless aliased. */\n readonly local: string;\n readonly specifier: string;\n readonly kind: 'import' | 'require';\n /** The node spelling the exported name; rewritten when the export is renamed. */\n readonly importedNode: Node;\n readonly aliased: boolean;\n readonly symbol: TsSymbol | undefined;\n /** The import declaration or variable declaration that binds it. */\n readonly declaration: Node;\n}\n\n/** A name the script re-exports straight from the package: `export { name } from 'payload-live-preview'`. */\nexport interface PackageReexport {\n /** The exported name, as the package spells it. */\n readonly imported: string;\n readonly specifier: string;\n /** The node spelling the package's name; rewritten when the export is renamed. */\n readonly importedNode: Node;\n /** The name the module exports it under, when the specifier has `as`. */\n readonly alias: string | undefined;\n readonly line: number;\n}\n\n/** packageBindings() sees imports; a re-export from the package binds nothing locally and needs its own pass. */\nexport function packageReexports(script: SourceFile): readonly PackageReexport[] {\n const out: PackageReexport[] = [];\n for (const declaration of script.getExportDeclarations()) {\n const specifier = declaration.getModuleSpecifierValue();\n if (specifier === undefined || !isPackageSpecifier(specifier)) continue;\n for (const spec of declaration.getNamedExports()) {\n out.push({\n imported: spec.getName(),\n specifier,\n importedNode: spec.getNameNode(),\n alias: spec.getAliasNode()?.getText(),\n line: spec.getStartLineNumber(),\n });\n }\n }\n return out;\n}\n\nexport function packageBindings(script: SourceFile): readonly PackageBinding[] {\n const { Node, SyntaxKind } = loadTsMorph();\n const out: PackageBinding[] = [];\n for (const declaration of script.getImportDeclarations()) {\n const specifier = declaration.getModuleSpecifierValue();\n if (!isPackageSpecifier(specifier)) continue;\n for (const spec of declaration.getNamedImports()) {\n const alias = spec.getAliasNode();\n const localNode = alias ?? spec.getNameNode();\n out.push({\n imported: spec.getName(),\n local: localNode.getText(),\n specifier,\n kind: 'import',\n importedNode: spec.getNameNode(),\n aliased: alias !== undefined,\n symbol: localNode.getSymbol(),\n declaration,\n });\n }\n }\n for (const declaration of script.getDescendantsOfKind(SyntaxKind.VariableDeclaration)) {\n const specifier = requiredSpecifier(declaration.getInitializer());\n const pattern = declaration.getNameNode();\n if (specifier === undefined || !isPackageSpecifier(specifier)) continue;\n if (!Node.isObjectBindingPattern(pattern)) continue;\n for (const element of pattern.getElements()) {\n const nameNode = element.getNameNode();\n if (!Node.isIdentifier(nameNode)) continue;\n const propertyName = element.getPropertyNameNode();\n out.push({\n imported: propertyName === undefined ? nameNode.getText() : literalName(propertyName),\n local: nameNode.getText(),\n specifier,\n kind: 'require',\n importedNode: propertyName ?? nameNode,\n aliased: propertyName !== undefined,\n symbol: nameNode.getSymbol(),\n declaration,\n });\n }\n }\n return out;\n}\n\nfunction requiredSpecifier(initializer: Node | undefined): string | undefined {\n const { Node, SyntaxKind } = loadTsMorph();\n const call =\n initializer !== undefined && Node.isAwaitExpression(initializer)\n ? initializer.getExpression()\n : initializer;\n if (call === undefined || !Node.isCallExpression(call)) return undefined;\n const callee = call.getExpression();\n const isRequire = Node.isIdentifier(callee) && callee.getText() === 'require';\n if (!isRequire && callee.getKind() !== SyntaxKind.ImportKeyword) return undefined;\n const [argument] = call.getArguments();\n return argument !== undefined && Node.isStringLiteral(argument)\n ? argument.getLiteralText()\n : undefined;\n}\n\nfunction literalName(node: Node): string {\n const { Node } = loadTsMorph();\n if (Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)) {\n return node.getLiteralText();\n }\n return node.getText();\n}\n\n/** The key of an object-literal member, or `undefined` when it is computed. */\nexport function propertyKey(property: ObjectLiteralElementLike): string | undefined {\n const { Node } = loadTsMorph();\n if (Node.isSpreadAssignment(property)) return undefined;\n const nameNode = property.getNameNode();\n if (Node.isComputedPropertyName(nameNode)) return undefined;\n return literalName(nameNode);\n}\n\nexport type ReferenceKind = 'reference' | 'shorthand' | 'export';\n\nexport interface BindingReference {\n readonly node: Identifier;\n /** `shorthand` is `{ name }`, `export` is `export { name }`; both keep the old key visible. */\n readonly kind: ReferenceKind;\n}\n\n/** Every use of the binding outside its own declaration, resolved by symbol so shadowing is respected. */\nexport function referencesTo(\n script: SourceFile,\n binding: PackageBinding,\n): readonly BindingReference[] {\n const { Node, SyntaxKind } = loadTsMorph();\n const target = binding.symbol?.compilerSymbol;\n if (target === undefined) return [];\n const checker = script.getProject().getTypeChecker();\n const out: BindingReference[] = [];\n for (const node of script.getDescendantsOfKind(SyntaxKind.Identifier)) {\n if (node.getText() !== binding.local || isInside(node, binding.declaration)) continue;\n const parent = node.getParent();\n if (Node.isShorthandPropertyAssignment(parent)) {\n if (checker.getShorthandAssignmentValueSymbol(parent)?.compilerSymbol === target) {\n out.push({ node, kind: 'shorthand' });\n }\n continue;\n }\n if (Node.isExportSpecifier(parent)) {\n if (\n parent.getNameNode() === node &&\n parent.getLocalTargetSymbol()?.compilerSymbol === target\n ) {\n out.push({ node, kind: 'export' });\n }\n continue;\n }\n if (node.getSymbol()?.compilerSymbol === target) out.push({ node, kind: 'reference' });\n }\n return out;\n}\n\nfunction isInside(node: Node, ancestor: Node): boolean {\n return node.getFirstAncestor((candidate) => candidate === ancestor) !== undefined;\n}\n\n/** The declaration that binds `name` anywhere in the script, ignoring those in `except`. */\nexport function declaresName(\n script: SourceFile,\n name: string,\n except: readonly Node[] = [],\n): Node | undefined {\n const { SyntaxKind } = loadTsMorph();\n for (const node of script.getDescendantsOfKind(SyntaxKind.Identifier)) {\n if (node.getText() !== name) continue;\n const parent = node.getParent();\n if (!bindsIdentifier(parent, node)) continue;\n if (except.some((skip) => skip === parent || isInside(parent, skip))) continue;\n return parent;\n }\n return undefined;\n}\n\nfunction bindsIdentifier(parent: Node, node: Identifier): boolean {\n const { Node } = loadTsMorph();\n if (\n Node.isVariableDeclaration(parent) ||\n Node.isBindingElement(parent) ||\n Node.isFunctionDeclaration(parent) ||\n Node.isClassDeclaration(parent) ||\n Node.isParameterDeclaration(parent) ||\n Node.isEnumDeclaration(parent)\n ) {\n return parent.getNameNode() === node;\n }\n if (Node.isImportSpecifier(parent)) {\n return (parent.getAliasNode() ?? parent.getNameNode()) === node;\n }\n if (Node.isImportClause(parent)) return parent.getDefaultImport() === node;\n if (Node.isNamespaceImport(parent)) return parent.getNameNode() === node;\n return false;\n}\n\n/** Identifiers spelled `name` that are member names (`x.name`), never the package's binding. */\nexport function memberAccesses(script: SourceFile, name: string): readonly Identifier[] {\n const { Node, SyntaxKind } = loadTsMorph();\n return script.getDescendantsOfKind(SyntaxKind.Identifier).filter((node) => {\n const parent = node.getParent();\n return (\n node.getText() === name &&\n Node.isPropertyAccessExpression(parent) &&\n parent.getNameNode() === node\n );\n });\n}\n\nexport function replaceNode(node: Node, text: string): TextEdit {\n return { start: node.getStart(), end: node.getEnd(), text };\n}\n\n/** Splice non-overlapping edits into `text`. */\nexport function applyTextEdits(text: string, edits: readonly TextEdit[]): string {\n const ordered = [...edits].sort((left, right) => right.start - left.start);\n let output = text;\n let floor = Number.POSITIVE_INFINITY;\n for (const edit of ordered) {\n if (edit.end > floor) throw new Error('overlapping codemod edits');\n output = `${output.slice(0, edit.start)}${edit.text}${output.slice(edit.end)}`;\n floor = edit.start;\n }\n return output;\n}\n","/**\n * The options literals a script hands to the package: an object literal passed\n * to a function or class the script binds from it, and a `const` object literal\n * such a call takes by name or spreads into its own. The option codemods rename\n * or expand keys there (ADR 0026); anything else they cannot see is left to the\n * development warning the package gives at run time.\n */\nimport type { JsxAttribute, Node, ObjectLiteralExpression, SourceFile } from 'ts-morph';\nimport { loadTsMorph, packageBindings, propertyKey, referencesTo } from './ast';\n\n/** Adapter options carry the request rows too; the root, `/core` and `/client` take runtime options. */\nexport type OptionsKind = 'adapter' | 'runtime';\n\n/** @internal */\nexport const ADAPTER_ENTRIES: ReadonlySet<string> = new Set(\n ['astro', 'nextjs', 'sveltekit', 'nuxt', 'nuxt-module'].map(\n (entry) => `payload-live-preview/${entry}`,\n ),\n);\n\n/** One call that uses a literal: the literal the call passes, which spreads the shared one or is it. */\nexport interface OptionsUse {\n readonly kind: OptionsKind;\n readonly outer: ObjectLiteralExpression;\n /** The index of the spread in `outer` that brings the shared literal in; absent when `outer` is it. */\n readonly at?: number;\n}\n\n/** Every literal the package receives, with the calls that give it. */\nexport function optionLiterals(\n script: SourceFile,\n): ReadonlyMap<ObjectLiteralExpression, readonly OptionsUse[]> {\n const { Node } = loadTsMorph();\n const found = new Map<ObjectLiteralExpression, OptionsUse[]>();\n const record = (literal: ObjectLiteralExpression, use: OptionsUse): void => {\n const uses = found.get(literal) ?? [];\n if (\n !uses.some(\n (known) => known.outer === use.outer && known.at === use.at && known.kind === use.kind,\n )\n ) {\n uses.push(use);\n }\n found.set(literal, uses);\n };\n const visit = (literal: ObjectLiteralExpression, kind: OptionsKind): void => {\n record(literal, { kind, outer: literal });\n literal.getProperties().forEach((property, at) => {\n if (!Node.isSpreadAssignment(property)) return;\n const shared = constLiteral(property.getExpression());\n if (shared !== undefined) record(shared, { kind, outer: literal, at });\n });\n };\n for (const binding of packageBindings(script)) {\n const kind: OptionsKind = ADAPTER_ENTRIES.has(binding.specifier) ? 'adapter' : 'runtime';\n for (const reference of referencesTo(script, binding)) {\n const call = reference.node.getParent();\n if (reference.kind !== 'reference') continue;\n if (!Node.isCallExpression(call) && !Node.isNewExpression(call)) continue;\n if (call.getExpression() !== reference.node) continue;\n for (const argument of call.getArguments()) {\n const inner = unwrap(argument);\n const literal = Node.isObjectLiteralExpression(inner) ? inner : constLiteral(inner);\n if (literal !== undefined) visit(literal, kind);\n }\n }\n }\n return found;\n}\n\n/** `name=\"…\"` or `name={…}` on a JSX element whose tag the script binds from the package. */\nexport function packageJsxAttributes(script: SourceFile, name: string): readonly JsxAttribute[] {\n const { Node, SyntaxKind } = loadTsMorph();\n const tags = new Set(packageBindings(script).map((binding) => binding.local));\n return script.getDescendantsOfKind(SyntaxKind.JsxAttribute).filter((attribute) => {\n const element = attribute.getParent().getParent();\n const isTag = Node.isJsxOpeningElement(element) || Node.isJsxSelfClosingElement(element);\n return (\n isTag &&\n tags.has(element.getTagNameNode().getText()) &&\n attribute.getNameNode().getText() === name\n );\n });\n}\n\n/** The member spelled `key`, or `undefined`. */\nexport function memberNamed(literal: ObjectLiteralExpression, key: string): Node | undefined {\n return literal.getProperties().find((property) => propertyKey(property) === key);\n}\n\n/** The literal a `const` declares, seen through `as const`, `satisfies` and parentheses. */\nfunction constLiteral(node: Node): ObjectLiteralExpression | undefined {\n const { Node, VariableDeclarationKind } = loadTsMorph();\n const target = unwrap(node);\n if (!Node.isIdentifier(target)) return undefined;\n for (const declaration of target.getSymbol()?.getDeclarations() ?? []) {\n if (!Node.isVariableDeclaration(declaration)) continue;\n if (\n declaration.getVariableStatement()?.getDeclarationKind() !== VariableDeclarationKind.Const\n ) {\n continue;\n }\n const initializer = declaration.getInitializer();\n const literal = initializer === undefined ? undefined : unwrap(initializer);\n if (literal !== undefined && Node.isObjectLiteralExpression(literal)) return literal;\n }\n return undefined;\n}\n\nfunction unwrap(node: Node): Node {\n const { Node } = loadTsMorph();\n let current = node;\n while (\n Node.isParenthesizedExpression(current) ||\n Node.isAsExpression(current) ||\n Node.isSatisfiesExpression(current) ||\n Node.isTypeAssertion(current)\n ) {\n current = current.getExpression();\n }\n return current;\n}\n","/**\n * Ledger entry 21: `defaults: 'v1'` → the rows it stands for, as explicit\n * options. The rows keep every value the profile gave, so nothing changes at\n * run time; they only move into the source, where a reviewer and\n * `pll doctor --v2` see each one (ADR 0026).\n */\nimport type { Node, ObjectLiteralElementLike, ObjectLiteralExpression } from 'ts-morph';\nimport { loadTsMorph, propertyKey } from '../ast';\nimport {\n memberNamed,\n optionLiterals,\n packageJsxAttributes,\n type OptionsKind,\n type OptionsUse,\n} from '../option-literals';\nimport type { CodemodImplementation, CodemodConflict, TextEdit } from '../types';\n\nconst ID = 'expand-defaults-v1';\nconst KEY = 'defaults';\n\n/** The 1.x rows (`src/types/defaults-profile.ts`), in source form; `Q` is the file's quote. */\nconst REQUEST_ROWS: readonly (readonly [string, (q: string) => string])[] = [\n ['strict', () => 'false'],\n [\n 'previewSignals',\n (q) => `[${[`${q}query${q}`, `${q}fetch-dest${q}`, `${q}referer${q}`].join(', ')}]`,\n ],\n];\nconst RUNTIME_ROWS: readonly (readonly [string, (q: string) => string])[] = [\n ['disableReferrerDetection', () => 'false'],\n ['eventSourcePolicy', (q) => `${q}any${q}`],\n ['skipUnchanged', () => 'false'],\n ['sanitizerPolicy', (q) => `${q}compat${q}`],\n];\nconst ROWS: Readonly<Record<OptionsKind, readonly (readonly [string, (q: string) => string])[]>> = {\n adapter: [...REQUEST_ROWS, ...RUNTIME_ROWS],\n runtime: RUNTIME_ROWS,\n};\nconst ROW_KEYS: ReadonlySet<string> = new Set(ROWS.adapter.map(([key]) => key));\nconst BY_HAND = \"write the rows `defaults: 'v1'` stands for by hand (docs/migration.md)\";\n\nexport const expandDefaultsV1: CodemodImplementation = {\n id: ID,\n summary: \"`defaults: 'v1'` → the 1.x rows as explicit options\",\n ledgerEntry: 21,\n notice:\n \"The rows keep the 1.x values `defaults: 'v1'` gave; `pll doctor --v2` names each one to drop once the page is ready for 2.0's.\",\n apply(script) {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const conflicts: CodemodConflict[] = [];\n for (const [literal, uses] of optionLiterals(script)) {\n const property = memberNamed(literal, KEY);\n if (property === undefined) continue;\n const line = property.getStartLineNumber();\n const conflict = (reason: string): void => {\n conflicts.push({ codemod: ID, line, reason: `${reason}; ${BY_HAND}` });\n };\n const value = Node.isPropertyAssignment(property) ? property.getInitializer() : undefined;\n if (value === undefined || !Node.isStringLiteral(value)) {\n conflict('`defaults` is not a literal');\n continue;\n }\n if (value.getLiteralText() !== 'v1') continue;\n const refusal = refuse(literal, property, uses);\n if (refusal !== undefined) {\n conflict(refusal);\n continue;\n }\n edits.push(expansion(literal, property, uses, value.getText().charAt(0)));\n }\n for (const attribute of packageJsxAttributes(script, KEY)) {\n conflicts.push({\n codemod: ID,\n line: attribute.getStartLineNumber(),\n reason: `a JSX attribute; ${BY_HAND} as attributes`,\n });\n }\n return { edits, conflicts };\n },\n};\n\n/** Why the rows cannot go where `defaults` was without changing what wins, if they cannot. */\nfunction refuse(\n literal: ObjectLiteralExpression,\n property: Node,\n uses: readonly OptionsUse[],\n): string | undefined {\n const { Node } = loadTsMorph();\n if (new Set(uses.map((use) => use.kind)).size > 1) {\n return 'the object is shared by an adapter and a client, which take different rows';\n }\n // A row is explicit once written, so whatever came before it no longer wins over it.\n const properties = literal.getProperties();\n const index = properties.findIndex((member) => member === property);\n if (properties.slice(0, index).some((member) => Node.isSpreadAssignment(member))) {\n return 'a spread before `defaults` may set a row the expansion would override';\n }\n for (const { outer, at } of uses) {\n if (at === undefined) continue;\n if (memberNamed(outer, KEY) !== undefined) {\n return 'a call that spreads it names its own defaults';\n }\n const before = outer.getProperties().slice(0, at);\n const overridden = (member: ObjectLiteralElementLike): boolean =>\n Node.isSpreadAssignment(member) || ROW_KEYS.has(propertyKey(member) ?? '');\n if (before.some(overridden)) {\n return 'a call sets a row before spreading the object, and the expansion would override it';\n }\n }\n return undefined;\n}\n\nfunction expansion(\n literal: ObjectLiteralExpression,\n property: Node,\n uses: readonly OptionsUse[],\n quote: string,\n): TextEdit {\n const { Node } = loadTsMorph();\n const kind = uses[0]?.kind ?? 'runtime';\n const present = new Set(literal.getProperties().map((member) => propertyKey(member)));\n const composed = [literal, ...uses.map((use) => use.outer)];\n const has = (key: string): boolean =>\n composed.some((part) => memberNamed(part, key) !== undefined);\n // A spread the codemod cannot see into may carry `serverURL`; the one that brings this object in is seen.\n const known = new Set(\n uses.map((use) => (use.at === undefined ? undefined : use.outer.getProperties()[use.at])),\n );\n const opaque = composed.some((part) =>\n part.getProperties().some((member) => Node.isSpreadAssignment(member) && !known.has(member)),\n );\n const rows = ROWS[kind]\n .filter(([key]) => !present.has(key))\n .map(([key, value]) => `${key}: ${value(quote)}`);\n // `'v1'` read an omitted depth as the 1.x default of 1; 2.0 asks for it with `serverURL`.\n if (!has('mergeDepth') && (has('serverURL') || opaque)) rows.push('mergeDepth: 1');\n const source = property.getSourceFile().getFullText();\n if (rows.length === 0) {\n // Every row is already explicit: only the key goes, with the separator after it.\n const next = literal.getProperties().find((member) => member.getStart() > property.getStart());\n return { start: property.getStart(), end: next?.getStart() ?? property.getEnd(), text: '' };\n }\n const lineStart = source.lastIndexOf('\\n', property.getStart()) + 1;\n const lead = source.slice(lineStart, property.getStart());\n const separator = /^\\s*$/u.test(lead) ? `,\\n${lead}` : ', ';\n return { start: property.getStart(), end: property.getEnd(), text: rows.join(separator) };\n}\n","/**\n * Ledger entry 9: `fetchPreviewDocument()`/`fetchPreviewGlobal()` on the root\n * entry → `definePreview({ serverURL, depth }).fetchDocument()`/`.fetchGlobal()`\n * on `payload-live-preview/server`.\n */\nimport {\n PACKAGE_NAME,\n declaresName,\n loadTsMorph,\n packageBindings,\n packageReexports,\n propertyKey,\n referencesTo,\n type PackageBinding,\n type PackageReexport,\n} from '../ast';\nimport type { CodemodImplementation, CodemodConflict, CodemodPlan, TextEdit } from '../types';\nimport type {\n CallExpression,\n ImportDeclaration,\n ObjectLiteralExpression,\n SourceFile,\n} from 'ts-morph';\n\nconst ID = 'move-fetch-preview-helpers';\nconst SERVER_SPECIFIER = `${PACKAGE_NAME}/server`;\nconst METHOD: Readonly<Record<string, string>> = {\n fetchPreviewDocument: 'fetchDocument',\n fetchPreviewGlobal: 'fetchGlobal',\n};\nconst SERVER_OPTIONS = new Set(['serverURL', 'apiRoute', 'depth']);\nconst DROPPED_OPTIONS = new Set(['draft', 'fetchFn']);\n/**\n * What `ReadDocumentOptions`/`ReadGlobalOptions` accept (src/server/preview.ts).\n * 1.x spelled the target `collection` and `global` too, so there is no rename to\n * make here — a key that is in neither set is one this codemod cannot place, and\n * passing it through unannounced produces a file that does not compile.\n */\nconst SHARED_READ_OPTIONS = ['authorization', 'locale', 'headers', 'signal', 'errorMode'];\nconst READ_OPTIONS: Readonly<Record<string, readonly string[]>> = {\n fetchPreviewDocument: ['collection', 'where', ...SHARED_READ_OPTIONS],\n fetchPreviewGlobal: ['global', ...SHARED_READ_OPTIONS],\n};\nconst DEPTH_TODO =\n 'depth: 1 /* TODO(pll migrate): the 1.x default; match the runtime mergeDepth */';\nconst AUTHORIZATION_TODO =\n 'authorization: null /* TODO(pll migrate): pass the verdict from authorizePreviewRequest(); ' +\n 'null reads the published document */';\n\nfunction conflict(line: number, reason: string): CodemodConflict {\n return { codemod: ID, reason, line };\n}\n\ninterface RewrittenCall {\n readonly edit: TextEdit;\n /** What the rewrite did; only true when the file is rewritten. */\n readonly done: CodemodConflict;\n /** What a reader has to place by hand, rewritten or not. */\n readonly advice: readonly CodemodConflict[];\n}\n\nfunction rewriteCall(\n call: CallExpression,\n options: ObjectLiteralExpression,\n imported: string,\n): RewrittenCall {\n const server: string[] = [];\n const read: string[] = [];\n const dropped: string[] = [];\n const keys = new Set<string>();\n for (const property of options.getProperties()) {\n const key = propertyKey(property);\n if (key !== undefined) keys.add(key);\n if (key !== undefined && SERVER_OPTIONS.has(key)) server.push(property.getText());\n else if (key !== undefined && DROPPED_OPTIONS.has(key)) dropped.push(key);\n else read.push(property.getText());\n }\n if (!keys.has('depth')) server.push(DEPTH_TODO);\n if (!keys.has('authorization')) read.push(AUTHORIZATION_TODO);\n const accepted = READ_OPTIONS[imported] ?? [];\n const unplaceable = [...keys].filter(\n (key) => !SERVER_OPTIONS.has(key) && !DROPPED_OPTIONS.has(key) && !accepted.includes(key),\n );\n const typeArguments = call.getTypeArguments().map((argument) => argument.getText());\n const generic = typeArguments.length === 0 ? '' : `<${typeArguments.join(', ')}>`;\n const method = METHOD[imported] ?? imported;\n const text = `definePreview({ ${server.join(', ')} }).${method}${generic}({ ${read.join(', ')} })`;\n const droppedNote = dropped.length === 0 ? '' : `, and ${dropped.join('/')} was dropped`;\n const line = call.getStartLineNumber();\n const done = conflict(\n line,\n `${imported}() was rewritten onto definePreview().${method}(); it now returns a ` +\n `PreviewFetchResult (check ok/data) and needs a real authorization for drafts${droppedNote}`,\n );\n const advice: CodemodConflict[] = [];\n if (unplaceable.length > 0) {\n advice.push(\n conflict(\n line,\n `${imported}() was passed ${unplaceable.map((key) => `\\`${key}\\``).join(', ')}, which ` +\n `.${method}() does not accept; it takes ${accepted.join(', ')}. The key was carried ` +\n 'over unchanged and will not compile — place it by hand',\n ),\n );\n }\n return { edit: { start: call.getStart(), end: call.getEnd(), text }, done, advice };\n}\n\nfunction importLine(quote: string, names: readonly string[], specifier: string): string {\n return `import { ${names.join(', ')} } from ${quote}${specifier}${quote};`;\n}\n\n/** Drop the moved names from their root imports and make sure `definePreview` is imported from the server entry. */\nfunction rewriteImports(script: SourceFile, bindings: readonly PackageBinding[]): TextEdit[] {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const declarations = new Set<ImportDeclaration>();\n for (const binding of bindings) {\n if (Node.isImportDeclaration(binding.declaration)) declarations.add(binding.declaration);\n }\n const serverImport = script\n .getImportDeclarations()\n .find(\n (declaration) =>\n declaration.getModuleSpecifierValue() === SERVER_SPECIFIER && !declaration.isTypeOnly(),\n );\n const hasDefinePreview =\n serverImport?.getNamedImports().some((spec) => spec.getName() === 'definePreview') === true;\n let serverLine: string | undefined;\n if (serverImport !== undefined && !hasDefinePreview) {\n const quote = serverImport.getModuleSpecifier().getQuoteKind();\n const names = [\n ...serverImport.getNamedImports().map((spec) => spec.getText()),\n 'definePreview',\n ];\n const defaultImport = serverImport.getDefaultImport()?.getText();\n const clauses =\n defaultImport === undefined ? names.join(', ') : `${defaultImport}, { ${names.join(', ')} }`;\n const text =\n defaultImport === undefined\n ? importLine(quote, names, SERVER_SPECIFIER)\n : `import ${clauses} from ${quote}${SERVER_SPECIFIER}${quote};`;\n edits.push({ start: serverImport.getStart(), end: serverImport.getEnd(), text });\n }\n for (const declaration of declarations) {\n const quote = declaration.getModuleSpecifier().getQuoteKind();\n const remaining = declaration\n .getNamedImports()\n .filter((spec) => !(spec.getName() in METHOD))\n .map((spec) => spec.getText());\n const defaultImport = declaration.getDefaultImport()?.getText();\n const clauses = [\n defaultImport,\n remaining.length === 0 ? undefined : `{ ${remaining.join(', ')} }`,\n ].filter((clause): clause is string => clause !== undefined);\n const typeOnly = declaration.isTypeOnly() ? 'type ' : '';\n const kept =\n clauses.length === 0\n ? ''\n : `import ${typeOnly}${clauses.join(', ')} from ${quote}${PACKAGE_NAME}${quote};`;\n if (serverImport === undefined && serverLine === undefined) {\n serverLine = importLine(quote, ['definePreview'], SERVER_SPECIFIER);\n edits.push({\n start: declaration.getStart(),\n end: declaration.getEnd(),\n text: kept === '' ? serverLine : `${kept}\\n${serverLine}`,\n });\n } else {\n // A removed declaration takes its line break with it.\n const end = declaration.getEnd();\n const trailingNewline = kept === '' && script.getFullText()[end] === '\\n' ? 1 : 0;\n edits.push({ start: declaration.getStart(), end: end + trailingNewline, text: kept });\n }\n }\n return edits;\n}\n\nfunction plan(\n script: SourceFile,\n bindings: readonly PackageBinding[],\n reexports: readonly PackageReexport[],\n): CodemodPlan {\n const { Node } = loadTsMorph();\n const blocking: CodemodConflict[] = reexports.map((reexport) =>\n conflict(\n reexport.line,\n `${reexport.imported} is re-exported straight from the package; it became ` +\n `definePreview().${METHOD[reexport.imported] ?? reexport.imported}() on ${SERVER_SPECIFIER}, ` +\n 'so rewrite the re-export and its importers by hand',\n ),\n );\n const notes: CodemodConflict[] = [];\n const advice: CodemodConflict[] = [];\n const edits: TextEdit[] = [];\n for (const binding of bindings) {\n if (binding.kind === 'require') {\n blocking.push(\n conflict(\n binding.declaration.getStartLineNumber(),\n `${binding.imported} is bound with require(); rewrite it onto definePreview() from ` +\n `${SERVER_SPECIFIER} by hand`,\n ),\n );\n continue;\n }\n for (const reference of referencesTo(script, binding)) {\n const line = reference.node.getStartLineNumber();\n const call = reference.node.getParent();\n const isCall =\n reference.kind === 'reference' &&\n Node.isCallExpression(call) &&\n call.getExpression() === reference.node;\n if (!isCall) {\n blocking.push(\n conflict(\n line,\n `${binding.local} is used other than as a direct call; rewrite it onto definePreview() by hand`,\n ),\n );\n continue;\n }\n const [options] = call.getArguments();\n if (\n options === undefined ||\n !Node.isObjectLiteralExpression(options) ||\n options.getProperties().some((property) => Node.isSpreadAssignment(property))\n ) {\n blocking.push(\n conflict(\n line,\n `${binding.imported}() options are not a plain object literal, so serverURL/depth ` +\n 'cannot be split out; rewrite it onto definePreview() by hand',\n ),\n );\n continue;\n }\n const rewritten = rewriteCall(call, options, binding.imported);\n edits.push(rewritten.edit);\n notes.push(rewritten.done, ...rewritten.advice);\n advice.push(...rewritten.advice);\n }\n }\n const serverDeclaration = script\n .getImportDeclarations()\n .filter((declaration) => declaration.getModuleSpecifierValue() === SERVER_SPECIFIER);\n const foreign = declaresName(script, 'definePreview', serverDeclaration);\n if (foreign !== undefined) {\n blocking.push(\n conflict(\n foreign.getStartLineNumber(),\n `this module already binds a definePreview that is not ${SERVER_SPECIFIER}'s; rename it, ` +\n 'then move the fetch helpers by hand',\n ),\n );\n }\n // A held-back file was not rewritten, so \"was rewritten\" would say the opposite; the advice still holds.\n if (blocking.length > 0) return { edits: [], conflicts: [...blocking, ...advice] };\n edits.push(...rewriteImports(script, bindings));\n return { edits, conflicts: notes };\n}\n\nexport const moveFetchPreviewHelpers: CodemodImplementation = {\n id: ID,\n summary:\n '`fetchPreviewDocument`/`fetchPreviewGlobal` from the root → `definePreview().fetchDocument`/`.fetchGlobal` (payload-live-preview/server)',\n ledgerEntry: 9,\n apply(script) {\n const bindings = packageBindings(script).filter(\n (binding) => binding.specifier === PACKAGE_NAME && binding.imported in METHOD,\n );\n const reexports = packageReexports(script).filter(\n (reexport) => reexport.specifier === PACKAGE_NAME && reexport.imported in METHOD,\n );\n if (bindings.length === 0 && reexports.length === 0) return { edits: [], conflicts: [] };\n return plan(script, bindings, reexports);\n },\n};\n","/** Ledger entry 13: `hasPreviewIntent(request, { adminOrigins })` → `{ allowedOrigins }`. */\nimport { loadTsMorph, packageBindings, propertyKey, referencesTo, replaceNode } from '../ast';\nimport type { CodemodImplementation, CodemodConflict, TextEdit } from '../types';\n\nconst ID = 'rename-admin-origins-option';\nconst CALLEE = 'hasPreviewIntent';\nconst OLD_KEY = 'adminOrigins';\nconst NEW_KEY = 'allowedOrigins';\nconst BY_HAND = `if they carry \\`${OLD_KEY}\\`, rename it to \\`${NEW_KEY}\\``;\n\nexport const renameAdminOriginsOption: CodemodImplementation = {\n id: ID,\n summary: '`hasPreviewIntent(request, { adminOrigins })` → `{ allowedOrigins }`',\n ledgerEntry: 13,\n apply(script) {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const conflicts: CodemodConflict[] = [];\n const bindings = packageBindings(script).filter((binding) => binding.imported === CALLEE);\n for (const binding of bindings) {\n for (const reference of referencesTo(script, binding)) {\n const call = reference.node.getParent();\n if (reference.kind !== 'reference' || !Node.isCallExpression(call)) continue;\n if (call.getExpression() !== reference.node) continue;\n const options = call.getArguments()[1];\n if (options === undefined) continue;\n const line = options.getStartLineNumber();\n if (!Node.isObjectLiteralExpression(options)) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `${CALLEE}() options are not a literal; ${BY_HAND}`,\n });\n continue;\n }\n const properties = options.getProperties();\n const keys = properties.map((property) => propertyKey(property));\n // With both names the package reads `allowedOrigins` and ignores the\n // alias; renamed, the later key would win instead.\n if (keys.includes(OLD_KEY) && keys.includes(NEW_KEY)) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `${CALLEE}() is given both ${OLD_KEY} and ${NEW_KEY}; ${NEW_KEY} wins, drop ${OLD_KEY} by hand`,\n });\n continue;\n }\n for (const property of properties) {\n if (Node.isSpreadAssignment(property)) {\n conflicts.push({\n codemod: ID,\n line: property.getStartLineNumber(),\n reason: `${CALLEE}() spreads its options; ${BY_HAND}`,\n });\n } else if (propertyKey(property) !== OLD_KEY) {\n continue;\n } else if (Node.isShorthandPropertyAssignment(property)) {\n edits.push(replaceNode(property, `${NEW_KEY}: ${OLD_KEY}`));\n } else if (Node.isPropertyAssignment(property)) {\n edits.push(replaceNode(property.getNameNode(), NEW_KEY));\n }\n }\n }\n }\n return { edits, conflicts };\n },\n};\n","/** Ledger entry 7: `createPreviewBindings({ authorized })` → `{ authorization }`. */\nimport { loadTsMorph, packageBindings, propertyKey, referencesTo, replaceNode } from '../ast';\nimport type { CodemodImplementation, CodemodConflict, TextEdit } from '../types';\n\nconst ID = 'rename-bindings-authorized-option';\nconst OLD_KEY = 'authorized';\nconst NEW_KEY = 'authorization';\nconst BY_HAND =\n `if they carry \\`${OLD_KEY}\\`, rename it to \\`${NEW_KEY}\\` and pass the verdict from ` +\n 'authorizePreviewRequest()';\n/**\n * `false` has an exact equivalent — an unauthorized response suppresses every\n * binding, which is what `null` means — so it is rewritten. Nothing else does:\n * only a real context from `authorizePreviewRequest()` authorizes emission, and\n * a boolean left under the new name does not compile (TS2322).\n */\nconst BOOLEAN_REFUSED =\n `\\`${NEW_KEY}\\` takes the context from authorizePreviewRequest(); the boolean 1.x ` +\n 'accepted is not. The key was renamed and its value left as it stands — pass the ' +\n 'verdict, or `null` for a public response';\n\nexport const renameBindingsAuthorizedOption: CodemodImplementation = {\n id: ID,\n summary: '`createPreviewBindings({ authorized })` → `{ authorization }`',\n ledgerEntry: 7,\n apply(script) {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const conflicts: CodemodConflict[] = [];\n const bindings = packageBindings(script).filter(\n (binding) => binding.imported === 'createPreviewBindings',\n );\n for (const binding of bindings) {\n for (const reference of referencesTo(script, binding)) {\n const call = reference.node.getParent();\n if (reference.kind !== 'reference' || !Node.isCallExpression(call)) continue;\n if (call.getExpression() !== reference.node) continue;\n const [options] = call.getArguments();\n if (options === undefined) continue;\n const line = options.getStartLineNumber();\n if (!Node.isObjectLiteralExpression(options)) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `createPreviewBindings() options are not a literal; ${BY_HAND}`,\n });\n continue;\n }\n for (const property of options.getProperties()) {\n if (Node.isSpreadAssignment(property)) {\n conflicts.push({\n codemod: ID,\n line: property.getStartLineNumber(),\n reason: `createPreviewBindings() spreads its options; ${BY_HAND}`,\n });\n } else if (propertyKey(property) !== OLD_KEY) {\n continue;\n } else if (Node.isShorthandPropertyAssignment(property)) {\n edits.push(replaceNode(property, `${NEW_KEY}: ${OLD_KEY}`));\n conflicts.push({\n codemod: ID,\n line: property.getStartLineNumber(),\n reason: BOOLEAN_REFUSED,\n });\n } else if (Node.isPropertyAssignment(property)) {\n const value = property.getInitializer();\n if (value !== undefined && Node.isFalseLiteral(value)) {\n edits.push(replaceNode(property, `${NEW_KEY}: null`));\n continue;\n }\n edits.push(replaceNode(property.getNameNode(), NEW_KEY));\n conflicts.push({\n codemod: ID,\n line: property.getStartLineNumber(),\n reason: BOOLEAN_REFUSED,\n });\n }\n }\n }\n }\n return { edits, conflicts };\n },\n};\n","/** Ledger entry 1: `isPreviewRequest()` → `hasPreviewIntent()`, same signature. */\nimport {\n declaresName,\n memberAccesses,\n packageBindings,\n packageReexports,\n referencesTo,\n replaceNode,\n type PackageBinding,\n type PackageReexport,\n} from '../ast';\nimport type { CodemodImplementation, CodemodConflict, CodemodPlan, TextEdit } from '../types';\n\nconst ID = 'rename-is-preview-request';\nconst OLD_NAME = 'isPreviewRequest';\nconst NEW_NAME = 'hasPreviewIntent';\n\nfunction conflict(line: number, reason: string): CodemodConflict {\n return { codemod: ID, reason, line };\n}\n\nfunction renameBinding(binding: PackageBinding): TextEdit {\n // `import { isPreviewRequest as hasPreviewIntent }` collapses to the bare name.\n if (binding.aliased && binding.local === NEW_NAME) {\n return replaceNode(binding.importedNode.getParentOrThrow(), NEW_NAME);\n }\n return replaceNode(binding.importedNode, NEW_NAME);\n}\n\nfunction plan(\n bindings: readonly PackageBinding[],\n reexports: readonly PackageReexport[],\n script: Parameters<CodemodImplementation['apply']>[0],\n): CodemodPlan {\n const blocking: CodemodConflict[] = [];\n const edits: TextEdit[] = [];\n for (const reexport of reexports) {\n if (reexport.alias === undefined) {\n // Renaming it would rename this module's export too; its importers decide.\n blocking.push(\n conflict(\n reexport.line,\n `${OLD_NAME} is re-exported straight from the package under its old name; write ` +\n `export { ${NEW_NAME} as ${OLD_NAME} } from '${reexport.specifier}', or rename it and its importers by hand`,\n ),\n );\n } else if (reexport.alias === NEW_NAME) {\n edits.push(replaceNode(reexport.importedNode.getParentOrThrow(), NEW_NAME));\n } else {\n edits.push(replaceNode(reexport.importedNode, NEW_NAME));\n }\n }\n const existing = declaresName(\n script,\n NEW_NAME,\n bindings.map((binding) => binding.declaration),\n );\n if (existing !== undefined) {\n blocking.push(\n conflict(\n existing.getStartLineNumber(),\n `this module already binds ${NEW_NAME}; rename it (or drop the wrapper and import the ` +\n `package's ${NEW_NAME} directly), then rename ${OLD_NAME} by hand`,\n ),\n );\n }\n for (const binding of bindings) {\n edits.push(renameBinding(binding));\n if (binding.aliased) continue;\n for (const reference of referencesTo(script, binding)) {\n if (reference.kind === 'reference') {\n edits.push(replaceNode(reference.node, NEW_NAME));\n } else if (reference.kind === 'shorthand') {\n blocking.push(\n conflict(\n reference.node.getStartLineNumber(),\n `{ ${OLD_NAME} } keeps the old key for whoever reads it; write ` +\n `{ ${OLD_NAME}: ${NEW_NAME} } or rename the key and its readers by hand`,\n ),\n );\n } else {\n blocking.push(\n conflict(\n reference.node.getStartLineNumber(),\n `${OLD_NAME} is re-exported under its old name; rename the export and its ` +\n `importers, or write export { ${NEW_NAME} as ${OLD_NAME} }`,\n ),\n );\n }\n }\n }\n const notes = memberAccesses(script, OLD_NAME).map((node) =>\n conflict(\n node.getStartLineNumber(),\n `.${OLD_NAME} is a member of this module's own object, not the package import, and was ` +\n 'left alone; check that it does not wrap the removed API',\n ),\n );\n if (blocking.length > 0) return { edits: [], conflicts: [...blocking, ...notes] };\n return { edits, conflicts: notes };\n}\n\nexport const renameIsPreviewRequest: CodemodImplementation = {\n id: ID,\n summary: '`isPreviewRequest()` → `hasPreviewIntent()` (same signature)',\n ledgerEntry: 1,\n // The rename keeps behaviour, and that is the part worth saying: the 2.0\n // adapters count only the query, and a renamed call silently does not.\n notice:\n 'hasPreviewIntent() takes the options isPreviewRequest() took and, without `signals`, counts ' +\n 'the same three: a preview query parameter, Sec-Fetch-Dest: iframe and an admin Referer. The ' +\n \"2.0 adapters count only the query; where a call should agree with them, pass { signals: ['query'] } \" +\n '(docs/migration.md).',\n apply(script) {\n const bindings = packageBindings(script).filter((binding) => binding.imported === OLD_NAME);\n const reexports = packageReexports(script).filter((reexport) => reexport.imported === OLD_NAME);\n if (bindings.length === 0 && reexports.length === 0) return { edits: [], conflicts: [] };\n return plan(bindings, reexports, script);\n },\n};\n","/** Ledger entry 19: `onUnboundChange: 'route' | 'ignore'` → `onUnfaithfulPatch: 'escalate' | 'ignore'`. */\nimport { loadTsMorph, replaceNode } from '../ast';\nimport { memberNamed, optionLiterals, packageJsxAttributes } from '../option-literals';\nimport type { CodemodImplementation, CodemodConflict, TextEdit } from '../types';\n\nconst ID = 'rename-on-unbound-change';\nconst OLD_KEY = 'onUnboundChange';\nconst NEW_KEY = 'onUnfaithfulPatch';\nconst RENAMED: Readonly<Record<string, string>> = { route: 'escalate', ignore: 'ignore' };\n\nexport const renameOnUnboundChange: CodemodImplementation = {\n id: ID,\n summary: \"`onUnboundChange: 'route'` → `onUnfaithfulPatch: 'escalate'`\",\n ledgerEntry: 19,\n apply(script) {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const conflicts: CodemodConflict[] = [];\n for (const [literal, uses] of optionLiterals(script)) {\n const property = memberNamed(literal, OLD_KEY);\n if (property === undefined) continue;\n const line = property.getStartLineNumber();\n // The package reads the new name first; renamed, the later key would win instead.\n const both = [literal, ...uses.map((use) => use.outer)].some(\n (candidate) => memberNamed(candidate, NEW_KEY) !== undefined,\n );\n if (both) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `both ${OLD_KEY} and ${NEW_KEY} are given; ${NEW_KEY} wins, drop ${OLD_KEY} by hand`,\n });\n continue;\n }\n const value = Node.isPropertyAssignment(property) ? property.getInitializer() : undefined;\n const text = value !== undefined && Node.isStringLiteral(value) ? value.getLiteralText() : '';\n const renamed = RENAMED[text];\n if (value === undefined || renamed === undefined) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `${OLD_KEY} is not a literal 'route' or 'ignore'; rename it to ${NEW_KEY} by hand ('route' is 'escalate')`,\n });\n continue;\n }\n const quote = value.getText().charAt(0);\n edits.push(replaceNode(property, `${NEW_KEY}: ${quote}${renamed}${quote}`));\n }\n for (const attribute of packageJsxAttributes(script, OLD_KEY)) {\n conflicts.push({\n codemod: ID,\n line: attribute.getStartLineNumber(),\n reason: `a JSX attribute; rename ${OLD_KEY} to ${NEW_KEY} by hand ('route' is 'escalate')`,\n });\n }\n return { edits, conflicts };\n },\n};\n","/** Where the script lives in a file: the whole file, or the script blocks of a component. */\nimport { extname } from 'node:path';\nimport type { ScriptKind } from './ast';\n\nexport interface ScriptBlock {\n readonly start: number;\n readonly end: number;\n readonly kind: ScriptKind;\n}\n\nconst WHOLE_FILE: Readonly<Record<string, ScriptKind>> = {\n '.ts': 'ts',\n '.mts': 'ts',\n '.cts': 'ts',\n '.tsx': 'tsx',\n '.js': 'js',\n '.mjs': 'js',\n '.cjs': 'js',\n '.jsx': 'jsx',\n};\nconst COMPONENT_EXTENSIONS = new Set(['.astro', '.vue', '.svelte']);\nconst FRONTMATTER = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/u;\n// Browsers close a script on `</script` followed by anything up to `>`, so the\n// end tag must accept that too, or a stray `</script foo>` would swallow the\n// rest of the file into one block.\nconst SCRIPT_TAG = /<script(?:\\s[^>]*)?>([\\s\\S]*?)<\\/script\\b[^>]*>/giu;\n\nexport function scriptBlocks(source: string, fileName: string): readonly ScriptBlock[] {\n const extension = extname(fileName).toLowerCase();\n if (!COMPONENT_EXTENSIONS.has(extension)) {\n return [{ start: 0, end: source.length, kind: WHOLE_FILE[extension] ?? 'ts' }];\n }\n const blocks: ScriptBlock[] = [];\n const frontmatter = extension === '.astro' ? FRONTMATTER.exec(source) : null;\n if (frontmatter?.[1] !== undefined) {\n const start = frontmatter.index + frontmatter[0].indexOf('\\n') + 1;\n blocks.push({ start, end: start + frontmatter[1].length, kind: 'ts' });\n }\n for (const match of source.matchAll(SCRIPT_TAG)) {\n const body = match[1] ?? '';\n if (body.trim() === '') continue;\n const start = match.index + match[0].lastIndexOf(body);\n blocks.push({ start, end: start + body.length, kind: 'ts' });\n }\n return blocks;\n}\n","/**\n * `pll migrate`: the 1.x → 2.0 codemods and the driver that applies them to one\n * source string. Rewrites are planned on the AST (ts-morph) so only names the\n * package binds are touched; see ADR 0007.\n */\nimport { applyTextEdits, parseScript } from './ast';\nimport { expandDefaultsV1 } from './codemods/expand-defaults-v1';\nimport { moveFetchPreviewHelpers } from './codemods/move-fetch-preview-helpers';\nimport { renameAdminOriginsOption } from './codemods/rename-admin-origins-option';\nimport { renameBindingsAuthorizedOption } from './codemods/rename-bindings-authorized-option';\nimport { renameIsPreviewRequest } from './codemods/rename-is-preview-request';\nimport { renameOnUnboundChange } from './codemods/rename-on-unbound-change';\nimport { scriptBlocks } from './script-blocks';\nimport type {\n Codemod,\n CodemodConflict,\n CodemodEdit,\n CodemodImplementation,\n CodemodLineEdit,\n} from './types';\n\nexport type {\n Codemod,\n CodemodConflict,\n CodemodEdit,\n CodemodLineEdit,\n CodemodPlan,\n TextEdit,\n} from './types';\n\nconst PACKAGE_REFERENCE =\n /(?:\\bfrom\\s*|\\bimport\\s*\\(?\\s*|\\brequire\\s*\\(\\s*)['\"]payload-live-preview(?:\\/[^'\"]*)?['\"]/u;\n\n/** Whether the source names the package in an `import`, `import()` or `require()`. @internal */\nexport function importsThisPackage(source: string): boolean {\n return PACKAGE_REFERENCE.test(source);\n}\n\n// The option rename follows the function rename so it sees the new binding.\nconst IMPLEMENTATIONS: readonly CodemodImplementation[] = [\n renameIsPreviewRequest,\n renameAdminOriginsOption,\n renameBindingsAuthorizedOption,\n moveFetchPreviewHelpers,\n renameOnUnboundChange,\n expandDefaultsV1,\n];\n\n/**\n * The codemods in the order they run. Each is idempotent. Metadata only: the\n * rewrite is internal, so importing this entry's types does not require\n * `ts-morph`, which is needed only to run `pll migrate`.\n * @internal\n */\nexport const CODEMODS: readonly Codemod[] = IMPLEMENTATIONS;\n\nexport interface MigrateSourceOptions {\n /** Restrict to these codemod ids. */\n readonly only?: readonly string[];\n /**\n * Decides how the source is parsed: `.astro`, `.vue` and `.svelte` by script\n * block, JSX by extension. Defaults to a `.ts` module.\n */\n readonly fileName?: string;\n}\n\nexport interface MigrateSourceResult {\n readonly output: string;\n readonly edits: readonly CodemodEdit[];\n readonly conflicts: readonly CodemodConflict[];\n}\n\nfunction lineNumberAt(source: string, offset: number): number {\n let line = 1;\n for (let index = 0; index < offset; index += 1) if (source[index] === '\\n') line += 1;\n return line;\n}\n\n/** The changed lines between two versions, trimmed to the differing middle. */\nfunction lineEdits(before: string, after: string, firstLine: number): CodemodLineEdit[] {\n const oldLines = before.split('\\n');\n const newLines = after.split('\\n');\n let prefix = 0;\n while (\n prefix < oldLines.length &&\n prefix < newLines.length &&\n oldLines[prefix] === newLines[prefix]\n ) {\n prefix += 1;\n }\n let suffix = 0;\n while (\n suffix < oldLines.length - prefix &&\n suffix < newLines.length - prefix &&\n oldLines[oldLines.length - 1 - suffix] === newLines[newLines.length - 1 - suffix]\n ) {\n suffix += 1;\n }\n const oldMiddle = oldLines.slice(prefix, oldLines.length - suffix);\n const newMiddle = newLines.slice(prefix, newLines.length - suffix);\n const changed: CodemodLineEdit[] = [];\n for (let index = 0; index < Math.max(oldMiddle.length, newMiddle.length); index += 1) {\n const before = oldMiddle[index] ?? '';\n const after = newMiddle[index] ?? '';\n if (before !== after) changed.push({ line: firstLine + prefix + index, before, after });\n }\n return changed;\n}\n\n/** Apply every codemod (or the chosen subset) to one source string. */\nexport function migrateSource(\n source: string,\n options: MigrateSourceOptions = {},\n): MigrateSourceResult {\n const chosen =\n options.only === undefined\n ? IMPLEMENTATIONS\n : IMPLEMENTATIONS.filter((codemod) => options.only?.includes(codemod.id));\n if (chosen.length === 0 || !importsThisPackage(source)) {\n return { output: source, edits: [], conflicts: [] };\n }\n const byCodemod = new Map<string, CodemodLineEdit[]>();\n const conflicts: CodemodConflict[] = [];\n let output = '';\n let cursor = 0;\n for (const block of scriptBlocks(source, options.fileName ?? 'source.ts')) {\n output += source.slice(cursor, block.start);\n const firstLine = lineNumberAt(source, block.start);\n let text = source.slice(block.start, block.end);\n for (const codemod of chosen) {\n const plan = codemod.apply(parseScript(text, block.kind));\n for (const item of plan.conflicts) {\n conflicts.push(\n item.line === undefined ? item : { ...item, line: item.line + firstLine - 1 },\n );\n }\n if (plan.edits.length === 0) continue;\n const next = applyTextEdits(text, plan.edits);\n const lines = byCodemod.get(codemod.id) ?? [];\n lines.push(...lineEdits(text, next, firstLine));\n byCodemod.set(codemod.id, lines);\n text = next;\n }\n output += text;\n cursor = block.end;\n }\n output += source.slice(cursor);\n const edits = [...byCodemod].map(([codemod, lines]) => ({ codemod, count: lines.length, lines }));\n return { output, edits, conflicts };\n}\n","/** The file walker behind `pll migrate`: find source files, apply the codemods, report or write. */\nimport { readFile, readdir, stat, writeFile } from 'node:fs/promises';\nimport { extname, join, relative } from 'node:path';\nimport { migrateSource } from './index';\nimport type { CodemodConflict, CodemodEdit } from './types';\n\nconst SOURCE_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.mts',\n '.cts',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.astro',\n '.svelte',\n '.vue',\n]);\nconst DECLARATION_FILE = /\\.d\\.[cm]?ts$/u;\nconst SKIP_DIRECTORIES = new Set([\n 'node_modules',\n 'dist',\n '.git',\n '.astro',\n '.svelte-kit',\n '.next',\n '.nuxt',\n 'coverage',\n]);\n\nexport interface MigrateFileResult {\n readonly file: string;\n readonly edits: readonly CodemodEdit[];\n readonly changed: boolean;\n /** What a codemod could not rewrite safely in this file. */\n readonly conflicts: readonly CodemodConflict[];\n}\n\nexport interface MigrateRunResult {\n readonly files: readonly MigrateFileResult[];\n /** Files the run changed (or would change, in dry-run). */\n readonly changedCount: number;\n /** Codemod id → number of files it touched. */\n readonly byCodemod: Readonly<Record<string, number>>;\n /** Files needing manual attention. */\n readonly conflictCount: number;\n}\n\nexport interface MigrateOptions {\n /** Apply and save; without it the run only reports. */\n readonly write?: boolean;\n /** Restrict to these codemod ids. */\n readonly only?: readonly string[];\n /** Reader/writer injection for tests. */\n readonly io?: {\n readonly read: (path: string) => Promise<string>;\n readonly write: (path: string, content: string) => Promise<void>;\n readonly list: (root: string) => Promise<readonly string[]>;\n };\n}\n\nfunction isSourceFile(name: string): boolean {\n return SOURCE_EXTENSIONS.has(extname(name)) && !DECLARATION_FILE.test(name);\n}\n\nasync function collectFiles(root: string): Promise<string[]> {\n const found: string[] = [];\n async function walk(directory: string): Promise<void> {\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) {\n if (!SKIP_DIRECTORIES.has(entry.name)) await walk(path);\n } else if (isSourceFile(entry.name)) {\n found.push(path);\n }\n }\n }\n const info = await stat(root);\n if (info.isDirectory()) await walk(root);\n else if (isSourceFile(root)) found.push(root);\n return found.sort();\n}\n\nfunction relativeTo(root: string, file: string): string {\n const rel = relative(root, file);\n return rel.length === 0 ? file : rel;\n}\n\n/** Migrate every source file under `root`. */\nexport async function runMigrate(\n root: string,\n options: MigrateOptions = {},\n): Promise<MigrateRunResult> {\n const io = options.io ?? {\n read: (path) => readFile(path, 'utf8'),\n write: (path, content) => writeFile(path, content, 'utf8'),\n list: collectFiles,\n };\n const results: MigrateFileResult[] = [];\n const byCodemod: Record<string, number> = {};\n for (const file of await io.list(root)) {\n const source = await io.read(file);\n const { output, edits, conflicts } = migrateSource(source, {\n fileName: file,\n ...(options.only === undefined ? {} : { only: options.only }),\n });\n const changed = output !== source;\n if (changed && options.write === true) await io.write(file, output);\n if (changed) {\n for (const edit of edits) byCodemod[edit.codemod] = (byCodemod[edit.codemod] ?? 0) + 1;\n }\n results.push({ file: relativeTo(root, file), edits, changed, conflicts });\n }\n return {\n files: results,\n changedCount: results.filter((result) => result.changed).length,\n byCodemod,\n conflictCount: results.filter((result) => result.conflicts.length > 0).length,\n };\n}\n","/**\n * `pll migrate <path> [--write] [--only <id,id>]`, hosted by the `pll` binary.\n * Exit codes: 0 clean, 1 usage or I/O error, 3 when conflicts need a human.\n */\nimport { CODEMODS } from './index';\nimport { runMigrate, type MigrateFileResult } from './runner';\n\nexport const MIGRATE_HELP = `pll migrate — rewrite 1.x APIs to their 2.0 names and homes (ADR 0007)\n\nUsage:\n pll migrate <path> [--write] [--only <id,id>]\n\nWithout --write the run only reports what it would change. Codemods touch\nonly names bound from payload-live-preview; anything they cannot rewrite\nsafely is listed as needing manual attention. Requires ts-morph.\n\nOptions:\n --write Apply the changes (otherwise dry-run)\n --only <ids> Run only these codemods (comma-separated); an id not\n listed below runs nothing\n -h, --help Show this help\n\nCodemods, in the order they run:\n${CODEMODS.map((codemod) => ` ${codemod.id}`).join('\\n')}\n\nExit codes:\n 0 nothing needs a human (changes applied, or would be with --write)\n 1 usage error, unreadable path, or ts-morph is not installed\n 3 at least one file needs manual attention\n`;\n\ninterface MigrateArgs {\n readonly target: string | undefined;\n readonly write: boolean;\n readonly only: readonly string[] | undefined;\n readonly help: boolean;\n readonly unknown: string | undefined;\n}\n\nfunction parseArgs(argv: readonly string[]): MigrateArgs {\n let target: string | undefined;\n let write = false;\n let only: string[] | undefined;\n let help = false;\n let unknown: string | undefined;\n const ids = (value: string): string[] => value.split(',').filter((id) => id.length > 0);\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n if (token === undefined) continue;\n if (token === '-h' || token === '--help') help = true;\n else if (token === '--write') write = true;\n else if (token === '--only') {\n only = ids(argv[index + 1] ?? '');\n index += 1;\n } else if (token.startsWith('--only=')) only = ids(token.slice('--only='.length));\n else if (token.startsWith('-')) unknown ??= token;\n else target ??= token;\n }\n return { target, write, only, help, unknown };\n}\n\nfunction describe(file: MigrateFileResult): string {\n return file.edits.map((edit) => `${edit.codemod}: ${String(edit.count)} line(s)`).join(', ');\n}\n\nexport async function runMigrateCommand(argv: readonly string[]): Promise<number> {\n const args = parseArgs(argv);\n if (args.help) {\n process.stdout.write(MIGRATE_HELP);\n return 0;\n }\n if (args.unknown !== undefined) {\n process.stderr.write(`pll migrate: unknown option ${args.unknown}\\n`);\n return 1;\n }\n if (args.target === undefined) {\n process.stderr.write('pll migrate: a path is required. Try `pll migrate --help`.\\n');\n return 1;\n }\n let result;\n try {\n result = await runMigrate(args.target, {\n write: args.write,\n ...(args.only === undefined ? {} : { only: args.only }),\n });\n } catch (error) {\n process.stderr.write(\n `pll migrate: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n return 1;\n }\n for (const file of result.files) {\n if (!file.changed) continue;\n process.stdout.write(\n `${args.write ? 'migrated' : 'would migrate'} ${file.file} (${describe(file)})\\n`,\n );\n }\n process.stdout.write(\n `\\n${args.write ? 'Migrated' : 'Would migrate'} ${String(result.changedCount)} file(s).` +\n `${args.write ? '' : ' Re-run with --write to apply.'}\\n`,\n );\n for (const { id, notice } of CODEMODS) {\n if (notice !== undefined && (result.byCodemod[id] ?? 0) > 0) {\n process.stdout.write(`\\nNote (${id}): ${notice}\\n`);\n }\n }\n const conflicted = result.files.filter((file) => file.conflicts.length > 0);\n if (conflicted.length === 0) return 0;\n process.stdout.write(`\\n${String(conflicted.length)} file(s) need manual attention:\\n`);\n for (const file of conflicted) {\n for (const item of file.conflicts) {\n const where = item.line === undefined ? file.file : `${file.file}:${String(item.line)}`;\n process.stdout.write(` ${where}: ${item.reason}\\n`);\n }\n }\n return 3;\n}\n","/** Terminal rendering of a doctor report. */\nimport type { DoctorReport } from './types';\n\nconst LEVEL_LABEL = { error: 'ERROR', warning: 'WARN ', info: 'INFO ' } as const;\n\n/** @internal */\nexport function formatReport(report: DoctorReport): string {\n const lines: string[] = [`pll doctor — ${report.url}`, ''];\n if (report.findings.length === 0) {\n lines.push('No findings. The preview response carries the runtime, a frame-ancestors');\n lines.push('policy, and bindings; the public response carries none of them.', '');\n return lines.join('\\n');\n }\n for (const finding of report.findings) {\n lines.push(`${LEVEL_LABEL[finding.level]} ${finding.code} ${finding.title}`);\n lines.push(` ${finding.detail}`);\n if (finding.remedy !== '') lines.push(` → ${finding.remedy}`);\n lines.push('');\n }\n lines.push(`${String(report.errors)} error(s), ${String(report.warnings)} warning(s).`, '');\n return lines.join('\\n');\n}\n","/**\n * Every diagnostic code the runtime and tools emit, so a consumer can branch\n * on `e.code` instead of matching message text. A code is never reused for a\n * different meaning; a retired one stays reserved.\n *\n * Browser-side reporting sites write the literal (`code: 'LP0603'`) rather than\n * reading it from this record: the frozen table would then ship in the inline\n * runtime for the sake of six characters — it did, 1 287 B in every page, for\n * the one read Z6 left in the strategy runner, and `diagnostic-codes.test.ts`\n * now holds the artifact free of it. Server-side tools may import it.\n */\n\n/**\n * Every diagnostic code the runtime can report, by name.\n *\n * ```ts\n * client.events.on('error', (e) => {\n * if (e.code === DIAGNOSTIC_CODES.TransformThrew) reportToSentry(e.error);\n * });\n * ```\n */\nexport const DIAGNOSTIC_CODES = Object.freeze({\n /** No trusted origin configured in production; nothing will be accepted. */\n NoTrustedOrigin: 'LP0101',\n /** Origin trust rests on `document.referrer`, so any framing site is trusted. */\n ReferrerOnlyTrust: 'LP0102',\n /** A plugin declares a runtime range this runtime does not satisfy; it was refused. */\n PluginIncompatible: 'LP0103',\n /** The page carries the lean runtime and needs a feature that profile leaves out. */\n ProfileFeatureOmitted: 'LP0104',\n\n /** An update named an empty field with no binding anchor on the page; an edit to it has nowhere to land. */\n OrphanField: 'LP0201',\n /** Owner scoping is on and the update names no document it could belong to. */\n UnattributableUpdate: 'LP0202',\n /** An update carried a value for a field the page binds nowhere; editing it changes nothing on this page. */\n UnboundField: 'LP0203',\n\n /** The visibility gate held offscreen writes back until they scroll into view. */\n VisibilityGateDeferred: 'LP0301',\n\n /** A value was refused because the attribute or the value itself is unsafe. */\n UnsafeAttributeWrite: 'LP0401',\n /** A text element has structured children, so replacing its text was skipped. */\n TextTargetHasChildren: 'LP0402',\n /** A structural container has no array template, so the update was skipped. */\n MissingArrayTemplate: 'LP0403',\n /** A structural item has no `id`; it pairs positionally, so an insert re-renders every row after it. */\n StructuralItemUnkeyed: 'LP0404',\n /** Two structural items share a key; later ones pair positionally. */\n StructuralDuplicateKey: 'LP0405',\n /** Every structural key changed while the length did not; the source generates keys per message. */\n StructuralUnstableKeys: 'LP0406',\n /** A binding asks for a delivery strategy this release does not have; it is left unchanged. */\n UnsupportedStrategy: 'LP0407',\n /** `data-payload-format` names a format the vocabulary does not contain; the default formatting was used instead. */\n UnknownValueFormat: 'LP0408',\n /** The strict sanitizer removed an attribute the 1.x `'compat'` policy kept. */\n SanitizerDroppedAttribute: 'LP0409',\n /** A Lexical block has no renderer; the markup the server rendered for it is kept instead. */\n UnrenderedBlockKept: 'LP0410',\n /** A patch cannot reach what the server would have drawn; `onUnfaithfulPatch` decided what happens next. */\n UnfaithfulPatch: 'LP0411',\n /** The first write to a date, number or checkbox binding replaced a different reading of the same value. */\n ServerFormatReplaced: 'LP0412',\n /** A Lexical block has no renderer, and the write could not keep the markup the server rendered for it; it is gone. */\n UnrenderedBlockLost: 'LP0413',\n\n /** A message was rejected before it reached the update pipeline. */\n MessageRejected: 'LP0501',\n /** A preview token was rejected. */\n TokenRejected: 'LP0502',\n /** A trusted origin sent a message this protocol version does not recognise. */\n ProtocolShapeUnknown: 'LP0503',\n\n /** A consumer event handler threw. */\n HandlerThrew: 'LP0601',\n /** A consumer transform threw; the original value was kept. */\n TransformThrew: 'LP0602',\n /** A renderer threw while writing a value. */\n RendererThrew: 'LP0603',\n // LP0604 is reserved and unassigned; codes are never reused or renumbered.\n /** Runtime startup failed. */\n StartupFailed: 'LP0605',\n /** Sending the ready handshake failed. */\n ReadyFailed: 'LP0606',\n /** The page declared hydration, but no React commit, Vue mount or SvelteKit mount came within the cap; the runtime started without waiting. */\n HydrationWaitTimedOut: 'LP0607',\n\n /** The audit found no runtime in a response that carried preview intent. */\n AuditRuntimeMissing: 'LP0701',\n /** The preview response declares no `frame-ancestors`. */\n AuditNoFrameAncestors: 'LP0702',\n /** `X-Frame-Options` forbids framing on a response that declares no `frame-ancestors`; `SAMEORIGIN` forbids it from another origin only. */\n AuditFrameOptionsBlocks: 'LP0703',\n /** Binding attributes are served to anonymous visitors. */\n AuditBindingsExposed: 'LP0704',\n /** More bindings than the visibility gate will write eagerly. */\n AuditGateThresholdExceeded: 'LP0705',\n /** Owner markers exist, but some bindings are outside all of them. */\n AuditUnownedBindings: 'LP0706',\n /** The preview response carries no bindings and no fragment boundary. */\n AuditNoBindings: 'LP0707',\n /** The URL did not return an HTML page, so nothing else can be judged. */\n AuditNotAPage: 'LP0708',\n /** A fragment request failed (network, timeout, server error); the boundary was patched instead. */\n FragmentRequestFailed: 'LP0801',\n /** The fragment response had the wrong content type or shape; the boundary was patched instead. */\n FragmentResponseInvalid: 'LP0802',\n /** The fragment endpoint refused the preview (not authorized); the boundary was patched instead. */\n FragmentUnauthorized: 'LP0803',\n /** A fragment response arrived for a revision that was already superseded and was discarded. */\n FragmentSuperseded: 'LP0804',\n /** A route refresh was refused: the loop guard, or the strategy's minimum interval. */\n RouteRefreshLoop: 'LP0805',\n /** A boundary asks for the fragment strategy but no fragment handler is configured; it is patched. */\n FragmentStrategyUnavailable: 'LP0806',\n /** A revision changed a field with no binding; `onUnfaithfulPatch` refreshed the route. */\n UnboundChangeRefresh: 'LP0807',\n /** `onUnfaithfulPatch: 'escalate'` found no route or fragment strategy, or no boundary, to hand an unfaithful patch to; the page keeps it. */\n EscalationUnavailable: 'LP0808',\n /** A fragment inserted an Astro island the page cannot start: it never loaded the island element or that client directive. */\n IslandStartUnavailable: 'LP0809',\n /** The host's route refresh returned no promise, so the revision was re-applied before the host committed. */\n RouteRefreshUnconfirmed: 'LP0810',\n /** A readiness row is not yet at its 2.0 value; `pll doctor --v2` reports it. */\n V2ReadinessGap: 'LP0709',\n /** The preview runtime is served to anonymous visitors, not only inside the admin frame. */\n RuntimeOnPublicPage: 'LP0710',\n} as const);\n\n/** A diagnostic code, as it appears in log output and on the `error` event. */\nexport type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[keyof typeof DIAGNOSTIC_CODES];\n","/**\n * `frame-ancestors` matching by the CSP3 source-expression rules. The audit\n * judges origins, so path parts of a host-source are ignored.\n */\n\nconst DEFAULT_PORT: Readonly<Record<string, string>> = {\n http: '80',\n https: '443',\n ws: '80',\n wss: '443',\n};\nconst SCHEME_SOURCE = /^([a-z][a-z0-9+.-]*):$/u;\nconst HOST_SOURCE =\n /^(?:([a-z][a-z0-9+.-]*):\\/\\/)?(\\*|(?:\\*\\.)?[a-z0-9-]+(?:\\.[a-z0-9-]+)*\\.?)(?::(\\*|\\d+))?(?:\\/.*)?$/u;\n\n/** The `frame-ancestors` directive of a policy, verbatim, or `undefined` when it has none. */\nexport function frameAncestorsOf(csp: string | undefined): string | undefined {\n if (csp === undefined) return undefined;\n for (const directive of csp.split(';')) {\n const trimmed = directive.trim();\n if (/^frame-ancestors(?:\\s|$)/iu.test(trimmed)) return trimmed;\n }\n return undefined;\n}\n\nfunction schemeOf(url: URL): string {\n return url.protocol.slice(0, -1).toLowerCase();\n}\n\nfunction portOf(url: URL): string {\n return url.port === '' ? (DEFAULT_PORT[schemeOf(url)] ?? '') : url.port;\n}\n\nfunction schemeMatches(expression: string, actual: string): boolean {\n return (\n expression === actual ||\n (expression === 'http' && actual === 'https') ||\n (expression === 'ws' && actual === 'wss')\n );\n}\n\nfunction hostMatches(pattern: string, host: string): boolean {\n if (pattern === '*') return true;\n const wanted = pattern.replace(/\\.$/u, '');\n const actual = host.replace(/\\.$/u, '');\n if (wanted.startsWith('*.')) {\n return actual.endsWith(wanted.slice(1)) && actual.length > wanted.length - 1;\n }\n return wanted === actual;\n}\n\nfunction isSelf(admin: URL, page: URL): boolean {\n if (admin.hostname !== page.hostname) return false;\n const adminScheme = schemeOf(admin);\n const pageScheme = schemeOf(page);\n if (adminScheme !== pageScheme && !(pageScheme === 'http' && adminScheme === 'https')) {\n return false;\n }\n return portOf(admin) === portOf(page) || (admin.port === '' && page.port === '');\n}\n\nfunction sourceMatches(source: string, admin: URL, page: URL): boolean {\n const scheme = SCHEME_SOURCE.exec(source);\n if (scheme?.[1] !== undefined) return schemeMatches(scheme[1], schemeOf(admin));\n const host = HOST_SOURCE.exec(source);\n if (host === null) return false;\n const expressionScheme = host[1];\n const expressionHost = host[2] ?? '';\n const expressionPort = host[3];\n const requiredScheme = expressionScheme ?? schemeOf(page);\n if (!schemeMatches(requiredScheme, schemeOf(admin))) return false;\n if (!hostMatches(expressionHost, admin.hostname)) return false;\n if (expressionPort === undefined) return admin.port === '';\n return expressionPort === '*' || expressionPort === portOf(admin);\n}\n\n/** Whether the directive admits `admin` as an ancestor of `page`. */\nexport function frameAncestorsAdmits(directive: string, admin: URL, page: URL): boolean {\n const sources = directive\n .split(/\\s+/u)\n .slice(1)\n .filter((source) => source.length > 0)\n .map((source) => source.toLowerCase());\n if (sources.length === 0 || (sources.length === 1 && sources[0] === \"'none'\")) return false;\n for (const source of sources) {\n if (source === \"'self'\") {\n if (isSelf(admin, page)) return true;\n } else if (source === '*') {\n return true;\n } else if (!source.startsWith(\"'\") && sourceMatches(source, admin, page)) {\n return true;\n }\n }\n return false;\n}\n","/**\n * The inline script's configuration and its positional wire order: the\n * generator writes the tuple, `src/core/runtime.ts` destructures it, and\n * `INLINE_CONFIG_KEYS` is where they agree. Append only, never reorder.\n */\n\nimport type { DefaultsProfile } from '@/types/defaults-profile';\n\nexport interface InlineScriptConfig {\n /** Trusted admin origins, merged with the detected ones. */\n readonly allowedOrigins?: readonly string[];\n /** Payload origin; every update is then re-fetched through the REST API with credentials. Requires `mergeDepth`. */\n readonly serverURL?: string;\n /** REST route prefix used with `serverURL`. Default `/api`. */\n readonly apiRoute?: string;\n /** Population depth used with `serverURL`. Required with `serverURL` unless `defaults: 'v1'`. */\n readonly mergeDepth?: number;\n /** Verbose console logging. Default `false`. */\n readonly debug?: boolean;\n /** Debounce window for incoming updates in ms. Default `50`. */\n readonly debounceMs?: number;\n /** Mount the screen-reader live region. Default `true`. */\n readonly enableA11y?: boolean;\n /** Heartbeat timeout in ms; `0` disables it (default), because the admin posts only on edits. */\n readonly heartbeatMs?: number;\n /** Apply every update regardless of viewport position. Default `false`. */\n readonly disableVisibilityGate?: boolean;\n /** Cache size above which off-screen updates wait for intersection. Default `50`. */\n readonly visibilityGateThreshold?: number;\n /** `rootMargin` of the IntersectionObserver. Default `'200px'`. */\n readonly intersectionRootMargin?: string;\n /** Ignore `document.referrer` as an origin source. Default `true`; `defaults: 'v1'` sets `false`. */\n readonly disableReferrerDetection?: boolean;\n /** Disable the dev-mode localhost matcher (any port on `localhost`/`127.0.0.1`). Default `false`. */\n readonly disableLocalhostMatching?: boolean;\n /** Update only bindings under a matching `data-payload-owner`. Default `false`. */\n readonly scopeBindingsByOwner?: boolean;\n /** Skip bindings whose value did not change. Default `true`; `defaults: 'v1'` sets `false`. */\n readonly skipUnchanged?: boolean;\n /** Scroll the preview to the field being edited. Default `false`. */\n readonly revealEditedField?: boolean;\n /** Which windows may post updates. Default `'parent-or-opener'`; `defaults: 'v1'` sets `'any'`. */\n readonly eventSourcePolicy?: 'any' | 'parent-or-opener';\n /** Sanitizer policy for rich text and HTML writes. Default `'strict'`; `defaults: 'v1'` sets `'compat'`. */\n readonly sanitizerPolicy?: 'compat' | 'strict';\n /** Same-origin path of a fragment endpoint; the script then carries the fragment client ahead of the runtime (ADR 0011). */\n readonly fragmentEndpoint?: string;\n /**\n * Carry the route strategy, so a binding in `<head>` or one marked\n * `data-payload-strategy=\"route\"` refreshes the route. `fragmentEndpoint`\n * implies it — the fragment prelude already contains it. Default `false`.\n */\n readonly routeStrategy?: boolean;\n /**\n * The 2.0 name for `onUnfaithfulPatch`, kept until 3.0. `'route'` means\n * `'escalate'`, `'ignore'` means `'ignore'`.\n *\n * @deprecated Renamed to `onUnfaithfulPatch`.\n */\n readonly onUnboundChange?: 'ignore' | 'route';\n /**\n * What to do when the runtime knows a patch cannot reach what the server\n * would have drawn. `'escalate'` (the default) hands the region to the\n * fragment strategy when a boundary covers it and to the route otherwise, so\n * it needs `fragmentEndpoint` or `routeStrategy` to do anything. `'warn'`\n * reports LP0411 and keeps the patch; `'ignore'` keeps it silently.\n */\n readonly onUnfaithfulPatch?: 'ignore' | 'warn' | 'escalate';\n /**\n * Find bindings by value on the connection's first message (ADR 0014): a\n * scalar whose value is the whole content of exactly one element is bound\n * to it as if `data-payload-field` stood there. Default `'off'`.\n */\n readonly autoBind?: 'off' | 'unique';\n /**\n * The framework that hydrates this page (ADR 0015). Under `'react'` the\n * runtime holds its first write until React has committed the tree that\n * holds the bindings — otherwise React finds markup it did not render,\n * throws `Hydration failed` and regenerates the tree, and the write is gone.\n * Under `'vue'` it holds the write until Vue has mounted the app around them\n * — otherwise Vue's hydration repairs the write back to the server's value,\n * quietly. Under `'sveltekit'` it holds the write until SvelteKit's root has\n * mounted, on a page SvelteKit's client runs on — otherwise Svelte's\n * hydration sets its own text back over it, as quietly. The Next.js, Nuxt\n * and SvelteKit adapters set it on every script they emit; a page built by\n * hand with `generateInlineScript()` may. Omitted: the runtime starts on\n * `DOMContentLoaded`, as on a static page.\n */\n readonly hydration?: 'react' | 'vue' | 'sveltekit';\n /**\n * Which defaults the omitted options fall back to, resolved by the generator\n * rather than the runtime, whose own fallbacks are the 2.0 rows: `'v1'`\n * writes its four runtime rows into their slots (an explicit option still\n * wins) and relaxes the `mergeDepth` check. The resolved value always\n * travels in slot 24, so a reader of the served page knows what an\n * empty slot means instead of guessing it — `pll doctor --v2` reads it. The\n * runtime does not use that value: every row the profile decides is already\n * in its slot. Slot 24 stays fixed as later options are appended.\n */\n readonly defaults?: DefaultsProfile;\n /**\n * Document events fired after a client router committed new markup. Each\n * rebuilds the binding cache and locally reapplies the last accepted state.\n * Adapter integrations set this from their framework lifecycle. It is a\n * low-level generator fact, not a `PreviewAdapterOptions` field. Empty by\n * default.\n */\n readonly softNavigationEvents?: readonly string[];\n /**\n * How a group counts as covered (ADR 0022). `'descendant'`, the 2.x default:\n * one bound path inside it covers all of it. `'declared'`: each changed path\n * inside such a group needs its own binding or a `data-payload-covers`\n * declaration; an uncovered one is an unbound change.\n */\n readonly subfieldCoverage?: 'descendant' | 'declared';\n /**\n * A runtime artifact to embed instead of the full one — today only\n * `LEAN_RUNTIME` from `payload-live-preview/lean`, which leaves out the\n * strategies, the keyed morph, the structural arrays, the item templates, the\n * announcer and auto-binding (about 7 KB gzip less on the page) and reports\n * LP0104 when a page needs one of them.\n *\n * It is an imported value rather than a `profile: 'lean'` string on purpose:\n * a second artifact behind a string option would sit in every build that can\n * reach the generator; measured, it grew each adapter entry by the artifact's\n * whole size. This way the bytes follow the import.\n *\n * Not serialized: it decides which bytes are emitted, not how they behave.\n */\n readonly runtime?: RuntimeArtifact;\n}\n\n/**\n * A runtime build this package produces. `source` is the IIFE the page runs;\n * the two digests describe the same bytes as a servable asset, so asset\n * delivery can hash-name and SRI-verify whichever artifact was chosen without\n * hashing anything at request time.\n */\nexport interface RuntimeArtifact {\n readonly profile: 'lean';\n readonly source: string;\n /** Short content hash, for the asset's file name. */\n readonly contentHash: string;\n /** `sha384-…`, for the bootstrap's `integrity` attribute. */\n readonly integrity: string;\n}\n\n/** Keys that travel in the wire tuple, in slot order. */\nexport const INLINE_CONFIG_KEYS = [\n 'allowedOrigins',\n 'serverURL',\n 'apiRoute',\n 'mergeDepth',\n 'debug',\n 'debounceMs',\n 'enableA11y',\n 'heartbeatMs',\n 'disableVisibilityGate',\n 'visibilityGateThreshold',\n 'intersectionRootMargin',\n 'disableReferrerDetection',\n 'disableLocalhostMatching',\n 'scopeBindingsByOwner',\n 'skipUnchanged',\n 'eventSourcePolicy',\n 'sanitizerPolicy',\n 'fragmentEndpoint',\n 'revealEditedField',\n 'routeStrategy',\n 'onUnboundChange',\n 'onUnfaithfulPatch',\n 'autoBind',\n 'hydration',\n 'defaults',\n 'softNavigationEvents',\n 'subfieldCoverage',\n] as const satisfies readonly Exclude<keyof InlineScriptConfig, 'runtime'>[];\n","/**\n * The two defaults profiles, row by row. 2.0 ships `v2`; `defaults: 'v1'` opts\n * back into the 1.x table for a staged migration. Each row belongs to exactly\n * one side — the adapter's request decision or the browser runtime — and a\n * test asserts the profile assigns every readiness row that has an option, so\n * a row added later cannot be forgotten. See ADR 0007.\n *\n * It lives in the leaf `types` domain, like `merge-depth.ts`, because the\n * inline generator resolves the profile too, and the generator is server-side\n * code that may not reach the browser runtime in `core`.\n */\n\n/** `'v2'` is the 2.0 default; `'v1'` is the 1.x table. */\nexport type DefaultsProfile = 'v1' | 'v2';\n\n/** How the runtime decides which windows may post updates. */\nexport type EventSourcePolicy = 'any' | 'parent-or-opener';\n\n/** Readiness rows that are options, keyed by the option they set. */\nexport const READINESS_ROWS = Object.freeze({\n strict: 'production response changes require an authorized context',\n previewSignals: 'query-only intent signal',\n disableReferrerDetection: 'referrer trust off',\n eventSourcePolicy: 'messages must come from parent/opener',\n skipUnchanged: 'skip unchanged bindings by default',\n sanitizerPolicy: 'hardened sanitizer id/data-* policy',\n} as const);\n\n/** Options an adapter's request decision reads from the profile. */\nexport interface AdapterProfileDefaults {\n readonly strict: boolean;\n readonly previewSignals: readonly ('query' | 'fetch-dest' | 'referer')[];\n}\n\n/** Options the browser runtime reads from the profile (through the inline configuration). */\nexport interface RuntimeProfileDefaults {\n readonly disableReferrerDetection: boolean;\n readonly eventSourcePolicy: EventSourcePolicy;\n readonly skipUnchanged: boolean;\n readonly sanitizerPolicy: 'compat' | 'strict';\n}\n\nexport const V2_ADAPTER_DEFAULTS: AdapterProfileDefaults = Object.freeze({\n strict: true,\n previewSignals: Object.freeze(['query'] as const),\n});\n\nexport const V2_RUNTIME_DEFAULTS: RuntimeProfileDefaults = Object.freeze({\n disableReferrerDetection: true,\n eventSourcePolicy: 'parent-or-opener',\n skipUnchanged: true,\n sanitizerPolicy: 'strict',\n});\n\n/** The 1.x table, spelled out so the profiles compare row by row. */\nexport const V1_ADAPTER_DEFAULTS: AdapterProfileDefaults = Object.freeze({\n strict: false,\n previewSignals: Object.freeze(['query', 'fetch-dest', 'referer'] as const),\n});\n\nexport const V1_RUNTIME_DEFAULTS: RuntimeProfileDefaults = Object.freeze({\n disableReferrerDetection: false,\n eventSourcePolicy: 'any',\n skipUnchanged: false,\n sanitizerPolicy: 'compat',\n});\n\n/** Only an explicit `'v1'` opts out; everything else gets the hardened rows. */\nexport function adapterDefaultsFor(profile: DefaultsProfile | undefined): AdapterProfileDefaults {\n return profile === 'v1' ? V1_ADAPTER_DEFAULTS : V2_ADAPTER_DEFAULTS;\n}\n\nexport function runtimeDefaultsFor(profile: DefaultsProfile | undefined): RuntimeProfileDefaults {\n return profile === 'v1' ? V1_RUNTIME_DEFAULTS : V2_RUNTIME_DEFAULTS;\n}\n","/**\n * `pll doctor --v2`: read the served configuration and report each runtime row\n * still at its 1.x value (ADR 0007).\n *\n * An empty slot means whatever the generation that wrote the script meant by\n * it, and that is exactly what changed between 1.x and 2.0. So the script\n * names the defaults it was resolved against in slot 24, and this reads\n * the answer instead of guessing it. A script without the marker predates it —\n * 1.x or 2.0.0-beta.0 — and is read as 1.x, with a line that says so.\n */\nimport { INLINE_CONFIG_KEYS } from '@/types/inline-config';\nimport {\n V1_RUNTIME_DEFAULTS,\n V2_RUNTIME_DEFAULTS,\n type RuntimeProfileDefaults,\n} from '@/types/defaults-profile';\nimport type { DoctorFinding, DoctorProbe } from './types';\n\nconst CONFIG_NAME = '__LIVE_PREVIEW_CONFIG__';\nconst CONFIG_MARKER = `var ${CONFIG_NAME}=`;\n// A comment or a script, in document order, so a script inside a comment is\n// skipped as the browser skips it. A quoted attribute value may hold `>`.\nconst COMMENT_OR_SCRIPT =\n /<!--[\\s\\S]*?-->|<script\\b((?:[^>\"']|\"[^\"]*\"|'[^']*')*)>([\\s\\S]*?)<\\/script\\b[^>]*>/giu;\n// The attribute name in any case, the value exactly, as `getElementById` compares it.\nconst CONFIG_ID = /(?:^|\\s)[iI][dD]\\s*=\\s*[\"']?__LIVE_PREVIEW_CONFIG__(?=[\"'\\s]|$)/u;\nconst JSON_TYPE = /(?:^|\\s)type\\s*=\\s*[\"']?application\\/json(?=[\"'\\s;]|$)/iu;\n\ntype InlineKey = (typeof INLINE_CONFIG_KEYS)[number];\n\n/** The configuration a preview response serves, whichever way the page writes it. */\nexport interface ServedConfig {\n /** `inline`: the generator's tuple. `element`: the JSON a page writes for a client it starts itself. */\n readonly source: 'inline' | 'element';\n /** The option under its inline name; `undefined` when the page does not set it. */\n value(key: InlineKey): unknown;\n}\n\n/** A runtime row of the readiness table, as a finding words it. */\ninterface ReadinessRow {\n readonly key: keyof RuntimeProfileDefaults;\n readonly title: string;\n /** What the 1.x value does. */\n readonly effect: string;\n /** What has to hold before the row can take its 2.0 value. */\n readonly condition: string;\n}\n\nconst ROWS: readonly ReadinessRow[] = [\n {\n key: 'disableReferrerDetection',\n title: 'Referrer trust is still on',\n effect: 'the runtime accepts the admin referer as a preview signal.',\n condition: 'no preview flow relies on the admin referer alone',\n },\n {\n key: 'eventSourcePolicy',\n title: 'Messages are accepted from any window',\n effect: 'any window that passes the origin check may post updates.',\n condition: 'no window but the parent or opener posts updates',\n },\n {\n key: 'sanitizerPolicy',\n title: 'Sanitizer is in compat mode',\n effect: 'id and every data-* pass.',\n condition: 'rich text no longer relies on `id` or `data-*`',\n },\n {\n key: 'skipUnchanged',\n title: 'Unchanged bindings are re-applied every message',\n effect: 'every binding is written again on every message.',\n condition: 'no renderer relies on running again for a value that did not change',\n },\n];\n\n/** Where a row's value came from, which decides what the reader can change. */\ntype Origin = 'profile' | 'explicit' | 'unmarked';\n\nconst ORIGIN_DETAIL: Readonly<Record<Origin, string>> = {\n profile: \"The script was generated with `defaults: 'v1'`.\",\n explicit: 'The script sets it explicitly.',\n unmarked: 'The script names no defaults, so its empty slot is read as the 1.x value.',\n};\n\nconst UNREADABLE: DoctorFinding = {\n code: 'LP0709',\n level: 'info',\n title: 'Could not read the inline configuration for a v2 readiness check',\n detail:\n 'The preview response carried no readable `__LIVE_PREVIEW_CONFIG__` inline script or JSON configuration element.',\n remedy:\n 'Run this against a page with the inline runtime (not loader mode without a preview context). ' +\n 'A preview behind authorizePreview serves it only to a request with credentials: pass them with --header, or a signed token as ?previewToken=… in the URL.',\n};\n\nconst UNMARKED: DoctorFinding = {\n code: 'LP0709',\n level: 'info',\n title: 'The inline configuration does not say which defaults it was generated against',\n detail:\n 'Scripts carry a `defaults` marker from 2.0.0-rc.1 on; this one has none, so a 1.x or 2.0.0-beta.0 generator wrote it. An empty slot is read as its 1.x value, which is what a 1.x runtime runs.',\n remedy:\n 'On 1.x the warnings stand as written. On 2.0.0-beta.0 an empty slot already runs its 2.0 value, so a warning about one does not apply there; upgrade and run `pll doctor --v2` again to read the marker.',\n};\n\n/**\n * The array literal after the marker, read as JSON. The generator writes `,,`\n * for unset slots, which JSON cannot express, so elisions outside strings\n * become `null`. Never evaluated: a page controls this text.\n */\nexport function readInlineConfig(body: string): readonly unknown[] | undefined {\n const start = body.indexOf(CONFIG_MARKER);\n if (start === -1) return undefined;\n const from = start + CONFIG_MARKER.length;\n if (body[from] !== '[') return undefined;\n let depth = 0;\n let inString = false;\n let previous = '';\n let json = '';\n for (let index = from; index < body.length; index += 1) {\n const char = body[index] ?? '';\n if (inString) {\n json += char;\n if (char === '\\\\') {\n json += body[index + 1] ?? '';\n index += 1;\n } else if (char === '\"') {\n inString = false;\n // A closed string is a value: without this, the next `,` reads as an elision.\n previous = '\"';\n }\n continue;\n }\n if (char === '\"') {\n inString = true;\n json += char;\n continue;\n }\n if (/\\s/u.test(char)) continue;\n const elision =\n (char === ',' && (previous === ',' || previous === '[')) ||\n (char === ']' && previous === ',');\n if (elision) json += 'null';\n json += char;\n previous = char;\n if (char === '[') depth += 1;\n if (char === ']') {\n depth -= 1;\n if (depth === 0) break;\n }\n }\n if (depth !== 0) return undefined;\n try {\n const value: unknown = JSON.parse(json);\n return Array.isArray(value) ? (value as readonly unknown[]) : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The inline tuple first, because it is what the runtime reads; else a\n * `<script type=\"application/json\" id=\"__LIVE_PREVIEW_CONFIG__\">` holding an\n * object that names the options as the client and the inline script spell\n * them. That is how a page that starts `LivePreviewClient` itself can show the\n * doctor its options. Never evaluated: a page controls this text.\n * @internal\n */\nexport function readServedConfig(body: string): ServedConfig | undefined {\n // Both ways spell the name, and the scan below is slow on hostile markup.\n if (!body.includes(CONFIG_NAME)) return undefined;\n const scripts = servedScripts(body);\n const inline = scripts.find(({ text }) => text.includes(CONFIG_MARKER));\n const tuple = inline === undefined ? undefined : readInlineConfig(inline.text);\n if (tuple !== undefined) {\n return {\n source: 'inline',\n value: (key) => tuple[INLINE_CONFIG_KEYS.indexOf(key)] ?? undefined,\n };\n }\n const named = readConfigElement(scripts);\n if (named === undefined) return undefined;\n return {\n source: 'element',\n value: (key) => (Object.hasOwn(named, key) ? (named[key] ?? undefined) : undefined),\n };\n}\n\ninterface ServedScript {\n readonly attributes: string;\n readonly text: string;\n}\n\n/** The scripts a browser would run or read, without those inside a comment. */\nfunction servedScripts(body: string): readonly ServedScript[] {\n const scripts: ServedScript[] = [];\n for (const [, attributes, text] of body.matchAll(COMMENT_OR_SCRIPT)) {\n // A comment captures neither group.\n if (attributes !== undefined && text !== undefined) scripts.push({ attributes, text });\n }\n return scripts;\n}\n\nfunction readConfigElement(\n scripts: readonly ServedScript[],\n): Readonly<Record<string, unknown>> | undefined {\n for (const { attributes, text } of scripts) {\n if (!CONFIG_ID.test(attributes)) continue;\n if (!JSON_TYPE.test(attributes)) return undefined;\n try {\n const value: unknown = JSON.parse(text);\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Readonly<Record<string, unknown>>)\n : undefined;\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\n/** `'compat'` rather than `\"compat\"`: remedies are read as source code. */\nfunction literal(value: unknown): string {\n return typeof value === 'string' ? `'${value}'` : JSON.stringify(value);\n}\n\nfunction remedyFor(origin: Origin, row: ReadinessRow, value: unknown): string {\n const wanted = `\\`${row.key}: ${literal(V2_RUNTIME_DEFAULTS[row.key])}\\``;\n switch (origin) {\n case 'profile':\n return (\n `Set ${wanted} or drop \\`defaults: 'v1'\\` once ${row.condition}. 3.0 removes the ` +\n 'profile; `pll migrate` writes its rows out, so each can go on its own.'\n );\n case 'explicit':\n return `Drop the explicit \\`${row.key}: ${literal(value)}\\` once ${row.condition}; 2.0 defaults to ${wanted}.`;\n case 'unmarked':\n // 1.8.1 has no `defaults` option and three of the four rows are not\n // inline options there, so the way out is the upgrade itself.\n return `Upgrading to 2.0 sets ${wanted}; check first that ${row.condition}.`;\n }\n}\n\nfunction gap(row: ReadinessRow, value: unknown, origin: Origin): DoctorFinding {\n return {\n code: 'LP0709',\n level: 'warning',\n title: row.title,\n detail: `${row.key} is ${literal(value)}: ${row.effect} ${ORIGIN_DETAIL[origin]}`,\n remedy: remedyFor(origin, row, value),\n };\n}\n\nfunction unknownGeneration(marker: unknown): DoctorFinding {\n return {\n code: 'LP0709',\n level: 'info',\n title: 'The inline configuration names defaults this doctor does not know',\n detail: `Its \\`defaults\\` marker is ${JSON.stringify(marker)}; this version reads 'v1' and 'v2', so no row was judged.`,\n remedy: 'Run the `pll doctor` of the package version that generated the page.',\n };\n}\n\n/**\n * One `LP0709` finding per runtime row not yet at its 2.0 value. An empty slot\n * has the value of the generation the script names, and the 1.x value when it\n * names none; a generation this version does not know is not judged at all.\n * A configuration element is written for a 2.x client, whose omitted options\n * are the 2.0 rows unless it names `'v1'`.\n * @internal\n */\nexport function analyzeV2Readiness(probe: DoctorProbe): readonly DoctorFinding[] {\n const config = readServedConfig(probe.previewResponse.body);\n if (config === undefined) return [UNREADABLE];\n const marker = config.value('defaults');\n if (marker !== undefined && marker !== 'v1' && marker !== 'v2') {\n return [unknownGeneration(marker)];\n }\n const generation = marker ?? (config.source === 'element' ? 'v2' : undefined);\n const fallback = generation === 'v2' ? V2_RUNTIME_DEFAULTS : V1_RUNTIME_DEFAULTS;\n const findings = ROWS.flatMap((row) => {\n const slot = config.value(row.key);\n const value = slot ?? fallback[row.key];\n if (value === V2_RUNTIME_DEFAULTS[row.key]) return [];\n const origin: Origin =\n generation === 'v1' ? 'profile' : slot === undefined ? 'unmarked' : 'explicit';\n return [gap(row, value, origin)];\n });\n return generation === undefined ? [...findings, UNMARKED] : findings;\n}\n","/**\n * The `pll doctor` audit: judge what a deployment serves from two fetches of\n * one URL, as a visitor and as the admin's iframe. Pure — the caller fetches.\n * Markup is read with regular expressions, which is enough to count\n * attributes inside start tags and find the runtime marker; findings say what\n * was observed.\n */\nimport { DIAGNOSTIC_CODES } from '../core/diagnostic-codes';\nimport { frameAncestorsAdmits, frameAncestorsOf } from './csp';\nimport { analyzeV2Readiness, readServedConfig } from './readiness';\nimport type {\n DoctorContext,\n DoctorFinding,\n DoctorProbe,\n DoctorReport,\n DoctorResponse,\n} from './types';\n\n/** Survives minification; the banner comment does not. */\nconst RUNTIME_MARKER = '__LIVE_PREVIEW_CONFIG__';\n/**\n * A start tag, quoted values read whole so a `>` inside one does not end it.\n * Text is never a tag: `&lt;h1 data-payload-field=…&gt;` in a code sample, or\n * a sentence that names the attribute, is what a page shows, not what it binds.\n * A raw `<` outside quotes ends the attempt, which keeps the scan linear: with\n * it, `<a<a<a…` and no `>` took 645 ms for 20 000 repetitions, 15 times the\n * time of 5 000.\n */\nconst START_TAG = /<[a-zA-Z](?:\"[^\"]*\"|'[^']*'|[^\"'<>])*>/gu;\n/** One attribute of a start tag: its name, and its value when it has one. */\nconst TAG_ATTRIBUTE = /([^\\s\"'>/=]+)(\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))?/gu;\n/** Mirrors the scheduler default; the audit must not import the runtime. */\nconst DEFAULT_VISIBILITY_GATE_THRESHOLD = 50;\nconst LEVEL_ORDER = { error: 0, warning: 1, info: 2 } as const;\n// An end tag may carry junk before its `>`; browsers still close on it, so the\n// pattern must too, or a `</script foo>` would leave the script body counted.\nconst NON_MARKUP =\n /<script\\b[^>]*>[\\s\\S]*?<\\/script\\b[^>]*>|<style\\b[^>]*>[\\s\\S]*?<\\/style\\b[^>]*>|<!--[\\s\\S]*?-->/giu;\n\n/**\n * The runtime's own source spells `data-payload-field=` in a message, so\n * scripts must not be counted. This is a counter's view of the page, not a\n * sanitiser — nothing here is rendered — but it strips to a fixed point all\n * the same, so a block that only appears once its neighbour is gone is still\n * removed rather than counted.\n */\nfunction visibleMarkup(body: string): string {\n let markup = body;\n for (;;) {\n const stripped = markup.replace(NON_MARKUP, '');\n if (stripped === markup) return markup;\n markup = stripped;\n }\n}\n\n/** An attribute as the markup carries it, at the offset of its tag. */\ninterface MarkupAttribute {\n readonly name: string;\n readonly value: string;\n readonly at: number;\n}\n\n/**\n * Every attribute with a value, in document order. Names are compared in lower\n * case, as a browser parses them; the tag name is read along and never matches\n * an attribute the audit asks about.\n */\nfunction markupAttributes(markup: string): readonly MarkupAttribute[] {\n const found: MarkupAttribute[] = [];\n for (const tag of markup.matchAll(START_TAG)) {\n for (const [, name = '', assigned, double, single, bare] of tag[0].matchAll(TAG_ATTRIBUTE)) {\n if (assigned === undefined) continue;\n found.push({\n name: name.toLowerCase(),\n value: double ?? single ?? bare ?? '',\n at: tag.index,\n });\n }\n }\n return found;\n}\n\nfunction named(attributes: readonly MarkupAttribute[], name: string): readonly MarkupAttribute[] {\n return attributes.filter((attribute) => attribute.name === name);\n}\n\n/** Bindings before the first owner marker are certainly unowned; nesting is not modelled, so this under-reports. */\nfunction unownedBindingsBeforeFirstOwner(attributes: readonly MarkupAttribute[]): number {\n const firstOwner = named(attributes, 'data-payload-owner')[0];\n if (firstOwner === undefined) return 0;\n return named(attributes, 'data-payload-field').filter((binding) => binding.at < firstOwner.at)\n .length;\n}\n\nfunction tryUrl(value: string | undefined): URL | undefined {\n if (value === undefined) return undefined;\n try {\n return new URL(value);\n } catch {\n return undefined;\n }\n}\n\n/** Why the preview response cannot be audited as a page; the public one may legitimately be gated. */\nfunction describeNonPage(preview: DoctorResponse): DoctorFinding | undefined {\n if (preview.status >= 300 && preview.status <= 399) {\n const location = preview.headers['location'];\n return {\n code: 'LP0708',\n level: 'error',\n title: `The preview request was redirected (${String(preview.status)})${location === undefined ? '' : ` to ${location}`}`,\n detail:\n 'The audit does not follow redirects: the page at the end of one is a different ' +\n 'resource, usually a login or a canonical host, and judging it would say nothing ' +\n 'about this URL.',\n remedy:\n 'The request carried the intent parameter (?preview=true, or the --param name), the ' +\n \"way the admin's iframe loads the page, so a rule that redirects on that query redirects \" +\n 'the iframe too. A redirect to a login means the route needs authentication that a ' +\n \"plain probe cannot supply: pass an editor's credentials with --header, or a signed token as ?previewToken=… in the URL. Probe the final \" +\n 'URL directly only when the redirect has nothing to do with either.',\n };\n }\n if (preview.status < 200 || preview.status > 299) {\n return {\n code: 'LP0708',\n level: 'error',\n title: `The preview request returned ${String(preview.status)}, not a page`,\n detail:\n 'Nothing below this can be judged: a status outside 2xx means the body is an ' +\n 'error page or empty.',\n remedy: 'Check the URL.',\n };\n }\n if (preview.body.trim() === '') {\n return {\n code: 'LP0708',\n level: 'error',\n title: `The preview request returned ${String(preview.status)} with an empty body`,\n detail:\n 'A 2xx status with nothing in it — 204 and 205 are defined that way — is not a page, ' +\n 'so its missing runtime and missing bindings say nothing.',\n remedy: 'Point the audit at a route that renders a document.',\n };\n }\n const contentType = preview.headers['content-type'];\n if (contentType !== undefined && !contentType.toLowerCase().includes('html')) {\n return {\n code: 'LP0708',\n level: 'error',\n title: `The preview request returned ${contentType}, not HTML`,\n detail:\n 'The audit reads a rendered page. A non-HTML response has no runtime and no ' +\n 'bindings by definition, so reporting their absence would say nothing.',\n remedy: 'Point the audit at a page route rather than an API or an asset.',\n };\n }\n return undefined;\n}\n\nfunction framingFindings(\n preview: DoctorResponse,\n runtimeInPreview: boolean,\n context: DoctorContext,\n): DoctorFinding[] {\n const findings: DoctorFinding[] = [];\n const page = tryUrl(context.url);\n const admin = tryUrl(context.adminOrigin);\n const sameOrigin = admin !== undefined && page?.origin === admin.origin;\n const frameAncestors = frameAncestorsOf(preview.headers['content-security-policy']);\n if (runtimeInPreview && frameAncestors === undefined) {\n findings.push({\n code: 'LP0702',\n level: 'warning',\n title: 'Preview response declares no frame-ancestors',\n detail:\n 'The runtime is injected but the response carries no frame-ancestors directive, ' +\n 'so nothing states which origins may embed this page.',\n remedy:\n 'Let the adapter manage CSP, or set frame-ancestors yourself to the admin origin. ' +\n 'Without it you are relying on the absence of a policy.',\n });\n } else if (frameAncestors !== undefined && context.adminOrigin !== undefined) {\n const admitted =\n admin !== undefined &&\n page !== undefined &&\n frameAncestorsAdmits(frameAncestors, admin, page);\n if (!admitted) {\n findings.push({\n code: 'LP0702',\n level: 'error',\n title: 'frame-ancestors does not admit the admin origin',\n detail:\n admin === undefined\n ? `\"${context.adminOrigin}\" is not an absolute URL, so no source expression can admit it.`\n : `Served: \"${frameAncestors}\". Expected it to allow ${admin.origin}.`,\n remedy:\n 'Add the admin origin to allowedOrigins so the adapter merges it into ' +\n 'frame-ancestors, or add it to your own policy.',\n });\n }\n }\n const frameOptions = preview.headers['x-frame-options'];\n // A response with a `frame-ancestors` directive is framed by that directive alone: the HTML\n // Standard skips the header for it (measured in Chromium, Firefox and WebKit). The header\n // decides only where the response declares none; the directive's own verdict is LP0702.\n const blocks =\n frameOptions !== undefined &&\n frameAncestors === undefined &&\n (/deny/iu.test(frameOptions) || (/sameorigin/iu.test(frameOptions) && !sameOrigin));\n if (blocks) {\n // `SAMEORIGIN` refuses a frame from *another* origin, so it is a verdict\n // about this preview only once the admin origin is known. Without --admin\n // the audit says what it saw and names the condition instead of asserting a\n // block it cannot have established: where the admin and the site share an\n // origin, the preview runs. `DENY` needs no origin to be a verdict.\n const judged = admin !== undefined || /deny/iu.test(frameOptions);\n findings.push(\n judged\n ? {\n code: 'LP0703',\n level: 'error',\n title: `X-Frame-Options: ${frameOptions} blocks the preview iframe`,\n detail:\n 'This header is older than CSP. A browser applies it to a response that has no ' +\n 'frame-ancestors directive, and this response has no frame-ancestors.',\n remedy:\n 'Remove X-Frame-Options for preview responses, or serve a frame-ancestors ' +\n 'directive that admits the admin: the header is then ignored. It is usually ' +\n 'set by a proxy or a security middleware rather than by the app.',\n }\n : {\n code: 'LP0703',\n level: 'warning',\n title: `X-Frame-Options: ${frameOptions} blocks every frame from another origin`,\n detail:\n 'This header is older than CSP. A browser applies it to a response that has no ' +\n 'frame-ancestors directive, and this response has no frame-ancestors. SAMEORIGIN ' +\n 'refuses a frame from another origin only, and no admin origin was given: whether ' +\n 'it blocks this preview depends on where the admin is served, which this probe ' +\n 'cannot see.',\n remedy:\n 'Re-run with --admin <origin> to have it judged. If the admin is on another ' +\n 'origin, remove X-Frame-Options for preview responses or serve a frame-ancestors ' +\n 'directive that admits it; a proxy or a security middleware usually sets the header.',\n },\n );\n }\n return findings;\n}\n\n/** The gate as the served script configures it; `threshold` is undefined when the gate is off. */\ninterface ServedGate {\n readonly threshold: number | undefined;\n readonly configured: boolean;\n}\n\n/**\n * Read from the served configuration, because an adapter now forwards both\n * options: judged against the default, a page that raised its threshold\n * would be told to raise it. A page whose configuration cannot be read\n * (loader mode, a client the page starts without a configuration element) is\n * judged against the default.\n */\nfunction servedGate(body: string): ServedGate {\n const config = readServedConfig(body);\n if (config?.value('disableVisibilityGate') === true) {\n return { threshold: undefined, configured: true };\n }\n const threshold = config?.value('visibilityGateThreshold');\n return typeof threshold === 'number'\n ? { threshold, configured: true }\n : { threshold: DEFAULT_VISIBILITY_GATE_THRESHOLD, configured: false };\n}\n\nfunction bindingFindings(\n previewMarkup: string,\n publicMarkup: string,\n runtime: boolean,\n gate: ServedGate,\n): DoctorFinding[] {\n const findings: DoctorFinding[] = [];\n const preview = markupAttributes(previewMarkup);\n const previewBindings = named(preview, 'data-payload-field').length;\n const publicBindings = named(markupAttributes(publicMarkup), 'data-payload-field').length;\n const owners = named(preview, 'data-payload-owner').length;\n // A boundary is rendered by the server from the form state, so an edit of a\n // field it depends on arrives without one field binding; an empty id names\n // no registry entry, and no strategy renders it.\n const boundaries = named(preview, 'data-payload-fragment').filter(\n (boundary) => boundary.value.length > 0,\n ).length;\n if (publicBindings > 0) {\n findings.push({\n code: 'LP0704',\n level: 'warning',\n title: `${String(publicBindings)} binding attribute(s) served to anonymous visitors`,\n detail:\n 'A request with no preview intent received data-payload-field attributes. These ' +\n 'disclose the CMS field taxonomy, and any CSS keyed on them changes public layout ' +\n 'the moment emission is gated.',\n remedy:\n 'Gate binding emission on an authorized preview context — see ' +\n 'createPreviewBindings(), whose suppressed form emits nothing at all.',\n });\n }\n if (gate.threshold !== undefined && previewBindings > gate.threshold) {\n findings.push({\n code: 'LP0705',\n level: 'warning',\n title: `${String(previewBindings)} bindings exceed the ${gate.configured ? 'configured' : 'default'} visibility gate`,\n detail:\n `Above visibilityGateThreshold (${String(gate.threshold)}) the ` +\n 'scheduler stops writing offscreen elements and buffers them until they scroll into ' +\n 'view. On a page nobody scrolls, that is never.',\n remedy:\n 'Raise visibilityGateThreshold, or set disableVisibilityGate, on the adapter, ' +\n 'LivePreviewClient or generateInlineScript() if the whole page must stay live, or ' +\n 'confirm that deferring below the fold is acceptable here.',\n });\n }\n if (runtime && previewBindings === 0 && boundaries === 0) {\n findings.push({\n code: 'LP0707',\n level: 'error',\n title: 'Preview response carries no bindings',\n detail:\n 'The runtime is present but there is not one data-payload-field element for it to ' +\n 'write into and not one data-payload-fragment boundary for a server to render, so ' +\n 'no edit can ever be visible on this page.',\n remedy:\n 'Add binding attributes or fragment boundaries to the markup. pll-codegen --inventory ' +\n 'lists every field the schema makes addressable.',\n });\n }\n const unowned = unownedBindingsBeforeFirstOwner(preview);\n if (owners > 0 && unowned > 0) {\n findings.push({\n code: 'LP0706',\n level: 'warning',\n title: `${String(unowned)} binding(s) outside every owner marker`,\n detail:\n `The page declares ${String(owners)} owner marker(s), so owner scoping is in use. ` +\n 'Bindings that belong to no owner receive nothing once scopeBindingsByOwner is on — ' +\n 'they fail closed.',\n remedy:\n 'Give every binding an owning ancestor, or leave scopeBindingsByOwner off until they ' +\n 'all have one. Counted before the first owner marker only, so the real number may be ' +\n 'higher.',\n });\n }\n return findings;\n}\n\n/** Audit a probed deployment. */\nexport function analyzeProbe(\n probe: DoctorProbe,\n context: DoctorContext & {\n readonly v2?: boolean;\n /** Whether the preview probe carried caller-supplied headers (`--header`). */\n readonly credentials?: boolean;\n },\n): DoctorReport {\n const { publicResponse: pub, previewResponse: preview } = probe;\n const notAPage = describeNonPage(preview);\n if (notAPage !== undefined) {\n return { url: context.url, findings: [notAPage], errors: 1, warnings: 0 };\n }\n const runtimeInPreview = preview.body.includes(RUNTIME_MARKER);\n const findings: DoctorFinding[] = [];\n if (!runtimeInPreview) {\n findings.push(\n context.credentials === true\n ? {\n code: 'LP0701',\n level: 'warning',\n title: 'No inline runtime in the preview response',\n detail:\n `The preview request returned ${String(preview.status)} without the inline ` +\n 'runtime, although it carried credentials (--header, or ?previewToken= in the URL). Three readings: ' +\n 'those credentials were not accepted — expired, issued for another page, or not ' +\n 'what authorizePreview reads — an adapter that did not recognise the request as a ' +\n 'preview, or a consumer that starts LivePreviewClient itself.',\n remedy:\n 'Check that the credentials are current and are the ones authorizePreview reads; ' +\n 'if you use an adapter, check its inject mode and previewSignals. If you start the ' +\n 'client yourself, this line is expected.',\n }\n : {\n code: 'LP0701',\n level: 'warning',\n title: 'No inline runtime in the preview response',\n detail:\n `The preview request returned ${String(preview.status)} without the inline ` +\n 'runtime. Three readings, and this audit cannot tell them apart from the response ' +\n 'alone: a preview behind authorizePreview — the strict 2.0 default — which answers ' +\n 'a request without credentials exactly like this, an adapter that did not recognise ' +\n 'the request as a preview, or a consumer that starts LivePreviewClient itself.',\n remedy:\n \"To audit a gated preview, send what an editor's browser sends: \" +\n \"--header 'Cookie: payload-token=…' for a Payload session; for a signed token, \" +\n 'the URL with ?previewToken=… (the default transport, dropped from the visitor ' +\n \"request), or --header 'x-preview-token: …' where the strategy sets transport: \" +\n \"{ kind: 'header' }. Otherwise check the adapter's \" +\n 'inject mode and previewSignals; if you start the client yourself, this line is ' +\n 'expected.',\n },\n );\n }\n findings.push(...framingFindings(preview, runtimeInPreview, context));\n findings.push(\n ...bindingFindings(\n visibleMarkup(preview.body),\n visibleMarkup(pub.body),\n runtimeInPreview,\n servedGate(preview.body),\n ),\n );\n if (pub.body.includes(RUNTIME_MARKER)) {\n // A page that starts its own client serves only the JSON element, which spells the name too.\n const inline = pub.body.includes(`var ${RUNTIME_MARKER}=`);\n findings.push({\n code: DIAGNOSTIC_CODES.RuntimeOnPublicPage,\n level: 'info',\n title: inline\n ? 'Runtime is also served to anonymous visitors'\n : 'Preview configuration is also served to anonymous visitors',\n detail: inline\n ? 'A request with no preview intent received the inline runtime. That is correct for ' +\n \"inject: 'always' and unintended for 'preview-only'.\"\n : 'A request with no preview intent received the configuration element a page writes ' +\n 'for a client it starts itself. That is correct if the page starts the client for ' +\n 'every request, and unintended if it writes the element only for a preview.',\n remedy: '',\n });\n }\n if (context.v2 === true) findings.push(...analyzeV2Readiness(probe));\n findings.sort((a, b) => LEVEL_ORDER[a.level] - LEVEL_ORDER[b.level]);\n return {\n url: context.url,\n findings,\n errors: findings.filter((finding) => finding.level === 'error').length,\n warnings: findings.filter((finding) => finding.level === 'warning').length,\n };\n}\n","/**\n * Fetching for `pll doctor`: the two probes, and the default fetch that talks\n * to a real server. Not in the barrel so it stays in the coverage report.\n */\nimport { analyzeProbe } from './analyze';\nimport type { DoctorReport, DoctorResponse } from './types';\n\n/** Injectable so tests can drive the audit without a server. */\nexport type DoctorFetch = (\n url: string,\n init: { readonly headers: Readonly<Record<string, string>> },\n) => Promise<DoctorResponse>;\n\nexport interface RunDoctorOptions {\n readonly url: string;\n /** Admin origin the preview is meant to be embedded from, when known. */\n readonly adminOrigin?: string | undefined;\n /** Defaults to a fetch built on `globalThis.fetch`. */\n readonly fetchImpl?: DoctorFetch | undefined;\n /** Also check the served page against the 2.0 readiness table. */\n readonly v2?: boolean;\n /**\n * Headers sent with the preview probe only, never with the visitor probe: the\n * credentials a preview behind `authorizePreview` needs, such as a Payload\n * session `Cookie`, or an `x-preview-token` where the token strategy reads a\n * header (a token in the URL is passed in `url` instead). Without them a gated page answers\n * the audit the way it answers any stranger. Their values never reach the report.\n */\n readonly previewHeaders?: Readonly<Record<string, string>> | undefined;\n /**\n * The query parameters the deployment reads as preview intent, when its\n * adapter sets `previewQueryParams`; the same list, since that option replaces\n * the default `preview`, `draft` and `livePreview`. The first one is what the\n * preview probe appends as `=true`; none of them reaches the visitor probe.\n */\n readonly previewQueryParams?: readonly string[] | undefined;\n /**\n * The query parameter the `signed-token` strategy reads, when its transport\n * names one other than `previewToken`. Treated like `previewToken`: dropped\n * from the visitor probe, counted as the credential, its value never shown.\n */\n readonly tokenQueryParam?: string | undefined;\n}\n\n/**\n * The query parameters an adapter reads as preview intent by default; the same\n * list as `DEFAULT_QUERY_PARAMS` in adapters/shared/preview-request.ts, which\n * `previewQueryParams` replaces rather than extends.\n */\nconst DEFAULT_INTENT_PARAMS: readonly string[] = ['preview', 'draft', 'livePreview'];\n\nfunction isIntentValue(value: string): boolean {\n return value === 'true' || value === '1';\n}\n\n/** `key=value` and `#fragment` split off a URL, with the query kept as the caller spelled it. */\nfunction splitUrl(url: string): {\n readonly base: string;\n readonly parts: string[];\n readonly hash: string;\n} {\n const hashAt = url.indexOf('#');\n const hash = hashAt === -1 ? '' : url.slice(hashAt);\n const beforeHash = hashAt === -1 ? url : url.slice(0, hashAt);\n const queryAt = beforeHash.indexOf('?');\n if (queryAt === -1) return { base: beforeHash, parts: [], hash };\n return {\n base: beforeHash.slice(0, queryAt),\n parts: beforeHash.slice(queryAt + 1).split('&'),\n hash,\n };\n}\n\nfunction decodePart(part: string): readonly [string, string] {\n const at = part.indexOf('=');\n const decode = (text: string): string => {\n try {\n return decodeURIComponent(text.replace(/\\+/gu, ' '));\n } catch {\n return text;\n }\n };\n return at === -1 ? [decode(part), ''] : [decode(part.slice(0, at)), decode(part.slice(at + 1))];\n}\n\n/**\n * The query parameter the `signed-token` strategy reads by default. A token\n * audit puts the token in the URL, and it belongs to the preview request only:\n * in the visitor request it would authorize the \"anonymous\" probe and, behind a\n * replay store, spend the token before the preview request arrives.\n */\nconst TOKEN_PARAM = 'previewToken';\n\n/**\n * The URL as the audit prints it: the token's value replaced by `…`. Header\n * values never reach the report, and a token passed in the URL is the same\n * credential, so the report, `--json` and the failure line all show this form.\n * @internal\n */\nexport function redactToken(url: string, tokenParam: string = TOKEN_PARAM): string {\n const { base, parts, hash } = splitUrl(url);\n const shown = parts.map((part) => {\n const at = part.indexOf('=');\n return at === -1 || decodePart(part)[0] !== tokenParam ? part : `${part.slice(0, at)}=…`;\n });\n return shown.some((part, index) => part !== parts[index])\n ? `${base}?${shown.join('&')}${hash}`\n : url;\n}\n\n/** Whether the URL carries a non-empty token for the preview request. */\nfunction carriesToken(url: string, tokenParam: string): boolean {\n return splitUrl(url).parts.some((part) => {\n const [key, value] = decodePart(part);\n return key === tokenParam && value !== '';\n });\n}\n\n/**\n * The page a visitor requests: the intent parameters removed, the rest of the\n * query byte for byte as given. A query is never re-serialised — `URLSearchParams`\n * would turn `%20` into `+` and add `=` to a bare key, and a page whose query is\n * signed by an edge token would answer a different request than a visitor makes.\n */\nfunction visitorUrl(url: string, params: readonly string[], tokenParam: string): string {\n const { base, parts, hash } = splitUrl(url);\n const dropped = new Set([...params, tokenParam]);\n const kept = parts.filter((part) => !dropped.has(decodePart(part)[0]));\n if (kept.length === parts.length) return url;\n return `${base}${kept.length === 0 ? '' : `?${kept.join('&')}`}${hash}`;\n}\n\n/**\n * The page the admin's iframe loads. A 2.0 adapter counts only the query as\n * intent (`previewSignals: ['query']`), and `buildLivePreviewUrl` writes\n * `preview=true`, so the first intent parameter is appended as `=true` unless the\n * URL already names one with a value that counts.\n */\nfunction previewUrl(url: string, params: readonly string[]): string {\n const { base, parts, hash } = splitUrl(url);\n const carries = parts.some((part) => {\n const [key, value] = decodePart(part);\n return params.includes(key) && isIntentValue(value);\n });\n if (carries) return url;\n const query = parts.join('&');\n const joiner = query === '' ? '?' : query.endsWith('&') ? '' : '&';\n const intent = `${encodeURIComponent(params[0] ?? 'preview')}=true`;\n return `${base}${parts.length === 0 ? '?' : `?${query}${joiner}`}${intent}${hash}`;\n}\n\nexport const DEFAULT_TIMEOUT_MS = 15_000;\nexport const MAX_BODY_BYTES = 10 * 1024 * 1024;\n\nexport interface DefaultFetchOptions {\n readonly fetchFn?: typeof fetch;\n readonly timeoutMs?: number;\n readonly maxBodyBytes?: number;\n}\n\n/** Header names lowercased; every check downstream reads a lowercase key. @internal */\nexport function lowercaseHeaders(headers: Headers): Record<string, string> {\n const out: Record<string, string> = {};\n headers.forEach((value, key) => {\n out[key.toLowerCase()] = value;\n });\n return out;\n}\n\n/** The error's message plus its cause's, which is where undici puts `self-signed certificate` and friends. */\nexport function describeFailure(error: unknown): string {\n if (!(error instanceof Error)) return String(error);\n const cause = error.cause;\n if (cause instanceof Error && cause.message !== '' && !error.message.includes(cause.message)) {\n return `${error.message} (${cause.message})`;\n }\n return error.message;\n}\n\nasync function readBody(response: Response, limit: number): Promise<string> {\n const reader = response.body?.getReader();\n if (reader === undefined) return response.text();\n const decoder = new TextDecoder();\n let received = 0;\n let text = '';\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n received += value.byteLength;\n if (received > limit) {\n await reader.cancel();\n throw new Error(\n `the response body exceeds ${String(limit)} bytes, which is not a page the audit can judge`,\n );\n }\n text += decoder.decode(value, { stream: true });\n }\n return text + decoder.decode();\n}\n\n/** Redirects are reported, not followed; a hanging origin is abandoned; a runaway body is refused. */\nexport function createDefaultFetch(options: DefaultFetchOptions = {}): DoctorFetch {\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const limit = options.maxBodyBytes ?? MAX_BODY_BYTES;\n return async (url, init) => {\n const fetchFn = options.fetchFn ?? globalThis.fetch;\n let response: Response;\n try {\n response = await fetchFn(url, {\n headers: init.headers,\n redirect: 'manual',\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (error) {\n if (error instanceof Error && error.name === 'TimeoutError') {\n throw new Error(`no response within ${String(timeoutMs / 1000)} s`, { cause: error });\n }\n throw error;\n }\n return {\n status: response.status,\n headers: lowercaseHeaders(response.headers),\n body: await readBody(response, limit),\n };\n };\n}\n\n/** The referer the admin's iframe would send: the origin (or the given admin path) with one slash. */\nexport function previewReferer(adminOrigin: string): string {\n try {\n return new URL(adminOrigin).href;\n } catch {\n return `${adminOrigin.replace(/\\/+$/u, '')}/`;\n }\n}\n\n/**\n * The caller's headers without the ones the probe sets itself. Header names are\n * case-insensitive, and `fetch` combines two spellings of one name into one\n * comma-joined value, so a caller's `sec-fetch-dest` would otherwise turn the\n * probe's `iframe` into `document, iframe`. The probe's own headers win.\n */\nfunction callerHeaders(\n headers: Readonly<Record<string, string>> | undefined,\n own: Readonly<Record<string, string>>,\n): Record<string, string> {\n const taken = new Set(Object.keys(own).map((name) => name.toLowerCase()));\n return Object.fromEntries(\n Object.entries(headers ?? {}).filter(([name]) => !taken.has(name.toLowerCase())),\n );\n}\n\n/** Fetch the URL twice — as a visitor and as the admin's iframe — and audit the difference. */\nexport async function runDoctor(options: RunDoctorOptions): Promise<DoctorReport> {\n const fetchImpl = options.fetchImpl ?? createDefaultFetch();\n const params =\n options.previewQueryParams === undefined || options.previewQueryParams.length === 0\n ? DEFAULT_INTENT_PARAMS\n : options.previewQueryParams;\n const tokenParam = options.tokenQueryParam ?? TOKEN_PARAM;\n // No referer, no intent parameter and no credentials on the visitor probe:\n // each of them is a preview signal or a way past one.\n const publicResponse = await fetchImpl(visitorUrl(options.url, params, tokenParam), {\n headers: {\n Accept: 'text/html',\n 'Sec-Fetch-Dest': 'document',\n 'Sec-Fetch-Mode': 'navigate',\n },\n });\n const probeHeaders: Record<string, string> = {\n Accept: 'text/html',\n 'Sec-Fetch-Dest': 'iframe',\n 'Sec-Fetch-Mode': 'navigate',\n ...(options.adminOrigin === undefined ? {} : { Referer: previewReferer(options.adminOrigin) }),\n };\n const sent = callerHeaders(options.previewHeaders, probeHeaders);\n const previewResponse = await fetchImpl(previewUrl(options.url, params), {\n headers: { ...sent, ...probeHeaders },\n });\n return analyzeProbe(\n { publicResponse, previewResponse },\n {\n url: redactToken(options.url, tokenParam),\n adminOrigin: options.adminOrigin,\n ...(options.v2 === true ? { v2: true } : {}),\n ...(Object.keys(sent).length > 0 || carriesToken(options.url, tokenParam)\n ? { credentials: true }\n : {}),\n },\n );\n}\n","#!/usr/bin/env node\n/**\n * The `pll` binary: `pll doctor <url>` here, `pll migrate <path>` in\n * migrate/cli. Doctor exit codes: 0 no error-level findings, 1 usage error or\n * the URL could not be fetched, 2 at least one error-level finding.\n */\nimport { runMigrateCommand } from '../migrate/cli';\nimport { formatReport } from './format';\nimport { describeFailure, redactToken, runDoctor, type DoctorFetch } from './probe';\n\ninterface ParsedArgs {\n url: string | undefined;\n adminOrigin: string | undefined;\n json: boolean;\n v2: boolean;\n showHelp: boolean;\n unknown: string[];\n /** Headers for the preview probe, from every `--header`/`-H`. */\n headers: Record<string, string>;\n /** The first `--header` or `--param` that could not be read, as the message to print. */\n usageError: string | undefined;\n /** Query parameter names from every `--param`. */\n params: string[];\n /** The token parameter from `--token-param`, where the strategy reads one other than `previewToken`. */\n tokenParam: string | undefined;\n}\n\n/** A query parameter name: no separator, no space, and not the next option. */\nconst PARAM_NAME = /^[^\\s&=#?-][^\\s&=#]*$/u;\n\n/** An HTTP field name (RFC 9110 token), a colon, then the value. */\nconst HEADER_LINE = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+):[ \\t]*(.*)$/u;\n\nfunction addHeader(parsed: ParsedArgs, line: string | undefined): void {\n // A missing value would otherwise read the next argument: `https://example.com/`\n // matches as name `https`, and `--v2` as no header at all.\n const match =\n line === undefined || line.startsWith('-') || isAbsoluteUrl(line)\n ? null\n : HEADER_LINE.exec(line);\n const name = match?.[1];\n const value = match?.[2];\n if (name === undefined || value === undefined) {\n // The value is not echoed: a mistyped header can still hold half a token.\n parsed.usageError ??=\n 'pll doctor: --header takes \"Name: value\", such as --header \"Cookie: payload-token=…\"';\n return;\n }\n // Header names are case-insensitive; a second spelling would be joined onto\n // the first by fetch, and a repeat would silently replace it.\n if (Object.keys(parsed.headers).some((given) => given.toLowerCase() === name.toLowerCase())) {\n parsed.usageError ??= `pll doctor: --header \"${name}\" is given twice; join the values into one header`;\n return;\n }\n parsed.headers[name] = value;\n}\n\nfunction addParam(parsed: ParsedArgs, name: string | undefined): void {\n if (name === undefined || !PARAM_NAME.test(name)) {\n parsed.usageError ??= 'pll doctor: --param takes a query parameter name, such as --param draft';\n return;\n }\n parsed.params.push(name);\n}\n\nfunction setTokenParam(parsed: ParsedArgs, name: string | undefined): void {\n if (name === undefined || !PARAM_NAME.test(name)) {\n parsed.usageError ??=\n 'pll doctor: --token-param takes a query parameter name, such as --token-param lpt';\n return;\n }\n parsed.tokenParam = name;\n}\n\nfunction parseArgs(argv: readonly string[]): ParsedArgs {\n const parsed: ParsedArgs = {\n url: undefined,\n adminOrigin: undefined,\n json: false,\n v2: false,\n showHelp: false,\n unknown: [],\n headers: {},\n usageError: undefined,\n params: [],\n tokenParam: undefined,\n };\n for (let i = 0; i < argv.length; i += 1) {\n const token = argv[i];\n if (token === undefined) continue;\n if (token === '-h' || token === '--help') parsed.showHelp = true;\n else if (token === '--json') parsed.json = true;\n else if (token === '--v2') parsed.v2 = true;\n else if (token === '--admin' || token === '-a') {\n parsed.adminOrigin = argv[i + 1];\n i += 1;\n } else if (token.startsWith('--admin=')) parsed.adminOrigin = token.slice('--admin='.length);\n else if (token === '--header' || token === '-H') {\n addHeader(parsed, argv[i + 1]);\n i += 1;\n } else if (token.startsWith('--header=')) addHeader(parsed, token.slice('--header='.length));\n else if (token === '--param') {\n addParam(parsed, argv[i + 1]);\n i += 1;\n } else if (token.startsWith('--param=')) addParam(parsed, token.slice('--param='.length));\n else if (token === '--token-param') {\n setTokenParam(parsed, argv[i + 1]);\n i += 1;\n } else if (token.startsWith('--token-param=')) {\n setTokenParam(parsed, token.slice('--token-param='.length));\n } else if (token.startsWith('-')) parsed.unknown.push(token);\n else parsed.url ??= token;\n }\n return parsed;\n}\n\nconst HELP_TEXT = `pll doctor — audit what a live-preview deployment actually serves\npll migrate — rewrite 1.x APIs to their 2.0 names and homes\n\nUsage:\n pll doctor <url> [--admin <origin>] [--header <name: value>]... [--param <name>]...\n [--token-param <name>] [--json] [--v2]\n pll migrate <path> [--write] [--only <id,id>]\n\nThe URL is fetched twice: once as an ordinary visitor, without any intent\nparameter, and once the way the Payload admin's iframe loads it, with\n?preview=true and the iframe's headers.\nMost findings come from the difference between the two responses. Redirects\nare reported, not followed.\n\nOptions of pll doctor:\n -a, --admin <origin> Admin origin the preview is embedded from. Enables the\n frame-ancestors check to verify the origin is admitted,\n not merely that a policy exists.\n -H, --header <h> A header for the preview request only, as \"Name: value\";\n repeat it for more. A preview behind authorizePreview\n needs an editor's credentials: a Payload session Cookie,\n or an x-preview-token where the token strategy sets\n transport: { kind: 'header' }. A signed token travels in\n the URL by default, as ?previewToken=…, which the visitor\n request drops. The visitor request stays anonymous and\n values are never printed, but a shell keeps them in its\n history, so prefer a short-lived token.\n --param <name> A query parameter the deployment reads as preview intent,\n for an adapter whose previewQueryParams replaces the\n default preview, draft and livePreview; repeat it for\n more. The first one is what the preview request carries\n as <name>=true; none of them reaches the visitor request.\n --token-param <n> The query parameter the signed-token strategy reads,\n where its transport names one other than previewToken.\n Treated like previewToken: dropped from the visitor\n request, counted as the credential, never printed.\n --json Emit the report as JSON instead of text\n --v2 Also check the page against the 2.0 readiness table\n -h, --help Show this help\n\nExit codes of pll doctor:\n 0 no error-level findings\n 1 usage error, or the URL could not be fetched\n 2 at least one error-level finding\n\npll migrate has its own options and exit codes: pll migrate --help\n\nExamples:\n pll doctor https://example.com/\n pll doctor https://example.com/blog/hello --admin https://cms.example.com\n pll doctor \"https://example.com/?previewToken=$PREVIEW_TOKEN\" --v2\n pll doctor https://example.com/ --header \"Cookie: payload-token=$PAYLOAD_TOKEN\"\n`;\n\nfunction isAbsoluteUrl(value: string): boolean {\n try {\n return new URL(value).origin !== 'null';\n } catch {\n return false;\n }\n}\n\n/** @param fetchImpl Seam for tests; the bin shim never passes it. */\nexport async function run(argv: readonly string[], fetchImpl?: DoctorFetch): Promise<number> {\n const [subcommand, ...rest] = argv;\n if (subcommand === undefined || subcommand === '-h' || subcommand === '--help') {\n process.stdout.write(HELP_TEXT);\n return subcommand === undefined ? 1 : 0;\n }\n if (subcommand === 'migrate') return runMigrateCommand(rest);\n if (subcommand !== 'doctor') {\n process.stderr.write(`pll: unknown command \"${subcommand}\". Try \\`pll --help\\`.\\n`);\n return 1;\n }\n const args = parseArgs(rest);\n if (args.showHelp) {\n process.stdout.write(HELP_TEXT);\n return 0;\n }\n if (args.unknown.length > 0) {\n process.stderr.write(`pll doctor: unknown option ${args.unknown.join(', ')}\\n`);\n return 1;\n }\n if (args.url === undefined) {\n process.stderr.write('pll doctor: a URL is required. Try `pll doctor --help`.\\n');\n return 1;\n }\n if (args.usageError !== undefined) {\n process.stderr.write(`${args.usageError}\\n`);\n return 1;\n }\n if (args.adminOrigin !== undefined && !isAbsoluteUrl(args.adminOrigin)) {\n process.stderr.write(\n `pll doctor: --admin must be an absolute URL such as https://cms.example.com (got \"${args.adminOrigin}\")\\n`,\n );\n return 1;\n }\n let report;\n try {\n report = await runDoctor({\n url: args.url,\n ...(args.adminOrigin !== undefined ? { adminOrigin: args.adminOrigin } : {}),\n ...(args.v2 ? { v2: true } : {}),\n ...(Object.keys(args.headers).length > 0 ? { previewHeaders: args.headers } : {}),\n ...(args.params.length > 0 ? { previewQueryParams: args.params } : {}),\n ...(args.tokenParam === undefined ? {} : { tokenQueryParam: args.tokenParam }),\n ...(fetchImpl !== undefined ? { fetchImpl } : {}),\n });\n } catch (error) {\n const message = describeFailure(error);\n const shown = redactToken(args.url, args.tokenParam);\n if (args.json) {\n process.stdout.write(`${JSON.stringify({ url: shown, error: message }, undefined, 2)}\\n`);\n } else {\n process.stderr.write(`pll doctor: could not probe ${shown}: ${message}\\n`);\n }\n return 1;\n }\n process.stdout.write(\n args.json ? `${JSON.stringify(report, undefined, 2)}\\n` : formatReport(report),\n );\n return report.errors > 0 ? 2 : 0;\n}\n\n/** Matches the entry's basename only, so importing this module from a path containing `pll` never runs it. */\nexport function isCliInvocation(argv: readonly (string | undefined)[] = process.argv): boolean {\n if (typeof process === 'undefined') return false;\n const entry = argv[1];\n if (entry === undefined || entry === '') return false;\n const name = entry.split(/[\\\\/]/u).pop() ?? '';\n return name === 'pll' || name === 'pll.cmd' || name.startsWith('doctor-cli');\n}\n\nif (isCliInvocation()) {\n void run(process.argv.slice(2)).then((code) => {\n process.exit(code);\n });\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"doctor-cli.js","names":["tsMorph","project","PACKAGE_NAME","loadTsMorph","createRequire","url","error","Error","cause","parseScript","text","kind","morph","Project","useInMemoryFileSystem","skipLoadingLibFiles","skipFileDependencyResolution","compilerOptions","allowJs","noLib","createSourceFile","overwrite","isPackageSpecifier","specifier","startsWith","packageReexports","script","out","declaration","getExportDeclarations","getModuleSpecifierValue","spec","getNamedExports","push","imported","getName","importedNode","getNameNode","alias","getAliasNode","getText","line","getStartLineNumber","packageBindings","Node","SyntaxKind","getImportDeclarations","getNamedImports","localNode","local","aliased","symbol","getSymbol","getDescendantsOfKind","VariableDeclaration","requiredSpecifier","getInitializer","pattern","isObjectBindingPattern","element","getElements","nameNode","isIdentifier","propertyName","getPropertyNameNode","literalName","initializer","call","isAwaitExpression","getExpression","isCallExpression","callee","getKind","ImportKeyword","argument","getArguments","isStringLiteral","getLiteralText","node","isNoSubstitutionTemplateLiteral","propertyKey","property","isSpreadAssignment","isComputedPropertyName","referencesTo","binding","target","compilerSymbol","checker","getProject","getTypeChecker","Identifier","isInside","parent","getParent","isShorthandPropertyAssignment","getShorthandAssignmentValueSymbol","isExportSpecifier","getLocalTargetSymbol","ancestor","getFirstAncestor","candidate","declaresName","name","except","bindsIdentifier","some","skip","isVariableDeclaration","isBindingElement","isFunctionDeclaration","isClassDeclaration","isParameterDeclaration","isEnumDeclaration","isImportSpecifier","isImportClause","getDefaultImport","isNamespaceImport","replaceNode","start","getStart","end","getEnd","applyTextEdits","edits","ordered","sort","left","right","output","floor","Number","POSITIVE_INFINITY","edit","slice","ADAPTER_ENTRIES","Set","map","entry","optionLiterals","found","Map","record","literal","use","uses","get","known","outer","at","set","visit","getProperties","forEach","shared","constLiteral","has","reference","isNewExpression","inner","unwrap","isObjectLiteralExpression","packageJsxAttributes","tags","JsxAttribute","filter","attribute","isJsxOpeningElement","isJsxSelfClosingElement","getTagNameNode","memberNamed","key","find","VariableDeclarationKind","getDeclarations","getVariableStatement","getDeclarationKind","Const","current","isParenthesizedExpression","isAsExpression","isSatisfiesExpression","isTypeAssertion","ID","KEY","RUNTIME_ROWS","q","ROWS","adapter","join","runtime","ROW_KEYS","BY_HAND","expandDefaultsV1","id","summary","ledgerEntry","notice","apply","conflicts","conflict","reason","codemod","value","isPropertyAssignment","refusal","refuse","expansion","charAt","size","properties","index","findIndex","member","overridden","quote","present","composed","part","opaque","rows","source","getSourceFile","getFullText","length","next","lineStart","lastIndexOf","lead","separator","test","SERVER_SPECIFIER","METHOD","fetchPreviewDocument","fetchPreviewGlobal","SERVER_OPTIONS","DROPPED_OPTIONS","SHARED_READ_OPTIONS","READ_OPTIONS","rewriteCall","options","server","read","dropped","keys","add","accepted","unplaceable","includes","typeArguments","getTypeArguments","generic","method","droppedNote","done","advice","importLine","names","moveFetchPreviewHelpers","bindings","reexports","reexport","blocking","notes","rewritten","serverDeclaration","foreign","declarations","isImportDeclaration","serverImport","isTypeOnly","hasDefinePreview","serverLine","getModuleSpecifier","getQuoteKind","defaultImport","clauses","remaining","clause","typeOnly","kept","trailingNewline","rewriteImports","plan","CALLEE","OLD_KEY","NEW_KEY","renameAdminOriginsOption","BOOLEAN_REFUSED","renameBindingsAuthorizedOption","isFalseLiteral","OLD_NAME","NEW_NAME","renameBinding","getParentOrThrow","renameIsPreviewRequest","existing","isPropertyAccessExpression","memberAccesses","RENAMED","route","ignore","renameOnUnboundChange","renamed","WHOLE_FILE","COMPONENT_EXTENSIONS","FRONTMATTER","SCRIPT_TAG","PACKAGE_REFERENCE","IMPLEMENTATIONS","CODEMODS","lineNumberAt","offset","lineEdits","before","after","firstLine","oldLines","split","newLines","prefix","suffix","oldMiddle","newMiddle","changed","Math","max","migrateSource","chosen","only","importsThisPackage","byCodemod","cursor","block","fileName","extension","extname","toLowerCase","blocks","frontmatter","exec","indexOf","match","matchAll","body","trim","scriptBlocks","item","lines","count","SOURCE_EXTENSIONS","DECLARATION_FILE","SKIP_DIRECTORIES","isSourceFile","async","collectFiles","root","stat","isDirectory","walk","directory","readdir","withFileTypes","path","relativeTo","file","rel","relative","MIGRATE_HELP","describe","String","LEVEL_LABEL","warning","info","DIAGNOSTIC_CODES","Object","freeze","NoTrustedOrigin","ReferrerOnlyTrust","PluginIncompatible","ProfileFeatureOmitted","OrphanField","UnattributableUpdate","UnboundField","CoverageDefaultChanges","VisibilityGateDeferred","UnsafeAttributeWrite","TextTargetHasChildren","MissingArrayTemplate","StructuralItemUnkeyed","StructuralDuplicateKey","StructuralUnstableKeys","UnsupportedStrategy","UnknownValueFormat","SanitizerDroppedAttribute","UnrenderedBlockKept","UnfaithfulPatch","ServerFormatReplaced","UnrenderedBlockLost","MessageRejected","TokenRejected","ProtocolShapeUnknown","HandlerThrew","TransformThrew","RendererThrew","StartupFailed","ReadyFailed","HydrationWaitTimedOut","AuditRuntimeMissing","AuditNoFrameAncestors","AuditFrameOptionsBlocks","AuditBindingsExposed","AuditGateThresholdExceeded","AuditUnownedBindings","AuditNoBindings","AuditNotAPage","FragmentRequestFailed","FragmentResponseInvalid","FragmentUnauthorized","FragmentSuperseded","RouteRefreshLoop","FragmentStrategyUnavailable","UnboundChangeRefresh","EscalationUnavailable","IslandStartUnavailable","RouteRefreshUnconfirmed","V2ReadinessGap","RuntimeOnPublicPage","AuditModifierWithoutField","DEFAULT_PORT","http","https","ws","wss","SCHEME_SOURCE","HOST_SOURCE","schemeOf","protocol","portOf","port","schemeMatches","expression","actual","isSelf","admin","page","hostname","adminScheme","pageScheme","sourceMatches","scheme","host","expressionScheme","expressionHost","expressionPort","wanted","replace","endsWith","hostMatches","INLINE_CONFIG_KEYS","V2_RUNTIME_DEFAULTS","disableReferrerDetection","eventSourcePolicy","skipUnchanged","sanitizerPolicy","V1_RUNTIME_DEFAULTS","CONFIG_NAME","CONFIG_MARKER","COMMENT_OR_SCRIPT","CONFIG_ID","JSON_TYPE","title","effect","condition","ORIGIN_DETAIL","profile","explicit","unmarked","UNREADABLE","code","level","detail","remedy","UNMARKED","readServedConfig","scripts","attributes","servedScripts","inline","tuple","from","depth","inString","previous","json","char","JSON","parse","Array","isArray","readInlineConfig","named","readConfigElement","hasOwn","stringify","remedyFor","origin","row","gap","unknownGeneration","marker","RUNTIME_MARKER","START_TAG","TAG_ATTRIBUTE","LEVEL_ORDER","NON_MARKUP","visibleMarkup","markup","stripped","FIELD_MODIFIERS","markupAttributes","tag","assigned","double","single","bare","tryUrl","URL","analyzeProbe","probe","context","publicResponse","pub","previewResponse","preview","notAPage","status","location","headers","contentType","describeNonPage","findings","errors","warnings","runtimeInPreview","credentials","adminOrigin","sameOrigin","frameAncestors","csp","directive","trimmed","frameAncestorsOf","admitted","sources","frameAncestorsAdmits","frameOptions","judged","framingFindings","previewMarkup","publicMarkup","gate","previewBindings","publicBindings","owners","boundaries","boundary","stranded","bound","values","modifiersWithoutField","threshold","configured","unowned","firstOwner","unownedBindingsBeforeFirstOwner","bindingFindings","config","servedGate","v2","generation","fallback","flatMap","slot","analyzeV2Readiness","a","b","finding","DEFAULT_INTENT_PARAMS","splitUrl","hashAt","hash","beforeHash","queryAt","base","parts","decodePart","decode","decodeURIComponent","TOKEN_PARAM","redactToken","tokenParam","shown","carriesToken","lowercaseHeaders","readBody","response","limit","reader","getReader","decoder","TextDecoder","received","byteLength","cancel","stream","previewReferer","href","PARAM_NAME","HEADER_LINE","ENV_NAME","addHeader","parsed","invalid","isAbsoluteUrl","given","usageError","addHeaderFromEnv","process","env","addParam","params","setTokenParam","HELP_TEXT","run","argv","fetchImpl","subcommand","rest","stdout","write","args","unknown","help","ids","token","parseArgs","stderr","result","io","readFile","content","writeFile","list","results","files","changedCount","conflictCount","runMigrate","message","conflicted","where","runMigrateCommand","showHelp","i","report","timeoutMs","maxBodyBytes","init","fetchFn","globalThis","fetch","redirect","signal","AbortSignal","timeout","createDefaultFetch","previewQueryParams","tokenQueryParam","visitorUrl","Accept","probeHeaders","Referer","sent","own","taken","fromEntries","entries","callerHeaders","previewHeaders","isIntentValue","query","joiner","intent","encodeURIComponent","previewUrl","runDoctor","describeFailure","formatReport","isCliInvocation","pop","then","exit"],"sources":["../src/migrate/ast.ts","../src/migrate/option-literals.ts","../src/migrate/codemods/expand-defaults-v1.ts","../src/migrate/codemods/move-fetch-preview-helpers.ts","../src/migrate/codemods/rename-admin-origins-option.ts","../src/migrate/codemods/rename-bindings-authorized-option.ts","../src/migrate/codemods/rename-is-preview-request.ts","../src/migrate/codemods/rename-on-unbound-change.ts","../src/migrate/script-blocks.ts","../src/migrate/index.ts","../src/migrate/runner.ts","../src/migrate/cli.ts","../src/doctor/format.ts","../src/core/diagnostic-codes.ts","../src/doctor/csp.ts","../src/types/inline-config.ts","../src/types/defaults-profile.ts","../src/doctor/readiness.ts","../src/doctor/analyze.ts","../src/doctor/probe.ts","../src/doctor/cli.ts"],"sourcesContent":["/**\n * ts-morph access for the codemods: parsing, the package's bindings in a\n * script and the references those bindings have. ts-morph is loaded on first\n * use so the entry stays importable without the optional peer.\n */\nimport { createRequire } from 'node:module';\nimport type * as TsMorphModule from 'ts-morph';\nimport type {\n Identifier,\n Node,\n ObjectLiteralElementLike,\n Project,\n SourceFile,\n Symbol as TsSymbol,\n} from 'ts-morph';\nimport type { TextEdit } from './types';\n\ntype TsMorph = typeof TsMorphModule;\n\nexport type ScriptKind = 'ts' | 'tsx' | 'js' | 'jsx';\n\nexport const PACKAGE_NAME = 'payload-live-preview';\n\nlet tsMorph: TsMorph | undefined;\nlet project: Project | undefined;\n\nexport function loadTsMorph(): TsMorph {\n if (tsMorph === undefined) {\n try {\n tsMorph = createRequire(import.meta.url)('ts-morph') as TsMorph;\n } catch (error) {\n throw new Error('pll migrate needs ts-morph: npm install --save-dev ts-morph', {\n cause: error,\n });\n }\n }\n return tsMorph;\n}\n\n/** Parse one script into a throwaway in-memory project; the previous script is discarded. */\nexport function parseScript(text: string, kind: ScriptKind): SourceFile {\n const morph = loadTsMorph();\n project ??= new morph.Project({\n useInMemoryFileSystem: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: { allowJs: true, noLib: true },\n });\n return project.createSourceFile(`/script.${kind}`, text, { overwrite: true });\n}\n\nexport function isPackageSpecifier(specifier: string): boolean {\n return specifier === PACKAGE_NAME || specifier.startsWith(`${PACKAGE_NAME}/`);\n}\n\n/** A name the script binds from the package, by `import` or by destructuring `require()`/`import()`. */\nexport interface PackageBinding {\n /** The exported name, as the package spells it. */\n readonly imported: string;\n /** The name the script uses; equals `imported` unless aliased. */\n readonly local: string;\n readonly specifier: string;\n readonly kind: 'import' | 'require';\n /** The node spelling the exported name; rewritten when the export is renamed. */\n readonly importedNode: Node;\n readonly aliased: boolean;\n readonly symbol: TsSymbol | undefined;\n /** The import declaration or variable declaration that binds it. */\n readonly declaration: Node;\n}\n\n/** A name the script re-exports straight from the package: `export { name } from 'payload-live-preview'`. */\nexport interface PackageReexport {\n /** The exported name, as the package spells it. */\n readonly imported: string;\n readonly specifier: string;\n /** The node spelling the package's name; rewritten when the export is renamed. */\n readonly importedNode: Node;\n /** The name the module exports it under, when the specifier has `as`. */\n readonly alias: string | undefined;\n readonly line: number;\n}\n\n/** packageBindings() sees imports; a re-export from the package binds nothing locally and needs its own pass. */\nexport function packageReexports(script: SourceFile): readonly PackageReexport[] {\n const out: PackageReexport[] = [];\n for (const declaration of script.getExportDeclarations()) {\n const specifier = declaration.getModuleSpecifierValue();\n if (specifier === undefined || !isPackageSpecifier(specifier)) continue;\n for (const spec of declaration.getNamedExports()) {\n out.push({\n imported: spec.getName(),\n specifier,\n importedNode: spec.getNameNode(),\n alias: spec.getAliasNode()?.getText(),\n line: spec.getStartLineNumber(),\n });\n }\n }\n return out;\n}\n\nexport function packageBindings(script: SourceFile): readonly PackageBinding[] {\n const { Node, SyntaxKind } = loadTsMorph();\n const out: PackageBinding[] = [];\n for (const declaration of script.getImportDeclarations()) {\n const specifier = declaration.getModuleSpecifierValue();\n if (!isPackageSpecifier(specifier)) continue;\n for (const spec of declaration.getNamedImports()) {\n const alias = spec.getAliasNode();\n const localNode = alias ?? spec.getNameNode();\n out.push({\n imported: spec.getName(),\n local: localNode.getText(),\n specifier,\n kind: 'import',\n importedNode: spec.getNameNode(),\n aliased: alias !== undefined,\n symbol: localNode.getSymbol(),\n declaration,\n });\n }\n }\n for (const declaration of script.getDescendantsOfKind(SyntaxKind.VariableDeclaration)) {\n const specifier = requiredSpecifier(declaration.getInitializer());\n const pattern = declaration.getNameNode();\n if (specifier === undefined || !isPackageSpecifier(specifier)) continue;\n if (!Node.isObjectBindingPattern(pattern)) continue;\n for (const element of pattern.getElements()) {\n const nameNode = element.getNameNode();\n if (!Node.isIdentifier(nameNode)) continue;\n const propertyName = element.getPropertyNameNode();\n out.push({\n imported: propertyName === undefined ? nameNode.getText() : literalName(propertyName),\n local: nameNode.getText(),\n specifier,\n kind: 'require',\n importedNode: propertyName ?? nameNode,\n aliased: propertyName !== undefined,\n symbol: nameNode.getSymbol(),\n declaration,\n });\n }\n }\n return out;\n}\n\nfunction requiredSpecifier(initializer: Node | undefined): string | undefined {\n const { Node, SyntaxKind } = loadTsMorph();\n const call =\n initializer !== undefined && Node.isAwaitExpression(initializer)\n ? initializer.getExpression()\n : initializer;\n if (call === undefined || !Node.isCallExpression(call)) return undefined;\n const callee = call.getExpression();\n const isRequire = Node.isIdentifier(callee) && callee.getText() === 'require';\n if (!isRequire && callee.getKind() !== SyntaxKind.ImportKeyword) return undefined;\n const [argument] = call.getArguments();\n return argument !== undefined && Node.isStringLiteral(argument)\n ? argument.getLiteralText()\n : undefined;\n}\n\nfunction literalName(node: Node): string {\n const { Node } = loadTsMorph();\n if (Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)) {\n return node.getLiteralText();\n }\n return node.getText();\n}\n\n/** The key of an object-literal member, or `undefined` when it is computed. */\nexport function propertyKey(property: ObjectLiteralElementLike): string | undefined {\n const { Node } = loadTsMorph();\n if (Node.isSpreadAssignment(property)) return undefined;\n const nameNode = property.getNameNode();\n if (Node.isComputedPropertyName(nameNode)) return undefined;\n return literalName(nameNode);\n}\n\nexport type ReferenceKind = 'reference' | 'shorthand' | 'export';\n\nexport interface BindingReference {\n readonly node: Identifier;\n /** `shorthand` is `{ name }`, `export` is `export { name }`; both keep the old key visible. */\n readonly kind: ReferenceKind;\n}\n\n/** Every use of the binding outside its own declaration, resolved by symbol so shadowing is respected. */\nexport function referencesTo(\n script: SourceFile,\n binding: PackageBinding,\n): readonly BindingReference[] {\n const { Node, SyntaxKind } = loadTsMorph();\n const target = binding.symbol?.compilerSymbol;\n if (target === undefined) return [];\n const checker = script.getProject().getTypeChecker();\n const out: BindingReference[] = [];\n for (const node of script.getDescendantsOfKind(SyntaxKind.Identifier)) {\n if (node.getText() !== binding.local || isInside(node, binding.declaration)) continue;\n const parent = node.getParent();\n if (Node.isShorthandPropertyAssignment(parent)) {\n if (checker.getShorthandAssignmentValueSymbol(parent)?.compilerSymbol === target) {\n out.push({ node, kind: 'shorthand' });\n }\n continue;\n }\n if (Node.isExportSpecifier(parent)) {\n if (\n parent.getNameNode() === node &&\n parent.getLocalTargetSymbol()?.compilerSymbol === target\n ) {\n out.push({ node, kind: 'export' });\n }\n continue;\n }\n if (node.getSymbol()?.compilerSymbol === target) out.push({ node, kind: 'reference' });\n }\n return out;\n}\n\nfunction isInside(node: Node, ancestor: Node): boolean {\n return node.getFirstAncestor((candidate) => candidate === ancestor) !== undefined;\n}\n\n/** The declaration that binds `name` anywhere in the script, ignoring those in `except`. */\nexport function declaresName(\n script: SourceFile,\n name: string,\n except: readonly Node[] = [],\n): Node | undefined {\n const { SyntaxKind } = loadTsMorph();\n for (const node of script.getDescendantsOfKind(SyntaxKind.Identifier)) {\n if (node.getText() !== name) continue;\n const parent = node.getParent();\n if (!bindsIdentifier(parent, node)) continue;\n if (except.some((skip) => skip === parent || isInside(parent, skip))) continue;\n return parent;\n }\n return undefined;\n}\n\nfunction bindsIdentifier(parent: Node, node: Identifier): boolean {\n const { Node } = loadTsMorph();\n if (\n Node.isVariableDeclaration(parent) ||\n Node.isBindingElement(parent) ||\n Node.isFunctionDeclaration(parent) ||\n Node.isClassDeclaration(parent) ||\n Node.isParameterDeclaration(parent) ||\n Node.isEnumDeclaration(parent)\n ) {\n return parent.getNameNode() === node;\n }\n if (Node.isImportSpecifier(parent)) {\n return (parent.getAliasNode() ?? parent.getNameNode()) === node;\n }\n if (Node.isImportClause(parent)) return parent.getDefaultImport() === node;\n if (Node.isNamespaceImport(parent)) return parent.getNameNode() === node;\n return false;\n}\n\n/** Identifiers spelled `name` that are member names (`x.name`), never the package's binding. */\nexport function memberAccesses(script: SourceFile, name: string): readonly Identifier[] {\n const { Node, SyntaxKind } = loadTsMorph();\n return script.getDescendantsOfKind(SyntaxKind.Identifier).filter((node) => {\n const parent = node.getParent();\n return (\n node.getText() === name &&\n Node.isPropertyAccessExpression(parent) &&\n parent.getNameNode() === node\n );\n });\n}\n\nexport function replaceNode(node: Node, text: string): TextEdit {\n return { start: node.getStart(), end: node.getEnd(), text };\n}\n\n/** Splice non-overlapping edits into `text`. */\nexport function applyTextEdits(text: string, edits: readonly TextEdit[]): string {\n const ordered = [...edits].sort((left, right) => right.start - left.start);\n let output = text;\n let floor = Number.POSITIVE_INFINITY;\n for (const edit of ordered) {\n if (edit.end > floor) throw new Error('overlapping codemod edits');\n output = `${output.slice(0, edit.start)}${edit.text}${output.slice(edit.end)}`;\n floor = edit.start;\n }\n return output;\n}\n","/**\n * The options literals a script hands to the package: an object literal passed\n * to a function or class the script binds from it, and a `const` object literal\n * such a call takes by name or spreads into its own. The option codemods rename\n * or expand keys there (ADR 0026); anything else they cannot see is left to the\n * development warning the package gives at run time.\n */\nimport type { JsxAttribute, Node, ObjectLiteralExpression, SourceFile } from 'ts-morph';\nimport { loadTsMorph, packageBindings, propertyKey, referencesTo } from './ast';\n\n/** Adapter options carry the request rows too; the root, `/core` and `/client` take runtime options. */\nexport type OptionsKind = 'adapter' | 'runtime';\n\n/** @internal */\nexport const ADAPTER_ENTRIES: ReadonlySet<string> = new Set(\n ['astro', 'nextjs', 'sveltekit', 'nuxt', 'nuxt-module'].map(\n (entry) => `payload-live-preview/${entry}`,\n ),\n);\n\n/** One call that uses a literal: the literal the call passes, which spreads the shared one or is it. */\nexport interface OptionsUse {\n readonly kind: OptionsKind;\n readonly outer: ObjectLiteralExpression;\n /** The index of the spread in `outer` that brings the shared literal in; absent when `outer` is it. */\n readonly at?: number;\n}\n\n/** Every literal the package receives, with the calls that give it. */\nexport function optionLiterals(\n script: SourceFile,\n): ReadonlyMap<ObjectLiteralExpression, readonly OptionsUse[]> {\n const { Node } = loadTsMorph();\n const found = new Map<ObjectLiteralExpression, OptionsUse[]>();\n const record = (literal: ObjectLiteralExpression, use: OptionsUse): void => {\n const uses = found.get(literal) ?? [];\n if (\n !uses.some(\n (known) => known.outer === use.outer && known.at === use.at && known.kind === use.kind,\n )\n ) {\n uses.push(use);\n }\n found.set(literal, uses);\n };\n const visit = (literal: ObjectLiteralExpression, kind: OptionsKind): void => {\n record(literal, { kind, outer: literal });\n literal.getProperties().forEach((property, at) => {\n if (!Node.isSpreadAssignment(property)) return;\n const shared = constLiteral(property.getExpression());\n if (shared !== undefined) record(shared, { kind, outer: literal, at });\n });\n };\n for (const binding of packageBindings(script)) {\n const kind: OptionsKind = ADAPTER_ENTRIES.has(binding.specifier) ? 'adapter' : 'runtime';\n for (const reference of referencesTo(script, binding)) {\n const call = reference.node.getParent();\n if (reference.kind !== 'reference') continue;\n if (!Node.isCallExpression(call) && !Node.isNewExpression(call)) continue;\n if (call.getExpression() !== reference.node) continue;\n for (const argument of call.getArguments()) {\n const inner = unwrap(argument);\n const literal = Node.isObjectLiteralExpression(inner) ? inner : constLiteral(inner);\n if (literal !== undefined) visit(literal, kind);\n }\n }\n }\n return found;\n}\n\n/** `name=\"…\"` or `name={…}` on a JSX element whose tag the script binds from the package. */\nexport function packageJsxAttributes(script: SourceFile, name: string): readonly JsxAttribute[] {\n const { Node, SyntaxKind } = loadTsMorph();\n const tags = new Set(packageBindings(script).map((binding) => binding.local));\n return script.getDescendantsOfKind(SyntaxKind.JsxAttribute).filter((attribute) => {\n const element = attribute.getParent().getParent();\n const isTag = Node.isJsxOpeningElement(element) || Node.isJsxSelfClosingElement(element);\n return (\n isTag &&\n tags.has(element.getTagNameNode().getText()) &&\n attribute.getNameNode().getText() === name\n );\n });\n}\n\n/** The member spelled `key`, or `undefined`. */\nexport function memberNamed(literal: ObjectLiteralExpression, key: string): Node | undefined {\n return literal.getProperties().find((property) => propertyKey(property) === key);\n}\n\n/** The literal a `const` declares, seen through `as const`, `satisfies` and parentheses. */\nfunction constLiteral(node: Node): ObjectLiteralExpression | undefined {\n const { Node, VariableDeclarationKind } = loadTsMorph();\n const target = unwrap(node);\n if (!Node.isIdentifier(target)) return undefined;\n for (const declaration of target.getSymbol()?.getDeclarations() ?? []) {\n if (!Node.isVariableDeclaration(declaration)) continue;\n if (\n declaration.getVariableStatement()?.getDeclarationKind() !== VariableDeclarationKind.Const\n ) {\n continue;\n }\n const initializer = declaration.getInitializer();\n const literal = initializer === undefined ? undefined : unwrap(initializer);\n if (literal !== undefined && Node.isObjectLiteralExpression(literal)) return literal;\n }\n return undefined;\n}\n\nfunction unwrap(node: Node): Node {\n const { Node } = loadTsMorph();\n let current = node;\n while (\n Node.isParenthesizedExpression(current) ||\n Node.isAsExpression(current) ||\n Node.isSatisfiesExpression(current) ||\n Node.isTypeAssertion(current)\n ) {\n current = current.getExpression();\n }\n return current;\n}\n","/**\n * Ledger entry 21: `defaults: 'v1'` → the rows it stands for, as explicit\n * options. The rows keep every value the profile gave, so nothing changes at\n * run time; they only move into the source, where a reviewer and\n * `pll doctor --v2` see each one (ADR 0026).\n */\nimport type { Node, ObjectLiteralElementLike, ObjectLiteralExpression } from 'ts-morph';\nimport { loadTsMorph, propertyKey } from '../ast';\nimport {\n memberNamed,\n optionLiterals,\n packageJsxAttributes,\n type OptionsKind,\n type OptionsUse,\n} from '../option-literals';\nimport type { CodemodImplementation, CodemodConflict, TextEdit } from '../types';\n\nconst ID = 'expand-defaults-v1';\nconst KEY = 'defaults';\n\n/** The 1.x rows (`src/types/defaults-profile.ts`), in source form; `Q` is the file's quote. */\nconst REQUEST_ROWS: readonly (readonly [string, (q: string) => string])[] = [\n ['strict', () => 'false'],\n [\n 'previewSignals',\n (q) => `[${[`${q}query${q}`, `${q}fetch-dest${q}`, `${q}referer${q}`].join(', ')}]`,\n ],\n];\nconst RUNTIME_ROWS: readonly (readonly [string, (q: string) => string])[] = [\n ['disableReferrerDetection', () => 'false'],\n ['eventSourcePolicy', (q) => `${q}any${q}`],\n ['skipUnchanged', () => 'false'],\n ['sanitizerPolicy', (q) => `${q}compat${q}`],\n];\nconst ROWS: Readonly<Record<OptionsKind, readonly (readonly [string, (q: string) => string])[]>> = {\n adapter: [...REQUEST_ROWS, ...RUNTIME_ROWS],\n runtime: RUNTIME_ROWS,\n};\nconst ROW_KEYS: ReadonlySet<string> = new Set(ROWS.adapter.map(([key]) => key));\nconst BY_HAND = \"write the rows `defaults: 'v1'` stands for by hand (docs/migration.md)\";\n\nexport const expandDefaultsV1: CodemodImplementation = {\n id: ID,\n summary: \"`defaults: 'v1'` → the 1.x rows as explicit options\",\n ledgerEntry: 21,\n notice:\n \"The rows keep the 1.x values `defaults: 'v1'` gave; `pll doctor --v2` names each one to drop once the page is ready for 2.0's.\",\n apply(script) {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const conflicts: CodemodConflict[] = [];\n for (const [literal, uses] of optionLiterals(script)) {\n const property = memberNamed(literal, KEY);\n if (property === undefined) continue;\n const line = property.getStartLineNumber();\n const conflict = (reason: string): void => {\n conflicts.push({ codemod: ID, line, reason: `${reason}; ${BY_HAND}` });\n };\n const value = Node.isPropertyAssignment(property) ? property.getInitializer() : undefined;\n if (value === undefined || !Node.isStringLiteral(value)) {\n conflict('`defaults` is not a literal');\n continue;\n }\n if (value.getLiteralText() !== 'v1') continue;\n const refusal = refuse(literal, property, uses);\n if (refusal !== undefined) {\n conflict(refusal);\n continue;\n }\n edits.push(expansion(literal, property, uses, value.getText().charAt(0)));\n }\n for (const attribute of packageJsxAttributes(script, KEY)) {\n conflicts.push({\n codemod: ID,\n line: attribute.getStartLineNumber(),\n reason: `a JSX attribute; ${BY_HAND} as attributes`,\n });\n }\n return { edits, conflicts };\n },\n};\n\n/** Why the rows cannot go where `defaults` was without changing what wins, if they cannot. */\nfunction refuse(\n literal: ObjectLiteralExpression,\n property: Node,\n uses: readonly OptionsUse[],\n): string | undefined {\n const { Node } = loadTsMorph();\n if (new Set(uses.map((use) => use.kind)).size > 1) {\n return 'the object is shared by an adapter and a client, which take different rows';\n }\n // A row is explicit once written, so whatever came before it no longer wins over it.\n const properties = literal.getProperties();\n const index = properties.findIndex((member) => member === property);\n if (properties.slice(0, index).some((member) => Node.isSpreadAssignment(member))) {\n return 'a spread before `defaults` may set a row the expansion would override';\n }\n for (const { outer, at } of uses) {\n if (at === undefined) continue;\n if (memberNamed(outer, KEY) !== undefined) {\n return 'a call that spreads it names its own defaults';\n }\n const before = outer.getProperties().slice(0, at);\n const overridden = (member: ObjectLiteralElementLike): boolean =>\n Node.isSpreadAssignment(member) || ROW_KEYS.has(propertyKey(member) ?? '');\n if (before.some(overridden)) {\n return 'a call sets a row before spreading the object, and the expansion would override it';\n }\n }\n return undefined;\n}\n\nfunction expansion(\n literal: ObjectLiteralExpression,\n property: Node,\n uses: readonly OptionsUse[],\n quote: string,\n): TextEdit {\n const { Node } = loadTsMorph();\n const kind = uses[0]?.kind ?? 'runtime';\n const present = new Set(literal.getProperties().map((member) => propertyKey(member)));\n const composed = [literal, ...uses.map((use) => use.outer)];\n const has = (key: string): boolean =>\n composed.some((part) => memberNamed(part, key) !== undefined);\n // A spread the codemod cannot see into may carry `serverURL`; the one that brings this object in is seen.\n const known = new Set(\n uses.map((use) => (use.at === undefined ? undefined : use.outer.getProperties()[use.at])),\n );\n const opaque = composed.some((part) =>\n part.getProperties().some((member) => Node.isSpreadAssignment(member) && !known.has(member)),\n );\n const rows = ROWS[kind]\n .filter(([key]) => !present.has(key))\n .map(([key, value]) => `${key}: ${value(quote)}`);\n // `'v1'` read an omitted depth as the 1.x default of 1; 2.0 asks for it with `serverURL`.\n if (!has('mergeDepth') && (has('serverURL') || opaque)) rows.push('mergeDepth: 1');\n const source = property.getSourceFile().getFullText();\n if (rows.length === 0) {\n // Every row is already explicit: only the key goes, with the separator after it.\n const next = literal.getProperties().find((member) => member.getStart() > property.getStart());\n return { start: property.getStart(), end: next?.getStart() ?? property.getEnd(), text: '' };\n }\n const lineStart = source.lastIndexOf('\\n', property.getStart()) + 1;\n const lead = source.slice(lineStart, property.getStart());\n const separator = /^\\s*$/u.test(lead) ? `,\\n${lead}` : ', ';\n return { start: property.getStart(), end: property.getEnd(), text: rows.join(separator) };\n}\n","/**\n * Ledger entry 9: `fetchPreviewDocument()`/`fetchPreviewGlobal()` on the root\n * entry → `definePreview({ serverURL, depth }).fetchDocument()`/`.fetchGlobal()`\n * on `payload-live-preview/server`.\n */\nimport {\n PACKAGE_NAME,\n declaresName,\n loadTsMorph,\n packageBindings,\n packageReexports,\n propertyKey,\n referencesTo,\n type PackageBinding,\n type PackageReexport,\n} from '../ast';\nimport type { CodemodImplementation, CodemodConflict, CodemodPlan, TextEdit } from '../types';\nimport type {\n CallExpression,\n ImportDeclaration,\n ObjectLiteralExpression,\n SourceFile,\n} from 'ts-morph';\n\nconst ID = 'move-fetch-preview-helpers';\nconst SERVER_SPECIFIER = `${PACKAGE_NAME}/server`;\nconst METHOD: Readonly<Record<string, string>> = {\n fetchPreviewDocument: 'fetchDocument',\n fetchPreviewGlobal: 'fetchGlobal',\n};\nconst SERVER_OPTIONS = new Set(['serverURL', 'apiRoute', 'depth']);\nconst DROPPED_OPTIONS = new Set(['draft', 'fetchFn']);\n/**\n * What `ReadDocumentOptions`/`ReadGlobalOptions` accept (src/server/preview.ts).\n * 1.x spelled the target `collection` and `global` too, so there is no rename to\n * make here — a key that is in neither set is one this codemod cannot place, and\n * passing it through unannounced produces a file that does not compile.\n */\nconst SHARED_READ_OPTIONS = ['authorization', 'locale', 'headers', 'signal', 'errorMode'];\nconst READ_OPTIONS: Readonly<Record<string, readonly string[]>> = {\n fetchPreviewDocument: ['collection', 'where', ...SHARED_READ_OPTIONS],\n fetchPreviewGlobal: ['global', ...SHARED_READ_OPTIONS],\n};\nconst DEPTH_TODO =\n 'depth: 1 /* TODO(pll migrate): the 1.x default; match the runtime mergeDepth */';\nconst AUTHORIZATION_TODO =\n 'authorization: null /* TODO(pll migrate): pass the verdict from authorizePreviewRequest(); ' +\n 'null reads the published document */';\n\nfunction conflict(line: number, reason: string): CodemodConflict {\n return { codemod: ID, reason, line };\n}\n\ninterface RewrittenCall {\n readonly edit: TextEdit;\n /** What the rewrite did; only true when the file is rewritten. */\n readonly done: CodemodConflict;\n /** What a reader has to place by hand, rewritten or not. */\n readonly advice: readonly CodemodConflict[];\n}\n\nfunction rewriteCall(\n call: CallExpression,\n options: ObjectLiteralExpression,\n imported: string,\n): RewrittenCall {\n const server: string[] = [];\n const read: string[] = [];\n const dropped: string[] = [];\n const keys = new Set<string>();\n for (const property of options.getProperties()) {\n const key = propertyKey(property);\n if (key !== undefined) keys.add(key);\n if (key !== undefined && SERVER_OPTIONS.has(key)) server.push(property.getText());\n else if (key !== undefined && DROPPED_OPTIONS.has(key)) dropped.push(key);\n else read.push(property.getText());\n }\n if (!keys.has('depth')) server.push(DEPTH_TODO);\n if (!keys.has('authorization')) read.push(AUTHORIZATION_TODO);\n const accepted = READ_OPTIONS[imported] ?? [];\n const unplaceable = [...keys].filter(\n (key) => !SERVER_OPTIONS.has(key) && !DROPPED_OPTIONS.has(key) && !accepted.includes(key),\n );\n const typeArguments = call.getTypeArguments().map((argument) => argument.getText());\n const generic = typeArguments.length === 0 ? '' : `<${typeArguments.join(', ')}>`;\n const method = METHOD[imported] ?? imported;\n const text = `definePreview({ ${server.join(', ')} }).${method}${generic}({ ${read.join(', ')} })`;\n const droppedNote = dropped.length === 0 ? '' : `, and ${dropped.join('/')} was dropped`;\n const line = call.getStartLineNumber();\n const done = conflict(\n line,\n `${imported}() was rewritten onto definePreview().${method}(); it now returns a ` +\n `PreviewFetchResult (check ok/data) and needs a real authorization for drafts${droppedNote}`,\n );\n const advice: CodemodConflict[] = [];\n if (unplaceable.length > 0) {\n advice.push(\n conflict(\n line,\n `${imported}() was passed ${unplaceable.map((key) => `\\`${key}\\``).join(', ')}, which ` +\n `.${method}() does not accept; it takes ${accepted.join(', ')}. The key was carried ` +\n 'over unchanged and will not compile — place it by hand',\n ),\n );\n }\n return { edit: { start: call.getStart(), end: call.getEnd(), text }, done, advice };\n}\n\nfunction importLine(quote: string, names: readonly string[], specifier: string): string {\n return `import { ${names.join(', ')} } from ${quote}${specifier}${quote};`;\n}\n\n/** Drop the moved names from their root imports and make sure `definePreview` is imported from the server entry. */\nfunction rewriteImports(script: SourceFile, bindings: readonly PackageBinding[]): TextEdit[] {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const declarations = new Set<ImportDeclaration>();\n for (const binding of bindings) {\n if (Node.isImportDeclaration(binding.declaration)) declarations.add(binding.declaration);\n }\n const serverImport = script\n .getImportDeclarations()\n .find(\n (declaration) =>\n declaration.getModuleSpecifierValue() === SERVER_SPECIFIER && !declaration.isTypeOnly(),\n );\n const hasDefinePreview =\n serverImport?.getNamedImports().some((spec) => spec.getName() === 'definePreview') === true;\n let serverLine: string | undefined;\n if (serverImport !== undefined && !hasDefinePreview) {\n const quote = serverImport.getModuleSpecifier().getQuoteKind();\n const names = [\n ...serverImport.getNamedImports().map((spec) => spec.getText()),\n 'definePreview',\n ];\n const defaultImport = serverImport.getDefaultImport()?.getText();\n const clauses =\n defaultImport === undefined ? names.join(', ') : `${defaultImport}, { ${names.join(', ')} }`;\n const text =\n defaultImport === undefined\n ? importLine(quote, names, SERVER_SPECIFIER)\n : `import ${clauses} from ${quote}${SERVER_SPECIFIER}${quote};`;\n edits.push({ start: serverImport.getStart(), end: serverImport.getEnd(), text });\n }\n for (const declaration of declarations) {\n const quote = declaration.getModuleSpecifier().getQuoteKind();\n const remaining = declaration\n .getNamedImports()\n .filter((spec) => !(spec.getName() in METHOD))\n .map((spec) => spec.getText());\n const defaultImport = declaration.getDefaultImport()?.getText();\n const clauses = [\n defaultImport,\n remaining.length === 0 ? undefined : `{ ${remaining.join(', ')} }`,\n ].filter((clause): clause is string => clause !== undefined);\n const typeOnly = declaration.isTypeOnly() ? 'type ' : '';\n const kept =\n clauses.length === 0\n ? ''\n : `import ${typeOnly}${clauses.join(', ')} from ${quote}${PACKAGE_NAME}${quote};`;\n if (serverImport === undefined && serverLine === undefined) {\n serverLine = importLine(quote, ['definePreview'], SERVER_SPECIFIER);\n edits.push({\n start: declaration.getStart(),\n end: declaration.getEnd(),\n text: kept === '' ? serverLine : `${kept}\\n${serverLine}`,\n });\n } else {\n // A removed declaration takes its line break with it.\n const end = declaration.getEnd();\n const trailingNewline = kept === '' && script.getFullText()[end] === '\\n' ? 1 : 0;\n edits.push({ start: declaration.getStart(), end: end + trailingNewline, text: kept });\n }\n }\n return edits;\n}\n\nfunction plan(\n script: SourceFile,\n bindings: readonly PackageBinding[],\n reexports: readonly PackageReexport[],\n): CodemodPlan {\n const { Node } = loadTsMorph();\n const blocking: CodemodConflict[] = reexports.map((reexport) =>\n conflict(\n reexport.line,\n `${reexport.imported} is re-exported straight from the package; it became ` +\n `definePreview().${METHOD[reexport.imported] ?? reexport.imported}() on ${SERVER_SPECIFIER}, ` +\n 'so rewrite the re-export and its importers by hand',\n ),\n );\n const notes: CodemodConflict[] = [];\n const advice: CodemodConflict[] = [];\n const edits: TextEdit[] = [];\n for (const binding of bindings) {\n if (binding.kind === 'require') {\n blocking.push(\n conflict(\n binding.declaration.getStartLineNumber(),\n `${binding.imported} is bound with require(); rewrite it onto definePreview() from ` +\n `${SERVER_SPECIFIER} by hand`,\n ),\n );\n continue;\n }\n for (const reference of referencesTo(script, binding)) {\n const line = reference.node.getStartLineNumber();\n const call = reference.node.getParent();\n const isCall =\n reference.kind === 'reference' &&\n Node.isCallExpression(call) &&\n call.getExpression() === reference.node;\n if (!isCall) {\n blocking.push(\n conflict(\n line,\n `${binding.local} is used other than as a direct call; rewrite it onto definePreview() by hand`,\n ),\n );\n continue;\n }\n const [options] = call.getArguments();\n if (\n options === undefined ||\n !Node.isObjectLiteralExpression(options) ||\n options.getProperties().some((property) => Node.isSpreadAssignment(property))\n ) {\n blocking.push(\n conflict(\n line,\n `${binding.imported}() options are not a plain object literal, so serverURL/depth ` +\n 'cannot be split out; rewrite it onto definePreview() by hand',\n ),\n );\n continue;\n }\n const rewritten = rewriteCall(call, options, binding.imported);\n edits.push(rewritten.edit);\n notes.push(rewritten.done, ...rewritten.advice);\n advice.push(...rewritten.advice);\n }\n }\n const serverDeclaration = script\n .getImportDeclarations()\n .filter((declaration) => declaration.getModuleSpecifierValue() === SERVER_SPECIFIER);\n const foreign = declaresName(script, 'definePreview', serverDeclaration);\n if (foreign !== undefined) {\n blocking.push(\n conflict(\n foreign.getStartLineNumber(),\n `this module already binds a definePreview that is not ${SERVER_SPECIFIER}'s; rename it, ` +\n 'then move the fetch helpers by hand',\n ),\n );\n }\n // A held-back file was not rewritten, so \"was rewritten\" would say the opposite; the advice still holds.\n if (blocking.length > 0) return { edits: [], conflicts: [...blocking, ...advice] };\n edits.push(...rewriteImports(script, bindings));\n return { edits, conflicts: notes };\n}\n\nexport const moveFetchPreviewHelpers: CodemodImplementation = {\n id: ID,\n summary:\n '`fetchPreviewDocument`/`fetchPreviewGlobal` from the root → `definePreview().fetchDocument`/`.fetchGlobal` (payload-live-preview/server)',\n ledgerEntry: 9,\n apply(script) {\n const bindings = packageBindings(script).filter(\n (binding) => binding.specifier === PACKAGE_NAME && binding.imported in METHOD,\n );\n const reexports = packageReexports(script).filter(\n (reexport) => reexport.specifier === PACKAGE_NAME && reexport.imported in METHOD,\n );\n if (bindings.length === 0 && reexports.length === 0) return { edits: [], conflicts: [] };\n return plan(script, bindings, reexports);\n },\n};\n","/** Ledger entry 13: `hasPreviewIntent(request, { adminOrigins })` → `{ allowedOrigins }`. */\nimport { loadTsMorph, packageBindings, propertyKey, referencesTo, replaceNode } from '../ast';\nimport type { CodemodImplementation, CodemodConflict, TextEdit } from '../types';\n\nconst ID = 'rename-admin-origins-option';\nconst CALLEE = 'hasPreviewIntent';\nconst OLD_KEY = 'adminOrigins';\nconst NEW_KEY = 'allowedOrigins';\nconst BY_HAND = `if they carry \\`${OLD_KEY}\\`, rename it to \\`${NEW_KEY}\\``;\n\nexport const renameAdminOriginsOption: CodemodImplementation = {\n id: ID,\n summary: '`hasPreviewIntent(request, { adminOrigins })` → `{ allowedOrigins }`',\n ledgerEntry: 13,\n apply(script) {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const conflicts: CodemodConflict[] = [];\n const bindings = packageBindings(script).filter((binding) => binding.imported === CALLEE);\n for (const binding of bindings) {\n for (const reference of referencesTo(script, binding)) {\n const call = reference.node.getParent();\n if (reference.kind !== 'reference' || !Node.isCallExpression(call)) continue;\n if (call.getExpression() !== reference.node) continue;\n const options = call.getArguments()[1];\n if (options === undefined) continue;\n const line = options.getStartLineNumber();\n if (!Node.isObjectLiteralExpression(options)) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `${CALLEE}() options are not a literal; ${BY_HAND}`,\n });\n continue;\n }\n const properties = options.getProperties();\n const keys = properties.map((property) => propertyKey(property));\n // With both names the package reads `allowedOrigins` and ignores the\n // alias; renamed, the later key would win instead.\n if (keys.includes(OLD_KEY) && keys.includes(NEW_KEY)) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `${CALLEE}() is given both ${OLD_KEY} and ${NEW_KEY}; ${NEW_KEY} wins, drop ${OLD_KEY} by hand`,\n });\n continue;\n }\n for (const property of properties) {\n if (Node.isSpreadAssignment(property)) {\n conflicts.push({\n codemod: ID,\n line: property.getStartLineNumber(),\n reason: `${CALLEE}() spreads its options; ${BY_HAND}`,\n });\n } else if (propertyKey(property) !== OLD_KEY) {\n continue;\n } else if (Node.isShorthandPropertyAssignment(property)) {\n edits.push(replaceNode(property, `${NEW_KEY}: ${OLD_KEY}`));\n } else if (Node.isPropertyAssignment(property)) {\n edits.push(replaceNode(property.getNameNode(), NEW_KEY));\n }\n }\n }\n }\n return { edits, conflicts };\n },\n};\n","/** Ledger entry 7: `createPreviewBindings({ authorized })` → `{ authorization }`. */\nimport { loadTsMorph, packageBindings, propertyKey, referencesTo, replaceNode } from '../ast';\nimport type { CodemodImplementation, CodemodConflict, TextEdit } from '../types';\n\nconst ID = 'rename-bindings-authorized-option';\nconst OLD_KEY = 'authorized';\nconst NEW_KEY = 'authorization';\nconst BY_HAND =\n `if they carry \\`${OLD_KEY}\\`, rename it to \\`${NEW_KEY}\\` and pass the verdict from ` +\n 'authorizePreviewRequest()';\n/**\n * `false` has an exact equivalent — an unauthorized response suppresses every\n * binding, which is what `null` means — so it is rewritten. Nothing else does:\n * only a real context from `authorizePreviewRequest()` authorizes emission, and\n * a boolean left under the new name does not compile (TS2322).\n */\nconst BOOLEAN_REFUSED =\n `\\`${NEW_KEY}\\` takes the context from authorizePreviewRequest(); the boolean 1.x ` +\n 'accepted is not. The key was renamed and its value left as it stands — pass the ' +\n 'verdict, or `null` for a public response';\n\nexport const renameBindingsAuthorizedOption: CodemodImplementation = {\n id: ID,\n summary: '`createPreviewBindings({ authorized })` → `{ authorization }`',\n ledgerEntry: 7,\n apply(script) {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const conflicts: CodemodConflict[] = [];\n const bindings = packageBindings(script).filter(\n (binding) => binding.imported === 'createPreviewBindings',\n );\n for (const binding of bindings) {\n for (const reference of referencesTo(script, binding)) {\n const call = reference.node.getParent();\n if (reference.kind !== 'reference' || !Node.isCallExpression(call)) continue;\n if (call.getExpression() !== reference.node) continue;\n const [options] = call.getArguments();\n if (options === undefined) continue;\n const line = options.getStartLineNumber();\n if (!Node.isObjectLiteralExpression(options)) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `createPreviewBindings() options are not a literal; ${BY_HAND}`,\n });\n continue;\n }\n for (const property of options.getProperties()) {\n if (Node.isSpreadAssignment(property)) {\n conflicts.push({\n codemod: ID,\n line: property.getStartLineNumber(),\n reason: `createPreviewBindings() spreads its options; ${BY_HAND}`,\n });\n } else if (propertyKey(property) !== OLD_KEY) {\n continue;\n } else if (Node.isShorthandPropertyAssignment(property)) {\n edits.push(replaceNode(property, `${NEW_KEY}: ${OLD_KEY}`));\n conflicts.push({\n codemod: ID,\n line: property.getStartLineNumber(),\n reason: BOOLEAN_REFUSED,\n });\n } else if (Node.isPropertyAssignment(property)) {\n const value = property.getInitializer();\n if (value !== undefined && Node.isFalseLiteral(value)) {\n edits.push(replaceNode(property, `${NEW_KEY}: null`));\n continue;\n }\n edits.push(replaceNode(property.getNameNode(), NEW_KEY));\n conflicts.push({\n codemod: ID,\n line: property.getStartLineNumber(),\n reason: BOOLEAN_REFUSED,\n });\n }\n }\n }\n }\n return { edits, conflicts };\n },\n};\n","/** Ledger entry 1: `isPreviewRequest()` → `hasPreviewIntent()`, same signature. */\nimport {\n declaresName,\n memberAccesses,\n packageBindings,\n packageReexports,\n referencesTo,\n replaceNode,\n type PackageBinding,\n type PackageReexport,\n} from '../ast';\nimport type { CodemodImplementation, CodemodConflict, CodemodPlan, TextEdit } from '../types';\n\nconst ID = 'rename-is-preview-request';\nconst OLD_NAME = 'isPreviewRequest';\nconst NEW_NAME = 'hasPreviewIntent';\n\nfunction conflict(line: number, reason: string): CodemodConflict {\n return { codemod: ID, reason, line };\n}\n\nfunction renameBinding(binding: PackageBinding): TextEdit {\n // `import { isPreviewRequest as hasPreviewIntent }` collapses to the bare name.\n if (binding.aliased && binding.local === NEW_NAME) {\n return replaceNode(binding.importedNode.getParentOrThrow(), NEW_NAME);\n }\n return replaceNode(binding.importedNode, NEW_NAME);\n}\n\nfunction plan(\n bindings: readonly PackageBinding[],\n reexports: readonly PackageReexport[],\n script: Parameters<CodemodImplementation['apply']>[0],\n): CodemodPlan {\n const blocking: CodemodConflict[] = [];\n const edits: TextEdit[] = [];\n for (const reexport of reexports) {\n if (reexport.alias === undefined) {\n // Renaming it would rename this module's export too; its importers decide.\n blocking.push(\n conflict(\n reexport.line,\n `${OLD_NAME} is re-exported straight from the package under its old name; write ` +\n `export { ${NEW_NAME} as ${OLD_NAME} } from '${reexport.specifier}', or rename it and its importers by hand`,\n ),\n );\n } else if (reexport.alias === NEW_NAME) {\n edits.push(replaceNode(reexport.importedNode.getParentOrThrow(), NEW_NAME));\n } else {\n edits.push(replaceNode(reexport.importedNode, NEW_NAME));\n }\n }\n const existing = declaresName(\n script,\n NEW_NAME,\n bindings.map((binding) => binding.declaration),\n );\n if (existing !== undefined) {\n blocking.push(\n conflict(\n existing.getStartLineNumber(),\n `this module already binds ${NEW_NAME}; rename it (or drop the wrapper and import the ` +\n `package's ${NEW_NAME} directly), then rename ${OLD_NAME} by hand`,\n ),\n );\n }\n for (const binding of bindings) {\n edits.push(renameBinding(binding));\n if (binding.aliased) continue;\n for (const reference of referencesTo(script, binding)) {\n if (reference.kind === 'reference') {\n edits.push(replaceNode(reference.node, NEW_NAME));\n } else if (reference.kind === 'shorthand') {\n blocking.push(\n conflict(\n reference.node.getStartLineNumber(),\n `{ ${OLD_NAME} } keeps the old key for whoever reads it; write ` +\n `{ ${OLD_NAME}: ${NEW_NAME} } or rename the key and its readers by hand`,\n ),\n );\n } else {\n blocking.push(\n conflict(\n reference.node.getStartLineNumber(),\n `${OLD_NAME} is re-exported under its old name; rename the export and its ` +\n `importers, or write export { ${NEW_NAME} as ${OLD_NAME} }`,\n ),\n );\n }\n }\n }\n const notes = memberAccesses(script, OLD_NAME).map((node) =>\n conflict(\n node.getStartLineNumber(),\n `.${OLD_NAME} is a member of this module's own object, not the package import, and was ` +\n 'left alone; check that it does not wrap the removed API',\n ),\n );\n if (blocking.length > 0) return { edits: [], conflicts: [...blocking, ...notes] };\n return { edits, conflicts: notes };\n}\n\nexport const renameIsPreviewRequest: CodemodImplementation = {\n id: ID,\n summary: '`isPreviewRequest()` → `hasPreviewIntent()` (same signature)',\n ledgerEntry: 1,\n // The rename keeps behaviour, and that is the part worth saying: the 2.0\n // adapters count only the query, and a renamed call silently does not.\n notice:\n 'hasPreviewIntent() takes the options isPreviewRequest() took and, without `signals`, counts ' +\n 'the same three: a preview query parameter, Sec-Fetch-Dest: iframe and an admin Referer. The ' +\n \"2.0 adapters count only the query; where a call should agree with them, pass { signals: ['query'] } \" +\n '(docs/migration.md).',\n apply(script) {\n const bindings = packageBindings(script).filter((binding) => binding.imported === OLD_NAME);\n const reexports = packageReexports(script).filter((reexport) => reexport.imported === OLD_NAME);\n if (bindings.length === 0 && reexports.length === 0) return { edits: [], conflicts: [] };\n return plan(bindings, reexports, script);\n },\n};\n","/** Ledger entry 19: `onUnboundChange: 'route' | 'ignore'` → `onUnfaithfulPatch: 'escalate' | 'ignore'`. */\nimport { loadTsMorph, replaceNode } from '../ast';\nimport { memberNamed, optionLiterals, packageJsxAttributes } from '../option-literals';\nimport type { CodemodImplementation, CodemodConflict, TextEdit } from '../types';\n\nconst ID = 'rename-on-unbound-change';\nconst OLD_KEY = 'onUnboundChange';\nconst NEW_KEY = 'onUnfaithfulPatch';\nconst RENAMED: Readonly<Record<string, string>> = { route: 'escalate', ignore: 'ignore' };\n\nexport const renameOnUnboundChange: CodemodImplementation = {\n id: ID,\n summary: \"`onUnboundChange: 'route'` → `onUnfaithfulPatch: 'escalate'`\",\n ledgerEntry: 19,\n apply(script) {\n const { Node } = loadTsMorph();\n const edits: TextEdit[] = [];\n const conflicts: CodemodConflict[] = [];\n for (const [literal, uses] of optionLiterals(script)) {\n const property = memberNamed(literal, OLD_KEY);\n if (property === undefined) continue;\n const line = property.getStartLineNumber();\n // The package reads the new name first; renamed, the later key would win instead.\n const both = [literal, ...uses.map((use) => use.outer)].some(\n (candidate) => memberNamed(candidate, NEW_KEY) !== undefined,\n );\n if (both) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `both ${OLD_KEY} and ${NEW_KEY} are given; ${NEW_KEY} wins, drop ${OLD_KEY} by hand`,\n });\n continue;\n }\n const value = Node.isPropertyAssignment(property) ? property.getInitializer() : undefined;\n const text = value !== undefined && Node.isStringLiteral(value) ? value.getLiteralText() : '';\n const renamed = RENAMED[text];\n if (value === undefined || renamed === undefined) {\n conflicts.push({\n codemod: ID,\n line,\n reason: `${OLD_KEY} is not a literal 'route' or 'ignore'; rename it to ${NEW_KEY} by hand ('route' is 'escalate')`,\n });\n continue;\n }\n const quote = value.getText().charAt(0);\n edits.push(replaceNode(property, `${NEW_KEY}: ${quote}${renamed}${quote}`));\n }\n for (const attribute of packageJsxAttributes(script, OLD_KEY)) {\n conflicts.push({\n codemod: ID,\n line: attribute.getStartLineNumber(),\n reason: `a JSX attribute; rename ${OLD_KEY} to ${NEW_KEY} by hand ('route' is 'escalate')`,\n });\n }\n return { edits, conflicts };\n },\n};\n","/** Where the script lives in a file: the whole file, or the script blocks of a component. */\nimport { extname } from 'node:path';\nimport type { ScriptKind } from './ast';\n\nexport interface ScriptBlock {\n readonly start: number;\n readonly end: number;\n readonly kind: ScriptKind;\n}\n\nconst WHOLE_FILE: Readonly<Record<string, ScriptKind>> = {\n '.ts': 'ts',\n '.mts': 'ts',\n '.cts': 'ts',\n '.tsx': 'tsx',\n '.js': 'js',\n '.mjs': 'js',\n '.cjs': 'js',\n '.jsx': 'jsx',\n};\nconst COMPONENT_EXTENSIONS = new Set(['.astro', '.vue', '.svelte']);\nconst FRONTMATTER = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/u;\n// Browsers close a script on `</script` followed by anything up to `>`, so the\n// end tag must accept that too, or a stray `</script foo>` would swallow the\n// rest of the file into one block.\nconst SCRIPT_TAG = /<script(?:\\s[^>]*)?>([\\s\\S]*?)<\\/script\\b[^>]*>/giu;\n\nexport function scriptBlocks(source: string, fileName: string): readonly ScriptBlock[] {\n const extension = extname(fileName).toLowerCase();\n if (!COMPONENT_EXTENSIONS.has(extension)) {\n return [{ start: 0, end: source.length, kind: WHOLE_FILE[extension] ?? 'ts' }];\n }\n const blocks: ScriptBlock[] = [];\n const frontmatter = extension === '.astro' ? FRONTMATTER.exec(source) : null;\n if (frontmatter?.[1] !== undefined) {\n const start = frontmatter.index + frontmatter[0].indexOf('\\n') + 1;\n blocks.push({ start, end: start + frontmatter[1].length, kind: 'ts' });\n }\n for (const match of source.matchAll(SCRIPT_TAG)) {\n const body = match[1] ?? '';\n if (body.trim() === '') continue;\n const start = match.index + match[0].lastIndexOf(body);\n blocks.push({ start, end: start + body.length, kind: 'ts' });\n }\n return blocks;\n}\n","/**\n * `pll migrate`: the 1.x → 2.0 codemods and the driver that applies them to one\n * source string. Rewrites are planned on the AST (ts-morph) so only names the\n * package binds are touched; see ADR 0007.\n */\nimport { applyTextEdits, parseScript } from './ast';\nimport { expandDefaultsV1 } from './codemods/expand-defaults-v1';\nimport { moveFetchPreviewHelpers } from './codemods/move-fetch-preview-helpers';\nimport { renameAdminOriginsOption } from './codemods/rename-admin-origins-option';\nimport { renameBindingsAuthorizedOption } from './codemods/rename-bindings-authorized-option';\nimport { renameIsPreviewRequest } from './codemods/rename-is-preview-request';\nimport { renameOnUnboundChange } from './codemods/rename-on-unbound-change';\nimport { scriptBlocks } from './script-blocks';\nimport type {\n Codemod,\n CodemodConflict,\n CodemodEdit,\n CodemodImplementation,\n CodemodLineEdit,\n} from './types';\n\nexport type {\n Codemod,\n CodemodConflict,\n CodemodEdit,\n CodemodLineEdit,\n CodemodPlan,\n TextEdit,\n} from './types';\n\nconst PACKAGE_REFERENCE =\n /(?:\\bfrom\\s*|\\bimport\\s*\\(?\\s*|\\brequire\\s*\\(\\s*)['\"]payload-live-preview(?:\\/[^'\"]*)?['\"]/u;\n\n/** Whether the source names the package in an `import`, `import()` or `require()`. @internal */\nexport function importsThisPackage(source: string): boolean {\n return PACKAGE_REFERENCE.test(source);\n}\n\n// The option rename follows the function rename so it sees the new binding.\nconst IMPLEMENTATIONS: readonly CodemodImplementation[] = [\n renameIsPreviewRequest,\n renameAdminOriginsOption,\n renameBindingsAuthorizedOption,\n moveFetchPreviewHelpers,\n renameOnUnboundChange,\n expandDefaultsV1,\n];\n\n/**\n * The codemods in the order they run. Each is idempotent. Metadata only: the\n * rewrite is internal, so importing this entry's types does not require\n * `ts-morph`, which is needed only to run `pll migrate`.\n * @internal\n */\nexport const CODEMODS: readonly Codemod[] = IMPLEMENTATIONS;\n\nexport interface MigrateSourceOptions {\n /** Restrict to these codemod ids. */\n readonly only?: readonly string[];\n /**\n * Decides how the source is parsed: `.astro`, `.vue` and `.svelte` by script\n * block, JSX by extension. Defaults to a `.ts` module.\n */\n readonly fileName?: string;\n}\n\nexport interface MigrateSourceResult {\n readonly output: string;\n readonly edits: readonly CodemodEdit[];\n readonly conflicts: readonly CodemodConflict[];\n}\n\nfunction lineNumberAt(source: string, offset: number): number {\n let line = 1;\n for (let index = 0; index < offset; index += 1) if (source[index] === '\\n') line += 1;\n return line;\n}\n\n/** The changed lines between two versions, trimmed to the differing middle. */\nfunction lineEdits(before: string, after: string, firstLine: number): CodemodLineEdit[] {\n const oldLines = before.split('\\n');\n const newLines = after.split('\\n');\n let prefix = 0;\n while (\n prefix < oldLines.length &&\n prefix < newLines.length &&\n oldLines[prefix] === newLines[prefix]\n ) {\n prefix += 1;\n }\n let suffix = 0;\n while (\n suffix < oldLines.length - prefix &&\n suffix < newLines.length - prefix &&\n oldLines[oldLines.length - 1 - suffix] === newLines[newLines.length - 1 - suffix]\n ) {\n suffix += 1;\n }\n const oldMiddle = oldLines.slice(prefix, oldLines.length - suffix);\n const newMiddle = newLines.slice(prefix, newLines.length - suffix);\n const changed: CodemodLineEdit[] = [];\n for (let index = 0; index < Math.max(oldMiddle.length, newMiddle.length); index += 1) {\n const before = oldMiddle[index] ?? '';\n const after = newMiddle[index] ?? '';\n if (before !== after) changed.push({ line: firstLine + prefix + index, before, after });\n }\n return changed;\n}\n\n/** Apply every codemod (or the chosen subset) to one source string. */\nexport function migrateSource(\n source: string,\n options: MigrateSourceOptions = {},\n): MigrateSourceResult {\n const chosen =\n options.only === undefined\n ? IMPLEMENTATIONS\n : IMPLEMENTATIONS.filter((codemod) => options.only?.includes(codemod.id));\n if (chosen.length === 0 || !importsThisPackage(source)) {\n return { output: source, edits: [], conflicts: [] };\n }\n const byCodemod = new Map<string, CodemodLineEdit[]>();\n const conflicts: CodemodConflict[] = [];\n let output = '';\n let cursor = 0;\n for (const block of scriptBlocks(source, options.fileName ?? 'source.ts')) {\n output += source.slice(cursor, block.start);\n const firstLine = lineNumberAt(source, block.start);\n let text = source.slice(block.start, block.end);\n for (const codemod of chosen) {\n const plan = codemod.apply(parseScript(text, block.kind));\n for (const item of plan.conflicts) {\n conflicts.push(\n item.line === undefined ? item : { ...item, line: item.line + firstLine - 1 },\n );\n }\n if (plan.edits.length === 0) continue;\n const next = applyTextEdits(text, plan.edits);\n const lines = byCodemod.get(codemod.id) ?? [];\n lines.push(...lineEdits(text, next, firstLine));\n byCodemod.set(codemod.id, lines);\n text = next;\n }\n output += text;\n cursor = block.end;\n }\n output += source.slice(cursor);\n const edits = [...byCodemod].map(([codemod, lines]) => ({ codemod, count: lines.length, lines }));\n return { output, edits, conflicts };\n}\n","/** The file walker behind `pll migrate`: find source files, apply the codemods, report or write. */\nimport { readFile, readdir, stat, writeFile } from 'node:fs/promises';\nimport { extname, join, relative } from 'node:path';\nimport { migrateSource } from './index';\nimport type { CodemodConflict, CodemodEdit } from './types';\n\nconst SOURCE_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.mts',\n '.cts',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.astro',\n '.svelte',\n '.vue',\n]);\nconst DECLARATION_FILE = /\\.d\\.[cm]?ts$/u;\nconst SKIP_DIRECTORIES = new Set([\n 'node_modules',\n 'dist',\n '.git',\n '.astro',\n '.svelte-kit',\n '.next',\n '.nuxt',\n 'coverage',\n]);\n\nexport interface MigrateFileResult {\n readonly file: string;\n readonly edits: readonly CodemodEdit[];\n readonly changed: boolean;\n /** What a codemod could not rewrite safely in this file. */\n readonly conflicts: readonly CodemodConflict[];\n}\n\nexport interface MigrateRunResult {\n readonly files: readonly MigrateFileResult[];\n /** Files the run changed (or would change, in dry-run). */\n readonly changedCount: number;\n /** Codemod id → number of files it touched. */\n readonly byCodemod: Readonly<Record<string, number>>;\n /** Files needing manual attention. */\n readonly conflictCount: number;\n}\n\nexport interface MigrateOptions {\n /** Apply and save; without it the run only reports. */\n readonly write?: boolean;\n /** Restrict to these codemod ids. */\n readonly only?: readonly string[];\n /** Reader/writer injection for tests. */\n readonly io?: {\n readonly read: (path: string) => Promise<string>;\n readonly write: (path: string, content: string) => Promise<void>;\n readonly list: (root: string) => Promise<readonly string[]>;\n };\n}\n\nfunction isSourceFile(name: string): boolean {\n return SOURCE_EXTENSIONS.has(extname(name)) && !DECLARATION_FILE.test(name);\n}\n\nasync function collectFiles(root: string): Promise<string[]> {\n const found: string[] = [];\n async function walk(directory: string): Promise<void> {\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) {\n if (!SKIP_DIRECTORIES.has(entry.name)) await walk(path);\n } else if (isSourceFile(entry.name)) {\n found.push(path);\n }\n }\n }\n const info = await stat(root);\n if (info.isDirectory()) await walk(root);\n else if (isSourceFile(root)) found.push(root);\n return found.sort();\n}\n\nfunction relativeTo(root: string, file: string): string {\n const rel = relative(root, file);\n return rel.length === 0 ? file : rel;\n}\n\n/** Migrate every source file under `root`. */\nexport async function runMigrate(\n root: string,\n options: MigrateOptions = {},\n): Promise<MigrateRunResult> {\n const io = options.io ?? {\n read: (path) => readFile(path, 'utf8'),\n write: (path, content) => writeFile(path, content, 'utf8'),\n list: collectFiles,\n };\n const results: MigrateFileResult[] = [];\n const byCodemod: Record<string, number> = {};\n for (const file of await io.list(root)) {\n const source = await io.read(file);\n const { output, edits, conflicts } = migrateSource(source, {\n fileName: file,\n ...(options.only === undefined ? {} : { only: options.only }),\n });\n const changed = output !== source;\n if (changed && options.write === true) await io.write(file, output);\n if (changed) {\n for (const edit of edits) byCodemod[edit.codemod] = (byCodemod[edit.codemod] ?? 0) + 1;\n }\n results.push({ file: relativeTo(root, file), edits, changed, conflicts });\n }\n return {\n files: results,\n changedCount: results.filter((result) => result.changed).length,\n byCodemod,\n conflictCount: results.filter((result) => result.conflicts.length > 0).length,\n };\n}\n","/**\n * `pll migrate <path> [--write] [--only <id,id>]`, hosted by the `pll` binary.\n * Exit codes: 0 clean, 1 usage or I/O error, 3 when conflicts need a human.\n */\nimport { CODEMODS } from './index';\nimport { runMigrate, type MigrateFileResult } from './runner';\n\nexport const MIGRATE_HELP = `pll migrate — rewrite 1.x APIs to their 2.0 names and homes (ADR 0007)\n\nUsage:\n pll migrate <path> [--write] [--only <id,id>]\n\nWithout --write the run only reports what it would change. Codemods touch\nonly names bound from payload-live-preview; anything they cannot rewrite\nsafely is listed as needing manual attention. Requires ts-morph.\n\nOptions:\n --write Apply the changes (otherwise dry-run)\n --only <ids> Run only these codemods (comma-separated); an id not\n listed below runs nothing\n -h, --help Show this help\n\nCodemods, in the order they run:\n${CODEMODS.map((codemod) => ` ${codemod.id}`).join('\\n')}\n\nExit codes:\n 0 nothing needs a human (changes applied, or would be with --write)\n 1 usage error, unreadable path, or ts-morph is not installed\n 3 at least one file needs manual attention\n`;\n\ninterface MigrateArgs {\n readonly target: string | undefined;\n readonly write: boolean;\n readonly only: readonly string[] | undefined;\n readonly help: boolean;\n readonly unknown: string | undefined;\n}\n\nfunction parseArgs(argv: readonly string[]): MigrateArgs {\n let target: string | undefined;\n let write = false;\n let only: string[] | undefined;\n let help = false;\n let unknown: string | undefined;\n const ids = (value: string): string[] => value.split(',').filter((id) => id.length > 0);\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index];\n if (token === undefined) continue;\n if (token === '-h' || token === '--help') help = true;\n else if (token === '--write') write = true;\n else if (token === '--only') {\n only = ids(argv[index + 1] ?? '');\n index += 1;\n } else if (token.startsWith('--only=')) only = ids(token.slice('--only='.length));\n else if (token.startsWith('-')) unknown ??= token;\n else target ??= token;\n }\n return { target, write, only, help, unknown };\n}\n\nfunction describe(file: MigrateFileResult): string {\n return file.edits.map((edit) => `${edit.codemod}: ${String(edit.count)} line(s)`).join(', ');\n}\n\nexport async function runMigrateCommand(argv: readonly string[]): Promise<number> {\n const args = parseArgs(argv);\n if (args.help) {\n process.stdout.write(MIGRATE_HELP);\n return 0;\n }\n if (args.unknown !== undefined) {\n process.stderr.write(`pll migrate: unknown option ${args.unknown}\\n`);\n return 1;\n }\n if (args.target === undefined) {\n process.stderr.write('pll migrate: a path is required. Try `pll migrate --help`.\\n');\n return 1;\n }\n let result;\n try {\n result = await runMigrate(args.target, {\n write: args.write,\n ...(args.only === undefined ? {} : { only: args.only }),\n });\n } catch (error) {\n process.stderr.write(\n `pll migrate: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n return 1;\n }\n for (const file of result.files) {\n if (!file.changed) continue;\n process.stdout.write(\n `${args.write ? 'migrated' : 'would migrate'} ${file.file} (${describe(file)})\\n`,\n );\n }\n process.stdout.write(\n `\\n${args.write ? 'Migrated' : 'Would migrate'} ${String(result.changedCount)} file(s).` +\n `${args.write ? '' : ' Re-run with --write to apply.'}\\n`,\n );\n for (const { id, notice } of CODEMODS) {\n if (notice !== undefined && (result.byCodemod[id] ?? 0) > 0) {\n process.stdout.write(`\\nNote (${id}): ${notice}\\n`);\n }\n }\n const conflicted = result.files.filter((file) => file.conflicts.length > 0);\n if (conflicted.length === 0) return 0;\n process.stdout.write(`\\n${String(conflicted.length)} file(s) need manual attention:\\n`);\n for (const file of conflicted) {\n for (const item of file.conflicts) {\n const where = item.line === undefined ? file.file : `${file.file}:${String(item.line)}`;\n process.stdout.write(` ${where}: ${item.reason}\\n`);\n }\n }\n return 3;\n}\n","/** Terminal rendering of a doctor report. */\nimport type { DoctorReport } from './types';\n\nconst LEVEL_LABEL = { error: 'ERROR', warning: 'WARN ', info: 'INFO ' } as const;\n\n/** @internal */\nexport function formatReport(report: DoctorReport): string {\n const lines: string[] = [`pll doctor — ${report.url}`, ''];\n if (report.findings.length === 0) {\n lines.push('No findings. The preview response carries the runtime, a frame-ancestors');\n lines.push('policy, and bindings; the public response carries none of them.', '');\n return lines.join('\\n');\n }\n for (const finding of report.findings) {\n lines.push(`${LEVEL_LABEL[finding.level]} ${finding.code} ${finding.title}`);\n lines.push(` ${finding.detail}`);\n if (finding.remedy !== '') lines.push(` → ${finding.remedy}`);\n lines.push('');\n }\n lines.push(`${String(report.errors)} error(s), ${String(report.warnings)} warning(s).`, '');\n return lines.join('\\n');\n}\n","/**\n * Every diagnostic code the runtime and tools emit, so a consumer can branch\n * on `e.code` instead of matching message text. A code is never reused for a\n * different meaning; a retired one stays reserved.\n *\n * Browser-side reporting sites write the literal (`code: 'LP0603'`) rather than\n * reading it from this record: the frozen table would then ship in the inline\n * runtime for the sake of six characters — it did, 1 287 B in every page, for\n * the one read Z6 left in the strategy runner, and `diagnostic-codes.test.ts`\n * now holds the artifact free of it. Server-side tools may import it.\n */\n\n/**\n * Every diagnostic code the runtime can report, by name.\n *\n * ```ts\n * client.events.on('error', (e) => {\n * if (e.code === DIAGNOSTIC_CODES.TransformThrew) reportToSentry(e.error);\n * });\n * ```\n */\nexport const DIAGNOSTIC_CODES = Object.freeze({\n /** No trusted origin configured in production; nothing will be accepted. */\n NoTrustedOrigin: 'LP0101',\n /** Origin trust rests on `document.referrer`, so any framing site is trusted. */\n ReferrerOnlyTrust: 'LP0102',\n /** A plugin declares a runtime range this runtime does not satisfy; it was refused. */\n PluginIncompatible: 'LP0103',\n /** The page carries the lean runtime and needs a feature that profile leaves out. */\n ProfileFeatureOmitted: 'LP0104',\n\n /** An update named an empty field with no binding anchor on the page; an edit to it has nowhere to land. */\n OrphanField: 'LP0201',\n /** Owner scoping is on and the update names no document it could belong to. */\n UnattributableUpdate: 'LP0202',\n /** An update carried a value for a field the page binds nowhere; editing it changes nothing on this page. */\n UnboundField: 'LP0203',\n /** In development: a bound path covers its group under the `descendant` default, which 3.0 changes. */\n CoverageDefaultChanges: 'LP0204',\n\n /** The visibility gate held offscreen writes back until they scroll into view. */\n VisibilityGateDeferred: 'LP0301',\n\n /** A value was refused because the attribute or the value itself is unsafe. */\n UnsafeAttributeWrite: 'LP0401',\n /** A text element has structured children, so replacing its text was skipped. */\n TextTargetHasChildren: 'LP0402',\n /** A structural container has no array template, so the update was skipped. */\n MissingArrayTemplate: 'LP0403',\n /** A structural item has no `id`; it pairs positionally, so an insert re-renders every row after it. */\n StructuralItemUnkeyed: 'LP0404',\n /** Two structural items share a key; later ones pair positionally. */\n StructuralDuplicateKey: 'LP0405',\n /** Every structural key changed while the length did not; the source generates keys per message. */\n StructuralUnstableKeys: 'LP0406',\n /** A binding asks for a delivery strategy this release does not have; it is left unchanged. */\n UnsupportedStrategy: 'LP0407',\n /** `data-payload-format` names a format the vocabulary does not contain; the default formatting was used instead. */\n UnknownValueFormat: 'LP0408',\n /** The strict sanitizer removed an attribute the 1.x `'compat'` policy kept. */\n SanitizerDroppedAttribute: 'LP0409',\n /** A Lexical block has no renderer; the markup the server rendered for it is kept instead. */\n UnrenderedBlockKept: 'LP0410',\n /** A patch cannot reach what the server would have drawn; `onUnfaithfulPatch` decided what happens next. */\n UnfaithfulPatch: 'LP0411',\n /** The first write to a date, number, checkbox, select or radio binding replaced a different reading of the same value. */\n ServerFormatReplaced: 'LP0412',\n /** A Lexical block has no renderer, and the write could not keep the markup the server rendered for it; it is gone. */\n UnrenderedBlockLost: 'LP0413',\n\n /** A message was rejected before it reached the update pipeline. */\n MessageRejected: 'LP0501',\n /** A preview token was rejected. */\n TokenRejected: 'LP0502',\n /** A trusted origin sent a message this protocol version does not recognise. */\n ProtocolShapeUnknown: 'LP0503',\n\n /** A consumer event handler threw. */\n HandlerThrew: 'LP0601',\n /** A consumer transform threw; the original value was kept. */\n TransformThrew: 'LP0602',\n /** A renderer threw while writing a value. */\n RendererThrew: 'LP0603',\n // LP0604 is reserved and unassigned; codes are never reused or renumbered.\n /** Runtime startup failed. */\n StartupFailed: 'LP0605',\n /** Sending the ready handshake failed. */\n ReadyFailed: 'LP0606',\n /** The page declared hydration, but no React commit, Vue mount, SvelteKit mount or `markHydrated()` call came within the cap; the runtime started without waiting. */\n HydrationWaitTimedOut: 'LP0607',\n\n /** The audit found no runtime in a response that carried preview intent. */\n AuditRuntimeMissing: 'LP0701',\n /** The preview response declares no `frame-ancestors`. */\n AuditNoFrameAncestors: 'LP0702',\n /** `X-Frame-Options` forbids framing on a response that declares no `frame-ancestors`; `SAMEORIGIN` forbids it from another origin only. */\n AuditFrameOptionsBlocks: 'LP0703',\n /** Binding attributes are served to anonymous visitors. */\n AuditBindingsExposed: 'LP0704',\n /** More bindings than the visibility gate will write eagerly. */\n AuditGateThresholdExceeded: 'LP0705',\n /** Owner markers exist, but some bindings are outside all of them. */\n AuditUnownedBindings: 'LP0706',\n /** The preview response carries no bindings and no fragment boundary. */\n AuditNoBindings: 'LP0707',\n /** The URL did not return an HTML page, so nothing else can be judged. */\n AuditNotAPage: 'LP0708',\n /** A fragment request failed (network, timeout, server error); the boundary was patched instead. */\n FragmentRequestFailed: 'LP0801',\n /** The fragment response had the wrong content type or shape; the boundary was patched instead. */\n FragmentResponseInvalid: 'LP0802',\n /** The fragment endpoint refused the preview (not authorized); the boundary was patched instead. */\n FragmentUnauthorized: 'LP0803',\n /** A fragment response arrived for a revision that was already superseded and was discarded. */\n FragmentSuperseded: 'LP0804',\n /** A route refresh was refused: the loop guard, or the strategy's minimum interval. */\n RouteRefreshLoop: 'LP0805',\n /** A boundary asks for the fragment strategy but no fragment handler is configured; it is patched. */\n FragmentStrategyUnavailable: 'LP0806',\n /** A revision changed a field with no binding; `onUnfaithfulPatch` refreshed the route. */\n UnboundChangeRefresh: 'LP0807',\n /** `onUnfaithfulPatch: 'escalate'` found no route or fragment strategy, or no boundary, to hand an unfaithful patch to; the page keeps it. */\n EscalationUnavailable: 'LP0808',\n /** A fragment inserted an Astro island the page cannot start: it never loaded the island element or that client directive. */\n IslandStartUnavailable: 'LP0809',\n /** The host's route refresh returned no promise, so the revision was re-applied before the host committed. */\n RouteRefreshUnconfirmed: 'LP0810',\n /** A readiness row is not yet at its 2.0 value; `pll doctor --v2` reports it. */\n V2ReadinessGap: 'LP0709',\n /** The preview runtime is served to anonymous visitors, not only inside the admin frame. */\n RuntimeOnPublicPage: 'LP0710',\n /** An element carries attributes that only mean something beside `data-payload-field`, and has none. */\n AuditModifierWithoutField: 'LP0711',\n} as const);\n\n/** A diagnostic code, as it appears in log output and on the `error` event. */\nexport type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[keyof typeof DIAGNOSTIC_CODES];\n","/**\n * `frame-ancestors` matching by the CSP3 source-expression rules. The audit\n * judges origins, so path parts of a host-source are ignored.\n */\n\nconst DEFAULT_PORT: Readonly<Record<string, string>> = {\n http: '80',\n https: '443',\n ws: '80',\n wss: '443',\n};\nconst SCHEME_SOURCE = /^([a-z][a-z0-9+.-]*):$/u;\nconst HOST_SOURCE =\n /^(?:([a-z][a-z0-9+.-]*):\\/\\/)?(\\*|(?:\\*\\.)?[a-z0-9-]+(?:\\.[a-z0-9-]+)*\\.?)(?::(\\*|\\d+))?(?:\\/.*)?$/u;\n\n/** The `frame-ancestors` directive of a policy, verbatim, or `undefined` when it has none. */\nexport function frameAncestorsOf(csp: string | undefined): string | undefined {\n if (csp === undefined) return undefined;\n for (const directive of csp.split(';')) {\n const trimmed = directive.trim();\n if (/^frame-ancestors(?:\\s|$)/iu.test(trimmed)) return trimmed;\n }\n return undefined;\n}\n\nfunction schemeOf(url: URL): string {\n return url.protocol.slice(0, -1).toLowerCase();\n}\n\nfunction portOf(url: URL): string {\n return url.port === '' ? (DEFAULT_PORT[schemeOf(url)] ?? '') : url.port;\n}\n\nfunction schemeMatches(expression: string, actual: string): boolean {\n return (\n expression === actual ||\n (expression === 'http' && actual === 'https') ||\n (expression === 'ws' && actual === 'wss')\n );\n}\n\nfunction hostMatches(pattern: string, host: string): boolean {\n if (pattern === '*') return true;\n const wanted = pattern.replace(/\\.$/u, '');\n const actual = host.replace(/\\.$/u, '');\n if (wanted.startsWith('*.')) {\n return actual.endsWith(wanted.slice(1)) && actual.length > wanted.length - 1;\n }\n return wanted === actual;\n}\n\nfunction isSelf(admin: URL, page: URL): boolean {\n if (admin.hostname !== page.hostname) return false;\n const adminScheme = schemeOf(admin);\n const pageScheme = schemeOf(page);\n if (adminScheme !== pageScheme && !(pageScheme === 'http' && adminScheme === 'https')) {\n return false;\n }\n return portOf(admin) === portOf(page) || (admin.port === '' && page.port === '');\n}\n\nfunction sourceMatches(source: string, admin: URL, page: URL): boolean {\n const scheme = SCHEME_SOURCE.exec(source);\n if (scheme?.[1] !== undefined) return schemeMatches(scheme[1], schemeOf(admin));\n const host = HOST_SOURCE.exec(source);\n if (host === null) return false;\n const expressionScheme = host[1];\n const expressionHost = host[2] ?? '';\n const expressionPort = host[3];\n const requiredScheme = expressionScheme ?? schemeOf(page);\n if (!schemeMatches(requiredScheme, schemeOf(admin))) return false;\n if (!hostMatches(expressionHost, admin.hostname)) return false;\n if (expressionPort === undefined) return admin.port === '';\n return expressionPort === '*' || expressionPort === portOf(admin);\n}\n\n/** Whether the directive admits `admin` as an ancestor of `page`. */\nexport function frameAncestorsAdmits(directive: string, admin: URL, page: URL): boolean {\n const sources = directive\n .split(/\\s+/u)\n .slice(1)\n .filter((source) => source.length > 0)\n .map((source) => source.toLowerCase());\n if (sources.length === 0 || (sources.length === 1 && sources[0] === \"'none'\")) return false;\n for (const source of sources) {\n if (source === \"'self'\") {\n if (isSelf(admin, page)) return true;\n } else if (source === '*') {\n return true;\n } else if (!source.startsWith(\"'\") && sourceMatches(source, admin, page)) {\n return true;\n }\n }\n return false;\n}\n","/**\n * The inline script's configuration and its positional wire order: the\n * generator writes the tuple, `src/core/runtime.ts` destructures it, and\n * `INLINE_CONFIG_KEYS` is where they agree. Append only, never reorder.\n */\n\nimport type { DefaultsProfile } from '@/types/defaults-profile';\n\nexport interface InlineScriptConfig {\n /** Trusted admin origins, merged with the detected ones. */\n readonly allowedOrigins?: readonly string[];\n /** Payload origin; every update is then re-fetched through the REST API with credentials. Requires `mergeDepth`. */\n readonly serverURL?: string;\n /** REST route prefix used with `serverURL`. Default `/api`. */\n readonly apiRoute?: string;\n /** Population depth used with `serverURL`. Required with `serverURL` unless `defaults: 'v1'`. */\n readonly mergeDepth?: number;\n /** Verbose console logging. Default `false`. */\n readonly debug?: boolean;\n /** Debounce window for incoming updates in ms. Default `50`. */\n readonly debounceMs?: number;\n /** Mount the screen-reader live region. Default `true`. */\n readonly enableA11y?: boolean;\n /** Heartbeat timeout in ms; `0` disables it (default), because the admin posts only on edits. */\n readonly heartbeatMs?: number;\n /** Apply every update regardless of viewport position. Default `false`. */\n readonly disableVisibilityGate?: boolean;\n /** Cache size above which off-screen updates wait for intersection. Default `50`. */\n readonly visibilityGateThreshold?: number;\n /** `rootMargin` of the IntersectionObserver. Default `'200px'`. */\n readonly intersectionRootMargin?: string;\n /** Ignore `document.referrer` as an origin source. Default `true`; `defaults: 'v1'` sets `false`. */\n readonly disableReferrerDetection?: boolean;\n /** Disable the dev-mode localhost matcher (any port on `localhost`/`127.0.0.1`). Default `false`. */\n readonly disableLocalhostMatching?: boolean;\n /** Update only bindings under a matching `data-payload-owner`. Default `false`. */\n readonly scopeBindingsByOwner?: boolean;\n /** Skip bindings whose value did not change. Default `true`; `defaults: 'v1'` sets `false`. */\n readonly skipUnchanged?: boolean;\n /** Scroll the preview to the field being edited. Default `false`. */\n readonly revealEditedField?: boolean;\n /** Which windows may post updates. Default `'parent-or-opener'`; `defaults: 'v1'` sets `'any'`. */\n readonly eventSourcePolicy?: 'any' | 'parent-or-opener';\n /** Sanitizer policy for rich text and HTML writes. Default `'strict'`; `defaults: 'v1'` sets `'compat'`. */\n readonly sanitizerPolicy?: 'compat' | 'strict';\n /** Same-origin path of a fragment endpoint; the script then carries the fragment client ahead of the runtime (ADR 0011). */\n readonly fragmentEndpoint?: string;\n /**\n * Carry the route strategy, so a binding in `<head>` or one marked\n * `data-payload-strategy=\"route\"` refreshes the route. `fragmentEndpoint`\n * implies it — the fragment prelude already contains it. Default `false`.\n * `'after-save'` renders the route only once Payload reports a save: before it, a\n * GET shows nothing the editor typed and costs a server render.\n */\n readonly routeStrategy?: boolean | 'after-save';\n /**\n * The 2.0 name for `onUnfaithfulPatch`, kept until 3.0. `'route'` means\n * `'escalate'`, `'ignore'` means `'ignore'`.\n *\n * @deprecated Renamed to `onUnfaithfulPatch`.\n */\n readonly onUnboundChange?: 'ignore' | 'route';\n /**\n * What to do when the runtime knows a patch cannot reach what the server\n * would have drawn. `'escalate'` (the default) hands the region to the\n * fragment strategy when a boundary covers it and to the route otherwise, so\n * it needs `fragmentEndpoint` or `routeStrategy` to do anything. `'warn'`\n * reports LP0411 and keeps the patch; `'ignore'` keeps it silently.\n */\n readonly onUnfaithfulPatch?: 'ignore' | 'warn' | 'escalate';\n /**\n * Find bindings by value on the connection's first message (ADR 0014): a\n * scalar whose value is the whole content of exactly one element is bound\n * to it as if `data-payload-field` stood there. Default `'off'`.\n */\n readonly autoBind?: 'off' | 'unique';\n /**\n * The framework that hydrates this page (ADR 0015). Under `'react'` the\n * runtime holds its first write until React has committed the tree that\n * holds the bindings — otherwise React finds markup it did not render,\n * throws `Hydration failed` and regenerates the tree, and the write is gone.\n * Under `'vue'` it holds the write until Vue has mounted the app around them\n * — otherwise Vue's hydration repairs the write back to the server's value,\n * quietly. Under `'sveltekit'` it holds the write until SvelteKit's root has\n * mounted, on a page SvelteKit's client runs on — otherwise Svelte's\n * hydration sets its own text back over it, as quietly. The Next.js, Nuxt\n * and SvelteKit adapters set it on every script they emit; a page built by\n * hand with `generateInlineScript()` may. Under `'manual'` it holds the write\n * until the page calls `markHydrated()`, for a framework this package cannot\n * observe. Omitted: the runtime starts on `DOMContentLoaded`, as on a static page.\n */\n readonly hydration?: 'react' | 'vue' | 'sveltekit' | 'manual';\n /**\n * Which defaults the omitted options fall back to, resolved by the generator\n * rather than the runtime, whose own fallbacks are the 2.0 rows: `'v1'`\n * writes its four runtime rows into their slots (an explicit option still\n * wins) and relaxes the `mergeDepth` check. The resolved value always\n * travels in slot 24, so a reader of the served page knows what an\n * empty slot means instead of guessing it — `pll doctor --v2` reads it. The\n * runtime does not use that value: every row the profile decides is already\n * in its slot. Slot 24 stays fixed as later options are appended.\n */\n readonly defaults?: DefaultsProfile;\n /**\n * Document events fired after a client router committed new markup. Each\n * rebuilds the binding cache and locally reapplies the last accepted state.\n * Adapter integrations set this from their framework lifecycle. It is a\n * low-level generator fact, not a `PreviewAdapterOptions` field. Empty by\n * default.\n */\n readonly softNavigationEvents?: readonly string[];\n /**\n * How a group counts as covered (ADR 0022). `'descendant'`, the 2.x default:\n * one bound path inside it covers all of it. `'declared'`: each changed path\n * inside such a group needs its own binding or a `data-payload-covers`\n * declaration; an uncovered one is an unbound change.\n */\n readonly subfieldCoverage?: 'descendant' | 'declared';\n /** Milliseconds the `serverURL` merge may wait before the update shows its raw values. Off by default. */\n readonly mergeTimeoutMs?: number;\n /** The route of a Lexical internal link with no `url` of its own, as `/{locale}/{slug}/`. */\n readonly internalLinkPattern?: string;\n /**\n * A runtime artifact to embed instead of the full one — today only\n * `LEAN_RUNTIME` from `payload-live-preview/lean`, which leaves out the\n * strategies, the keyed morph, the structural arrays, the item templates, the\n * announcer and auto-binding (about 7 KB gzip less on the page) and reports\n * LP0104 when a page needs one of them.\n *\n * It is an imported value rather than a `profile: 'lean'` string on purpose:\n * a second artifact behind a string option would sit in every build that can\n * reach the generator; measured, it grew each adapter entry by the artifact's\n * whole size. This way the bytes follow the import.\n *\n * Not serialized: it decides which bytes are emitted, not how they behave.\n */\n readonly runtime?: RuntimeArtifact;\n}\n\n/**\n * A runtime build this package produces. `source` is the IIFE the page runs;\n * the two digests describe the same bytes as a servable asset, so asset\n * delivery can hash-name and SRI-verify whichever artifact was chosen without\n * hashing anything at request time.\n */\nexport interface RuntimeArtifact {\n readonly profile: 'lean';\n readonly source: string;\n /** Short content hash, for the asset's file name. */\n readonly contentHash: string;\n /** `sha384-…`, for the bootstrap's `integrity` attribute. */\n readonly integrity: string;\n}\n\n/** Keys that travel in the wire tuple, in slot order. */\nexport const INLINE_CONFIG_KEYS = [\n 'allowedOrigins',\n 'serverURL',\n 'apiRoute',\n 'mergeDepth',\n 'debug',\n 'debounceMs',\n 'enableA11y',\n 'heartbeatMs',\n 'disableVisibilityGate',\n 'visibilityGateThreshold',\n 'intersectionRootMargin',\n 'disableReferrerDetection',\n 'disableLocalhostMatching',\n 'scopeBindingsByOwner',\n 'skipUnchanged',\n 'eventSourcePolicy',\n 'sanitizerPolicy',\n 'fragmentEndpoint',\n 'revealEditedField',\n 'routeStrategy',\n 'onUnboundChange',\n 'onUnfaithfulPatch',\n 'autoBind',\n 'hydration',\n 'defaults',\n 'softNavigationEvents',\n 'subfieldCoverage',\n 'mergeTimeoutMs',\n 'internalLinkPattern',\n] as const satisfies readonly Exclude<keyof InlineScriptConfig, 'runtime'>[];\n","/**\n * The two defaults profiles, row by row. 2.0 ships `v2`; `defaults: 'v1'` opts\n * back into the 1.x table for a staged migration. Each row belongs to exactly\n * one side — the adapter's request decision or the browser runtime — and a\n * test asserts the profile assigns every readiness row that has an option, so\n * a row added later cannot be forgotten. See ADR 0007.\n *\n * It lives in the leaf `types` domain, like `merge-depth.ts`, because the\n * inline generator resolves the profile too, and the generator is server-side\n * code that may not reach the browser runtime in `core`.\n */\n\n/** `'v2'` is the 2.0 default; `'v1'` is the 1.x table. */\nexport type DefaultsProfile = 'v1' | 'v2';\n\n/** How the runtime decides which windows may post updates. */\nexport type EventSourcePolicy = 'any' | 'parent-or-opener';\n\n/** Readiness rows that are options, keyed by the option they set. */\nexport const READINESS_ROWS = Object.freeze({\n strict: 'production response changes require an authorized context',\n previewSignals: 'query-only intent signal',\n disableReferrerDetection: 'referrer trust off',\n eventSourcePolicy: 'messages must come from parent/opener',\n skipUnchanged: 'skip unchanged bindings by default',\n sanitizerPolicy: 'hardened sanitizer id/data-* policy',\n} as const);\n\n/** Options an adapter's request decision reads from the profile. */\nexport interface AdapterProfileDefaults {\n readonly strict: boolean;\n readonly previewSignals: readonly ('query' | 'fetch-dest' | 'referer')[];\n}\n\n/** Options the browser runtime reads from the profile (through the inline configuration). */\nexport interface RuntimeProfileDefaults {\n readonly disableReferrerDetection: boolean;\n readonly eventSourcePolicy: EventSourcePolicy;\n readonly skipUnchanged: boolean;\n readonly sanitizerPolicy: 'compat' | 'strict';\n}\n\nexport const V2_ADAPTER_DEFAULTS: AdapterProfileDefaults = Object.freeze({\n strict: true,\n previewSignals: Object.freeze(['query'] as const),\n});\n\nexport const V2_RUNTIME_DEFAULTS: RuntimeProfileDefaults = Object.freeze({\n disableReferrerDetection: true,\n eventSourcePolicy: 'parent-or-opener',\n skipUnchanged: true,\n sanitizerPolicy: 'strict',\n});\n\n/** The 1.x table, spelled out so the profiles compare row by row. */\nexport const V1_ADAPTER_DEFAULTS: AdapterProfileDefaults = Object.freeze({\n strict: false,\n previewSignals: Object.freeze(['query', 'fetch-dest', 'referer'] as const),\n});\n\nexport const V1_RUNTIME_DEFAULTS: RuntimeProfileDefaults = Object.freeze({\n disableReferrerDetection: false,\n eventSourcePolicy: 'any',\n skipUnchanged: false,\n sanitizerPolicy: 'compat',\n});\n\n/** Only an explicit `'v1'` opts out; everything else gets the hardened rows. */\nexport function adapterDefaultsFor(profile: DefaultsProfile | undefined): AdapterProfileDefaults {\n return profile === 'v1' ? V1_ADAPTER_DEFAULTS : V2_ADAPTER_DEFAULTS;\n}\n\nexport function runtimeDefaultsFor(profile: DefaultsProfile | undefined): RuntimeProfileDefaults {\n return profile === 'v1' ? V1_RUNTIME_DEFAULTS : V2_RUNTIME_DEFAULTS;\n}\n","/**\n * `pll doctor --v2`: read the served configuration and report each runtime row\n * still at its 1.x value (ADR 0007).\n *\n * An empty slot means whatever the generation that wrote the script meant by\n * it, and that is exactly what changed between 1.x and 2.0. So the script\n * names the defaults it was resolved against in slot 24, and this reads\n * the answer instead of guessing it. A script without the marker predates it —\n * 1.x or 2.0.0-beta.0 — and is read as 1.x, with a line that says so.\n */\nimport { INLINE_CONFIG_KEYS } from '@/types/inline-config';\nimport {\n V1_RUNTIME_DEFAULTS,\n V2_RUNTIME_DEFAULTS,\n type RuntimeProfileDefaults,\n} from '@/types/defaults-profile';\nimport type { DoctorFinding, DoctorProbe } from './types';\n\nconst CONFIG_NAME = '__LIVE_PREVIEW_CONFIG__';\nconst CONFIG_MARKER = `var ${CONFIG_NAME}=`;\n// A comment or a script, in document order, so a script inside a comment is\n// skipped as the browser skips it. A quoted attribute value may hold `>`.\nconst COMMENT_OR_SCRIPT =\n /<!--[\\s\\S]*?-->|<script\\b((?:[^>\"']|\"[^\"]*\"|'[^']*')*)>([\\s\\S]*?)<\\/script\\b[^>]*>/giu;\n// The attribute name in any case, the value exactly, as `getElementById` compares it.\nconst CONFIG_ID = /(?:^|\\s)[iI][dD]\\s*=\\s*[\"']?__LIVE_PREVIEW_CONFIG__(?=[\"'\\s]|$)/u;\nconst JSON_TYPE = /(?:^|\\s)type\\s*=\\s*[\"']?application\\/json(?=[\"'\\s;]|$)/iu;\n\ntype InlineKey = (typeof INLINE_CONFIG_KEYS)[number];\n\n/** The configuration a preview response serves, whichever way the page writes it. */\nexport interface ServedConfig {\n /** `inline`: the generator's tuple. `element`: the JSON a page writes for a client it starts itself. */\n readonly source: 'inline' | 'element';\n /** The option under its inline name; `undefined` when the page does not set it. */\n value(key: InlineKey): unknown;\n}\n\n/** A runtime row of the readiness table, as a finding words it. */\ninterface ReadinessRow {\n readonly key: keyof RuntimeProfileDefaults;\n readonly title: string;\n /** What the 1.x value does. */\n readonly effect: string;\n /** What has to hold before the row can take its 2.0 value. */\n readonly condition: string;\n}\n\nconst ROWS: readonly ReadinessRow[] = [\n {\n key: 'disableReferrerDetection',\n title: 'Referrer trust is still on',\n effect: 'the runtime accepts the admin referer as a preview signal.',\n condition: 'no preview flow relies on the admin referer alone',\n },\n {\n key: 'eventSourcePolicy',\n title: 'Messages are accepted from any window',\n effect: 'any window that passes the origin check may post updates.',\n condition: 'no window but the parent or opener posts updates',\n },\n {\n key: 'sanitizerPolicy',\n title: 'Sanitizer is in compat mode',\n effect: 'id and every data-* pass.',\n condition: 'rich text no longer relies on `id` or `data-*`',\n },\n {\n key: 'skipUnchanged',\n title: 'Unchanged bindings are re-applied every message',\n effect: 'every binding is written again on every message.',\n condition: 'no renderer relies on running again for a value that did not change',\n },\n];\n\n/** Where a row's value came from, which decides what the reader can change. */\ntype Origin = 'profile' | 'explicit' | 'unmarked';\n\nconst ORIGIN_DETAIL: Readonly<Record<Origin, string>> = {\n profile: \"The script was generated with `defaults: 'v1'`.\",\n explicit: 'The script sets it explicitly.',\n unmarked: 'The script names no defaults, so its empty slot is read as the 1.x value.',\n};\n\nconst UNREADABLE: DoctorFinding = {\n code: 'LP0709',\n level: 'info',\n title: 'Could not read the inline configuration for a v2 readiness check',\n detail:\n 'The preview response carried no readable `__LIVE_PREVIEW_CONFIG__` inline script or JSON configuration element.',\n remedy:\n 'Run this against a page with the inline runtime (not loader mode without a preview context). ' +\n 'A preview behind authorizePreview serves it only to a request with credentials: pass them with --header, or a signed token as ?previewToken=… in the URL.',\n};\n\nconst UNMARKED: DoctorFinding = {\n code: 'LP0709',\n level: 'info',\n title: 'The inline configuration does not say which defaults it was generated against',\n detail:\n 'Scripts carry a `defaults` marker from 2.0.0-rc.1 on; this one has none, so a 1.x or 2.0.0-beta.0 generator wrote it. An empty slot is read as its 1.x value, which is what a 1.x runtime runs.',\n remedy:\n 'On 1.x the warnings stand as written. On 2.0.0-beta.0 an empty slot already runs its 2.0 value, so a warning about one does not apply there; upgrade and run `pll doctor --v2` again to read the marker.',\n};\n\n/**\n * The array literal after the marker, read as JSON. The generator writes `,,`\n * for unset slots, which JSON cannot express, so elisions outside strings\n * become `null`. Never evaluated: a page controls this text.\n */\nexport function readInlineConfig(body: string): readonly unknown[] | undefined {\n const start = body.indexOf(CONFIG_MARKER);\n if (start === -1) return undefined;\n const from = start + CONFIG_MARKER.length;\n if (body[from] !== '[') return undefined;\n let depth = 0;\n let inString = false;\n let previous = '';\n let json = '';\n for (let index = from; index < body.length; index += 1) {\n const char = body[index] ?? '';\n if (inString) {\n json += char;\n if (char === '\\\\') {\n json += body[index + 1] ?? '';\n index += 1;\n } else if (char === '\"') {\n inString = false;\n // A closed string is a value: without this, the next `,` reads as an elision.\n previous = '\"';\n }\n continue;\n }\n if (char === '\"') {\n inString = true;\n json += char;\n continue;\n }\n if (/\\s/u.test(char)) continue;\n const elision =\n (char === ',' && (previous === ',' || previous === '[')) ||\n (char === ']' && previous === ',');\n if (elision) json += 'null';\n json += char;\n previous = char;\n if (char === '[') depth += 1;\n if (char === ']') {\n depth -= 1;\n if (depth === 0) break;\n }\n }\n if (depth !== 0) return undefined;\n try {\n const value: unknown = JSON.parse(json);\n return Array.isArray(value) ? (value as readonly unknown[]) : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The inline tuple first, because it is what the runtime reads; else a\n * `<script type=\"application/json\" id=\"__LIVE_PREVIEW_CONFIG__\">` holding an\n * object that names the options as the client and the inline script spell\n * them. That is how a page that starts `LivePreviewClient` itself can show the\n * doctor its options. Never evaluated: a page controls this text.\n * @internal\n */\nexport function readServedConfig(body: string): ServedConfig | undefined {\n // Both ways spell the name, and the scan below is slow on hostile markup.\n if (!body.includes(CONFIG_NAME)) return undefined;\n const scripts = servedScripts(body);\n const inline = scripts.find(({ text }) => text.includes(CONFIG_MARKER));\n const tuple = inline === undefined ? undefined : readInlineConfig(inline.text);\n if (tuple !== undefined) {\n return {\n source: 'inline',\n value: (key) => tuple[INLINE_CONFIG_KEYS.indexOf(key)] ?? undefined,\n };\n }\n const named = readConfigElement(scripts);\n if (named === undefined) return undefined;\n return {\n source: 'element',\n value: (key) => (Object.hasOwn(named, key) ? (named[key] ?? undefined) : undefined),\n };\n}\n\ninterface ServedScript {\n readonly attributes: string;\n readonly text: string;\n}\n\n/** The scripts a browser would run or read, without those inside a comment. */\nfunction servedScripts(body: string): readonly ServedScript[] {\n const scripts: ServedScript[] = [];\n for (const [, attributes, text] of body.matchAll(COMMENT_OR_SCRIPT)) {\n // A comment captures neither group.\n if (attributes !== undefined && text !== undefined) scripts.push({ attributes, text });\n }\n return scripts;\n}\n\nfunction readConfigElement(\n scripts: readonly ServedScript[],\n): Readonly<Record<string, unknown>> | undefined {\n for (const { attributes, text } of scripts) {\n if (!CONFIG_ID.test(attributes)) continue;\n if (!JSON_TYPE.test(attributes)) return undefined;\n try {\n const value: unknown = JSON.parse(text);\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Readonly<Record<string, unknown>>)\n : undefined;\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\n/** `'compat'` rather than `\"compat\"`: remedies are read as source code. */\nfunction literal(value: unknown): string {\n return typeof value === 'string' ? `'${value}'` : JSON.stringify(value);\n}\n\nfunction remedyFor(origin: Origin, row: ReadinessRow, value: unknown): string {\n const wanted = `\\`${row.key}: ${literal(V2_RUNTIME_DEFAULTS[row.key])}\\``;\n switch (origin) {\n case 'profile':\n return (\n `Set ${wanted} or drop \\`defaults: 'v1'\\` once ${row.condition}. 3.0 removes the ` +\n 'profile; `pll migrate` writes its rows out, so each can go on its own.'\n );\n case 'explicit':\n return `Drop the explicit \\`${row.key}: ${literal(value)}\\` once ${row.condition}; 2.0 defaults to ${wanted}.`;\n case 'unmarked':\n // 1.8.1 has no `defaults` option and three of the four rows are not\n // inline options there, so the way out is the upgrade itself.\n return `Upgrading to 2.0 sets ${wanted}; check first that ${row.condition}.`;\n }\n}\n\nfunction gap(row: ReadinessRow, value: unknown, origin: Origin): DoctorFinding {\n return {\n code: 'LP0709',\n level: 'warning',\n title: row.title,\n detail: `${row.key} is ${literal(value)}: ${row.effect} ${ORIGIN_DETAIL[origin]}`,\n remedy: remedyFor(origin, row, value),\n };\n}\n\nfunction unknownGeneration(marker: unknown): DoctorFinding {\n return {\n code: 'LP0709',\n level: 'info',\n title: 'The inline configuration names defaults this doctor does not know',\n detail: `Its \\`defaults\\` marker is ${JSON.stringify(marker)}; this version reads 'v1' and 'v2', so no row was judged.`,\n remedy: 'Run the `pll doctor` of the package version that generated the page.',\n };\n}\n\n/**\n * One `LP0709` finding per runtime row not yet at its 2.0 value. An empty slot\n * has the value of the generation the script names, and the 1.x value when it\n * names none; a generation this version does not know is not judged at all.\n * A configuration element is written for a 2.x client, whose omitted options\n * are the 2.0 rows unless it names `'v1'`.\n * @internal\n */\nexport function analyzeV2Readiness(probe: DoctorProbe): readonly DoctorFinding[] {\n const config = readServedConfig(probe.previewResponse.body);\n if (config === undefined) return [UNREADABLE];\n const marker = config.value('defaults');\n if (marker !== undefined && marker !== 'v1' && marker !== 'v2') {\n return [unknownGeneration(marker)];\n }\n const generation = marker ?? (config.source === 'element' ? 'v2' : undefined);\n const fallback = generation === 'v2' ? V2_RUNTIME_DEFAULTS : V1_RUNTIME_DEFAULTS;\n const findings = ROWS.flatMap((row) => {\n const slot = config.value(row.key);\n const value = slot ?? fallback[row.key];\n if (value === V2_RUNTIME_DEFAULTS[row.key]) return [];\n const origin: Origin =\n generation === 'v1' ? 'profile' : slot === undefined ? 'unmarked' : 'explicit';\n return [gap(row, value, origin)];\n });\n return generation === undefined ? [...findings, UNMARKED] : findings;\n}\n","/**\n * The `pll doctor` audit: judge what a deployment serves from two fetches of\n * one URL, as a visitor and as the admin's iframe. Pure — the caller fetches.\n * Markup is read with regular expressions, which is enough to count\n * attributes inside start tags and find the runtime marker; findings say what\n * was observed.\n */\nimport { DIAGNOSTIC_CODES } from '../core/diagnostic-codes';\nimport { frameAncestorsAdmits, frameAncestorsOf } from './csp';\nimport { analyzeV2Readiness, readServedConfig } from './readiness';\nimport type {\n DoctorContext,\n DoctorFinding,\n DoctorProbe,\n DoctorReport,\n DoctorResponse,\n} from './types';\n\n/** Survives minification; the banner comment does not. */\nconst RUNTIME_MARKER = '__LIVE_PREVIEW_CONFIG__';\n/**\n * A start tag, quoted values read whole so a `>` inside one does not end it.\n * Text is never a tag: `&lt;h1 data-payload-field=…&gt;` in a code sample, or\n * a sentence that names the attribute, is what a page shows, not what it binds.\n * A raw `<` outside quotes ends the attempt, which keeps the scan linear: with\n * it, `<a<a<a…` and no `>` took 645 ms for 20 000 repetitions, 15 times the\n * time of 5 000.\n */\nconst START_TAG = /<[a-zA-Z](?:\"[^\"]*\"|'[^']*'|[^\"'<>])*>/gu;\n/** One attribute of a start tag: its name, and its value when it has one. */\nconst TAG_ATTRIBUTE = /([^\\s\"'>/=]+)(\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))?/gu;\n/** Mirrors the scheduler default; the audit must not import the runtime. */\nconst DEFAULT_VISIBILITY_GATE_THRESHOLD = 50;\nconst LEVEL_ORDER = { error: 0, warning: 1, info: 2 } as const;\n// An end tag may carry junk before its `>`; browsers still close on it, so the\n// pattern must too, or a `</script foo>` would leave the script body counted.\nconst NON_MARKUP =\n /<script\\b[^>]*>[\\s\\S]*?<\\/script\\b[^>]*>|<style\\b[^>]*>[\\s\\S]*?<\\/style\\b[^>]*>|<!--[\\s\\S]*?-->/giu;\n\n/**\n * The runtime's own source spells `data-payload-field=` in a message, so\n * scripts must not be counted. This is a counter's view of the page, not a\n * sanitiser — nothing here is rendered — but it strips to a fixed point all\n * the same, so a block that only appears once its neighbour is gone is still\n * removed rather than counted.\n */\nfunction visibleMarkup(body: string): string {\n let markup = body;\n for (;;) {\n const stripped = markup.replace(NON_MARKUP, '');\n if (stripped === markup) return markup;\n markup = stripped;\n }\n}\n\n/** Read only beside `data-payload-field`; an owner, a strategy or a dependency also means something alone. */\nconst FIELD_MODIFIERS: ReadonlySet<string> = new Set(\n [\n 'type',\n 'attribute',\n 'href',\n 'src',\n 'alt',\n 'richtext',\n 'html',\n 'text',\n 'array',\n 'array-template',\n 'array-separator',\n 'structural',\n 'locale',\n 'format',\n 'boundary',\n ].map((name) => `data-payload-${name}`),\n);\n\n/** An attribute as the markup carries it, at the offset of its tag. */\ninterface MarkupAttribute {\n readonly name: string;\n readonly value: string;\n readonly at: number;\n}\n\n/**\n * Every attribute with a value, in document order. Names are compared in lower\n * case, as a browser parses them; the tag name is read along and never matches\n * an attribute the audit asks about.\n */\nfunction markupAttributes(markup: string): readonly MarkupAttribute[] {\n const found: MarkupAttribute[] = [];\n for (const tag of markup.matchAll(START_TAG)) {\n for (const [, name = '', assigned, double, single, bare] of tag[0].matchAll(TAG_ATTRIBUTE)) {\n if (assigned === undefined) continue;\n found.push({\n name: name.toLowerCase(),\n value: double ?? single ?? bare ?? '',\n at: tag.index,\n });\n }\n }\n return found;\n}\n\n/** The modifiers on start tags that bind no field, one entry per tag. */\nfunction modifiersWithoutField(attributes: readonly MarkupAttribute[]): readonly string[] {\n const bound = new Set(named(attributes, 'data-payload-field').map((attribute) => attribute.at));\n const tags = new Map<number, string>();\n for (const { name, at } of attributes) {\n if (FIELD_MODIFIERS.has(name) && !bound.has(at) && !tags.has(at)) tags.set(at, name);\n }\n return [...tags.values()];\n}\n\nfunction named(attributes: readonly MarkupAttribute[], name: string): readonly MarkupAttribute[] {\n return attributes.filter((attribute) => attribute.name === name);\n}\n\n/** Bindings before the first owner marker are certainly unowned; nesting is not modelled, so this under-reports. */\nfunction unownedBindingsBeforeFirstOwner(attributes: readonly MarkupAttribute[]): number {\n const firstOwner = named(attributes, 'data-payload-owner')[0];\n if (firstOwner === undefined) return 0;\n return named(attributes, 'data-payload-field').filter((binding) => binding.at < firstOwner.at)\n .length;\n}\n\nfunction tryUrl(value: string | undefined): URL | undefined {\n if (value === undefined) return undefined;\n try {\n return new URL(value);\n } catch {\n return undefined;\n }\n}\n\n/** Why the preview response cannot be audited as a page; the public one may legitimately be gated. */\nfunction describeNonPage(preview: DoctorResponse): DoctorFinding | undefined {\n if (preview.status >= 300 && preview.status <= 399) {\n const location = preview.headers['location'];\n return {\n code: 'LP0708',\n level: 'error',\n title: `The preview request was redirected (${String(preview.status)})${location === undefined ? '' : ` to ${location}`}`,\n detail:\n 'The audit does not follow redirects: the page at the end of one is a different ' +\n 'resource, usually a login or a canonical host, and judging it would say nothing ' +\n 'about this URL.',\n remedy:\n 'The request carried the intent parameter (?preview=true, or the --param name), the ' +\n \"way the admin's iframe loads the page, so a rule that redirects on that query redirects \" +\n 'the iframe too. A redirect to a login means the route needs authentication that a ' +\n \"plain probe cannot supply: pass an editor's credentials with --header, or a signed token as ?previewToken=… in the URL. Probe the final \" +\n 'URL directly only when the redirect has nothing to do with either.',\n };\n }\n if (preview.status < 200 || preview.status > 299) {\n return {\n code: 'LP0708',\n level: 'error',\n title: `The preview request returned ${String(preview.status)}, not a page`,\n detail:\n 'Nothing below this can be judged: a status outside 2xx means the body is an ' +\n 'error page or empty.',\n remedy: 'Check the URL.',\n };\n }\n if (preview.body.trim() === '') {\n return {\n code: 'LP0708',\n level: 'error',\n title: `The preview request returned ${String(preview.status)} with an empty body`,\n detail:\n 'A 2xx status with nothing in it — 204 and 205 are defined that way — is not a page, ' +\n 'so its missing runtime and missing bindings say nothing.',\n remedy: 'Point the audit at a route that renders a document.',\n };\n }\n const contentType = preview.headers['content-type'];\n if (contentType !== undefined && !contentType.toLowerCase().includes('html')) {\n return {\n code: 'LP0708',\n level: 'error',\n title: `The preview request returned ${contentType}, not HTML`,\n detail:\n 'The audit reads a rendered page. A non-HTML response has no runtime and no ' +\n 'bindings by definition, so reporting their absence would say nothing.',\n remedy: 'Point the audit at a page route rather than an API or an asset.',\n };\n }\n return undefined;\n}\n\nfunction framingFindings(\n preview: DoctorResponse,\n runtimeInPreview: boolean,\n context: DoctorContext,\n): DoctorFinding[] {\n const findings: DoctorFinding[] = [];\n const page = tryUrl(context.url);\n const admin = tryUrl(context.adminOrigin);\n const sameOrigin = admin !== undefined && page?.origin === admin.origin;\n const frameAncestors = frameAncestorsOf(preview.headers['content-security-policy']);\n if (runtimeInPreview && frameAncestors === undefined) {\n findings.push({\n code: 'LP0702',\n level: 'warning',\n title: 'Preview response declares no frame-ancestors',\n detail:\n 'The runtime is injected but the response carries no frame-ancestors directive, ' +\n 'so nothing states which origins may embed this page.',\n remedy:\n 'Let the adapter manage CSP, or set frame-ancestors yourself to the admin origin. ' +\n 'Without it you are relying on the absence of a policy.',\n });\n } else if (frameAncestors !== undefined && context.adminOrigin !== undefined) {\n const admitted =\n admin !== undefined &&\n page !== undefined &&\n frameAncestorsAdmits(frameAncestors, admin, page);\n if (!admitted) {\n findings.push({\n code: 'LP0702',\n level: 'error',\n title: 'frame-ancestors does not admit the admin origin',\n detail:\n admin === undefined\n ? `\"${context.adminOrigin}\" is not an absolute URL, so no source expression can admit it.`\n : `Served: \"${frameAncestors}\". Expected it to allow ${admin.origin}.`,\n remedy:\n 'Add the admin origin to allowedOrigins so the adapter merges it into ' +\n 'frame-ancestors, or add it to your own policy.',\n });\n }\n }\n const frameOptions = preview.headers['x-frame-options'];\n // A response with a `frame-ancestors` directive is framed by that directive alone: the HTML\n // Standard skips the header for it (measured in Chromium, Firefox and WebKit). The header\n // decides only where the response declares none; the directive's own verdict is LP0702.\n const blocks =\n frameOptions !== undefined &&\n frameAncestors === undefined &&\n (/deny/iu.test(frameOptions) || (/sameorigin/iu.test(frameOptions) && !sameOrigin));\n if (blocks) {\n // `SAMEORIGIN` refuses a frame from *another* origin, so it is a verdict\n // about this preview only once the admin origin is known. Without --admin\n // the audit says what it saw and names the condition instead of asserting a\n // block it cannot have established: where the admin and the site share an\n // origin, the preview runs. `DENY` needs no origin to be a verdict.\n const judged = admin !== undefined || /deny/iu.test(frameOptions);\n findings.push(\n judged\n ? {\n code: 'LP0703',\n level: 'error',\n title: `X-Frame-Options: ${frameOptions} blocks the preview iframe`,\n detail:\n 'This header is older than CSP. A browser applies it to a response that has no ' +\n 'frame-ancestors directive, and this response has no frame-ancestors.',\n remedy:\n 'Remove X-Frame-Options for preview responses, or serve a frame-ancestors ' +\n 'directive that admits the admin: the header is then ignored. It is usually ' +\n 'set by a proxy or a security middleware rather than by the app.',\n }\n : {\n code: 'LP0703',\n level: 'warning',\n title: `X-Frame-Options: ${frameOptions} blocks every frame from another origin`,\n detail:\n 'This header is older than CSP. A browser applies it to a response that has no ' +\n 'frame-ancestors directive, and this response has no frame-ancestors. SAMEORIGIN ' +\n 'refuses a frame from another origin only, and no admin origin was given: whether ' +\n 'it blocks this preview depends on where the admin is served, which this probe ' +\n 'cannot see.',\n remedy:\n 'Re-run with --admin <origin> to have it judged. If the admin is on another ' +\n 'origin, remove X-Frame-Options for preview responses or serve a frame-ancestors ' +\n 'directive that admits it; a proxy or a security middleware usually sets the header.',\n },\n );\n }\n return findings;\n}\n\n/** The gate as the served script configures it; `threshold` is undefined when the gate is off. */\ninterface ServedGate {\n readonly threshold: number | undefined;\n readonly configured: boolean;\n}\n\n/**\n * Read from the served configuration, because an adapter now forwards both\n * options: judged against the default, a page that raised its threshold\n * would be told to raise it. A page whose configuration cannot be read\n * (loader mode, a client the page starts without a configuration element) is\n * judged against the default.\n */\nfunction servedGate(body: string): ServedGate {\n const config = readServedConfig(body);\n if (config?.value('disableVisibilityGate') === true) {\n return { threshold: undefined, configured: true };\n }\n const threshold = config?.value('visibilityGateThreshold');\n return typeof threshold === 'number'\n ? { threshold, configured: true }\n : { threshold: DEFAULT_VISIBILITY_GATE_THRESHOLD, configured: false };\n}\n\nfunction bindingFindings(\n previewMarkup: string,\n publicMarkup: string,\n runtime: boolean,\n gate: ServedGate,\n): DoctorFinding[] {\n const findings: DoctorFinding[] = [];\n const preview = markupAttributes(previewMarkup);\n const previewBindings = named(preview, 'data-payload-field').length;\n const publicBindings = named(markupAttributes(publicMarkup), 'data-payload-field').length;\n const owners = named(preview, 'data-payload-owner').length;\n // A boundary is rendered by the server from the form state, so an edit of a\n // field it depends on arrives without one field binding; an empty id names\n // no registry entry, and no strategy renders it.\n const boundaries = named(preview, 'data-payload-fragment').filter(\n (boundary) => boundary.value.length > 0,\n ).length;\n if (publicBindings > 0) {\n findings.push({\n code: 'LP0704',\n level: 'warning',\n title: `${String(publicBindings)} binding attribute(s) served to anonymous visitors`,\n detail:\n 'A request with no preview intent received data-payload-field attributes. These ' +\n 'disclose the CMS field taxonomy, and any CSS keyed on them changes public layout ' +\n 'the moment emission is gated.',\n remedy:\n 'Gate binding emission on an authorized preview context — see ' +\n 'createPreviewBindings(), whose suppressed form emits nothing at all.',\n });\n }\n const stranded = modifiersWithoutField(preview);\n if (stranded.length > 0) {\n findings.push({\n code: 'LP0711',\n level: 'warning',\n title: `${String(stranded.length)} element(s) carry ${stranded[0] ?? ''} or the like without a field`,\n detail:\n 'The runtime reads these attributes only on a bound element, so they do nothing here, ' +\n 'and it says nothing about them either.',\n remedy: 'Add data-payload-field to the element, or remove them.',\n });\n }\n if (gate.threshold !== undefined && previewBindings > gate.threshold) {\n findings.push({\n code: 'LP0705',\n level: 'warning',\n title: `${String(previewBindings)} bindings exceed the ${gate.configured ? 'configured' : 'default'} visibility gate`,\n detail:\n `Above visibilityGateThreshold (${String(gate.threshold)}) the ` +\n 'scheduler stops writing offscreen elements and buffers them until they scroll into ' +\n 'view. On a page nobody scrolls, that is never.',\n remedy:\n 'Raise visibilityGateThreshold, or set disableVisibilityGate, on the adapter, ' +\n 'LivePreviewClient or generateInlineScript() if the whole page must stay live, or ' +\n 'confirm that deferring below the fold is acceptable here.',\n });\n }\n if (runtime && previewBindings === 0 && boundaries === 0) {\n findings.push({\n code: 'LP0707',\n level: 'error',\n title: 'Preview response carries no bindings',\n detail:\n 'The runtime is present but there is not one data-payload-field element for it to ' +\n 'write into and not one data-payload-fragment boundary for a server to render, so ' +\n 'no edit can ever be visible on this page.',\n remedy:\n 'Add binding attributes or fragment boundaries to the markup. pll-codegen --inventory ' +\n 'lists every field the schema makes addressable.',\n });\n }\n const unowned = unownedBindingsBeforeFirstOwner(preview);\n if (owners > 0 && unowned > 0) {\n findings.push({\n code: 'LP0706',\n level: 'warning',\n title: `${String(unowned)} binding(s) outside every owner marker`,\n detail:\n `The page declares ${String(owners)} owner marker(s), so owner scoping is in use. ` +\n 'Bindings that belong to no owner receive nothing once scopeBindingsByOwner is on — ' +\n 'they fail closed.',\n remedy:\n 'Give every binding an owning ancestor, or leave scopeBindingsByOwner off until they ' +\n 'all have one. Counted before the first owner marker only, so the real number may be ' +\n 'higher.',\n });\n }\n return findings;\n}\n\n/** Audit a probed deployment. */\nexport function analyzeProbe(\n probe: DoctorProbe,\n context: DoctorContext & {\n readonly v2?: boolean;\n /** Whether the preview probe carried caller-supplied headers (`--header`). */\n readonly credentials?: boolean;\n },\n): DoctorReport {\n const { publicResponse: pub, previewResponse: preview } = probe;\n const notAPage = describeNonPage(preview);\n if (notAPage !== undefined) {\n return { url: context.url, findings: [notAPage], errors: 1, warnings: 0 };\n }\n const runtimeInPreview = preview.body.includes(RUNTIME_MARKER);\n const findings: DoctorFinding[] = [];\n if (!runtimeInPreview) {\n findings.push(\n context.credentials === true\n ? {\n code: 'LP0701',\n level: 'warning',\n title: 'No inline runtime in the preview response',\n detail:\n `The preview request returned ${String(preview.status)} without the inline ` +\n 'runtime, although it carried credentials (--header, or ?previewToken= in the URL). Three readings: ' +\n 'those credentials were not accepted — expired, issued for another page, or not ' +\n 'what authorizePreview reads — an adapter that did not recognise the request as a ' +\n 'preview, or a consumer that starts LivePreviewClient itself.',\n remedy:\n 'Check that the credentials are current and are the ones authorizePreview reads; ' +\n 'if you use an adapter, check its inject mode and previewSignals. If you start the ' +\n 'client yourself, this line is expected.',\n }\n : {\n code: 'LP0701',\n level: 'warning',\n title: 'No inline runtime in the preview response',\n detail:\n `The preview request returned ${String(preview.status)} without the inline ` +\n 'runtime. Three readings, and this audit cannot tell them apart from the response ' +\n 'alone: a preview behind authorizePreview — the strict 2.0 default — which answers ' +\n 'a request without credentials exactly like this, an adapter that did not recognise ' +\n 'the request as a preview, or a consumer that starts LivePreviewClient itself.',\n remedy:\n \"To audit a gated preview, send what an editor's browser sends: \" +\n \"--header 'Cookie: payload-token=…' for a Payload session; for a signed token, \" +\n 'the URL with ?previewToken=… (the default transport, dropped from the visitor ' +\n \"request), or --header 'x-preview-token: …' where the strategy sets transport: \" +\n \"{ kind: 'header' }. Otherwise check the adapter's \" +\n 'inject mode and previewSignals; if you start the client yourself, this line is ' +\n 'expected.',\n },\n );\n }\n findings.push(...framingFindings(preview, runtimeInPreview, context));\n findings.push(\n ...bindingFindings(\n visibleMarkup(preview.body),\n visibleMarkup(pub.body),\n runtimeInPreview,\n servedGate(preview.body),\n ),\n );\n if (pub.body.includes(RUNTIME_MARKER)) {\n // A page that starts its own client serves only the JSON element, which spells the name too.\n const inline = pub.body.includes(`var ${RUNTIME_MARKER}=`);\n findings.push({\n code: DIAGNOSTIC_CODES.RuntimeOnPublicPage,\n level: 'info',\n title: inline\n ? 'Runtime is also served to anonymous visitors'\n : 'Preview configuration is also served to anonymous visitors',\n detail: inline\n ? 'A request with no preview intent received the inline runtime. That is correct for ' +\n \"inject: 'always' and unintended for 'preview-only'.\"\n : 'A request with no preview intent received the configuration element a page writes ' +\n 'for a client it starts itself. That is correct if the page starts the client for ' +\n 'every request, and unintended if it writes the element only for a preview.',\n remedy: '',\n });\n }\n if (context.v2 === true) findings.push(...analyzeV2Readiness(probe));\n findings.sort((a, b) => LEVEL_ORDER[a.level] - LEVEL_ORDER[b.level]);\n return {\n url: context.url,\n findings,\n errors: findings.filter((finding) => finding.level === 'error').length,\n warnings: findings.filter((finding) => finding.level === 'warning').length,\n };\n}\n","/**\n * Fetching for `pll doctor`: the two probes, and the default fetch that talks\n * to a real server. Not in the barrel so it stays in the coverage report.\n */\nimport { analyzeProbe } from './analyze';\nimport type { DoctorReport, DoctorResponse } from './types';\n\n/** Injectable so tests can drive the audit without a server. */\nexport type DoctorFetch = (\n url: string,\n init: { readonly headers: Readonly<Record<string, string>> },\n) => Promise<DoctorResponse>;\n\nexport interface RunDoctorOptions {\n readonly url: string;\n /** Admin origin the preview is meant to be embedded from, when known. */\n readonly adminOrigin?: string | undefined;\n /** Defaults to a fetch built on `globalThis.fetch`. */\n readonly fetchImpl?: DoctorFetch | undefined;\n /** Also check the served page against the 2.0 readiness table. */\n readonly v2?: boolean;\n /**\n * Headers sent with the preview probe only, never with the visitor probe: the\n * credentials a preview behind `authorizePreview` needs, such as a Payload\n * session `Cookie`, or an `x-preview-token` where the token strategy reads a\n * header (a token in the URL is passed in `url` instead). Without them a gated page answers\n * the audit the way it answers any stranger. Their values never reach the report.\n */\n readonly previewHeaders?: Readonly<Record<string, string>> | undefined;\n /**\n * The query parameters the deployment reads as preview intent, when its\n * adapter sets `previewQueryParams`; the same list, since that option replaces\n * the default `preview`, `draft` and `livePreview`. The first one is what the\n * preview probe appends as `=true`; none of them reaches the visitor probe.\n */\n readonly previewQueryParams?: readonly string[] | undefined;\n /**\n * The query parameter the `signed-token` strategy reads, when its transport\n * names one other than `previewToken`. Treated like `previewToken`: dropped\n * from the visitor probe, counted as the credential, its value never shown.\n */\n readonly tokenQueryParam?: string | undefined;\n}\n\n/**\n * The query parameters an adapter reads as preview intent by default; the same\n * list as `DEFAULT_QUERY_PARAMS` in adapters/shared/preview-request.ts, which\n * `previewQueryParams` replaces rather than extends.\n */\nconst DEFAULT_INTENT_PARAMS: readonly string[] = ['preview', 'draft', 'livePreview'];\n\nfunction isIntentValue(value: string): boolean {\n return value === 'true' || value === '1';\n}\n\n/** `key=value` and `#fragment` split off a URL, with the query kept as the caller spelled it. */\nfunction splitUrl(url: string): {\n readonly base: string;\n readonly parts: string[];\n readonly hash: string;\n} {\n const hashAt = url.indexOf('#');\n const hash = hashAt === -1 ? '' : url.slice(hashAt);\n const beforeHash = hashAt === -1 ? url : url.slice(0, hashAt);\n const queryAt = beforeHash.indexOf('?');\n if (queryAt === -1) return { base: beforeHash, parts: [], hash };\n return {\n base: beforeHash.slice(0, queryAt),\n parts: beforeHash.slice(queryAt + 1).split('&'),\n hash,\n };\n}\n\nfunction decodePart(part: string): readonly [string, string] {\n const at = part.indexOf('=');\n const decode = (text: string): string => {\n try {\n return decodeURIComponent(text.replace(/\\+/gu, ' '));\n } catch {\n return text;\n }\n };\n return at === -1 ? [decode(part), ''] : [decode(part.slice(0, at)), decode(part.slice(at + 1))];\n}\n\n/**\n * The query parameter the `signed-token` strategy reads by default. A token\n * audit puts the token in the URL, and it belongs to the preview request only:\n * in the visitor request it would authorize the \"anonymous\" probe and, behind a\n * replay store, spend the token before the preview request arrives.\n */\nconst TOKEN_PARAM = 'previewToken';\n\n/**\n * The URL as the audit prints it: the token's value replaced by `…`. Header\n * values never reach the report, and a token passed in the URL is the same\n * credential, so the report, `--json` and the failure line all show this form.\n * @internal\n */\nexport function redactToken(url: string, tokenParam: string = TOKEN_PARAM): string {\n const { base, parts, hash } = splitUrl(url);\n const shown = parts.map((part) => {\n const at = part.indexOf('=');\n return at === -1 || decodePart(part)[0] !== tokenParam ? part : `${part.slice(0, at)}=…`;\n });\n return shown.some((part, index) => part !== parts[index])\n ? `${base}?${shown.join('&')}${hash}`\n : url;\n}\n\n/** Whether the URL carries a non-empty token for the preview request. */\nfunction carriesToken(url: string, tokenParam: string): boolean {\n return splitUrl(url).parts.some((part) => {\n const [key, value] = decodePart(part);\n return key === tokenParam && value !== '';\n });\n}\n\n/**\n * The page a visitor requests: the intent parameters removed, the rest of the\n * query byte for byte as given. A query is never re-serialised — `URLSearchParams`\n * would turn `%20` into `+` and add `=` to a bare key, and a page whose query is\n * signed by an edge token would answer a different request than a visitor makes.\n */\nfunction visitorUrl(url: string, params: readonly string[], tokenParam: string): string {\n const { base, parts, hash } = splitUrl(url);\n const dropped = new Set([...params, tokenParam]);\n const kept = parts.filter((part) => !dropped.has(decodePart(part)[0]));\n if (kept.length === parts.length) return url;\n return `${base}${kept.length === 0 ? '' : `?${kept.join('&')}`}${hash}`;\n}\n\n/**\n * The page the admin's iframe loads. A 2.0 adapter counts only the query as\n * intent (`previewSignals: ['query']`), and `buildLivePreviewUrl` writes\n * `preview=true`, so the first intent parameter is appended as `=true` unless the\n * URL already names one with a value that counts.\n */\nfunction previewUrl(url: string, params: readonly string[]): string {\n const { base, parts, hash } = splitUrl(url);\n const carries = parts.some((part) => {\n const [key, value] = decodePart(part);\n return params.includes(key) && isIntentValue(value);\n });\n if (carries) return url;\n const query = parts.join('&');\n const joiner = query === '' ? '?' : query.endsWith('&') ? '' : '&';\n const intent = `${encodeURIComponent(params[0] ?? 'preview')}=true`;\n return `${base}${parts.length === 0 ? '?' : `?${query}${joiner}`}${intent}${hash}`;\n}\n\nexport const DEFAULT_TIMEOUT_MS = 15_000;\nexport const MAX_BODY_BYTES = 10 * 1024 * 1024;\n\nexport interface DefaultFetchOptions {\n readonly fetchFn?: typeof fetch;\n readonly timeoutMs?: number;\n readonly maxBodyBytes?: number;\n}\n\n/** Header names lowercased; every check downstream reads a lowercase key. @internal */\nexport function lowercaseHeaders(headers: Headers): Record<string, string> {\n const out: Record<string, string> = {};\n headers.forEach((value, key) => {\n out[key.toLowerCase()] = value;\n });\n return out;\n}\n\n/** The error's message plus its cause's, which is where undici puts `self-signed certificate` and friends. */\nexport function describeFailure(error: unknown): string {\n if (!(error instanceof Error)) return String(error);\n const cause = error.cause;\n if (cause instanceof Error && cause.message !== '' && !error.message.includes(cause.message)) {\n return `${error.message} (${cause.message})`;\n }\n return error.message;\n}\n\nasync function readBody(response: Response, limit: number): Promise<string> {\n const reader = response.body?.getReader();\n if (reader === undefined) return response.text();\n const decoder = new TextDecoder();\n let received = 0;\n let text = '';\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n received += value.byteLength;\n if (received > limit) {\n await reader.cancel();\n throw new Error(\n `the response body exceeds ${String(limit)} bytes, which is not a page the audit can judge`,\n );\n }\n text += decoder.decode(value, { stream: true });\n }\n return text + decoder.decode();\n}\n\n/** Redirects are reported, not followed; a hanging origin is abandoned; a runaway body is refused. */\nexport function createDefaultFetch(options: DefaultFetchOptions = {}): DoctorFetch {\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const limit = options.maxBodyBytes ?? MAX_BODY_BYTES;\n return async (url, init) => {\n const fetchFn = options.fetchFn ?? globalThis.fetch;\n let response: Response;\n try {\n response = await fetchFn(url, {\n headers: init.headers,\n redirect: 'manual',\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (error) {\n if (error instanceof Error && error.name === 'TimeoutError') {\n throw new Error(`no response within ${String(timeoutMs / 1000)} s`, { cause: error });\n }\n throw error;\n }\n return {\n status: response.status,\n headers: lowercaseHeaders(response.headers),\n body: await readBody(response, limit),\n };\n };\n}\n\n/** The referer the admin's iframe would send: the origin (or the given admin path) with one slash. */\nexport function previewReferer(adminOrigin: string): string {\n try {\n return new URL(adminOrigin).href;\n } catch {\n return `${adminOrigin.replace(/\\/+$/u, '')}/`;\n }\n}\n\n/**\n * The caller's headers without the ones the probe sets itself. Header names are\n * case-insensitive, and `fetch` combines two spellings of one name into one\n * comma-joined value, so a caller's `sec-fetch-dest` would otherwise turn the\n * probe's `iframe` into `document, iframe`. The probe's own headers win.\n */\nfunction callerHeaders(\n headers: Readonly<Record<string, string>> | undefined,\n own: Readonly<Record<string, string>>,\n): Record<string, string> {\n const taken = new Set(Object.keys(own).map((name) => name.toLowerCase()));\n return Object.fromEntries(\n Object.entries(headers ?? {}).filter(([name]) => !taken.has(name.toLowerCase())),\n );\n}\n\n/** Fetch the URL twice — as a visitor and as the admin's iframe — and audit the difference. */\nexport async function runDoctor(options: RunDoctorOptions): Promise<DoctorReport> {\n const fetchImpl = options.fetchImpl ?? createDefaultFetch();\n const params =\n options.previewQueryParams === undefined || options.previewQueryParams.length === 0\n ? DEFAULT_INTENT_PARAMS\n : options.previewQueryParams;\n const tokenParam = options.tokenQueryParam ?? TOKEN_PARAM;\n // No referer, no intent parameter and no credentials on the visitor probe:\n // each of them is a preview signal or a way past one.\n const publicResponse = await fetchImpl(visitorUrl(options.url, params, tokenParam), {\n headers: {\n Accept: 'text/html',\n 'Sec-Fetch-Dest': 'document',\n 'Sec-Fetch-Mode': 'navigate',\n },\n });\n const probeHeaders: Record<string, string> = {\n Accept: 'text/html',\n 'Sec-Fetch-Dest': 'iframe',\n 'Sec-Fetch-Mode': 'navigate',\n ...(options.adminOrigin === undefined ? {} : { Referer: previewReferer(options.adminOrigin) }),\n };\n const sent = callerHeaders(options.previewHeaders, probeHeaders);\n const previewResponse = await fetchImpl(previewUrl(options.url, params), {\n headers: { ...sent, ...probeHeaders },\n });\n return analyzeProbe(\n { publicResponse, previewResponse },\n {\n url: redactToken(options.url, tokenParam),\n adminOrigin: options.adminOrigin,\n ...(options.v2 === true ? { v2: true } : {}),\n ...(Object.keys(sent).length > 0 || carriesToken(options.url, tokenParam)\n ? { credentials: true }\n : {}),\n },\n );\n}\n","#!/usr/bin/env node\n/**\n * The `pll` binary: `pll doctor <url>` here, `pll migrate <path>` in\n * migrate/cli. Doctor exit codes: 0 no error-level findings, 1 usage error or\n * the URL could not be fetched, 2 at least one error-level finding.\n */\nimport { runMigrateCommand } from '../migrate/cli';\nimport { formatReport } from './format';\nimport { describeFailure, redactToken, runDoctor, type DoctorFetch } from './probe';\n\ninterface ParsedArgs {\n url: string | undefined;\n adminOrigin: string | undefined;\n json: boolean;\n v2: boolean;\n showHelp: boolean;\n unknown: string[];\n /** Headers for the preview probe, from every `--header`/`-H` and `--header-env`. */\n headers: Record<string, string>;\n /** The first `--header`, `--header-env` or `--param` that could not be read, as the message to print. */\n usageError: string | undefined;\n /** Query parameter names from every `--param`. */\n params: string[];\n /** The token parameter from `--token-param`, where the strategy reads one other than `previewToken`. */\n tokenParam: string | undefined;\n}\n\n/** A query parameter name: no separator, no space, and not the next option. */\nconst PARAM_NAME = /^[^\\s&=#?-][^\\s&=#]*$/u;\n\n/** An HTTP field name (RFC 9110 token), a colon, then the value. */\nconst HEADER_LINE = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+):[ \\t]*(.*)$/u;\n\n/** A POSIX shell variable name. */\nconst ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/u;\n\nconst HEADER_USAGE =\n 'pll doctor: --header takes \"Name: value\", such as --header \"Cookie: payload-token=…\"';\n\nfunction addHeader(parsed: ParsedArgs, line: string | undefined, invalid = HEADER_USAGE): void {\n // A missing value would otherwise read the next argument: `https://example.com/`\n // matches as name `https`, and `--v2` as no header at all.\n const match =\n line === undefined || line.startsWith('-') || isAbsoluteUrl(line)\n ? null\n : HEADER_LINE.exec(line);\n const name = match?.[1];\n const value = match?.[2];\n if (name === undefined || value === undefined) {\n // The value is not echoed: a mistyped header can still hold half a token.\n parsed.usageError ??= invalid;\n return;\n }\n // Header names are case-insensitive; a second spelling would be joined onto\n // the first by fetch, and a repeat would silently replace it.\n if (Object.keys(parsed.headers).some((given) => given.toLowerCase() === name.toLowerCase())) {\n parsed.usageError ??= `pll doctor: --header \"${name}\" is given twice; join the values into one header`;\n return;\n }\n parsed.headers[name] = value;\n}\n\n/**\n * A header line read from the environment. The shell expands `--header \"Cookie: …=$TOKEN\"` into\n * the doctor's argv, which every user of a Linux host can read in /proc/<pid>/cmdline while it\n * runs; /proc/<pid>/environ is readable by the owner alone.\n */\nfunction addHeaderFromEnv(parsed: ParsedArgs, name: string | undefined): void {\n if (name === undefined || !ENV_NAME.test(name)) {\n parsed.usageError ??=\n 'pll doctor: --header-env takes the name of an environment variable that holds \"Name: value\", such as --header-env PLP_DOCTOR_HEADER';\n return;\n }\n const line = process.env[name];\n if (line === undefined || line === '') {\n parsed.usageError ??= `pll doctor: --header-env ${name}: the variable is not set`;\n return;\n }\n addHeader(\n parsed,\n line,\n `pll doctor: --header-env ${name} must hold \"Name: value\", such as \"Cookie: payload-token=…\"`,\n );\n}\n\nfunction addParam(parsed: ParsedArgs, name: string | undefined): void {\n if (name === undefined || !PARAM_NAME.test(name)) {\n parsed.usageError ??= 'pll doctor: --param takes a query parameter name, such as --param draft';\n return;\n }\n parsed.params.push(name);\n}\n\nfunction setTokenParam(parsed: ParsedArgs, name: string | undefined): void {\n if (name === undefined || !PARAM_NAME.test(name)) {\n parsed.usageError ??=\n 'pll doctor: --token-param takes a query parameter name, such as --token-param lpt';\n return;\n }\n parsed.tokenParam = name;\n}\n\nfunction parseArgs(argv: readonly string[]): ParsedArgs {\n const parsed: ParsedArgs = {\n url: undefined,\n adminOrigin: undefined,\n json: false,\n v2: false,\n showHelp: false,\n unknown: [],\n headers: {},\n usageError: undefined,\n params: [],\n tokenParam: undefined,\n };\n for (let i = 0; i < argv.length; i += 1) {\n const token = argv[i];\n if (token === undefined) continue;\n if (token === '-h' || token === '--help') parsed.showHelp = true;\n else if (token === '--json') parsed.json = true;\n else if (token === '--v2') parsed.v2 = true;\n else if (token === '--admin' || token === '-a') {\n parsed.adminOrigin = argv[i + 1];\n i += 1;\n } else if (token.startsWith('--admin=')) parsed.adminOrigin = token.slice('--admin='.length);\n else if (token === '--header' || token === '-H') {\n addHeader(parsed, argv[i + 1]);\n i += 1;\n } else if (token.startsWith('--header=')) addHeader(parsed, token.slice('--header='.length));\n else if (token === '--header-env') {\n addHeaderFromEnv(parsed, argv[i + 1]);\n i += 1;\n } else if (token.startsWith('--header-env=')) {\n addHeaderFromEnv(parsed, token.slice('--header-env='.length));\n } else if (token === '--param') {\n addParam(parsed, argv[i + 1]);\n i += 1;\n } else if (token.startsWith('--param=')) addParam(parsed, token.slice('--param='.length));\n else if (token === '--token-param') {\n setTokenParam(parsed, argv[i + 1]);\n i += 1;\n } else if (token.startsWith('--token-param=')) {\n setTokenParam(parsed, token.slice('--token-param='.length));\n } else if (token.startsWith('-')) parsed.unknown.push(token);\n else parsed.url ??= token;\n }\n return parsed;\n}\n\nconst HELP_TEXT = `pll doctor — audit what a live-preview deployment actually serves\npll migrate — rewrite 1.x APIs to their 2.0 names and homes\n\nUsage:\n pll doctor <url> [--admin <origin>] [--header <name: value>]... [--header-env <var>]...\n [--param <name>]... [--token-param <name>] [--json] [--v2]\n pll migrate <path> [--write] [--only <id,id>]\n\nThe URL is fetched twice: once as an ordinary visitor, without any intent\nparameter, and once the way the Payload admin's iframe loads it, with\n?preview=true and the iframe's headers.\nMost findings come from the difference between the two responses. Redirects\nare reported, not followed.\n\nOptions of pll doctor:\n -a, --admin <origin> Admin origin the preview is embedded from. Enables the\n frame-ancestors check to verify the origin is admitted,\n not merely that a policy exists.\n -H, --header <h> A header for the preview request only, as \"Name: value\";\n repeat it for more. A preview behind authorizePreview\n needs an editor's credentials: a Payload session Cookie,\n or an x-preview-token where the token strategy sets\n transport: { kind: 'header' }. A signed token travels in\n the URL by default, as ?previewToken=…, which the visitor\n request drops. The visitor request stays anonymous and\n values are never printed, but a shell keeps them in its\n history, so prefer a short-lived token.\n --header-env <var>\n Like --header, with \"Name: value\" read from the\n environment variable <var>; repeat it for more. The\n shell puts a --header value into the doctor's command\n line, which other users of the host can read while it\n runs; the environment only the doctor's owner can.\n --param <name> A query parameter the deployment reads as preview intent,\n for an adapter whose previewQueryParams replaces the\n default preview, draft and livePreview; repeat it for\n more. The first one is what the preview request carries\n as <name>=true; none of them reaches the visitor request.\n --token-param <n> The query parameter the signed-token strategy reads,\n where its transport names one other than previewToken.\n Treated like previewToken: dropped from the visitor\n request, counted as the credential, never printed.\n --json Emit the report as JSON instead of text\n --v2 Also check the page against the 2.0 readiness table\n -h, --help Show this help\n\nExit codes of pll doctor:\n 0 no error-level findings\n 1 usage error, or the URL could not be fetched\n 2 at least one error-level finding\n\npll migrate has its own options and exit codes: pll migrate --help\n\nExamples:\n pll doctor https://example.com/\n pll doctor https://example.com/blog/hello --admin https://cms.example.com\n pll doctor \"https://example.com/?previewToken=$PREVIEW_TOKEN\" --v2\n pll doctor https://example.com/ --header \"Cookie: payload-token=$PAYLOAD_TOKEN\"\n PLP_DOCTOR_HEADER=\"Cookie: payload-token=$PAYLOAD_TOKEN\" \\\\\n pll doctor https://example.com/ --header-env PLP_DOCTOR_HEADER\n`;\n\nfunction isAbsoluteUrl(value: string): boolean {\n try {\n return new URL(value).origin !== 'null';\n } catch {\n return false;\n }\n}\n\n/** @param fetchImpl Seam for tests; the bin shim never passes it. */\nexport async function run(argv: readonly string[], fetchImpl?: DoctorFetch): Promise<number> {\n const [subcommand, ...rest] = argv;\n if (subcommand === undefined || subcommand === '-h' || subcommand === '--help') {\n process.stdout.write(HELP_TEXT);\n return subcommand === undefined ? 1 : 0;\n }\n if (subcommand === 'migrate') return runMigrateCommand(rest);\n if (subcommand !== 'doctor') {\n process.stderr.write(`pll: unknown command \"${subcommand}\". Try \\`pll --help\\`.\\n`);\n return 1;\n }\n const args = parseArgs(rest);\n if (args.showHelp) {\n process.stdout.write(HELP_TEXT);\n return 0;\n }\n if (args.unknown.length > 0) {\n process.stderr.write(`pll doctor: unknown option ${args.unknown.join(', ')}\\n`);\n return 1;\n }\n if (args.url === undefined) {\n process.stderr.write('pll doctor: a URL is required. Try `pll doctor --help`.\\n');\n return 1;\n }\n if (args.usageError !== undefined) {\n process.stderr.write(`${args.usageError}\\n`);\n return 1;\n }\n if (args.adminOrigin !== undefined && !isAbsoluteUrl(args.adminOrigin)) {\n process.stderr.write(\n `pll doctor: --admin must be an absolute URL such as https://cms.example.com (got \"${args.adminOrigin}\")\\n`,\n );\n return 1;\n }\n let report;\n try {\n report = await runDoctor({\n url: args.url,\n ...(args.adminOrigin !== undefined ? { adminOrigin: args.adminOrigin } : {}),\n ...(args.v2 ? { v2: true } : {}),\n ...(Object.keys(args.headers).length > 0 ? { previewHeaders: args.headers } : {}),\n ...(args.params.length > 0 ? { previewQueryParams: args.params } : {}),\n ...(args.tokenParam === undefined ? {} : { tokenQueryParam: args.tokenParam }),\n ...(fetchImpl !== undefined ? { fetchImpl } : {}),\n });\n } catch (error) {\n const message = describeFailure(error);\n const shown = redactToken(args.url, args.tokenParam);\n if (args.json) {\n process.stdout.write(`${JSON.stringify({ url: shown, error: message }, undefined, 2)}\\n`);\n } else {\n process.stderr.write(`pll doctor: could not probe ${shown}: ${message}\\n`);\n }\n return 1;\n }\n process.stdout.write(\n args.json ? `${JSON.stringify(report, undefined, 2)}\\n` : formatReport(report),\n );\n return report.errors > 0 ? 2 : 0;\n}\n\n/** Matches the entry's basename only, so importing this module from a path containing `pll` never runs it. */\nexport function isCliInvocation(argv: readonly (string | undefined)[] = process.argv): boolean {\n if (typeof process === 'undefined') return false;\n const entry = argv[1];\n if (entry === undefined || entry === '') return false;\n const name = entry.split(/[\\\\/]/u).pop() ?? '';\n return name === 'pll' || name === 'pll.cmd' || name.startsWith('doctor-cli');\n}\n\nif (isCliInvocation()) {\n void run(process.argv.slice(2)).then((code) => {\n process.exit(code);\n });\n}\n"],"mappings":"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","ignoreList":[]}