livelocale 0.8.0 → 0.9.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 (53) hide show
  1. package/README.md +230 -5
  2. package/dist/client/index.cjs +178 -70
  3. package/dist/client/index.cjs.map +1 -1
  4. package/dist/client/index.d.cts +36 -22
  5. package/dist/client/index.d.ts +36 -22
  6. package/dist/client/index.js +177 -70
  7. package/dist/client/index.js.map +1 -1
  8. package/dist/codemod/index.cjs +3057 -152
  9. package/dist/codemod/index.cjs.map +1 -1
  10. package/dist/codemod/index.js +3058 -153
  11. package/dist/codemod/index.js.map +1 -1
  12. package/dist/react/index.cjs +185 -77
  13. package/dist/react/index.cjs.map +1 -1
  14. package/dist/react/index.js +185 -77
  15. package/dist/react/index.js.map +1 -1
  16. package/dist/server/index.cjs +108 -66
  17. package/dist/server/index.cjs.map +1 -1
  18. package/dist/server/index.d.cts +13 -3
  19. package/dist/server/index.d.ts +13 -3
  20. package/dist/server/index.js +107 -66
  21. package/dist/server/index.js.map +1 -1
  22. package/dist/studio/assets/index-Bvbtkry-.css +1 -0
  23. package/dist/studio/assets/index-DC_jRsox.js +13 -0
  24. package/dist/studio/assets/inter-latin-300-normal-BVlfKGgI.woff2 +0 -0
  25. package/dist/studio/assets/inter-latin-300-normal-i8F0SvXL.woff +0 -0
  26. package/dist/studio/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  27. package/dist/studio/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  28. package/dist/studio/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  29. package/dist/studio/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  30. package/dist/studio/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
  31. package/dist/studio/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  32. package/dist/studio/assets/inter-latin-700-normal-BLAVimhd.woff +0 -0
  33. package/dist/studio/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
  34. package/dist/studio/assets/outfit-latin-400-normal-BGsTXAXT.woff2 +0 -0
  35. package/dist/studio/assets/outfit-latin-400-normal-DMwTpYkH.woff +0 -0
  36. package/dist/studio/assets/outfit-latin-500-normal-ClnHRwRh.woff +0 -0
  37. package/dist/studio/assets/outfit-latin-500-normal-DKnIMDSk.woff2 +0 -0
  38. package/dist/studio/assets/outfit-latin-600-normal-B7SfZ07L.woff2 +0 -0
  39. package/dist/studio/assets/outfit-latin-600-normal-BEfTtDA7.woff +0 -0
  40. package/dist/studio/assets/outfit-latin-700-normal-Cu9v6i1X.woff2 +0 -0
  41. package/dist/studio/assets/outfit-latin-700-normal-D4itBLBr.woff +0 -0
  42. package/dist/studio/index.html +3 -6
  43. package/dist/vite/index.cjs +739 -77
  44. package/dist/vite/index.cjs.map +1 -1
  45. package/dist/vite/index.d.cts +22 -2
  46. package/dist/vite/index.d.ts +22 -2
  47. package/dist/vite/index.js +738 -77
  48. package/dist/vite/index.js.map +1 -1
  49. package/dist/{wrap-CsOtHp8r.d.cts → wrap-2qVxLN9Q.d.cts} +10 -18
  50. package/dist/{wrap-CsOtHp8r.d.ts → wrap-2qVxLN9Q.d.ts} +10 -18
  51. package/package.json +4 -1
  52. package/dist/studio/assets/index-D7ifnqy5.js +0 -10
  53. package/dist/studio/assets/index-Zh0KtFUH.css +0 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/codemod/transform.ts","../../src/codemod/index.ts","../../src/codemod/studio-server.ts","../../src/codemod/doctor.ts","../../src/core/validate.ts","../../src/codemod/check.ts","../../src/core/placeholders.ts","../../src/server/key-scanner.ts","../../src/core/env.ts","../../src/core/gitignore.ts"],"sourcesContent":["// Type-only import: the runtime module is loaded lazily by `loadTypeScript()`.\nimport type * as ts from 'typescript';\n\ntype TypeScriptModule = typeof ts;\n\n/**\n * `typescript` is an optional peer: it is only needed by `migrate`. Loading it\n * lazily keeps `init` and `studio` working in JavaScript-only projects.\n */\nexport async function loadTypeScript(): Promise<TypeScriptModule> {\n try {\n const mod: any = await import('typescript');\n return (mod.default ?? mod) as TypeScriptModule;\n } catch {\n throw new Error(\n \"The 'typescript' package is required for the migrate command. Install it with: npm install -D typescript\"\n );\n }\n}\n\nexport interface TransformResult {\n code: string;\n modified: boolean;\n}\n\n/**\n * Transforms a source file by wrapping react-i18next useTranslation hook calls\n * with wrapTranslationEngine.\n */\nexport async function transformReactI18next(\n sourceText: string,\n filename: string\n): Promise<TransformResult> {\n const ts = await loadTypeScript();\n const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true);\n\n let hasUseTranslationImport = false;\n let alreadyHasWrapImport = false;\n let useTranslationImportNode: ts.Node | null = null;\n let localUseTranslationName = 'useTranslation';\n\n // Step 1: Find imports\n function findImports(node: ts.Node) {\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = node.moduleSpecifier;\n if (ts.isStringLiteral(moduleSpecifier)) {\n if (moduleSpecifier.text === 'react-i18next') {\n const importClause = node.importClause;\n if (\n importClause &&\n importClause.namedBindings &&\n ts.isNamedImports(importClause.namedBindings)\n ) {\n for (const specifier of importClause.namedBindings.elements) {\n const importedName = specifier.propertyName\n ? specifier.propertyName.text\n : specifier.name.text;\n if (importedName === 'useTranslation') {\n hasUseTranslationImport = true;\n localUseTranslationName = specifier.name.text;\n useTranslationImportNode = node;\n }\n }\n }\n }\n if (\n moduleSpecifier.text === 'livelocale/client' ||\n moduleSpecifier.text === 'livelocale/server'\n ) {\n alreadyHasWrapImport = true;\n }\n }\n }\n ts.forEachChild(node, findImports);\n }\n\n findImports(sourceFile);\n\n if (!hasUseTranslationImport) {\n return { code: sourceText, modified: false };\n }\n\n interface Edit {\n start: number;\n end: number;\n text: string;\n index: number; // for stable sorting\n }\n const edits: Edit[] = [];\n let editCount = 0;\n\n // Step 2: Find useTranslation calls and their statement structures\n function findHookCalls(node: ts.Node) {\n if (ts.isVariableStatement(node)) {\n const declList = node.declarationList;\n for (const decl of declList.declarations) {\n if (decl.initializer && ts.isCallExpression(decl.initializer)) {\n const expr = decl.initializer.expression;\n if (ts.isIdentifier(expr) && expr.text === localUseTranslationName) {\n processHookCall(decl, node);\n }\n }\n }\n }\n ts.forEachChild(node, findHookCalls);\n }\n\n function isAlreadyWrapped(\n tLocalName: string,\n originalName: string,\n parentNode: ts.Node\n ): boolean {\n let found = false;\n function visit(node: ts.Node) {\n if (ts.isVariableDeclaration(node)) {\n if (ts.isIdentifier(node.name) && node.name.text === originalName) {\n if (node.initializer) {\n if (ts.isCallExpression(node.initializer)) {\n const expr = node.initializer.expression;\n if (ts.isIdentifier(expr) && expr.text === 'wrapTranslationEngine') {\n if (node.initializer.arguments.length > 0) {\n const arg = node.initializer.arguments[0];\n if (arg && ts.isIdentifier(arg) && arg.text === tLocalName) {\n found = true;\n }\n }\n }\n } else if (ts.isObjectLiteralExpression(node.initializer)) {\n let hasSpread = false;\n let hasWrap = false;\n for (const prop of node.initializer.properties) {\n if (ts.isSpreadAssignment(prop)) {\n if (ts.isIdentifier(prop.expression) && prop.expression.text === tLocalName) {\n hasSpread = true;\n }\n } else if (ts.isPropertyAssignment(prop)) {\n if (ts.isIdentifier(prop.name) && prop.name.text === 't') {\n if (ts.isCallExpression(prop.initializer)) {\n const expr = prop.initializer.expression;\n if (ts.isIdentifier(expr) && expr.text === 'wrapTranslationEngine') {\n hasWrap = true;\n }\n }\n }\n }\n }\n if (hasSpread && hasWrap) {\n found = true;\n }\n }\n }\n }\n }\n if (!found) {\n ts.forEachChild(node, visit);\n }\n }\n visit(parentNode);\n return found;\n }\n\n function processHookCall(\n declaration: ts.VariableDeclaration,\n variableStatement: ts.VariableStatement\n ) {\n const callNode = declaration.initializer as ts.CallExpression;\n\n // Extract keyPrefix expression if present\n let keyPrefixExpr: string | undefined = undefined;\n if (callNode.arguments.length > 0) {\n const firstArg = callNode.arguments[0]!;\n if (ts.isStringLiteral(firstArg)) {\n keyPrefixExpr = `'${firstArg.text}'`;\n } else if (ts.isArrayLiteralExpression(firstArg)) {\n if (firstArg.elements.length > 0) {\n const firstElem = firstArg.elements[0]!;\n keyPrefixExpr = firstElem.getText(sourceFile);\n }\n } else {\n keyPrefixExpr = firstArg.getText(sourceFile);\n }\n }\n\n // Determine indentation of the statement\n const statementStart = variableStatement.getStart(sourceFile);\n let lineStart = statementStart;\n while (\n lineStart > 0 &&\n sourceText[lineStart - 1] !== '\\n' &&\n sourceText[lineStart - 1] !== '\\r'\n ) {\n lineStart--;\n }\n const indentation = sourceText.slice(lineStart, statementStart).match(/^\\s*/)?.[0] || '';\n const wrapOptions = keyPrefixExpr ? `, { keyPrefix: ${keyPrefixExpr} }` : '';\n\n const nameNode = declaration.name;\n\n // Pattern A: Object Destructuring: const { t } = useTranslation()\n if (ts.isObjectBindingPattern(nameNode)) {\n let tElement: ts.BindingElement | null = null;\n for (const element of nameNode.elements) {\n if (ts.isIdentifier(element.name)) {\n const propName = element.propertyName\n ? ts.isIdentifier(element.propertyName)\n ? element.propertyName.text\n : element.propertyName.getText(sourceFile)\n : (element.name as ts.Identifier).text;\n if (propName === 't') {\n tElement = element;\n break;\n }\n }\n }\n\n if (tElement && ts.isIdentifier(tElement.name)) {\n const tLocalName = tElement.name.text;\n\n // Determine original/desired name of the translation variable (e.g. 't' or a custom rename)\n let desiredName = tLocalName;\n if (tLocalName.startsWith('raw') && tLocalName.length > 3) {\n const base = tLocalName.slice(3);\n desiredName = base.charAt(0).toLowerCase() + base.slice(1);\n } else if (tElement.propertyName && ts.isIdentifier(tElement.propertyName)) {\n desiredName = tLocalName;\n } else {\n desiredName = 't';\n }\n\n if (\n variableStatement.parent &&\n isAlreadyWrapped(tLocalName, desiredName, variableStatement.parent)\n ) {\n return;\n }\n\n const rawLocalName = `raw${desiredName.charAt(0).toUpperCase()}${desiredName.slice(1)}`;\n\n // Replace \"t\" or \"t: customName\" with \"t: rawName\"\n edits.push({\n start: tElement.getStart(sourceFile),\n end: tElement.getEnd(),\n text: `t: ${rawLocalName}`,\n index: editCount++,\n });\n\n // Insert wrap translation statement right after the variable statement\n edits.push({\n start: variableStatement.getEnd(),\n end: variableStatement.getEnd(),\n text: `\\n${indentation}const ${desiredName} = wrapTranslationEngine(${rawLocalName}${wrapOptions});`,\n index: editCount++,\n });\n }\n }\n // Pattern B: Array Destructuring: const [ t ] = useTranslation()\n else if (ts.isArrayBindingPattern(nameNode)) {\n if (nameNode.elements.length > 0) {\n const firstElement = nameNode.elements[0]!;\n if (ts.isBindingElement(firstElement) && ts.isIdentifier(firstElement.name)) {\n const tLocalName = firstElement.name.text;\n\n let desiredName = tLocalName;\n if (tLocalName.startsWith('raw') && tLocalName.length > 3) {\n const base = tLocalName.slice(3);\n desiredName = base.charAt(0).toLowerCase() + base.slice(1);\n }\n\n if (\n variableStatement.parent &&\n isAlreadyWrapped(tLocalName, desiredName, variableStatement.parent)\n ) {\n return;\n }\n\n const rawLocalName = `raw${desiredName.charAt(0).toUpperCase()}${desiredName.slice(1)}`;\n\n // Replace first element with rawName\n edits.push({\n start: firstElement.getStart(sourceFile),\n end: firstElement.getEnd(),\n text: rawLocalName,\n index: editCount++,\n });\n\n // Insert wrap translation statement right after the variable statement\n edits.push({\n start: variableStatement.getEnd(),\n end: variableStatement.getEnd(),\n text: `\\n${indentation}const ${desiredName} = wrapTranslationEngine(${rawLocalName}${wrapOptions});`,\n index: editCount++,\n });\n }\n }\n }\n // Pattern C: Simple Assignment: const translation = useTranslation()\n else if (ts.isIdentifier(nameNode)) {\n const tLocalName = nameNode.text;\n\n let desiredName = tLocalName;\n if (tLocalName.startsWith('raw') && tLocalName.length > 3) {\n const base = tLocalName.slice(3);\n desiredName = base.charAt(0).toLowerCase() + base.slice(1);\n }\n\n if (\n variableStatement.parent &&\n isAlreadyWrapped(tLocalName, desiredName, variableStatement.parent)\n ) {\n return;\n }\n\n const rawLocalName = `raw${desiredName.charAt(0).toUpperCase()}${desiredName.slice(1)}`;\n\n // Replace name with rawName\n edits.push({\n start: nameNode.getStart(sourceFile),\n end: nameNode.getEnd(),\n text: rawLocalName,\n index: editCount++,\n });\n\n // Insert wrapper structure right after the variable statement\n edits.push({\n start: variableStatement.getEnd(),\n end: variableStatement.getEnd(),\n text: `\\n${indentation}const ${desiredName} = { ...${rawLocalName}, t: wrapTranslationEngine(${rawLocalName}.t${wrapOptions}) };`,\n index: editCount++,\n });\n }\n }\n\n findHookCalls(sourceFile);\n\n if (edits.length === 0) {\n return { code: sourceText, modified: false };\n }\n\n // Step 3: Insert wrap import if not already present\n if (!alreadyHasWrapImport) {\n if (useTranslationImportNode) {\n const insertPos = (useTranslationImportNode as ts.Node).getEnd();\n edits.push({\n start: insertPos,\n end: insertPos,\n text: `\\nimport { wrapTranslationEngine } from 'livelocale/client';`,\n index: editCount++,\n });\n } else {\n let insertPos = 0;\n const useClientMatch = sourceText.match(/^['\"]use client['\"];?\\s*/);\n if (useClientMatch) {\n insertPos = useClientMatch[0].length;\n }\n edits.push({\n start: insertPos,\n end: insertPos,\n text: `import { wrapTranslationEngine } from 'livelocale/client';\\n`,\n index: editCount++,\n });\n }\n }\n\n // Step 4: Apply edits in reverse order\n edits.sort((a, b) => {\n if (b.start !== a.start) {\n return b.start - a.start;\n }\n // If same start index, preserve original relative order descending (so insertions don't scramble)\n return b.index - a.index;\n });\n\n let newText = sourceText;\n for (const edit of edits) {\n newText = newText.slice(0, edit.start) + edit.text + newText.slice(edit.end);\n }\n\n return { code: newText, modified: true };\n}\n","#!/usr/bin/env node\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as net from 'net';\nimport { fileURLToPath } from 'url';\nimport { createStudioServer } from './studio-server.js';\nimport { runDoctor, formatFindings, hasFailures } from './doctor.js';\nimport { runCheck, formatCheckReport, hasCheckFailures } from './check.js';\n\nconst getDirname = () => {\n if (typeof __dirname !== 'undefined') {\n return __dirname;\n }\n return path.dirname(fileURLToPath((import.meta as any).url));\n};\n\nconst DEFAULT_STUDIO_PORT = 3010;\nconst DEFAULT_APP_ORIGIN = 'http://localhost:3000';\n\nfunction printHelp() {\n console.log(`\nLiveLocale (livelocale) CLI\n\nUsage:\n npx livelocale <command> [options]\n\nCommands:\n migrate Bulk migrate existing react-i18next translation usages to wrap them with wrapTranslationEngine automatically.\n init Initialize the API route handler inside a Next.js project automatically.\n studio Start the visual editing studio local web server.\n doctor Check the project for common integration problems (route, provider, middleware, CSP, locales).\n check Check translations for missing keys, placeholder drift, broken ICU syntax and unused keys (CI-friendly).\n\nOptions for migrate:\n --dir <path> Directory to scan (default: current directory)\n --exclude <list> Comma-separated list of directories to exclude (default: node_modules,.next,dist,.git)\n --dry-run Preview changes without writing them to disk\n\nOptions for init:\n --dir <path> Target project directory (default: current directory)\n\nOptions for studio:\n --port <number> Port to run the studio server on (default: ${DEFAULT_STUDIO_PORT})\n --app <origin> Origin of the app being edited (default: ${DEFAULT_APP_ORIGIN})\n Can also be changed at run time with ?app=<origin> on the Studio URL.\n\nOptions for doctor:\n --dir <path> Project directory to inspect (default: current directory)\n --locales <path> Locales directory relative to the project (default: locales)\n --app <origin> Also probe the running app, e.g. http://localhost:3000\n --token <token> Access token for a preview deployment (default: LIVELOCALE_TOKEN)\n\nOptions for check:\n --dir <path> Project directory to scan (default: current directory)\n --locales <path> Locales directory relative to the project (default: locales)\n --source <locale> Locale the others are compared against (default: en, else the first locale)\n --no-unused Do not report keys that code never references\n --strict Treat warnings (unused keys, empty values) as failures\n --json Print the full report as JSON\n\nGlobal Options:\n -h, --help Show help information\n`);\n}\n\nfunction normalizeOriginArg(value: string, flag: string): string {\n try {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') throw new Error('bad protocol');\n return url.origin;\n } catch {\n console.error(\n `Error: ${flag} must be an http(s) origin such as http://localhost:3001 (got \"${value}\").`\n );\n process.exit(1);\n }\n}\n\n/**\n * True when something already accepts connections on localhost:port. On Windows\n * another process can hold [::1]:port while our [::]:port bind still succeeds,\n * so the browser would silently reach the other server.\n */\nfunction isPortAnswering(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = net.connect({ host: 'localhost', port });\n const done = (answering: boolean) => {\n socket.destroy();\n resolve(answering);\n };\n socket.setTimeout(1000, () => done(false));\n socket.once('connect', () => done(true));\n socket.once('error', () => done(false));\n });\n}\n\nasync function runStudio(port: number, appOrigin: string) {\n console.log(`\\n🚀 Starting LiveLocale Studio...`);\n const studioDir = path.resolve(getDirname(), '../studio');\n\n if (!fs.existsSync(path.join(studioDir, 'index.html'))) {\n console.error(`Error: Studio assets not found at \"${studioDir}\".`);\n console.error(`Did you build the project? Run \"npm run build\" first.`);\n process.exit(1);\n }\n\n if (await isPortAnswering(port)) {\n console.error(\n `Error: something is already running on localhost:${port}. Stop it or pick another port with --port <number>.`\n );\n process.exit(1);\n }\n\n const server = createStudioServer({ studioDir, appOrigin });\n\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.error(`Error: port ${port} is already in use. Pick another with --port <number>.`);\n } else {\n console.error(`Error: failed to start the Studio server: ${err.message}`);\n }\n process.exit(1);\n });\n\n server.listen(port, () => {\n console.log(`\\n🎨 LiveLocale Studio is running!`);\n console.log(`📡 Studio: http://localhost:${port}`);\n console.log(`🔗 Editing app at: ${appOrigin}`);\n console.log(`💡 Press Ctrl+C to stop the studio server.\\n`);\n });\n}\n\nfunction runInit(projectDir: string) {\n console.log(`\\n🚀 Initializing LiveLocale API handler...`);\n const absoluteDir = path.resolve(projectDir);\n if (!fs.existsSync(absoluteDir)) {\n console.error(`Error: Directory \"${projectDir}\" does not exist.`);\n process.exit(1);\n }\n\n // 1. Detect TypeScript vs. JavaScript\n const isTypeScript = fs.existsSync(path.join(absoluteDir, 'tsconfig.json'));\n const fileExt = isTypeScript ? 'ts' : 'js';\n console.log(`📁 Target: ${absoluteDir}`);\n console.log(`🔧 Language detected: ${isTypeScript ? 'TypeScript' : 'JavaScript'}`);\n\n // 2. Check for installed libraries in package.json\n let hasNextIntl = false;\n let hasReactI18next = false;\n const targetPkgPath = path.join(absoluteDir, 'package.json');\n if (fs.existsSync(targetPkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(targetPkgPath, 'utf8'));\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n hasNextIntl = Boolean(allDeps['next-intl']);\n hasReactI18next = Boolean(allDeps['react-i18next']);\n } catch {}\n }\n\n // 3. Check for App Router vs Pages Router\n const appDirPath = path.join(absoluteDir, 'app');\n const pagesDirPath = path.join(absoluteDir, 'pages');\n const srcAppDirPath = path.join(absoluteDir, 'src', 'app');\n const srcPagesDirPath = path.join(absoluteDir, 'src', 'pages');\n\n let targetPath = '';\n let routerType = '';\n let content = '';\n\n if (fs.existsSync(appDirPath)) {\n targetPath = path.join(appDirPath, 'api', 'livelocale', `route.${fileExt}`);\n routerType = 'Next.js App Router (root)';\n } else if (fs.existsSync(srcAppDirPath)) {\n targetPath = path.join(srcAppDirPath, 'api', 'livelocale', `route.${fileExt}`);\n routerType = 'Next.js App Router (src/)';\n } else if (fs.existsSync(pagesDirPath)) {\n targetPath = path.join(pagesDirPath, 'api', `livelocale.${fileExt}`);\n routerType = 'Next.js Pages Router (root)';\n } else if (fs.existsSync(srcPagesDirPath)) {\n targetPath = path.join(srcPagesDirPath, 'api', `livelocale.${fileExt}`);\n routerType = 'Next.js Pages Router (src/)';\n } else {\n // Default fallback to root app router structure\n targetPath = path.join(absoluteDir, 'app', 'api', 'livelocale', `route.${fileExt}`);\n routerType = 'Default App Router (app/ not found)';\n }\n\n console.log(`📍 Project structure: ${routerType}`);\n\n if (routerType.includes('App Router')) {\n content = `import { createLiveLocaleHandler } from 'livelocale/server';\nimport * as path from 'path';\n\nconst handler = createLiveLocaleHandler({\n localesPath: path.resolve('./locales'), // Adjust relative to project root\n});\n\nexport const GET = handler;\nexport const POST = handler;\nexport const OPTIONS = handler;\n`;\n } else {\n content = `import { createLiveLocaleHandler } from 'livelocale/server';\nimport * as path from 'path';\n\n// Pages Router API route: the handler accepts the (req, res) signature.\nconst handler = createLiveLocaleHandler({\n localesPath: path.resolve('./locales'), // Adjust relative to project root\n});\n\nexport default handler;\n`;\n }\n\n // Ensure target folder exists\n const targetDir = path.dirname(targetPath);\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n\n // Write file\n try {\n fs.writeFileSync(targetPath, content, 'utf8');\n console.log(`✅ Created API Route Handler successfully at:`);\n console.log(` ${path.relative(absoluteDir, targetPath)}`);\n if (hasNextIntl) {\n console.log(`\\n💡 Detected 'next-intl' in your project!`);\n console.log(\n ` Wrap your translation hook with: import { wrapNextIntl } from 'livelocale/client';`\n );\n console.log(` const t = wrapNextIntl(useTranslations('namespace'), 'namespace');`);\n } else if (hasReactI18next) {\n console.log(`\\n💡 Detected 'react-i18next' in your project!`);\n console.log(` You can auto-wrap usages by running: npx livelocale migrate`);\n }\n console.log(`\\n🎉 Initialization completed successfully!\\n`);\n } catch (err: any) {\n console.error(`❌ Failed to write route handler: ${err.message}`);\n process.exit(1);\n }\n}\n\nasync function runMigrate(args: string[]) {\n let dir = '.';\n let excludes = ['node_modules', '.next', 'dist', '.git'];\n let dryRun = false;\n\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--dir') {\n dir = args[++i] || '.';\n } else if (arg === '--exclude') {\n const val = args[++i];\n if (val) {\n excludes = val.split(',').map((s) => s.trim());\n }\n } else if (arg === '--dry-run') {\n dryRun = true;\n } else {\n // Positional dir arg if not prefixed\n if (arg && !arg.startsWith('--')) {\n dir = arg;\n }\n }\n }\n\n const absoluteDir = path.resolve(dir);\n if (!fs.existsSync(absoluteDir)) {\n console.error(`Error: Directory \"${dir}\" does not exist.`);\n process.exit(1);\n }\n\n // The codemod depends on the optional `typescript` peer; load it only here.\n let transformReactI18next: typeof import('./transform.js').transformReactI18next;\n try {\n const transform = await import('./transform.js');\n await transform.loadTypeScript();\n transformReactI18next = transform.transformReactI18next;\n } catch (err: any) {\n console.error(`❌ ${err.message}`);\n process.exit(1);\n }\n\n console.log(`\\n🚀 Starting migration scanner...`);\n console.log(`📁 Target: ${absoluteDir}`);\n console.log(`🚫 Excluded: ${excludes.join(', ')}`);\n if (dryRun) {\n console.log(`🧪 Mode: DRY RUN (no files will be modified)`);\n }\n console.log('--------------------------------------------------');\n\n let scannedCount = 0;\n let migratedCount = 0;\n\n async function walk(currentDir: string) {\n const files = fs.readdirSync(currentDir, { withFileTypes: true });\n\n for (const file of files) {\n const fullPath = path.join(currentDir, file.name);\n\n if (file.isDirectory()) {\n if (excludes.includes(file.name)) {\n continue;\n }\n await walk(fullPath);\n } else if (file.isFile()) {\n const ext = path.extname(file.name);\n if (['.js', '.jsx', '.ts', '.tsx'].includes(ext)) {\n scannedCount++;\n try {\n const content = fs.readFileSync(fullPath, 'utf8');\n const result = await transformReactI18next(content, fullPath);\n\n if (result.modified) {\n migratedCount++;\n const relativePath = path.relative(absoluteDir, fullPath);\n if (dryRun) {\n console.log(`[DRY RUN] Would migrate: ${relativePath}`);\n } else {\n fs.writeFileSync(fullPath, result.code, 'utf8');\n console.log(`✅ Migrated: ${relativePath}`);\n }\n }\n } catch (err: any) {\n console.error(`❌ Error processing file ${fullPath}:`, err.message);\n }\n }\n }\n }\n }\n\n try {\n await walk(absoluteDir);\n } catch (err: any) {\n console.error(`❌ Walk error:`, err.message);\n }\n\n console.log('--------------------------------------------------');\n console.log(`📊 Summary:`);\n console.log(` Scanned: ${scannedCount} files`);\n if (dryRun) {\n console.log(` Would migrate: ${migratedCount} files`);\n } else {\n console.log(` Migrated: ${migratedCount} files`);\n }\n console.log(`\\n🎉 Done!`);\n}\n\nasync function runDoctorCommand(args: string[]) {\n let dir = '.';\n let localesPath: string | undefined;\n let appOrigin: string | undefined;\n let token: string | undefined;\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--dir') {\n dir = args[++i] || '.';\n } else if (arg === '--locales') {\n localesPath = args[++i];\n } else if (arg === '--app') {\n appOrigin = normalizeOriginArg(args[++i] || '', '--app');\n } else if (arg === '--token') {\n token = args[++i];\n } else if (arg && !arg.startsWith('--')) {\n dir = arg;\n }\n }\n\n const projectDir = path.resolve(dir);\n if (!fs.existsSync(projectDir)) {\n console.error(`Error: Directory \"${dir}\" does not exist.`);\n process.exit(1);\n }\n\n console.log(`\n🩺 LiveLocale doctor — ${projectDir}`);\n if (appOrigin) console.log(`🔗 Probing app at ${appOrigin}`);\n console.log('--------------------------------------------------');\n\n const findings = await runDoctor({ projectDir, localesPath, appOrigin, token });\n console.log(formatFindings(findings));\n console.log('--------------------------------------------------');\n\n const fails = findings.filter((f) => f.level === 'fail').length;\n const warns = findings.filter((f) => f.level === 'warn').length;\n if (hasFailures(findings)) {\n console.log(`❌ ${fails} problem(s), ${warns} warning(s). Fix the problems above and re-run.`);\n // exitCode, not exit(): open fetch sockets from --app probes crash Node on Windows otherwise.\n process.exitCode = 1;\n return;\n }\n console.log(\n warns > 0\n ? `✅ No blocking problems, ${warns} warning(s) worth a look.`\n : `✅ Everything looks good.`\n );\n if (!appOrigin) {\n console.log(\n `💡 Start your dev server and re-run with --app http://localhost:3000 for live checks.`\n );\n }\n}\n\nasync function runCheckCommand(args: string[]) {\n let dir = '.';\n let localesPath: string | undefined;\n let sourceLocale: string | undefined;\n let unused = true;\n let strict = false;\n let json = false;\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--dir') {\n dir = args[++i] || '.';\n } else if (arg === '--locales') {\n localesPath = args[++i];\n } else if (arg === '--source') {\n sourceLocale = args[++i];\n } else if (arg === '--no-unused') {\n unused = false;\n } else if (arg === '--strict') {\n strict = true;\n } else if (arg === '--json') {\n json = true;\n } else if (arg && !arg.startsWith('--')) {\n dir = arg;\n }\n }\n\n const projectDir = path.resolve(dir);\n if (!fs.existsSync(projectDir)) {\n console.error(`Error: Directory \"${dir}\" does not exist.`);\n process.exit(1);\n }\n\n let report;\n try {\n report = await runCheck({ projectDir, localesPath, sourceLocale, unused, strict });\n } catch (err: any) {\n console.error(`❌ ${err.message}`);\n process.exit(1);\n }\n\n const failed = hasCheckFailures(report);\n if (json) {\n console.log(JSON.stringify(report, null, 2));\n // exitCode, not exit(): exiting immediately can truncate a large report piped to another tool.\n process.exitCode = failed ? 1 : 0;\n return;\n }\n\n console.log(`\\n🔎 LiveLocale check — ${projectDir}`);\n console.log(\n `🌐 Locales: ${report.locales.join(', ') || 'none'}` +\n (report.sourceLocale ? ` (source: ${report.sourceLocale})` : '') +\n ` · ${report.codeKeyCount} key(s) referenced in code`\n );\n console.log('--------------------------------------------------');\n if (report.issues.length > 0) {\n console.log(formatCheckReport(report));\n console.log('--------------------------------------------------');\n }\n\n const fails = report.issues.filter((i) => i.level === 'fail').length;\n const warns = report.issues.filter((i) => i.level === 'warn').length;\n if (failed) {\n console.log(`❌ ${fails} problem(s), ${warns} warning(s).`);\n process.exitCode = 1;\n return;\n }\n console.log(\n warns > 0 ? `✅ No problems, ${warns} warning(s) worth a look.` : `✅ Translations look good.`\n );\n}\n\nasync function run() {\n const args = process.argv.slice(2);\n\n if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {\n printHelp();\n process.exit(0);\n }\n\n const COMMANDS = ['migrate', 'init', 'studio', 'doctor', 'check'];\n if (!args[0] || !COMMANDS.includes(args[0])) {\n console.error(`Unknown command: \"${args[0]}\". Expected one of: ${COMMANDS.join(', ')}.`);\n printHelp();\n process.exit(1);\n }\n\n if (args[0] === 'doctor') {\n await runDoctorCommand(args);\n return;\n }\n\n if (args[0] === 'check') {\n await runCheckCommand(args);\n return;\n }\n\n if (args[0] === 'init') {\n let dir = '.';\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--dir') {\n dir = args[++i] || '.';\n } else if (arg && !arg.startsWith('--')) {\n dir = arg;\n }\n }\n runInit(dir);\n process.exit(0);\n }\n\n if (args[0] === 'studio') {\n let port = DEFAULT_STUDIO_PORT;\n let appOrigin = DEFAULT_APP_ORIGIN;\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--port') {\n const val = parseInt(args[++i] || String(DEFAULT_STUDIO_PORT), 10);\n if (!isNaN(val)) port = val;\n } else if (arg === '--app') {\n appOrigin = normalizeOriginArg(args[++i] || '', '--app');\n }\n }\n await runStudio(port, appOrigin);\n return;\n }\n\n await runMigrate(args);\n}\n\nrun().catch((err: any) => {\n console.error(`❌ ${err?.message || err}`);\n process.exit(1);\n});\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as http from 'http';\n\nexport interface StudioConfig {\n /** Origin of the application being edited, e.g. `http://localhost:3001`. */\n appOrigin: string;\n}\n\nexport interface StudioServerOptions extends StudioConfig {\n /** Directory containing the built Studio assets (index.html + assets/). */\n studioDir: string;\n}\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css',\n '.js': 'application/javascript',\n '.mjs': 'application/javascript',\n '.map': 'application/json',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.json': 'application/json',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n};\n\n/** Any localhost origin (any port) is trusted — remote websites are not (RULE SEC-009). */\nconst LOCALHOST_ORIGIN_RE = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(:\\d+)?$/;\n\n/**\n * Injects `window.__LIVELOCALE_CONFIG__` into the Studio's index.html so the\n * app origin can be chosen at run time instead of at build time.\n *\n * RULE SEC-008: \"<\" and the U+2028/U+2029 line terminators are escaped so no\n * config value can terminate the script tag.\n */\nexport function injectStudioConfig(html: string, config: StudioConfig): string {\n const safeJson = JSON.stringify(config)\n .replace(/</g, '\\\\u003c')\n .replace(new RegExp(String.fromCharCode(0x2028), 'g'), '\\\\u2028')\n .replace(new RegExp(String.fromCharCode(0x2029), 'g'), '\\\\u2029');\n const script = `<script>window.__LIVELOCALE_CONFIG__ = ${safeJson};</script>`;\n if (html.includes('</head>')) {\n return html.replace('</head>', `${script}\\n</head>`);\n }\n return `${script}\\n${html}`;\n}\n\n/**\n * Creates (but does not start) the static HTTP server that hosts the Studio.\n */\nexport function createStudioServer(options: StudioServerOptions): http.Server {\n const studioDir = path.resolve(options.studioDir);\n const indexPath = path.join(studioDir, 'index.html');\n const config: StudioConfig = { appOrigin: options.appOrigin };\n\n const sendIndex = (res: http.ServerResponse) => {\n fs.readFile(indexPath, 'utf-8', (err, html) => {\n if (err) {\n res.statusCode = 500;\n res.end(`Server Error: ${err.code}`);\n return;\n }\n res.writeHead(200, { 'Content-Type': MIME_TYPES['.html']!, 'Cache-Control': 'no-store' });\n res.end(injectStudioConfig(html, config));\n });\n };\n\n return http.createServer((req, res) => {\n const origin = req.headers.origin || '';\n if (LOCALHOST_ORIGIN_RE.test(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Vary', 'Origin');\n }\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.statusCode = 204;\n res.end();\n return;\n }\n\n // RULE SEC-010: PATH CONTAINMENT — resolve the requested path and verify\n // it stays inside the studio directory (blocks /../../etc/passwd escapes).\n const urlPath = req.url?.split('?')[0] || '/';\n let filePath: string;\n try {\n filePath = path.resolve(studioDir, `.${decodeURIComponent(urlPath)}`);\n } catch {\n res.statusCode = 400;\n res.end('Bad Request');\n return;\n }\n\n if (filePath !== studioDir && !filePath.startsWith(studioDir + path.sep)) {\n res.statusCode = 403;\n res.end('Forbidden');\n return;\n }\n\n // Root, directories, and unknown paths all serve the SPA shell.\n if (\n urlPath === '/' ||\n filePath === studioDir ||\n filePath === indexPath ||\n !fs.existsSync(filePath) ||\n fs.statSync(filePath).isDirectory()\n ) {\n sendIndex(res);\n return;\n }\n\n const ext = path.extname(filePath);\n const contentType = MIME_TYPES[ext] || 'application/octet-stream';\n\n fs.readFile(filePath, (err, content) => {\n if (err) {\n res.statusCode = 500;\n res.end(`Server Error: ${err.code}`);\n } else {\n res.writeHead(200, { 'Content-Type': contentType });\n res.end(content);\n }\n });\n });\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { LOCALE_RE } from '../core/validate.js';\n\nexport type FindingLevel = 'ok' | 'warn' | 'fail';\n\nexport interface Finding {\n level: FindingLevel;\n title: string;\n detail?: string;\n}\n\nexport interface DoctorOptions {\n /** Project root to inspect. */\n projectDir: string;\n /** Locales directory, absolute or relative to `projectDir`. Defaults to `locales`. */\n localesPath?: string;\n /** When given, the running app is probed over HTTP. */\n appOrigin?: string;\n /** Bearer token for an app that requires one (preview mode). Defaults to `LIVELOCALE_TOKEN`. */\n token?: string;\n /** Injectable fetch for tests. Defaults to the global fetch. */\n fetchImpl?: typeof fetch;\n}\n\nconst ROUTE_CANDIDATES = [\n 'app/api/livelocale/route.ts',\n 'app/api/livelocale/route.js',\n 'src/app/api/livelocale/route.ts',\n 'src/app/api/livelocale/route.js',\n 'pages/api/livelocale.ts',\n 'pages/api/livelocale.js',\n 'src/pages/api/livelocale.ts',\n 'src/pages/api/livelocale.js',\n];\n\nconst LAYOUT_CANDIDATES = [\n 'app/layout.tsx',\n 'app/layout.jsx',\n 'app/layout.js',\n 'src/app/layout.tsx',\n 'src/app/layout.jsx',\n 'src/app/layout.js',\n 'pages/_app.tsx',\n 'pages/_app.jsx',\n 'pages/_app.js',\n 'src/pages/_app.tsx',\n 'src/pages/_app.jsx',\n 'src/pages/_app.js',\n];\n\n// Next.js 16 renamed middleware.ts to proxy.ts; both are checked.\nconst MIDDLEWARE_CANDIDATES = [\n 'middleware.ts',\n 'middleware.js',\n 'middleware.mjs',\n 'src/middleware.ts',\n 'src/middleware.js',\n 'proxy.ts',\n 'proxy.js',\n 'src/proxy.ts',\n 'src/proxy.js',\n];\n\nconst NEXT_CONFIG_CANDIDATES = [\n 'next.config.js',\n 'next.config.mjs',\n 'next.config.ts',\n 'next.config.cjs',\n];\n\nconst API_ROUTE = '/api/livelocale';\n\nfunction firstExisting(root: string, candidates: string[]): string | null {\n for (const rel of candidates) {\n if (fs.existsSync(path.join(root, rel))) return rel;\n }\n return null;\n}\n\nfunction readText(file: string): string {\n try {\n return fs.readFileSync(file, 'utf-8');\n } catch {\n return '';\n }\n}\n\n// ─── Static checks ──────────────────────────────────────────────────────────\n\nfunction checkRouteHandler(root: string): Finding {\n const found = firstExisting(root, ROUTE_CANDIDATES);\n if (found) return { level: 'ok', title: 'Mutation route handler', detail: found };\n return {\n level: 'fail',\n title: 'Mutation route handler',\n detail: `No route file found at ${ROUTE_CANDIDATES[0]} (or the src/ and pages/ variants). Run: npx livelocale init`,\n };\n}\n\nfunction checkProvider(root: string): Finding {\n const existing = LAYOUT_CANDIDATES.filter((rel) => fs.existsSync(path.join(root, rel)));\n if (existing.length === 0) {\n return {\n level: 'warn',\n title: 'LiveLocaleProvider mounted',\n detail:\n 'No root layout (app/layout.*) or pages/_app.* found, so the provider could not be verified.',\n };\n }\n const mounted = existing.find((rel) => /LiveLocaleProvider/.test(readText(path.join(root, rel))));\n if (mounted) return { level: 'ok', title: 'LiveLocaleProvider mounted', detail: mounted };\n return {\n level: 'warn',\n title: 'LiveLocaleProvider mounted',\n detail: `Add <LiveLocaleProvider /> from 'livelocale/react' to ${existing[0]} so the Studio can talk to the page.`,\n };\n}\n\nfunction checkMiddleware(root: string): Finding {\n const found = firstExisting(root, MIDDLEWARE_CANDIDATES);\n if (!found) return { level: 'ok', title: 'Middleware matcher', detail: 'no middleware file' };\n const text = readText(path.join(root, found));\n if (text.includes('api/livelocale')) {\n return { level: 'ok', title: 'Middleware matcher', detail: `${found} excludes ${API_ROUTE}` };\n }\n return {\n level: 'warn',\n title: 'Middleware matcher',\n detail: `${found} does not mention api/livelocale. If it enforces auth or redirects, exclude the route: matcher: ['/((?!api/livelocale).*)']`,\n };\n}\n\n/** The default Studio origin inside a frame-ancestors source or config text. */\nconst STUDIO_ORIGIN_RE = /(?:localhost|127\\.0\\.0\\.1):3010(?!\\d)/;\n\n/** True when a frame-ancestors directive lets the default Studio embed the page. */\nfunction allowsStudio(frameAncestors: string): boolean {\n const sources = frameAncestors.split(/\\s+/).slice(1);\n return sources.includes('*') || sources.some((src) => STUDIO_ORIGIN_RE.test(src));\n}\n\nfunction checkFrameHeaders(root: string): Finding {\n const found = firstExisting(root, NEXT_CONFIG_CANDIDATES);\n if (!found)\n return { level: 'ok', title: 'Frame-blocking headers in next.config', detail: 'none' };\n const text = readText(path.join(root, found));\n if (STUDIO_ORIGIN_RE.test(text)) {\n return {\n level: 'ok',\n title: 'Frame-blocking headers in next.config',\n detail: `${found} sets frame headers that name the Studio origin`,\n };\n }\n const hits: string[] = [];\n if (/frame-ancestors/i.test(text)) hits.push('frame-ancestors');\n if (/x-frame-options/i.test(text)) hits.push('X-Frame-Options');\n if (hits.length === 0) {\n return { level: 'ok', title: 'Frame-blocking headers in next.config', detail: 'none' };\n }\n return {\n level: 'warn',\n title: 'Frame-blocking headers in next.config',\n detail: `${found} sets ${hits.join(' and ')}. The Studio embeds your app in an iframe; allow http://localhost:3010 (or your Studio origin) when NODE_ENV is development.`,\n };\n}\n\nfunction checkLocales(root: string, localesPath: string | undefined): Finding {\n const dir = path.resolve(root, localesPath ?? 'locales');\n const rel = path.relative(root, dir) || '.';\n if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {\n return {\n level: 'fail',\n title: 'Locale files',\n detail: `Directory not found: ${rel}. Create it or pass --locales <path> (and set localesPath in the route handler).`,\n };\n }\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n const flat = entries.filter((e) => e.isFile() && e.name.endsWith('.json'));\n const dirs = entries.filter((e) => e.isDirectory() && LOCALE_RE.test(e.name));\n const invalid: string[] = [];\n let fileCount = 0;\n\n const validate = (file: string, label: string) => {\n fileCount++;\n try {\n const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n invalid.push(`${label} (root must be an object)`);\n }\n } catch (err: any) {\n invalid.push(`${label} (${err.message})`);\n }\n };\n\n for (const f of flat) validate(path.join(dir, f.name), f.name);\n for (const d of dirs) {\n for (const f of fs.readdirSync(path.join(dir, d.name))) {\n if (f.endsWith('.json')) validate(path.join(dir, d.name, f), `${d.name}/${f}`);\n }\n }\n\n if (invalid.length > 0) {\n return { level: 'fail', title: 'Locale files', detail: `Invalid JSON: ${invalid.join('; ')}` };\n }\n if (fileCount === 0) {\n return {\n level: 'fail',\n title: 'Locale files',\n detail: `${rel} contains no *.json locale files.`,\n };\n }\n if (flat.length > 0 && dirs.length > 0) {\n return {\n level: 'warn',\n title: 'Locale files',\n detail: `${rel} mixes flat files (${flat.length}) and namespace folders (${dirs.length}); pick one layout.`,\n };\n }\n const layout =\n dirs.length > 0\n ? `${dirs.length} namespaced locale folder(s)`\n : `${flat.length} flat locale file(s)`;\n return {\n level: 'ok',\n title: 'Locale files',\n detail: `${rel}: ${layout}, ${fileCount} file(s) parse`,\n };\n}\n\n// ─── Live checks ────────────────────────────────────────────────────────────\n\nasync function probe(\n fetchImpl: typeof fetch,\n url: string,\n token?: string\n): Promise<{ ok: true; res: Response } | { ok: false; error: string }> {\n try {\n // Preview deployments answer in cold starts and GitHub round trips; allow more time there.\n const signal =\n typeof AbortSignal.timeout === 'function' ? AbortSignal.timeout(15000) : undefined;\n const headers: Record<string, string> = token ? { Authorization: `Bearer ${token}` } : {};\n const res = await fetchImpl(url, { signal, redirect: 'manual', headers });\n return { ok: true, res };\n } catch (err: any) {\n return { ok: false, error: err?.message || String(err) };\n }\n}\n\n/**\n * Describes a redirect to a hosting provider's login page (Vercel Deployment\n * Protection, Netlify password protection, …), or returns null for any other response.\n */\nfunction loginWall(res: Response, origin: string): string | null {\n if (res.status < 300 || res.status >= 400) return null;\n const location = res.headers.get('location') || '';\n let target: URL;\n try {\n target = new URL(location, origin);\n } catch {\n return null;\n }\n if (target.origin === new URL(origin).origin) return null;\n if (/(^|\\.)vercel\\.com$/i.test(target.hostname)) {\n return 'Vercel Deployment Protection redirects visitors to a Vercel login. Turn off Vercel Authentication for preview deployments (Project Settings → Deployment Protection).';\n }\n return `The app redirects to ${target.host}, which looks like a hosting login wall. Allow the Studio through it or turn it off for this deployment.`;\n}\n\nasync function checkServerInfo(\n origin: string,\n fetchImpl: typeof fetch,\n token: string | undefined\n): Promise<Finding[]> {\n const res = await probe(fetchImpl, `${origin}${API_ROUTE}?action=info`, token);\n if (!res.ok || res.res.status !== 200) return [];\n let info: any = null;\n try {\n info = await res.res.json();\n } catch {}\n if (!info || typeof info.mode !== 'string') return [];\n const findings: Finding[] = [\n {\n level: 'ok',\n title: 'Server mode',\n detail: `${info.mode}${info.authRequired ? ', token required' : ''}${info.git ? ', git actions available' : ''}`,\n },\n ];\n for (const problem of Array.isArray(info.problems) ? info.problems : []) {\n findings.push({ level: 'fail', title: 'Repository access', detail: String(problem) });\n }\n return findings;\n}\n\nasync function checkLive(\n appOrigin: string,\n fetchImpl: typeof fetch,\n token: string | undefined\n): Promise<Finding[]> {\n const findings: Finding[] = [];\n const origin = appOrigin.replace(/\\/+$/, '');\n\n const api = await probe(fetchImpl, `${origin}${API_ROUTE}`, token);\n if (!api.ok) {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: `${origin} is not reachable (${api.error}). Is the dev server running?`,\n });\n } else {\n const { res } = api;\n let body: any = null;\n try {\n body = await res.json();\n } catch {}\n if (res.status === 200 && Array.isArray(body)) {\n findings.push({\n level: 'ok',\n title: 'Mutation API',\n detail: `${origin}${API_ROUTE} responded with ${body.length} locale(s)`,\n });\n findings.push(...(await checkServerInfo(origin, fetchImpl, token)));\n } else if (res.status === 401) {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: token\n ? 'The server rejected the access token. Check LIVELOCALE_TOKEN on the deployment.'\n : 'The server requires an access token (preview mode). Re-run with --token <token> or set LIVELOCALE_TOKEN.',\n });\n } else if (res.status === 403) {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: `Server refused the request: ${body?.error || 'HTTP 403'}`,\n });\n } else if (res.status === 404) {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: `HTTP 404 at ${origin}${API_ROUTE}. The route handler is not served; run npx livelocale init and restart the dev server.`,\n });\n } else if (res.status >= 300 && res.status < 400) {\n const wall = loginWall(res, origin);\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: wall\n ? `${wall} The Studio cannot reach the app through it.`\n : `HTTP ${res.status} redirect at ${API_ROUTE}; auth middleware is probably intercepting it. Exclude api/livelocale from the matcher.`,\n });\n } else {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: `Unexpected HTTP ${res.status}: ${body?.error || 'no error body'}`,\n });\n }\n }\n\n const page = await probe(fetchImpl, `${origin}/`);\n const pageWall = page.ok ? loginWall(page.res, origin) : null;\n if (pageWall) {\n findings.push({ level: 'fail', title: 'Studio can embed the app', detail: pageWall });\n } else if (page.ok) {\n const csp = page.res.headers.get('content-security-policy') || '';\n const xfo = page.res.headers.get('x-frame-options') || '';\n const blockers: string[] = [];\n const frameAncestors = csp.match(/frame-ancestors[^;]*/i)?.[0];\n if (frameAncestors && !allowsStudio(frameAncestors.trim())) {\n blockers.push(`Content-Security-Policy: ${frameAncestors}`);\n }\n if (xfo) blockers.push(`X-Frame-Options: ${xfo}`);\n if (blockers.length > 0) {\n findings.push({\n level: 'warn',\n title: 'Studio can embed the app',\n detail: `${origin}/ sends ${blockers.join(' and ')}. Unless the Studio origin is allowed, the preview iframe will be blank.`,\n });\n } else {\n findings.push({\n level: 'ok',\n title: 'Studio can embed the app',\n detail: 'no frame-blocking headers',\n });\n }\n }\n\n return findings;\n}\n\n// ─── Entry points ───────────────────────────────────────────────────────────\n\nexport async function runDoctor(options: DoctorOptions): Promise<Finding[]> {\n const root = path.resolve(options.projectDir);\n const findings: Finding[] = [\n checkRouteHandler(root),\n checkProvider(root),\n checkMiddleware(root),\n checkFrameHeaders(root),\n checkLocales(root, options.localesPath),\n ];\n\n if (options.appOrigin) {\n const fetchImpl = options.fetchImpl ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') {\n findings.push({\n level: 'warn',\n title: 'Mutation API',\n detail: 'Live checks need Node 18+ (global fetch).',\n });\n } else {\n const token = options.token ?? process.env['LIVELOCALE_TOKEN'] ?? undefined;\n findings.push(...(await checkLive(options.appOrigin, fetchImpl, token || undefined)));\n }\n }\n\n return findings;\n}\n\nexport function hasFailures(findings: Finding[]): boolean {\n return findings.some((f) => f.level === 'fail');\n}\n\nconst GLYPH: Record<FindingLevel, string> = { ok: '✅', warn: '⚠️ ', fail: '❌' };\n\nexport function formatFindings(findings: Finding[]): string {\n const lines: string[] = [];\n for (const f of findings) {\n lines.push(`${GLYPH[f.level]} ${f.title}`);\n if (f.detail) lines.push(` ${f.detail}`);\n }\n return lines.join('\\n');\n}\n","/**\n * Shared validation rules for locale codes, translation keys, and values.\n *\n * Platform-agnostic: used by the server router, FileMutator, and the Studio\n * UI so that every layer enforces exactly the same contract.\n */\n\nexport const LOCALE_RE = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,4})?$/;\n\nexport const KEY_RE = /^[a-zA-Z0-9._-]+$/;\n\nexport const MAX_LOCALE_LENGTH = 10;\nexport const MAX_KEY_LENGTH = 200;\nexport const MAX_VALUE_LENGTH = 10000;\n\n/**\n * Object-prototype member names that must never be used as translation key\n * segments. Assigning through these bypasses own-property checks and can\n * pollute `Object.prototype` process-wide (prototype pollution).\n */\nexport const DANGEROUS_KEY_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Returns true if no segment of the dot-separated `key` is a dangerous\n * object-prototype member name.\n */\nexport function isSafeKeyPath(key: unknown): boolean {\n if (typeof key !== 'string') return false;\n return !key.split('.').some((segment) => DANGEROUS_KEY_SEGMENTS.has(segment));\n}\n\n/**\n * Returns true if `locale` is a 2-10 character code matching the loose\n * standard pattern (supports es-419, zh-Hans, eng, etc.).\n */\nexport function isValidLocaleFormat(locale: unknown): boolean {\n return (\n typeof locale === 'string' &&\n locale.length >= 2 &&\n locale.length <= MAX_LOCALE_LENGTH &&\n LOCALE_RE.test(locale)\n );\n}\n\n/**\n * Returns true if `key` is a 1-200 character dot-separated path containing\n * only alphanumerics, dots, underscores, or hyphens.\n */\nexport function isValidKeyFormat(key: unknown): boolean {\n return (\n typeof key === 'string' && key.length >= 1 && key.length <= MAX_KEY_LENGTH && KEY_RE.test(key)\n );\n}\n\n/**\n * Returns true if `value` is a string no longer than MAX_VALUE_LENGTH.\n */\nexport function isValidValueFormat(value: unknown): boolean {\n return typeof value === 'string' && value.length <= MAX_VALUE_LENGTH;\n}\n\n/**\n * Rejects locale identifiers that could escape the locales directory.\n */\nexport function isSafeLocaleSegment(locale: string): boolean {\n return !(\n locale.includes('..') ||\n locale.includes('/') ||\n locale.includes('\\\\') ||\n locale.includes('%') ||\n locale.includes('\\0')\n );\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { LOCALE_RE } from '../core/validate.js';\nimport { comparePlaceholders, validateMessageSyntax } from '../core/placeholders.js';\nimport { KeyScanner } from '../server/key-scanner.js';\n\nexport type IssueKind =\n | 'invalid-json'\n | 'missing-in-locale'\n | 'missing-from-code'\n | 'placeholder-mismatch'\n | 'syntax'\n | 'empty'\n | 'unused';\n\nexport type IssueLevel = 'fail' | 'warn';\n\nexport interface CheckIssue {\n kind: IssueKind;\n level: IssueLevel;\n locale?: string;\n key?: string;\n /** Locale file (or folder) relative to the project, for invalid JSON. */\n file?: string;\n message: string;\n}\n\nexport interface CheckOptions {\n /** Project root to scan for source files. */\n projectDir: string;\n /** Locales directory, absolute or relative to `projectDir`. Defaults to `locales`. */\n localesPath?: string;\n /** Locale the others are compared against. Defaults to `en` when present, else the first locale. */\n sourceLocale?: string;\n /** Report keys that exist in locale files but are never referenced in code. Defaults to true. */\n unused?: boolean;\n /** Treat warnings (unused and empty values) as failures. */\n strict?: boolean;\n}\n\nexport interface CheckReport {\n localesDir: string;\n sourceLocale: string | null;\n locales: string[];\n codeKeyCount: number;\n issues: CheckIssue[];\n}\n\n/** i18next plural suffixes; `t('items')` resolves `items_one`, `items_other`, … at run time. */\nconst PLURAL_SUFFIX_RE = /_(?:ordinal_)?(?:zero|one|two|few|many|other)$/;\n\nconst KIND_ORDER: IssueKind[] = [\n 'invalid-json',\n 'syntax',\n 'missing-from-code',\n 'missing-in-locale',\n 'placeholder-mismatch',\n 'empty',\n 'unused',\n];\n\nconst KIND_TITLE: Record<IssueKind, string> = {\n 'invalid-json': 'Locale files that are not valid JSON',\n syntax: 'Broken ICU message syntax',\n 'missing-from-code': 'Keys used in code but missing from a locale',\n 'missing-in-locale': 'Keys missing compared to the source locale',\n 'placeholder-mismatch': 'Placeholders that differ from the source locale',\n empty: 'Empty translations',\n unused: 'Keys never referenced in code',\n};\n\ninterface LocaleData {\n /** Leaf key → value. Non-string leaves (numbers, arrays) are kept but not validated. */\n leaves: Map<string, unknown>;\n /** Every intermediate object path, so `t.home` counts as a reference to `home.*`. */\n branches: Set<string>;\n}\n\nfunction listLocales(localesDir: string): string[] {\n const locales = new Set<string>();\n for (const item of fs.readdirSync(localesDir, { withFileTypes: true })) {\n if (item.isDirectory() && LOCALE_RE.test(item.name)) locales.add(item.name);\n else if (item.isFile() && item.name.endsWith('.json')) {\n const name = path.basename(item.name, '.json');\n if (LOCALE_RE.test(name)) locales.add(name);\n }\n }\n return Array.from(locales).sort();\n}\n\nfunction flatten(obj: unknown, prefix: string, data: LocaleData): void {\n if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return;\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const full = prefix ? `${prefix}.${key}` : key;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n data.branches.add(full);\n flatten(value, full, data);\n } else {\n data.leaves.set(full, value);\n }\n }\n}\n\n/**\n * Reads one locale the way the runtime does: a flat `{locale}.json`, or every\n * `*.json` inside `{locale}/` merged under its file name as the namespace.\n */\nfunction readLocale(\n localesDir: string,\n locale: string,\n projectDir: string,\n issues: CheckIssue[]\n): LocaleData {\n const data: LocaleData = { leaves: new Map(), branches: new Set() };\n const rel = (p: string) => path.relative(projectDir, p).split(path.sep).join('/');\n const parse = (file: string): unknown => {\n try {\n return JSON.parse(fs.readFileSync(file, 'utf-8'));\n } catch (err: any) {\n issues.push({\n kind: 'invalid-json',\n level: 'fail',\n locale,\n file: rel(file),\n message: err?.message ?? String(err),\n });\n return undefined;\n }\n };\n\n const dir = path.join(localesDir, locale);\n if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {\n for (const file of fs.readdirSync(dir).sort()) {\n if (!file.endsWith('.json')) continue;\n const ns = path.basename(file, '.json');\n const parsed = parse(path.join(dir, file));\n if (parsed === undefined) continue;\n data.branches.add(ns);\n flatten(parsed, ns, data);\n }\n } else {\n flatten(parse(path.join(localesDir, `${locale}.json`)), '', data);\n }\n return data;\n}\n\n/** True when `key` resolves in `data`: as a leaf, an object, or an i18next plural family. */\nfunction hasKey(data: LocaleData, key: string): boolean {\n if (data.leaves.has(key) || data.branches.has(key)) return true;\n for (const leaf of data.leaves.keys()) {\n if (leaf.startsWith(`${key}_`) && PLURAL_SUFFIX_RE.test(leaf)) return true;\n }\n return false;\n}\n\n/** True when a locale key is reached by some code reference (directly, via a parent object, or as a plural form). */\nfunction isReferenced(key: string, codeKeys: Set<string>): boolean {\n const base = key.replace(PLURAL_SUFFIX_RE, '');\n for (const candidate of base === key ? [key] : [key, base]) {\n if (codeKeys.has(candidate)) return true;\n let dot = candidate.lastIndexOf('.');\n while (dot > 0) {\n if (codeKeys.has(candidate.slice(0, dot))) return true;\n dot = candidate.lastIndexOf('.', dot - 1);\n }\n }\n return false;\n}\n\n/**\n * Read-only consistency check of a project's translations, meant for CI:\n * missing keys, broken ICU syntax, placeholder drift between locales, empty\n * values, and keys nothing references.\n */\nexport async function runCheck(options: CheckOptions): Promise<CheckReport> {\n const projectDir = path.resolve(options.projectDir);\n const localesDir = path.resolve(projectDir, options.localesPath ?? 'locales');\n const issues: CheckIssue[] = [];\n const strict = options.strict ?? false;\n const warn: IssueLevel = strict ? 'fail' : 'warn';\n\n if (!fs.existsSync(localesDir) || !fs.statSync(localesDir).isDirectory()) {\n throw new Error(`Locales directory not found: ${localesDir}`);\n }\n\n const locales = listLocales(localesDir);\n const data = new Map(locales.map((l) => [l, readLocale(localesDir, l, projectDir, issues)]));\n\n const sourceLocale =\n options.sourceLocale ?? (locales.includes('en') ? 'en' : (locales[0] ?? null));\n if (sourceLocale && !data.has(sourceLocale)) {\n throw new Error(\n `Source locale \"${sourceLocale}\" not found in ${localesDir} (found: ${locales.join(', ') || 'none'}).`\n );\n }\n\n const scanner = new KeyScanner({ requireEnabled: false });\n const codeKeys = new Set(await scanner.scanSourceKeys(projectDir));\n\n for (const [locale, localeData] of data) {\n for (const [key, value] of localeData.leaves) {\n if (typeof value !== 'string') continue;\n const error = validateMessageSyntax(value);\n if (error) {\n issues.push({ kind: 'syntax', level: 'fail', locale, key, message: error });\n }\n if (value.trim() === '') {\n issues.push({ kind: 'empty', level: warn, locale, key, message: 'Value is empty.' });\n }\n }\n\n for (const key of codeKeys) {\n if (!hasKey(localeData, key)) {\n issues.push({\n kind: 'missing-from-code',\n level: 'fail',\n locale,\n key,\n message: `Used in code but not defined in ${locale}.`,\n });\n }\n }\n }\n\n if (sourceLocale) {\n const source = data.get(sourceLocale)!;\n for (const [locale, localeData] of data) {\n if (locale === sourceLocale) continue;\n for (const [key, sourceValue] of source.leaves) {\n if (!localeData.leaves.has(key)) {\n // Keys the code uses are already reported as missing-from-code, and plural\n // families differ legitimately between languages (Arabic has six forms).\n if (codeKeys.has(key) || PLURAL_SUFFIX_RE.test(key)) continue;\n issues.push({\n kind: 'missing-in-locale',\n level: 'fail',\n locale,\n key,\n message: `Defined in ${sourceLocale} but not in ${locale}.`,\n });\n continue;\n }\n\n const value = localeData.leaves.get(key);\n if (typeof sourceValue !== 'string' || typeof value !== 'string' || value === '') continue;\n const cmp = comparePlaceholders(sourceValue, value);\n if (!cmp.ok) {\n const parts: string[] = [];\n if (cmp.missing.length) parts.push(`missing ${cmp.missing.join(', ')}`);\n if (cmp.extra.length) parts.push(`extra ${cmp.extra.join(', ')}`);\n issues.push({\n kind: 'placeholder-mismatch',\n level: 'fail',\n locale,\n key,\n message: `${parts.join('; ')} (compared to ${sourceLocale}).`,\n });\n }\n }\n }\n\n if (options.unused ?? true) {\n for (const key of source.leaves.keys()) {\n if (!isReferenced(key, codeKeys)) {\n issues.push({\n kind: 'unused',\n level: warn,\n locale: sourceLocale,\n key,\n message: 'Not referenced in code (dynamic keys cannot be detected).',\n });\n }\n }\n }\n }\n\n issues.sort(\n (a, b) =>\n KIND_ORDER.indexOf(a.kind) - KIND_ORDER.indexOf(b.kind) ||\n (a.locale ?? '').localeCompare(b.locale ?? '') ||\n (a.key ?? a.file ?? '').localeCompare(b.key ?? b.file ?? '')\n );\n\n return {\n localesDir,\n sourceLocale,\n locales,\n codeKeyCount: codeKeys.size,\n issues,\n };\n}\n\nexport function hasCheckFailures(report: CheckReport): boolean {\n return report.issues.some((i) => i.level === 'fail');\n}\n\n/** Human-readable report, grouped by issue kind, with at most `limit` lines per group. */\nexport function formatCheckReport(report: CheckReport, limit = 25): string {\n const lines: string[] = [];\n for (const kind of KIND_ORDER) {\n const group = report.issues.filter((i) => i.kind === kind);\n if (group.length === 0) continue;\n const glyph = group.some((i) => i.level === 'fail') ? '✖' : '⚠';\n lines.push(`${glyph} ${KIND_TITLE[kind]} (${group.length})`);\n for (const issue of group.slice(0, limit)) {\n const where = issue.key\n ? `${issue.locale ? `[${issue.locale}] ` : ''}${issue.key}`\n : (issue.file ?? issue.locale ?? '');\n lines.push(` ${where} — ${issue.message}`);\n }\n if (group.length > limit) lines.push(` …and ${group.length - limit} more`);\n }\n return lines.join('\\n');\n}\n","/**\n * Placeholder analysis for translation messages.\n *\n * Understands the formats the supported libraries use:\n * - ICU MessageFormat (next-intl, react-intl, FormatJS): `{name}`, `{count, number}`,\n * `{count, plural, one {…} other {…}}`, apostrophe quoting.\n * - i18next: `{{name}}`, `{{count, number}}`, nesting `$t(key)`.\n * - printf-style: `%s`, `%d`, `%1$s`.\n * - rich-text tags (react-intl, next-intl `t.rich`, i18next `<Trans>`): `<b>…</b>`, `<0>…</0>`.\n *\n * A placeholder token is a canonical string such as `{name}`, `{{name}}`, `%s` or `<b>`,\n * so two messages can be compared as sets.\n */\n\nconst PLURAL_TYPES = new Set(['plural', 'select', 'selectordinal']);\n\ninterface ParseResult {\n args: Set<string>;\n error: string | null;\n}\n\n/**\n * Removes ICU apostrophe-quoted spans (`'{'`, `'{literal}'`) and turns `''`\n * into a plain apostrophe so the structural scan only sees real syntax.\n */\nfunction unquoteIcu(message: string): string {\n let out = '';\n let i = 0;\n while (i < message.length) {\n const ch = message[i]!;\n if (ch !== \"'\") {\n out += ch;\n i += 1;\n continue;\n }\n if (message[i + 1] === \"'\") {\n out += \"'\";\n i += 2;\n continue;\n }\n const next = message[i + 1];\n if (next === '{' || next === '}' || next === '#' || next === '|') {\n // Quoted span: skip to the closing single apostrophe (doubled ones are literal).\n let j = i + 1;\n while (j < message.length) {\n if (message[j] === \"'\") {\n if (message[j + 1] === \"'\") {\n j += 2;\n continue;\n }\n break;\n }\n j += 1;\n }\n i = j + 1;\n continue;\n }\n out += ch;\n i += 1;\n }\n return out;\n}\n\n/** Recursive-descent walk over ICU structure collecting argument names and the first error. */\nfunction parseIcu(message: string): ParseResult {\n const args = new Set<string>();\n let pos = 0;\n let error: string | null = null;\n\n const fail = (msg: string) => {\n if (!error) error = msg;\n };\n\n const parseMessage = (depth: number): void => {\n while (pos < message.length) {\n const ch = message[pos]!;\n if (ch === '{') {\n pos += 1;\n parseArgument(depth + 1);\n } else if (ch === '}') {\n if (depth === 0) {\n fail('Unbalanced braces: unexpected \"}\"');\n pos += 1;\n } else {\n return; // caller consumes the brace\n }\n } else {\n pos += 1;\n }\n }\n if (depth > 0) fail('Unbalanced braces: missing \"}\"');\n };\n\n const readUntil = (stops: string[]): string => {\n let out = '';\n while (pos < message.length && !stops.includes(message[pos]!)) {\n out += message[pos]!;\n pos += 1;\n }\n return out;\n };\n\n const parseArgument = (depth: number): void => {\n const name = readUntil([',', '}']).trim();\n if (name && !name.includes('{')) args.add(name);\n if (pos >= message.length) {\n fail('Unbalanced braces: missing \"}\"');\n return;\n }\n if (message[pos] === '}') {\n pos += 1;\n return;\n }\n pos += 1; // ','\n const type = readUntil([',', '}']).trim();\n if (pos >= message.length) {\n fail('Unbalanced braces: missing \"}\"');\n return;\n }\n if (message[pos] === '}') {\n pos += 1;\n return;\n }\n pos += 1; // ','\n\n if (PLURAL_TYPES.has(type)) {\n let hasOther = false;\n while (pos < message.length) {\n // skip whitespace\n while (pos < message.length && /\\s/.test(message[pos]!)) pos += 1;\n if (message[pos] === '}') {\n pos += 1;\n if (!hasOther) fail(`\"${name}\" (${type}) has no \"other\" branch`);\n return;\n }\n const selector = readUntil(['{', '}', ' ', '\\t', '\\n']).trim();\n while (pos < message.length && /\\s/.test(message[pos]!)) pos += 1;\n if (message[pos] !== '{') {\n fail(`\"${name}\" (${type}): expected \"{\" after \"${selector}\"`);\n return;\n }\n if (selector === 'other') hasOther = true;\n pos += 1;\n parseMessage(depth + 1);\n if (message[pos] === '}') pos += 1;\n }\n fail('Unbalanced braces: missing \"}\"');\n return;\n }\n\n // number/date/time style, or unknown: skip to the matching brace\n let level = 1;\n while (pos < message.length && level > 0) {\n if (message[pos] === '{') level += 1;\n else if (message[pos] === '}') level -= 1;\n pos += 1;\n }\n if (level > 0) fail('Unbalanced braces: missing \"}\"');\n };\n\n parseMessage(0);\n return { args, error };\n}\n\nconst I18NEXT_RE = /\\{\\{\\s*([^{}]*?)\\s*\\}\\}/g;\nconst NESTING_RE = /\\$t\\([^)]*\\)/g;\nconst PRINTF_RE = /%(?:\\d+\\$)?[-+ 0#]*\\d*(?:\\.\\d+)?[sdifgxXoc]/g;\nconst TAG_RE = /<\\/?([A-Za-z][\\w-]*|\\d+)\\b[^<>]*>/g;\n\n/** Returns the sorted, de-duplicated placeholder tokens found in `message`. */\nexport function extractPlaceholders(message: string): string[] {\n if (typeof message !== 'string' || message === '') return [];\n const tokens = new Set<string>();\n\n // i18next interpolation first, then blank it out so the ICU scan does not see `{{`.\n const withoutI18next = message.replace(I18NEXT_RE, (_m, inner: string) => {\n const name = inner.split(',')[0]!.trim();\n if (name) tokens.add(`{{${name}}}`);\n return ' ';\n });\n\n for (const m of withoutI18next.match(NESTING_RE) ?? []) tokens.add(m);\n for (const m of withoutI18next.replace(/%%/g, '').match(PRINTF_RE) ?? []) tokens.add(m);\n for (const m of withoutI18next.matchAll(TAG_RE)) tokens.add(`<${m[1]}>`);\n\n const icu = parseIcu(unquoteIcu(withoutI18next.replace(TAG_RE, ' ')));\n for (const arg of icu.args) tokens.add(`{${arg}}`);\n\n return Array.from(tokens).sort();\n}\n\nexport interface PlaceholderComparison {\n ok: boolean;\n /** Present in the reference but not in the value. */\n missing: string[];\n /** Present in the value but not in the reference. */\n extra: string[];\n}\n\n/** Compares placeholder sets; an empty reference is compatible with anything. */\nexport function comparePlaceholders(\n reference: string | undefined | null,\n value: string\n): PlaceholderComparison {\n if (!reference) return { ok: true, missing: [], extra: [] };\n const ref = new Set(extractPlaceholders(reference));\n const val = new Set(extractPlaceholders(value));\n const missing = Array.from(ref).filter((t) => !val.has(t));\n const extra = Array.from(val).filter((t) => !ref.has(t));\n return { ok: missing.length === 0 && extra.length === 0, missing, extra };\n}\n\n/** Returns a description of the first ICU structural problem, or null when the message is sound. */\nexport function validateMessageSyntax(message: string): string | null {\n if (typeof message !== 'string') return null;\n const prepared = unquoteIcu(message.replace(I18NEXT_RE, ' ').replace(TAG_RE, ' '));\n return parseIcu(prepared).error;\n}\n","import { promises as fs } from 'fs';\nimport * as path from 'path';\nimport { isSafeLocaleSegment } from '../core/validate.js';\nimport { getDisabledReason } from '../core/env.js';\nimport { parseGitignore, type GitignoreMatcher } from '../core/gitignore.js';\n\nconst IGNORE_DIRS = new Set([\n 'node_modules',\n '.next',\n 'dist',\n 'build',\n '.git',\n 'coverage',\n 'test-results',\n 'out',\n '.idea',\n '.vscode',\n '.turbo',\n '.cache',\n]);\n\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);\n\n/** Files above this size are almost certainly bundles or fixtures, not components. */\nconst MAX_SOURCE_BYTES = 1_000_000;\n\nconst PROP_RE = /\\bt(?:\\??\\.[a-zA-Z0-9_]+)+/g;\nconst IGNORE_PROPS = new Set([\n 'toString',\n 'length',\n 'constructor',\n 'prototype',\n 'map',\n 'forEach',\n 'filter',\n 'reduce',\n 'call',\n 'apply',\n 'bind',\n 'name',\n 'displayName',\n 'raw',\n 'rich',\n 'markup',\n 'has',\n]);\n\nconst KEY_SHAPE = /^[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)*$/;\nconst DECL = String.raw`(?:const|let|var)\\s+`;\n/** A string literal in any quote style; read the value with `stringArg(match)`. */\nconst STR = String.raw`(?:'(?<s1>[^']*)'|\"(?<s2>[^\"]*)\"|\\x60(?<s3>[^\\x60]*)\\x60)`;\nconst stringArg = (m: RegExpMatchArray): string | undefined =>\n m.groups?.['s1'] ?? m.groups?.['s2'] ?? m.groups?.['s3'];\n\n/** Translator-method names whose first argument is a key. */\nconst METHODS = String.raw`(?:\\.(?:rich|raw|markup|has))?`;\n\n/**\n * Maps translator variable names to their key prefix (namespace) from the\n * declarations in a file:\n * const t = useTranslations('home') // next-intl (also getTranslations, await)\n * const { t } = useTranslation('auth') // react-i18next\n * const t = wrapTranslationEngine(x, { keyPrefix: 'auth' })\n * const t = wrapNextIntl(x, 'checkout')\n * Scope is not tracked; the last declaration of a name in the file wins.\n */\nfunction namespaceBindings(content: string): Map<string, string> {\n const map = new Map<string, string>();\n\n const hookRe = new RegExp(\n DECL +\n String.raw`(?<name>\\w+)\\s*=\\s*(?:await\\s+)?(?:useTranslations|getTranslations)\\(\\s*(?:` +\n STR +\n String.raw`)?\\s*\\)`,\n 'g'\n );\n for (const m of content.matchAll(hookRe)) map.set(m.groups!['name']!, stringArg(m) ?? '');\n\n const wrapNextIntlRe = new RegExp(\n DECL + String.raw`(?<name>\\w+)\\s*=\\s*wrapNextIntl\\([^;]*?,\\s*` + STR + String.raw`\\s*\\)`,\n 'g'\n );\n for (const m of content.matchAll(wrapNextIntlRe)) {\n map.set(m.groups!['name']!, stringArg(m) ?? '');\n }\n\n const wrapEngineRe = new RegExp(\n DECL + String.raw`(?<name>\\w+)\\s*=\\s*wrapTranslationEngine\\([^;]*?keyPrefix:\\s*` + STR,\n 'g'\n );\n for (const m of content.matchAll(wrapEngineRe)) {\n map.set(m.groups!['name']!, stringArg(m) ?? '');\n }\n\n const i18nextRe = new RegExp(\n DECL + String.raw`\\{(?<bindings>[^}]*)\\}\\s*=\\s*useTranslation\\(\\s*(?:` + STR + String.raw`)?`,\n 'g'\n );\n for (const m of content.matchAll(i18nextRe)) {\n const binding = /\\bt\\s*(?::\\s*(\\w+))?/.exec(m.groups!['bindings']!);\n if (binding) map.set(binding[1] ?? 't', stringArg(m) ?? '');\n }\n\n return map;\n}\n\n/** Extracts translation key references from one source file's text. */\nexport function extractKeys(content: string): string[] {\n const keys = new Set<string>();\n const bindings = namespaceBindings(content);\n const translators = new Set<string>(['t', ...bindings.keys()]);\n\n for (const name of translators) {\n const prefix = bindings.get(name) ?? '';\n const callRe = new RegExp(String.raw`\\b` + name + METHODS + String.raw`\\(\\s*` + STR, 'g');\n for (const m of content.matchAll(callRe)) {\n const key = stringArg(m);\n if (!key || key.includes('${') || !KEY_SHAPE.test(key)) continue;\n keys.add(prefix ? `${prefix}.${key}` : key);\n }\n }\n\n let match: RegExpExecArray | null;\n PROP_RE.lastIndex = 0;\n while ((match = PROP_RE.exec(content)) !== null) {\n const clean = match[0].replace(/\\bt/, '').replace(/\\?/g, '');\n const segments = clean\n .split('.')\n .map((seg) => seg.trim())\n .filter(Boolean);\n if (segments.length > 0 && !segments.some((seg) => IGNORE_PROPS.has(seg))) {\n keys.add(segments.join('.'));\n }\n }\n\n return Array.from(keys).sort();\n}\n\ninterface CachedFile<T> {\n mtimeMs: number;\n size: number;\n value: T;\n}\n\nconst NO_IGNORES: GitignoreMatcher = { ignores: () => false };\n\n/**\n * Read-only analysis of translation keys: scans the codebase for `t(...)`\n * references and compiles the set of keys present in locale files.\n *\n * Scans are incremental: each source file's extracted keys are cached by\n * mtime and size, so a rescan only re-reads files that changed. The project's\n * root `.gitignore` is honoured in addition to the built-in ignore list.\n */\nexport interface KeyScannerOptions {\n /**\n * Refuse to scan unless LiveLocale is enabled (development or preview mode).\n * Defaults to true; read-only tooling such as `check` turns it off so it can run in CI.\n */\n requireEnabled?: boolean;\n}\n\nexport class KeyScanner {\n private fileCache = new Map<string, CachedFile<string[]>>();\n private gitignoreCache: CachedFile<GitignoreMatcher> | null = null;\n private readonly requireEnabled: boolean;\n\n constructor(options: KeyScannerOptions = {}) {\n this.requireEnabled = options.requireEnabled ?? true;\n }\n\n private assertEnabled(): void {\n if (!this.requireEnabled) return;\n const reason = getDisabledReason();\n if (reason !== null) {\n throw new Error(\n `[livelocale] KeyScanner can only be executed in development mode (${reason}).`\n );\n }\n }\n\n private async loadGitignore(projectRoot: string): Promise<GitignoreMatcher> {\n const gitignorePath = path.join(projectRoot, '.gitignore');\n let stat;\n try {\n stat = await fs.stat(gitignorePath);\n } catch {\n this.gitignoreCache = null;\n return NO_IGNORES;\n }\n const hit = this.gitignoreCache;\n if (hit && hit.mtimeMs === stat.mtimeMs && hit.size === stat.size) {\n return hit.value;\n }\n try {\n const content = await fs.readFile(gitignorePath, 'utf-8');\n const matcher = parseGitignore(content);\n this.gitignoreCache = { mtimeMs: stat.mtimeMs, size: stat.size, value: matcher };\n return matcher;\n } catch {\n return NO_IGNORES;\n }\n }\n\n /**\n * Scans the project (the parent directory of `basePath`) for translation key references.\n */\n async scanCodebaseKeys(basePath: string): Promise<string[]> {\n return this.scanSourceKeys(path.dirname(path.resolve(basePath)));\n }\n\n /** Scans every source file under `projectRoot` for translation key references. */\n async scanSourceKeys(projectRoot: string): Promise<string[]> {\n this.assertEnabled();\n\n projectRoot = path.resolve(projectRoot);\n const gitignore = await this.loadGitignore(projectRoot);\n const keysSet = new Set<string>();\n const seen = new Set<string>();\n\n const toRel = (fullPath: string) =>\n path.relative(projectRoot, fullPath).split(path.sep).join('/');\n\n const scanDir = async (dir: string): Promise<void> => {\n let items;\n try {\n items = await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const item of items) {\n const fullPath = path.join(dir, item.name);\n\n if (item.isDirectory()) {\n if (IGNORE_DIRS.has(item.name)) continue;\n if (gitignore.ignores(toRel(fullPath), true)) continue;\n await scanDir(fullPath);\n continue;\n }\n\n if (!item.isFile()) continue;\n if (!SOURCE_EXTENSIONS.has(path.extname(item.name))) continue;\n if (item.name.endsWith('.d.ts')) continue;\n if (gitignore.ignores(toRel(fullPath), false)) continue;\n\n let stat;\n try {\n stat = await fs.stat(fullPath);\n } catch {\n continue;\n }\n if (stat.size > MAX_SOURCE_BYTES) continue;\n\n seen.add(fullPath);\n const cached = this.fileCache.get(fullPath);\n if (cached && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) {\n for (const k of cached.value) keysSet.add(k);\n continue;\n }\n\n try {\n const content = await fs.readFile(fullPath, 'utf-8');\n const keys = extractKeys(content);\n this.fileCache.set(fullPath, { mtimeMs: stat.mtimeMs, size: stat.size, value: keys });\n for (const k of keys) keysSet.add(k);\n } catch {}\n }\n };\n\n await scanDir(projectRoot);\n\n // Forget files that disappeared so the cache cannot grow without bound.\n for (const cachedPath of this.fileCache.keys()) {\n if (!seen.has(cachedPath)) this.fileCache.delete(cachedPath);\n }\n\n return Array.from(keysSet).sort();\n }\n\n /**\n * Scans all locale files/folders to compile the set of all keys currently in locales.\n */\n async scanLocalesKeys(\n basePath: string,\n listLocales: (base: string) => Promise<string[]>\n ): Promise<string[]> {\n this.assertEnabled();\n\n const locales = await listLocales(basePath);\n const keysSet = new Set<string>();\n\n for (const locale of locales) {\n try {\n const resolvedBasePath = path.resolve(basePath);\n const localePath = path.resolve(resolvedBasePath, locale);\n\n let isDir = false;\n try {\n const stats = await fs.stat(localePath);\n isDir = stats.isDirectory();\n } catch {}\n\n let data: Record<string, any> = {};\n\n if (isDir) {\n const files = await fs.readdir(localePath);\n for (const file of files) {\n if (file.endsWith('.json')) {\n const ns = path.basename(file, '.json');\n try {\n const content = await fs.readFile(path.join(localePath, file), 'utf-8');\n data[ns] = JSON.parse(content);\n } catch {}\n }\n }\n } else {\n try {\n if (!isSafeLocaleSegment(locale)) {\n continue;\n }\n const filePath = path.resolve(resolvedBasePath, `${locale}.json`);\n if (filePath.startsWith(resolvedBasePath)) {\n const content = await fs.readFile(filePath, 'utf-8');\n data = JSON.parse(content);\n }\n } catch {}\n }\n\n const flatten = (obj: any, prefix = '') => {\n if (!obj || typeof obj !== 'object') return;\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n const newKey = prefix ? `${prefix}.${key}` : key;\n if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {\n flatten(obj[key], newKey);\n } else {\n keysSet.add(newKey);\n }\n }\n }\n };\n\n flatten(data);\n } catch {}\n }\n\n return Array.from(keysSet).sort();\n }\n\n /**\n * Returns merged lists of keys from codebase and existing locale files.\n */\n async getKeysMetadata(\n basePath: string,\n listLocales: (base: string) => Promise<string[]>\n ): Promise<{ allKeys: string[]; codeKeys: string[] }> {\n const codeKeys = await this.scanCodebaseKeys(basePath);\n const localeKeys = await this.scanLocalesKeys(basePath, listLocales);\n const allKeys = Array.from(new Set([...codeKeys, ...localeKeys])).sort();\n return {\n allKeys,\n codeKeys,\n };\n }\n}\n","/**\n * Single source of truth for \"is LiveLocale active right now, and in which mode?\".\n *\n * Modes:\n * - `development`: NODE_ENV is `development` (the default, zero-config mode).\n * - `preview`: explicitly opted in with `LIVELOCALE=preview` (server) or\n * `NEXT_PUBLIC_LIVELOCALE=preview` (client bundles). Works in production builds so a\n * preview deployment can be edited through a hosted Studio. The mutation API then\n * requires a bearer token (see the router).\n * - `off`: everything else.\n *\n * Rules, in order:\n * 1. `LIVELOCALE=off|0|false` (or `NEXT_PUBLIC_LIVELOCALE=off`) always wins → off.\n * 2. `LIVELOCALE=preview` / `NEXT_PUBLIC_LIVELOCALE=preview` → preview.\n * 3. `NODE_ENV` must be `development`, otherwise off.\n * 4. `LIVELOCALE=force` skips rule 5.\n * 5. On the server, a known hosting platform (Vercel preview/production, Netlify,\n * Kubernetes, Render, Fly.io, Railway, Heroku) → off, so a mis-configured staging\n * deploy cannot leak watermarks. A one-time warning is logged.\n *\n * `process.env.NODE_ENV` and `process.env.NEXT_PUBLIC_LIVELOCALE` are referenced as\n * literal member expressions so Next.js and Vite can inline them in browser bundles.\n */\n\nexport type LiveLocaleMode = 'off' | 'development' | 'preview';\n\nconst OFF_VALUES = new Set(['off', '0', 'false']);\n\nlet warnedDeployed = false;\n\n/** Test hook: forget that the deployed-platform warning was already printed. */\nexport function resetEnvWarnings(): void {\n warnedDeployed = false;\n}\n\nfunction readNodeEnv(): string | undefined {\n try {\n return process.env.NODE_ENV;\n } catch {\n return undefined;\n }\n}\n\n/** Set by the Vite plugin (and usable by any host) to mirror the server flag into the page. */\nexport const BROWSER_FLAG_GLOBAL = '__LIVELOCALE_FLAG__';\n\nfunction readPublicFlag(): string | undefined {\n let value: string | undefined;\n try {\n value = process.env.NEXT_PUBLIC_LIVELOCALE;\n } catch {\n value = undefined;\n }\n if (value) return value;\n try {\n const g = globalThis as any;\n const fromGlobal = g.window?.[BROWSER_FLAG_GLOBAL] ?? g[BROWSER_FLAG_GLOBAL];\n return typeof fromGlobal === 'string' ? fromGlobal : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readEnv(name: string): string | undefined {\n if (typeof process === 'undefined' || !process.env) return undefined;\n const value = process.env[name];\n return value === '' ? undefined : value;\n}\n\n/** Returns a human-readable platform name when running on a known hosting platform. */\nexport function detectDeployedPlatform(): string | null {\n if (typeof window !== 'undefined') return null; // browser: nothing to detect\n const vercelEnv = readEnv('VERCEL_ENV');\n if (vercelEnv === 'production' || vercelEnv === 'preview')\n return `Vercel (VERCEL_ENV=${vercelEnv})`;\n const netlifyContext = readEnv('CONTEXT');\n if (readEnv('NETLIFY') === 'true' && netlifyContext && netlifyContext !== 'dev') {\n return `Netlify (CONTEXT=${netlifyContext})`;\n }\n if (readEnv('KUBERNETES_SERVICE_HOST')) return 'Kubernetes';\n if (readEnv('RENDER') === 'true') return 'Render';\n if (readEnv('FLY_APP_NAME')) return 'Fly.io';\n if (readEnv('RAILWAY_ENVIRONMENT')) return 'Railway';\n if (readEnv('DYNO')) return 'Heroku';\n return null;\n}\n\nfunction evaluate(): { mode: LiveLocaleMode; reason: string | null } {\n const flag = (readEnv('LIVELOCALE') ?? '').toLowerCase();\n const publicFlag = (readPublicFlag() ?? '').toLowerCase();\n\n if (OFF_VALUES.has(flag)) return { mode: 'off', reason: 'LIVELOCALE kill switch is set' };\n if (OFF_VALUES.has(publicFlag)) {\n return { mode: 'off', reason: 'NEXT_PUBLIC_LIVELOCALE kill switch is set' };\n }\n\n if (flag === 'preview' || publicFlag === 'preview') return { mode: 'preview', reason: null };\n\n const nodeEnv = readNodeEnv();\n if (nodeEnv !== 'development') {\n return {\n mode: 'off',\n reason: `NODE_ENV is \"${nodeEnv ?? 'undefined'}\" (must be \"development\", or set LIVELOCALE=preview)`,\n };\n }\n\n if (flag === 'force') return { mode: 'development', reason: null };\n\n const platform = detectDeployedPlatform();\n if (platform) {\n if (!warnedDeployed) {\n warnedDeployed = true;\n console.warn(\n `[livelocale] Disabled: deployed environment detected (${platform}) while NODE_ENV=development. ` +\n `Set LIVELOCALE=force to override, LIVELOCALE=preview for a hosted preview, or LIVELOCALE=off to silence this warning.`\n );\n }\n return { mode: 'off', reason: `deployed environment detected (${platform})` };\n }\n\n return { mode: 'development', reason: null };\n}\n\n/** The active mode: `off`, `development`, or `preview`. */\nexport function getLiveLocaleMode(): LiveLocaleMode {\n return evaluate().mode;\n}\n\n/**\n * Returns `null` when LiveLocale should be active, otherwise a short reason\n * suitable for error messages and logs.\n */\nexport function getDisabledReason(): string | null {\n return evaluate().reason;\n}\n\n/** True when watermarking, the mutation API, and the client scanner should run. */\nexport function isLiveLocaleEnabled(): boolean {\n return evaluate().mode !== 'off';\n}\n","/**\n * A small, dependency-free `.gitignore` matcher covering the patterns that\n * matter for skipping generated code during key scanning: directory rules\n * (`build/`), anchored rules (`/dist`), globs (`*.log`, `**\\/tmp`,\n * `docs/**\\/*.snap`) and negation (`!keep.log`). Last matching rule wins, and a\n * path whose ancestor directory is ignored is ignored too.\n */\n\nexport interface GitignoreMatcher {\n /** `relPath` is relative to the directory holding the .gitignore, using `/` separators. */\n ignores(relPath: string, isDir: boolean): boolean;\n}\n\ninterface Rule {\n regex: RegExp;\n negated: boolean;\n dirOnly: boolean;\n}\n\nfunction globToRegexSource(pattern: string): string {\n let out = '';\n let i = 0;\n while (i < pattern.length) {\n const ch = pattern[i]!;\n if (ch === '*') {\n if (pattern[i + 1] === '*') {\n // `**/` → any number of directories (including none); `**` elsewhere → anything\n if (pattern[i + 2] === '/') {\n out += '(?:.*/)?';\n i += 3;\n } else {\n out += '.*';\n i += 2;\n }\n } else {\n out += '[^/]*';\n i += 1;\n }\n } else if (ch === '?') {\n out += '[^/]';\n i += 1;\n } else {\n out += /[.+^${}()|[\\]\\\\]/.test(ch) ? `\\\\${ch}` : ch;\n i += 1;\n }\n }\n return out;\n}\n\nfunction compileRule(rawLine: string): Rule | null {\n let line = rawLine.replace(/\\r$/, '');\n if (!line.trim() || line.trimStart().startsWith('#')) return null;\n // Trailing spaces are ignored unless escaped\n line = line.replace(/(?<!\\\\)\\s+$/, '');\n\n let negated = false;\n if (line.startsWith('!')) {\n negated = true;\n line = line.slice(1);\n }\n\n let dirOnly = false;\n if (line.endsWith('/')) {\n dirOnly = true;\n line = line.slice(0, -1);\n }\n\n let anchored = false;\n if (line.startsWith('/')) {\n anchored = true;\n line = line.slice(1);\n } else if (line.includes('/')) {\n anchored = true;\n }\n\n if (!line) return null;\n\n const body = globToRegexSource(line);\n const regex = anchored ? new RegExp(`^${body}$`) : new RegExp(`(?:^|/)${body}$`);\n return { regex, negated, dirOnly };\n}\n\nexport function parseGitignore(content: string): GitignoreMatcher {\n const rules: Rule[] = [];\n for (const line of content.split('\\n')) {\n const rule = compileRule(line);\n if (rule) rules.push(rule);\n }\n\n const matchOne = (relPath: string, isDir: boolean): boolean => {\n let ignored = false;\n for (const rule of rules) {\n if (rule.dirOnly && !isDir) continue;\n if (rule.regex.test(relPath)) ignored = !rule.negated;\n }\n return ignored;\n };\n\n return {\n ignores(relPath: string, isDir: boolean): boolean {\n if (rules.length === 0) return false;\n const normalized = relPath.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/^\\/+/, '');\n if (!normalized) return false;\n if (matchOne(normalized, isDir)) return true;\n\n // An ignored ancestor directory ignores everything beneath it.\n const segments = normalized.split('/');\n for (let i = 1; i < segments.length; i++) {\n if (matchOne(segments.slice(0, i).join('/'), true)) return true;\n }\n return false;\n },\n };\n}\n"],"mappings":"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","names":["fs","path","fs","path","fs","path","path","fs","listLocales","flatten","resolve","transformReactI18next"]}
1
+ {"version":3,"sources":["../../src/codemod/transform.ts","../../src/codemod/index.ts","../../src/server/module-dir.ts","../../src/codemod/studio-server.ts","../../src/codemod/doctor.ts","../../src/core/validate.ts","../../src/core/flag-script.ts","../../src/core/change-link.ts","../../src/core/share-manifest.ts","../../src/codemod/check.ts","../../src/core/placeholders.ts","../../src/server/key-scanner.ts","../../src/core/env.ts","../../src/core/gitignore.ts","../../src/server/pack.ts","../../src/server/build-info.ts","../../src/server/build-target.ts","../../src/server/pack-error.ts","../../src/server/share-html.ts","../../src/codemod/apply/cli.ts","../../src/codemod/apply/link-input.ts","../../src/codemod/apply/local.ts","../../src/core/change-link-node.ts","../../src/client/watermark.ts","../../src/core/json-path.ts","../../src/core/save-rules.ts","../../src/core/apply-plan.ts","../../src/server/file-mutator.ts","../../src/core/safe-path.ts","../../src/server/git-client.ts","../../src/codemod/apply/report.ts"],"sourcesContent":["// Type-only import: the runtime module is loaded lazily by `loadTypeScript()`.\nimport type * as ts from 'typescript';\n\ntype TypeScriptModule = typeof ts;\n\n/**\n * `typescript` is an optional peer: it is only needed by `migrate`. Loading it\n * lazily keeps `init` and `studio` working in JavaScript-only projects.\n */\nexport async function loadTypeScript(): Promise<TypeScriptModule> {\n try {\n const mod: any = await import('typescript');\n return (mod.default ?? mod) as TypeScriptModule;\n } catch {\n throw new Error(\n \"The 'typescript' package is required for the migrate command. Install it with: npm install -D typescript\"\n );\n }\n}\n\nexport interface TransformResult {\n code: string;\n modified: boolean;\n}\n\n/**\n * Transforms a source file by wrapping react-i18next useTranslation hook calls\n * with wrapTranslationEngine.\n */\nexport async function transformReactI18next(\n sourceText: string,\n filename: string\n): Promise<TransformResult> {\n const ts = await loadTypeScript();\n const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true);\n\n let hasUseTranslationImport = false;\n let alreadyHasWrapImport = false;\n let useTranslationImportNode: ts.Node | null = null;\n let localUseTranslationName = 'useTranslation';\n\n // Step 1: Find imports\n function findImports(node: ts.Node) {\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = node.moduleSpecifier;\n if (ts.isStringLiteral(moduleSpecifier)) {\n if (moduleSpecifier.text === 'react-i18next') {\n const importClause = node.importClause;\n if (\n importClause &&\n importClause.namedBindings &&\n ts.isNamedImports(importClause.namedBindings)\n ) {\n for (const specifier of importClause.namedBindings.elements) {\n const importedName = specifier.propertyName\n ? specifier.propertyName.text\n : specifier.name.text;\n if (importedName === 'useTranslation') {\n hasUseTranslationImport = true;\n localUseTranslationName = specifier.name.text;\n useTranslationImportNode = node;\n }\n }\n }\n }\n if (\n moduleSpecifier.text === 'livelocale/client' ||\n moduleSpecifier.text === 'livelocale/server'\n ) {\n alreadyHasWrapImport = true;\n }\n }\n }\n ts.forEachChild(node, findImports);\n }\n\n findImports(sourceFile);\n\n if (!hasUseTranslationImport) {\n return { code: sourceText, modified: false };\n }\n\n interface Edit {\n start: number;\n end: number;\n text: string;\n index: number; // for stable sorting\n }\n const edits: Edit[] = [];\n let editCount = 0;\n\n // Step 2: Find useTranslation calls and their statement structures\n function findHookCalls(node: ts.Node) {\n if (ts.isVariableStatement(node)) {\n const declList = node.declarationList;\n for (const decl of declList.declarations) {\n if (decl.initializer && ts.isCallExpression(decl.initializer)) {\n const expr = decl.initializer.expression;\n if (ts.isIdentifier(expr) && expr.text === localUseTranslationName) {\n processHookCall(decl, node);\n }\n }\n }\n }\n ts.forEachChild(node, findHookCalls);\n }\n\n function isAlreadyWrapped(\n tLocalName: string,\n originalName: string,\n parentNode: ts.Node\n ): boolean {\n let found = false;\n function visit(node: ts.Node) {\n if (ts.isVariableDeclaration(node)) {\n if (ts.isIdentifier(node.name) && node.name.text === originalName) {\n if (node.initializer) {\n if (ts.isCallExpression(node.initializer)) {\n const expr = node.initializer.expression;\n if (ts.isIdentifier(expr) && expr.text === 'wrapTranslationEngine') {\n if (node.initializer.arguments.length > 0) {\n const arg = node.initializer.arguments[0];\n if (arg && ts.isIdentifier(arg) && arg.text === tLocalName) {\n found = true;\n }\n }\n }\n } else if (ts.isObjectLiteralExpression(node.initializer)) {\n let hasSpread = false;\n let hasWrap = false;\n for (const prop of node.initializer.properties) {\n if (ts.isSpreadAssignment(prop)) {\n if (ts.isIdentifier(prop.expression) && prop.expression.text === tLocalName) {\n hasSpread = true;\n }\n } else if (ts.isPropertyAssignment(prop)) {\n if (ts.isIdentifier(prop.name) && prop.name.text === 't') {\n if (ts.isCallExpression(prop.initializer)) {\n const expr = prop.initializer.expression;\n if (ts.isIdentifier(expr) && expr.text === 'wrapTranslationEngine') {\n hasWrap = true;\n }\n }\n }\n }\n }\n if (hasSpread && hasWrap) {\n found = true;\n }\n }\n }\n }\n }\n if (!found) {\n ts.forEachChild(node, visit);\n }\n }\n visit(parentNode);\n return found;\n }\n\n function processHookCall(\n declaration: ts.VariableDeclaration,\n variableStatement: ts.VariableStatement\n ) {\n const callNode = declaration.initializer as ts.CallExpression;\n\n // Extract keyPrefix expression if present\n let keyPrefixExpr: string | undefined = undefined;\n if (callNode.arguments.length > 0) {\n const firstArg = callNode.arguments[0]!;\n if (ts.isStringLiteral(firstArg)) {\n keyPrefixExpr = `'${firstArg.text}'`;\n } else if (ts.isArrayLiteralExpression(firstArg)) {\n if (firstArg.elements.length > 0) {\n const firstElem = firstArg.elements[0]!;\n keyPrefixExpr = firstElem.getText(sourceFile);\n }\n } else {\n keyPrefixExpr = firstArg.getText(sourceFile);\n }\n }\n\n // Determine indentation of the statement\n const statementStart = variableStatement.getStart(sourceFile);\n let lineStart = statementStart;\n while (\n lineStart > 0 &&\n sourceText[lineStart - 1] !== '\\n' &&\n sourceText[lineStart - 1] !== '\\r'\n ) {\n lineStart--;\n }\n const indentation = sourceText.slice(lineStart, statementStart).match(/^\\s*/)?.[0] || '';\n const wrapOptions = keyPrefixExpr ? `, { keyPrefix: ${keyPrefixExpr} }` : '';\n\n const nameNode = declaration.name;\n\n // Pattern A: Object Destructuring: const { t } = useTranslation()\n if (ts.isObjectBindingPattern(nameNode)) {\n let tElement: ts.BindingElement | null = null;\n for (const element of nameNode.elements) {\n if (ts.isIdentifier(element.name)) {\n const propName = element.propertyName\n ? ts.isIdentifier(element.propertyName)\n ? element.propertyName.text\n : element.propertyName.getText(sourceFile)\n : (element.name as ts.Identifier).text;\n if (propName === 't') {\n tElement = element;\n break;\n }\n }\n }\n\n if (tElement && ts.isIdentifier(tElement.name)) {\n const tLocalName = tElement.name.text;\n\n // Determine original/desired name of the translation variable (e.g. 't' or a custom rename)\n let desiredName = tLocalName;\n if (tLocalName.startsWith('raw') && tLocalName.length > 3) {\n const base = tLocalName.slice(3);\n desiredName = base.charAt(0).toLowerCase() + base.slice(1);\n } else if (tElement.propertyName && ts.isIdentifier(tElement.propertyName)) {\n desiredName = tLocalName;\n } else {\n desiredName = 't';\n }\n\n if (\n variableStatement.parent &&\n isAlreadyWrapped(tLocalName, desiredName, variableStatement.parent)\n ) {\n return;\n }\n\n const rawLocalName = `raw${desiredName.charAt(0).toUpperCase()}${desiredName.slice(1)}`;\n\n // Replace \"t\" or \"t: customName\" with \"t: rawName\"\n edits.push({\n start: tElement.getStart(sourceFile),\n end: tElement.getEnd(),\n text: `t: ${rawLocalName}`,\n index: editCount++,\n });\n\n // Insert wrap translation statement right after the variable statement\n edits.push({\n start: variableStatement.getEnd(),\n end: variableStatement.getEnd(),\n text: `\\n${indentation}const ${desiredName} = wrapTranslationEngine(${rawLocalName}${wrapOptions});`,\n index: editCount++,\n });\n }\n }\n // Pattern B: Array Destructuring: const [ t ] = useTranslation()\n else if (ts.isArrayBindingPattern(nameNode)) {\n if (nameNode.elements.length > 0) {\n const firstElement = nameNode.elements[0]!;\n if (ts.isBindingElement(firstElement) && ts.isIdentifier(firstElement.name)) {\n const tLocalName = firstElement.name.text;\n\n let desiredName = tLocalName;\n if (tLocalName.startsWith('raw') && tLocalName.length > 3) {\n const base = tLocalName.slice(3);\n desiredName = base.charAt(0).toLowerCase() + base.slice(1);\n }\n\n if (\n variableStatement.parent &&\n isAlreadyWrapped(tLocalName, desiredName, variableStatement.parent)\n ) {\n return;\n }\n\n const rawLocalName = `raw${desiredName.charAt(0).toUpperCase()}${desiredName.slice(1)}`;\n\n // Replace first element with rawName\n edits.push({\n start: firstElement.getStart(sourceFile),\n end: firstElement.getEnd(),\n text: rawLocalName,\n index: editCount++,\n });\n\n // Insert wrap translation statement right after the variable statement\n edits.push({\n start: variableStatement.getEnd(),\n end: variableStatement.getEnd(),\n text: `\\n${indentation}const ${desiredName} = wrapTranslationEngine(${rawLocalName}${wrapOptions});`,\n index: editCount++,\n });\n }\n }\n }\n // Pattern C: Simple Assignment: const translation = useTranslation()\n else if (ts.isIdentifier(nameNode)) {\n const tLocalName = nameNode.text;\n\n let desiredName = tLocalName;\n if (tLocalName.startsWith('raw') && tLocalName.length > 3) {\n const base = tLocalName.slice(3);\n desiredName = base.charAt(0).toLowerCase() + base.slice(1);\n }\n\n if (\n variableStatement.parent &&\n isAlreadyWrapped(tLocalName, desiredName, variableStatement.parent)\n ) {\n return;\n }\n\n const rawLocalName = `raw${desiredName.charAt(0).toUpperCase()}${desiredName.slice(1)}`;\n\n // Replace name with rawName\n edits.push({\n start: nameNode.getStart(sourceFile),\n end: nameNode.getEnd(),\n text: rawLocalName,\n index: editCount++,\n });\n\n // Insert wrapper structure right after the variable statement\n edits.push({\n start: variableStatement.getEnd(),\n end: variableStatement.getEnd(),\n text: `\\n${indentation}const ${desiredName} = { ...${rawLocalName}, t: wrapTranslationEngine(${rawLocalName}.t${wrapOptions}) };`,\n index: editCount++,\n });\n }\n }\n\n findHookCalls(sourceFile);\n\n if (edits.length === 0) {\n return { code: sourceText, modified: false };\n }\n\n // Step 3: Insert wrap import if not already present\n if (!alreadyHasWrapImport) {\n if (useTranslationImportNode) {\n const insertPos = (useTranslationImportNode as ts.Node).getEnd();\n edits.push({\n start: insertPos,\n end: insertPos,\n text: `\\nimport { wrapTranslationEngine } from 'livelocale/client';`,\n index: editCount++,\n });\n } else {\n let insertPos = 0;\n const useClientMatch = sourceText.match(/^['\"]use client['\"];?\\s*/);\n if (useClientMatch) {\n insertPos = useClientMatch[0].length;\n }\n edits.push({\n start: insertPos,\n end: insertPos,\n text: `import { wrapTranslationEngine } from 'livelocale/client';\\n`,\n index: editCount++,\n });\n }\n }\n\n // Step 4: Apply edits in reverse order\n edits.sort((a, b) => {\n if (b.start !== a.start) {\n return b.start - a.start;\n }\n // If same start index, preserve original relative order descending (so insertions don't scramble)\n return b.index - a.index;\n });\n\n let newText = sourceText;\n for (const edit of edits) {\n newText = newText.slice(0, edit.start) + edit.text + newText.slice(edit.end);\n }\n\n return { code: newText, modified: true };\n}\n","#!/usr/bin/env node\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as net from 'net';\nimport { moduleDir } from '../server/module-dir.js';\nimport { createStudioServer } from './studio-server.js';\nimport { runDoctor, formatFindings, hasFailures, normalizeAppUrl } from './doctor.js';\nimport { runCheck, formatCheckReport, hasCheckFailures } from './check.js';\nimport {\n BUILD_USAGE,\n packOutput,\n parseShareArgs,\n runBuildCommand,\n type PackResult,\n} from '../server/pack.js';\nimport { PackError } from '../server/pack-error.js';\nimport { runApplyCommand } from './apply/cli.js';\n\nconst DEFAULT_STUDIO_PORT = 3010;\nconst DEFAULT_APP_ORIGIN = 'http://localhost:3000';\n\nfunction printHelp() {\n console.log(`\nLiveLocale (livelocale) CLI\n\nUsage:\n npx livelocale <command> [options]\n\nCommands:\n migrate Bulk migrate existing react-i18next translation usages to wrap them with wrapTranslationEngine automatically.\n init Initialize the API route handler inside a Next.js project automatically.\n studio Start the visual editing studio local web server.\n doctor Check the project for common integration problems (route, provider, middleware, CSP, locales).\n check Check translations for missing keys, placeholder drift, broken ICU syntax and unused keys (CI-friendly).\n pack Write the share Studio (livelocale/) into a built site folder and link every HTML page to it.\n build Run your build command, then pack its output (Next.js: packs into public/livelocale/ first).\n apply Apply a LiveLocale change link to your locale files (--pr opens a pull request)\n\nOptions for migrate:\n --dir <path> Directory to scan (default: current directory)\n --exclude <list> Comma-separated list of directories to exclude (default: node_modules,.next,dist,.git)\n --dry-run Preview changes without writing them to disk\n\nOptions for init:\n --dir <path> Target project directory (default: current directory)\n\nOptions for studio:\n --port <number> Port to run the studio server on (default: ${DEFAULT_STUDIO_PORT})\n --app <origin> Origin of the app being edited (default: ${DEFAULT_APP_ORIGIN})\n Can also be changed at run time with ?app=<origin> on the Studio URL.\n\nOptions for doctor:\n --dir <path> Project directory to inspect (default: current directory)\n --locales <path> Locales directory relative to the project (default: locales)\n --app <url> Also probe the running app or deployed site, e.g. http://localhost:3000\n or https://user.github.io/repo/ (a path is the app base)\n --share Run the share link probes even when livelocale/manifest.json is missing\n --token <token> Access token for a preview deployment (default: LIVELOCALE_TOKEN)\n\nOptions for check:\n --dir <path> Project directory to scan (default: current directory)\n --locales <path> Locales directory relative to the project (default: locales)\n --source <locale> Locale the others are compared against (default: en, else the first locale)\n --no-unused Do not report keys that code never references\n --strict Treat warnings (unused keys, empty values) as failures\n --json Print the full report as JSON\n\nOptions for pack:\n pack <outDir> Built site folder, relative to --dir (e.g. dist, build, out)\n --dir <path> Project directory (default: current directory)\n --locales <path> Locales directory relative to the project (default: locales)\n --source <locale> Source locale (default: en, else the first locale)\n --base <path> Site path the app is served from, e.g. /repo/ (default: detected, else /)\n --expose-repo Put the GitHub owner/repo into livelocale/manifest.json\n --no-inject Do not add the flag.js script to HTML files\n\nOptions for build:\n build [--preview] [--out <dir>] [pack options] -- <command...>\n --preview Run the command with LIVELOCALE=preview and NEXT_PUBLIC_LIVELOCALE=preview\n --out <dir> Build output folder (default: detected from dist/, build/, out/)\n\nOptions for apply:\n apply <link|file|-> The change link, a file that holds it, or - to read stdin\n --clipboard Read the change link from the clipboard instead\n --pr Commit the changes on a new branch and open a pull request\n --dir <path> Project directory (default: current directory)\n --locales <path> Locales directory relative to the project (default: locales)\n --source <locale> Source locale (default: en, else the first locale)\n --force Apply edits the translator saved with \"Save anyway\"\n --dry-run Show what would change without writing files\n\nGlobal Options:\n -h, --help Show help information\n`);\n}\n\nfunction normalizeOriginArg(value: string, flag: string): string {\n try {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') throw new Error('bad protocol');\n return url.origin;\n } catch {\n console.error(\n `Error: ${flag} must be an http(s) origin such as http://localhost:3001 (got \"${value}\").`\n );\n process.exit(1);\n }\n}\n\n/** `doctor --app`: an http(s) URL whose path, when given, is the app base. */\nfunction normalizeAppArg(value: string): { origin: string; base: string } {\n try {\n return normalizeAppUrl(value);\n } catch {\n console.error(\n `Error: --app must be an http(s) URL such as http://localhost:3000 or https://user.github.io/repo/ (got \"${value}\").`\n );\n process.exit(1);\n }\n}\n\n/**\n * True when something already accepts connections on localhost:port. On Windows\n * another process can hold [::1]:port while our [::]:port bind still succeeds,\n * so the browser would silently reach the other server.\n */\nfunction isPortAnswering(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = net.connect({ host: 'localhost', port });\n const done = (answering: boolean) => {\n socket.destroy();\n resolve(answering);\n };\n socket.setTimeout(1000, () => done(false));\n socket.once('connect', () => done(true));\n socket.once('error', () => done(false));\n });\n}\n\nasync function runStudio(port: number, appOrigin: string) {\n console.log(`\\n🚀 Starting LiveLocale Studio...`);\n const studioDir = path.resolve(moduleDir(), '../studio');\n\n if (!fs.existsSync(path.join(studioDir, 'index.html'))) {\n console.error(`Error: Studio assets not found at \"${studioDir}\".`);\n console.error(`Did you build the project? Run \"npm run build\" first.`);\n process.exit(1);\n }\n\n if (await isPortAnswering(port)) {\n console.error(\n `Error: something is already running on localhost:${port}. Stop it or pick another port with --port <number>.`\n );\n process.exit(1);\n }\n\n const server = createStudioServer({ studioDir, appOrigin });\n\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.error(`Error: port ${port} is already in use. Pick another with --port <number>.`);\n } else {\n console.error(`Error: failed to start the Studio server: ${err.message}`);\n }\n process.exit(1);\n });\n\n server.listen(port, () => {\n console.log(`\\n🎨 LiveLocale Studio is running!`);\n console.log(`📡 Studio: http://localhost:${port}`);\n console.log(`🔗 Editing app at: ${appOrigin}`);\n console.log(`💡 Press Ctrl+C to stop the studio server.\\n`);\n });\n}\n\nfunction runInit(projectDir: string) {\n console.log(`\\n🚀 Initializing LiveLocale API handler...`);\n const absoluteDir = path.resolve(projectDir);\n if (!fs.existsSync(absoluteDir)) {\n console.error(`Error: Directory \"${projectDir}\" does not exist.`);\n process.exit(1);\n }\n\n // 1. Detect TypeScript vs. JavaScript\n const isTypeScript = fs.existsSync(path.join(absoluteDir, 'tsconfig.json'));\n const fileExt = isTypeScript ? 'ts' : 'js';\n console.log(`📁 Target: ${absoluteDir}`);\n console.log(`🔧 Language detected: ${isTypeScript ? 'TypeScript' : 'JavaScript'}`);\n\n // 2. Check for installed libraries in package.json\n let hasNextIntl = false;\n let hasReactI18next = false;\n const targetPkgPath = path.join(absoluteDir, 'package.json');\n if (fs.existsSync(targetPkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(targetPkgPath, 'utf8'));\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n hasNextIntl = Boolean(allDeps['next-intl']);\n hasReactI18next = Boolean(allDeps['react-i18next']);\n } catch {}\n }\n\n // 3. Check for App Router vs Pages Router\n const appDirPath = path.join(absoluteDir, 'app');\n const pagesDirPath = path.join(absoluteDir, 'pages');\n const srcAppDirPath = path.join(absoluteDir, 'src', 'app');\n const srcPagesDirPath = path.join(absoluteDir, 'src', 'pages');\n\n let targetPath = '';\n let routerType = '';\n let content = '';\n\n if (fs.existsSync(appDirPath)) {\n targetPath = path.join(appDirPath, 'api', 'livelocale', `route.${fileExt}`);\n routerType = 'Next.js App Router (root)';\n } else if (fs.existsSync(srcAppDirPath)) {\n targetPath = path.join(srcAppDirPath, 'api', 'livelocale', `route.${fileExt}`);\n routerType = 'Next.js App Router (src/)';\n } else if (fs.existsSync(pagesDirPath)) {\n targetPath = path.join(pagesDirPath, 'api', `livelocale.${fileExt}`);\n routerType = 'Next.js Pages Router (root)';\n } else if (fs.existsSync(srcPagesDirPath)) {\n targetPath = path.join(srcPagesDirPath, 'api', `livelocale.${fileExt}`);\n routerType = 'Next.js Pages Router (src/)';\n } else {\n // Default fallback to root app router structure\n targetPath = path.join(absoluteDir, 'app', 'api', 'livelocale', `route.${fileExt}`);\n routerType = 'Default App Router (app/ not found)';\n }\n\n console.log(`📍 Project structure: ${routerType}`);\n\n if (routerType.includes('App Router')) {\n content = `import { createLiveLocaleHandler } from 'livelocale/server';\nimport * as path from 'path';\n\nconst handler = createLiveLocaleHandler({\n localesPath: path.resolve('./locales'), // Adjust relative to project root\n});\n\nexport const GET = handler;\nexport const POST = handler;\nexport const OPTIONS = handler;\n`;\n } else {\n content = `import { createLiveLocaleHandler } from 'livelocale/server';\nimport * as path from 'path';\n\n// Pages Router API route: the handler accepts the (req, res) signature.\nconst handler = createLiveLocaleHandler({\n localesPath: path.resolve('./locales'), // Adjust relative to project root\n});\n\nexport default handler;\n`;\n }\n\n // Ensure target folder exists\n const targetDir = path.dirname(targetPath);\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n\n // Write file\n try {\n fs.writeFileSync(targetPath, content, 'utf8');\n console.log(`✅ Created API Route Handler successfully at:`);\n console.log(` ${path.relative(absoluteDir, targetPath)}`);\n if (hasNextIntl) {\n console.log(`\\n💡 Detected 'next-intl' in your project!`);\n console.log(\n ` Wrap your translation hook with: import { wrapNextIntl } from 'livelocale/client';`\n );\n console.log(` const t = wrapNextIntl(useTranslations('namespace'), 'namespace');`);\n } else if (hasReactI18next) {\n console.log(`\\n💡 Detected 'react-i18next' in your project!`);\n console.log(` You can auto-wrap usages by running: npx livelocale migrate`);\n }\n console.log(`\\n🎉 Initialization completed successfully!\\n`);\n } catch (err: any) {\n console.error(`❌ Failed to write route handler: ${err.message}`);\n process.exit(1);\n }\n}\n\nasync function runMigrate(args: string[]) {\n let dir = '.';\n let excludes = ['node_modules', '.next', 'dist', '.git'];\n let dryRun = false;\n\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--dir') {\n dir = args[++i] || '.';\n } else if (arg === '--exclude') {\n const val = args[++i];\n if (val) {\n excludes = val.split(',').map((s) => s.trim());\n }\n } else if (arg === '--dry-run') {\n dryRun = true;\n } else {\n // Positional dir arg if not prefixed\n if (arg && !arg.startsWith('--')) {\n dir = arg;\n }\n }\n }\n\n const absoluteDir = path.resolve(dir);\n if (!fs.existsSync(absoluteDir)) {\n console.error(`Error: Directory \"${dir}\" does not exist.`);\n process.exit(1);\n }\n\n // The codemod depends on the optional `typescript` peer; load it only here.\n let transformReactI18next: typeof import('./transform.js').transformReactI18next;\n try {\n const transform = await import('./transform.js');\n await transform.loadTypeScript();\n transformReactI18next = transform.transformReactI18next;\n } catch (err: any) {\n console.error(`❌ ${err.message}`);\n process.exit(1);\n }\n\n console.log(`\\n🚀 Starting migration scanner...`);\n console.log(`📁 Target: ${absoluteDir}`);\n console.log(`🚫 Excluded: ${excludes.join(', ')}`);\n if (dryRun) {\n console.log(`🧪 Mode: DRY RUN (no files will be modified)`);\n }\n console.log('--------------------------------------------------');\n\n let scannedCount = 0;\n let migratedCount = 0;\n\n async function walk(currentDir: string) {\n const files = fs.readdirSync(currentDir, { withFileTypes: true });\n\n for (const file of files) {\n const fullPath = path.join(currentDir, file.name);\n\n if (file.isDirectory()) {\n if (excludes.includes(file.name)) {\n continue;\n }\n await walk(fullPath);\n } else if (file.isFile()) {\n const ext = path.extname(file.name);\n if (['.js', '.jsx', '.ts', '.tsx'].includes(ext)) {\n scannedCount++;\n try {\n const content = fs.readFileSync(fullPath, 'utf8');\n const result = await transformReactI18next(content, fullPath);\n\n if (result.modified) {\n migratedCount++;\n const relativePath = path.relative(absoluteDir, fullPath);\n if (dryRun) {\n console.log(`[DRY RUN] Would migrate: ${relativePath}`);\n } else {\n fs.writeFileSync(fullPath, result.code, 'utf8');\n console.log(`✅ Migrated: ${relativePath}`);\n }\n }\n } catch (err: any) {\n console.error(`❌ Error processing file ${fullPath}:`, err.message);\n }\n }\n }\n }\n }\n\n try {\n await walk(absoluteDir);\n } catch (err: any) {\n console.error(`❌ Walk error:`, err.message);\n }\n\n console.log('--------------------------------------------------');\n console.log(`📊 Summary:`);\n console.log(` Scanned: ${scannedCount} files`);\n if (dryRun) {\n console.log(` Would migrate: ${migratedCount} files`);\n } else {\n console.log(` Migrated: ${migratedCount} files`);\n }\n console.log(`\\n🎉 Done!`);\n}\n\nasync function runDoctorCommand(args: string[]) {\n let dir = '.';\n let localesPath: string | undefined;\n let app: { origin: string; base: string } | undefined;\n let share = false;\n let token: string | undefined;\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--dir') {\n dir = args[++i] || '.';\n } else if (arg === '--locales') {\n localesPath = args[++i];\n } else if (arg === '--app') {\n app = normalizeAppArg(args[++i] || '');\n } else if (arg === '--share') {\n share = true;\n } else if (arg === '--token') {\n token = args[++i];\n } else if (arg && !arg.startsWith('--')) {\n dir = arg;\n }\n }\n\n const projectDir = path.resolve(dir);\n if (!fs.existsSync(projectDir)) {\n console.error(`Error: Directory \"${dir}\" does not exist.`);\n process.exit(1);\n }\n\n console.log(`\n🩺 LiveLocale doctor — ${projectDir}`);\n if (app) console.log(`🔗 Probing app at ${app.base}`);\n console.log('--------------------------------------------------');\n\n const findings = await runDoctor({\n projectDir,\n localesPath,\n appOrigin: app?.origin,\n appBase: app?.base,\n share,\n token,\n });\n console.log(formatFindings(findings));\n console.log('--------------------------------------------------');\n\n const fails = findings.filter((f) => f.level === 'fail').length;\n const warns = findings.filter((f) => f.level === 'warn').length;\n if (hasFailures(findings)) {\n console.log(`❌ ${fails} problem(s), ${warns} warning(s). Fix the problems above and re-run.`);\n // exitCode, not exit(): open fetch sockets from --app probes crash Node on Windows otherwise.\n process.exitCode = 1;\n return;\n }\n console.log(\n warns > 0\n ? `✅ No blocking problems, ${warns} warning(s) worth a look.`\n : `✅ Everything looks good.`\n );\n const shareLink = findings.find((f) => f.title === 'Share link')?.detail;\n if (shareLink) console.log(`🔗 Share link: ${shareLink}`);\n if (!app) {\n console.log(\n `💡 Start your dev server and re-run with --app http://localhost:3000 for live checks.`\n );\n }\n}\n\nasync function runCheckCommand(args: string[]) {\n let dir = '.';\n let localesPath: string | undefined;\n let sourceLocale: string | undefined;\n let unused = true;\n let strict = false;\n let json = false;\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--dir') {\n dir = args[++i] || '.';\n } else if (arg === '--locales') {\n localesPath = args[++i];\n } else if (arg === '--source') {\n sourceLocale = args[++i];\n } else if (arg === '--no-unused') {\n unused = false;\n } else if (arg === '--strict') {\n strict = true;\n } else if (arg === '--json') {\n json = true;\n } else if (arg && !arg.startsWith('--')) {\n dir = arg;\n }\n }\n\n const projectDir = path.resolve(dir);\n if (!fs.existsSync(projectDir)) {\n console.error(`Error: Directory \"${dir}\" does not exist.`);\n process.exit(1);\n }\n\n let report;\n try {\n report = await runCheck({ projectDir, localesPath, sourceLocale, unused, strict });\n } catch (err: any) {\n console.error(`❌ ${err.message}`);\n process.exit(1);\n }\n\n const failed = hasCheckFailures(report);\n if (json) {\n console.log(JSON.stringify(report, null, 2));\n // exitCode, not exit(): exiting immediately can truncate a large report piped to another tool.\n process.exitCode = failed ? 1 : 0;\n return;\n }\n\n console.log(`\\n🔎 LiveLocale check — ${projectDir}`);\n console.log(\n `🌐 Locales: ${report.locales.join(', ') || 'none'}` +\n (report.sourceLocale ? ` (source: ${report.sourceLocale})` : '') +\n ` · ${report.codeKeyCount} key(s) referenced in code`\n );\n console.log('--------------------------------------------------');\n if (report.issues.length > 0) {\n console.log(formatCheckReport(report));\n console.log('--------------------------------------------------');\n }\n\n const fails = report.issues.filter((i) => i.level === 'fail').length;\n const warns = report.issues.filter((i) => i.level === 'warn').length;\n if (failed) {\n console.log(`❌ ${fails} problem(s), ${warns} warning(s).`);\n process.exitCode = 1;\n return;\n }\n console.log(\n warns > 0 ? `✅ No problems, ${warns} warning(s) worth a look.` : `✅ Translations look good.`\n );\n}\n\nconst PACK_USAGE = 'Usage: livelocale pack <outDir> [options]';\n\n/** Prints each pack warning, then where the share folder went and the link path to open. */\nfunction printPackSummary(result: PackResult, projectDir: string, warnings: string[]) {\n for (const warning of warnings) console.log(`⚠️ ${warning}`);\n const outRel =\n path.relative(projectDir, path.dirname(result.shareDir)).split(path.sep).join('/') || '.';\n console.log(\n `✅ LiveLocale share folder written to ${outRel}/livelocale/ (${result.manifest.locales.length} locales, ${result.manifest.codeKeys.length} code keys, ${result.htmlInjected.length} HTML files linked).`\n );\n console.log(`🔗 Open ${result.shareUrlPath} on the deployed site.`);\n}\n\nasync function runPackCommand(args: string[]) {\n try {\n const options = parseShareArgs(args.slice(1));\n if (\n options.positional.length !== 1 ||\n options.out !== undefined ||\n options.preview ||\n options.command.length > 0\n ) {\n throw new PackError('USAGE', PACK_USAGE);\n }\n const projectDir = path.resolve(options.dir);\n const result = await packOutput({\n projectDir,\n outDir: options.positional[0]!,\n localesPath: options.locales,\n sourceLocale: options.source,\n base: options.base,\n exposeRepo: options.exposeRepo,\n injectHtml: options.inject ? 'auto' : false,\n });\n printPackSummary(result, projectDir, result.warnings);\n } catch (err) {\n if (!(err instanceof PackError)) throw err;\n console.error(`❌ ${err.message}`);\n process.exitCode = 1;\n }\n}\n\nasync function runBuildCli(args: string[]) {\n try {\n const options = parseShareArgs(args.slice(1));\n if (options.positional.length > 0 || !options.inject) {\n throw new PackError('USAGE', BUILD_USAGE);\n }\n const projectDir = path.resolve(options.dir);\n const result = await runBuildCommand({\n projectDir,\n command: options.command,\n preview: options.preview,\n outDir: options.out,\n localesPath: options.locales,\n sourceLocale: options.source,\n base: options.base,\n exposeRepo: options.exposeRepo,\n });\n if (result.pack !== null) {\n printPackSummary(result.pack, projectDir, result.warnings);\n } else {\n for (const warning of result.warnings) console.log(`⚠️ ${warning}`);\n }\n process.exitCode = result.exitCode;\n } catch (err) {\n if (!(err instanceof PackError)) throw err;\n console.error(`❌ ${err.message}`);\n process.exitCode = 1;\n }\n}\n\nasync function run() {\n const args = process.argv.slice(2);\n\n if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {\n printHelp();\n process.exit(0);\n }\n\n const COMMANDS = ['migrate', 'init', 'studio', 'doctor', 'check', 'pack', 'build', 'apply'];\n if (!args[0] || !COMMANDS.includes(args[0])) {\n console.error(`Unknown command: \"${args[0]}\". Expected one of: ${COMMANDS.join(', ')}.`);\n printHelp();\n process.exit(1);\n }\n\n if (args[0] === 'doctor') {\n await runDoctorCommand(args);\n return;\n }\n\n if (args[0] === 'check') {\n await runCheckCommand(args);\n return;\n }\n\n if (args[0] === 'pack') {\n await runPackCommand(args);\n return;\n }\n\n if (args[0] === 'build') {\n await runBuildCli(args);\n return;\n }\n\n if (args[0] === 'apply') {\n await runApplyCommand(args.slice(1));\n return;\n }\n\n if (args[0] === 'init') {\n let dir = '.';\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--dir') {\n dir = args[++i] || '.';\n } else if (arg && !arg.startsWith('--')) {\n dir = arg;\n }\n }\n runInit(dir);\n process.exit(0);\n }\n\n if (args[0] === 'studio') {\n let port = DEFAULT_STUDIO_PORT;\n let appOrigin = DEFAULT_APP_ORIGIN;\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--port') {\n const val = parseInt(args[++i] || String(DEFAULT_STUDIO_PORT), 10);\n if (!isNaN(val)) port = val;\n } else if (arg === '--app') {\n appOrigin = normalizeOriginArg(args[++i] || '', '--app');\n }\n }\n await runStudio(port, appOrigin);\n return;\n }\n\n await runMigrate(args);\n}\n\nrun().catch((err: any) => {\n console.error(`❌ ${err?.message || err}`);\n process.exit(1);\n});\n","import * as path from 'path';\nimport { fileURLToPath } from 'url';\n\n/** The folder of the running module: `__dirname` in CommonJS, else derived from `import.meta.url`. */\nexport function moduleDir(): string {\n if (typeof __dirname !== 'undefined') {\n return __dirname;\n }\n return path.dirname(fileURLToPath((import.meta as any).url));\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as http from 'http';\n\nexport interface StudioConfig {\n /** Origin of the application being edited, e.g. `http://localhost:3001`. */\n appOrigin: string;\n}\n\nexport interface StudioServerOptions extends StudioConfig {\n /** Directory containing the built Studio assets (index.html + assets/). */\n studioDir: string;\n}\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css',\n '.js': 'application/javascript',\n '.mjs': 'application/javascript',\n '.map': 'application/json',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.json': 'application/json',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n};\n\n/** Any localhost origin (any port) is trusted — remote websites are not (RULE SEC-009). */\nconst LOCALHOST_ORIGIN_RE = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(:\\d+)?$/;\n\n/**\n * Injects `window.__LIVELOCALE_CONFIG__` into the Studio's index.html so the\n * app origin can be chosen at run time instead of at build time.\n *\n * RULE SEC-008: \"<\" and the U+2028/U+2029 line terminators are escaped so no\n * config value can terminate the script tag.\n */\nexport function injectStudioConfig(html: string, config: StudioConfig): string {\n const safeJson = JSON.stringify(config)\n .replace(/</g, '\\\\u003c')\n .replace(new RegExp(String.fromCharCode(0x2028), 'g'), '\\\\u2028')\n .replace(new RegExp(String.fromCharCode(0x2029), 'g'), '\\\\u2029');\n const script = `<script>window.__LIVELOCALE_CONFIG__ = ${safeJson};</script>`;\n if (html.includes('</head>')) {\n return html.replace('</head>', `${script}\\n</head>`);\n }\n return `${script}\\n${html}`;\n}\n\n/**\n * Creates (but does not start) the static HTTP server that hosts the Studio.\n */\nexport function createStudioServer(options: StudioServerOptions): http.Server {\n const studioDir = path.resolve(options.studioDir);\n const indexPath = path.join(studioDir, 'index.html');\n const config: StudioConfig = { appOrigin: options.appOrigin };\n\n const sendIndex = (res: http.ServerResponse) => {\n fs.readFile(indexPath, 'utf-8', (err, html) => {\n if (err) {\n res.statusCode = 500;\n res.end(`Server Error: ${err.code}`);\n return;\n }\n res.writeHead(200, { 'Content-Type': MIME_TYPES['.html']!, 'Cache-Control': 'no-store' });\n res.end(injectStudioConfig(html, config));\n });\n };\n\n return http.createServer((req, res) => {\n const origin = req.headers.origin || '';\n if (LOCALHOST_ORIGIN_RE.test(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Vary', 'Origin');\n }\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.statusCode = 204;\n res.end();\n return;\n }\n\n // RULE SEC-010: PATH CONTAINMENT — resolve the requested path and verify\n // it stays inside the studio directory (blocks /../../etc/passwd escapes).\n const urlPath = req.url?.split('?')[0] || '/';\n let filePath: string;\n try {\n filePath = path.resolve(studioDir, `.${decodeURIComponent(urlPath)}`);\n } catch {\n res.statusCode = 400;\n res.end('Bad Request');\n return;\n }\n\n if (filePath !== studioDir && !filePath.startsWith(studioDir + path.sep)) {\n res.statusCode = 403;\n res.end('Forbidden');\n return;\n }\n\n // Root, directories, and unknown paths all serve the SPA shell.\n if (\n urlPath === '/' ||\n filePath === studioDir ||\n filePath === indexPath ||\n !fs.existsSync(filePath) ||\n fs.statSync(filePath).isDirectory()\n ) {\n sendIndex(res);\n return;\n }\n\n const ext = path.extname(filePath);\n const contentType = MIME_TYPES[ext] || 'application/octet-stream';\n\n fs.readFile(filePath, (err, content) => {\n if (err) {\n res.statusCode = 500;\n res.end(`Server Error: ${err.code}`);\n } else {\n res.writeHead(200, { 'Content-Type': contentType });\n res.end(content);\n }\n });\n });\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { LOCALE_RE } from '../core/validate.js';\nimport { FLAG_SCRIPT_SIGNATURE } from '../core/flag-script.js';\nimport {\n SHARE_DIR,\n SHARE_FLAG_FILE,\n SHARE_MANIFEST_FILE,\n isShareManifest,\n} from '../core/share-manifest.js';\n\nexport type FindingLevel = 'ok' | 'warn' | 'fail';\n\nexport interface Finding {\n level: FindingLevel;\n title: string;\n detail?: string;\n}\n\nexport interface DoctorOptions {\n /** Project root to inspect. */\n projectDir: string;\n /** Locales directory, absolute or relative to `projectDir`. Defaults to `locales`. */\n localesPath?: string;\n /** When given, the running app is probed over HTTP. */\n appOrigin?: string;\n /** Absolute URL of the app base, ending in `/`. Defaults to `appOrigin + '/'`. */\n appBase?: string;\n /** Run the share-link probes even when `<base>livelocale/manifest.json` does not answer. */\n share?: boolean;\n /** Bearer token for an app that requires one (preview mode). Defaults to `LIVELOCALE_TOKEN`. */\n token?: string;\n /** Injectable fetch for tests. Defaults to the global fetch. */\n fetchImpl?: typeof fetch;\n}\n\nconst ROUTE_CANDIDATES = [\n 'app/api/livelocale/route.ts',\n 'app/api/livelocale/route.js',\n 'src/app/api/livelocale/route.ts',\n 'src/app/api/livelocale/route.js',\n 'pages/api/livelocale.ts',\n 'pages/api/livelocale.js',\n 'src/pages/api/livelocale.ts',\n 'src/pages/api/livelocale.js',\n];\n\nconst LAYOUT_CANDIDATES = [\n 'app/layout.tsx',\n 'app/layout.jsx',\n 'app/layout.js',\n 'src/app/layout.tsx',\n 'src/app/layout.jsx',\n 'src/app/layout.js',\n 'pages/_app.tsx',\n 'pages/_app.jsx',\n 'pages/_app.js',\n 'src/pages/_app.tsx',\n 'src/pages/_app.jsx',\n 'src/pages/_app.js',\n];\n\n// Next.js 16 renamed middleware.ts to proxy.ts; both are checked.\nconst MIDDLEWARE_CANDIDATES = [\n 'middleware.ts',\n 'middleware.js',\n 'middleware.mjs',\n 'src/middleware.ts',\n 'src/middleware.js',\n 'proxy.ts',\n 'proxy.js',\n 'src/proxy.ts',\n 'src/proxy.js',\n];\n\nconst NEXT_CONFIG_CANDIDATES = [\n 'next.config.js',\n 'next.config.mjs',\n 'next.config.ts',\n 'next.config.cjs',\n];\n\nconst VITE_CONFIG_CANDIDATES = [\n 'vite.config.ts',\n 'vite.config.mts',\n 'vite.config.js',\n 'vite.config.mjs',\n 'vite.config.cjs',\n 'vite.config.cts',\n];\n\n/** Files that can configure a Workbox service worker (vite-plugin-pwa or workbox-webpack-plugin). */\nconst SERVICE_WORKER_CONFIG_CANDIDATES = [\n ...VITE_CONFIG_CANDIDATES,\n 'webpack.config.js',\n 'webpack.config.cjs',\n 'webpack.config.mjs',\n 'webpack.config.ts',\n 'craco.config.js',\n 'craco.config.ts',\n 'vue.config.js',\n 'config-overrides.js',\n ...NEXT_CONFIG_CANDIDATES,\n 'package.json',\n];\n\nconst API_ROUTE = '/api/livelocale';\n\n/** The Workbox option that keeps the app shell off the share Studio, printed verbatim. */\nconst DENYLIST_LINE = 'navigateFallbackDenylist: [/^\\\\/livelocale\\\\//]';\n\nfunction firstExisting(root: string, candidates: string[]): string | null {\n for (const rel of candidates) {\n if (fs.existsSync(path.join(root, rel))) return rel;\n }\n return null;\n}\n\nfunction readText(file: string): string {\n try {\n return fs.readFileSync(file, 'utf-8');\n } catch {\n return '';\n }\n}\n\n// ─── Static checks ──────────────────────────────────────────────────────────\n\n/** True when the project builds a static share link, which needs no route handler. */\nfunction buildsStaticShare(root: string): boolean {\n const vite = firstExisting(root, VITE_CONFIG_CANDIDATES);\n const viteText = vite ? readText(path.join(root, vite)) : '';\n if (/liveLocaleVite\\s*\\(\\s*\\{[^)]*\\bshare\\b(?!\\s*:\\s*false)/.test(viteText)) return true;\n let scripts: unknown;\n try {\n scripts = JSON.parse(readText(path.join(root, 'package.json')) || '{}')?.scripts;\n } catch {\n return false;\n }\n if (typeof scripts !== 'object' || scripts === null) return false;\n return Object.values(scripts).some(\n (cmd) => typeof cmd === 'string' && /\\blivelocale\\s+(?:pack|build)\\b/.test(cmd)\n );\n}\n\nfunction checkRouteHandler(root: string): Finding {\n const found = firstExisting(root, ROUTE_CANDIDATES);\n if (found) return { level: 'ok', title: 'Mutation route handler', detail: found };\n if (buildsStaticShare(root)) {\n return {\n level: 'ok',\n title: 'Mutation route handler',\n detail: 'not needed for the share link (static build)',\n };\n }\n return {\n level: 'fail',\n title: 'Mutation route handler',\n detail: `No route file found at ${ROUTE_CANDIDATES[0]} (or the src/ and pages/ variants). Run: npx livelocale init`,\n };\n}\n\nfunction checkProvider(root: string): Finding {\n const existing = LAYOUT_CANDIDATES.filter((rel) => fs.existsSync(path.join(root, rel)));\n if (existing.length === 0) {\n return {\n level: 'warn',\n title: 'LiveLocaleProvider mounted',\n detail:\n 'No root layout (app/layout.*) or pages/_app.* found, so the provider could not be verified.',\n };\n }\n const mounted = existing.find((rel) => /LiveLocaleProvider/.test(readText(path.join(root, rel))));\n if (mounted) return { level: 'ok', title: 'LiveLocaleProvider mounted', detail: mounted };\n return {\n level: 'warn',\n title: 'LiveLocaleProvider mounted',\n detail: `Add <LiveLocaleProvider /> from 'livelocale/react' to ${existing[0]} so the Studio can talk to the page.`,\n };\n}\n\nfunction checkMiddleware(root: string): Finding {\n const found = firstExisting(root, MIDDLEWARE_CANDIDATES);\n if (!found) return { level: 'ok', title: 'Middleware matcher', detail: 'no middleware file' };\n const text = readText(path.join(root, found));\n if (text.includes('api/livelocale')) {\n return { level: 'ok', title: 'Middleware matcher', detail: `${found} excludes ${API_ROUTE}` };\n }\n return {\n level: 'warn',\n title: 'Middleware matcher',\n detail: `${found} does not mention api/livelocale. If it enforces auth or redirects, exclude the route: matcher: ['/((?!api/livelocale).*)']`,\n };\n}\n\n/** The default Studio origin inside a frame-ancestors source or config text. */\nconst STUDIO_ORIGIN_RE = /(?:localhost|127\\.0\\.0\\.1):3010(?!\\d)/;\n\n/** True when a frame-ancestors directive lets the default Studio embed the page. */\nfunction allowsStudio(frameAncestors: string): boolean {\n const sources = frameAncestors.split(/\\s+/).slice(1);\n return sources.includes('*') || sources.some((src) => STUDIO_ORIGIN_RE.test(src));\n}\n\nfunction checkFrameHeaders(root: string): Finding {\n const found = firstExisting(root, NEXT_CONFIG_CANDIDATES);\n if (!found)\n return { level: 'ok', title: 'Frame-blocking headers in next.config', detail: 'none' };\n const text = readText(path.join(root, found));\n if (STUDIO_ORIGIN_RE.test(text)) {\n return {\n level: 'ok',\n title: 'Frame-blocking headers in next.config',\n detail: `${found} sets frame headers that name the Studio origin`,\n };\n }\n const hits: string[] = [];\n if (/frame-ancestors/i.test(text)) hits.push('frame-ancestors');\n if (/x-frame-options/i.test(text)) hits.push('X-Frame-Options');\n if (hits.length === 0) {\n return { level: 'ok', title: 'Frame-blocking headers in next.config', detail: 'none' };\n }\n return {\n level: 'warn',\n title: 'Frame-blocking headers in next.config',\n detail: `${found} sets ${hits.join(' and ')}. The Studio embeds your app in an iframe; allow http://localhost:3010 (or your Studio origin) when NODE_ENV is development.`,\n };\n}\n\nfunction checkLocales(root: string, localesPath: string | undefined): Finding {\n const dir = path.resolve(root, localesPath ?? 'locales');\n const rel = path.relative(root, dir) || '.';\n if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {\n return {\n level: 'fail',\n title: 'Locale files',\n detail: `Directory not found: ${rel}. Create it or pass --locales <path> (and set localesPath in the route handler).`,\n };\n }\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n const flat = entries.filter((e) => e.isFile() && e.name.endsWith('.json'));\n const dirs = entries.filter((e) => e.isDirectory() && LOCALE_RE.test(e.name));\n const invalid: string[] = [];\n let fileCount = 0;\n\n const validate = (file: string, label: string) => {\n fileCount++;\n try {\n const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n invalid.push(`${label} (root must be an object)`);\n }\n } catch (err: any) {\n invalid.push(`${label} (${err.message})`);\n }\n };\n\n for (const f of flat) validate(path.join(dir, f.name), f.name);\n for (const d of dirs) {\n for (const f of fs.readdirSync(path.join(dir, d.name))) {\n if (f.endsWith('.json')) validate(path.join(dir, d.name, f), `${d.name}/${f}`);\n }\n }\n\n if (invalid.length > 0) {\n return { level: 'fail', title: 'Locale files', detail: `Invalid JSON: ${invalid.join('; ')}` };\n }\n if (fileCount === 0) {\n return {\n level: 'fail',\n title: 'Locale files',\n detail: `${rel} contains no *.json locale files.`,\n };\n }\n if (flat.length > 0 && dirs.length > 0) {\n return {\n level: 'warn',\n title: 'Locale files',\n detail: `${rel} mixes flat files (${flat.length}) and namespace folders (${dirs.length}); pick one layout.`,\n };\n }\n const layout =\n dirs.length > 0\n ? `${dirs.length} namespaced locale folder(s)`\n : `${flat.length} flat locale file(s)`;\n return {\n level: 'ok',\n title: 'Locale files',\n detail: `${rel}: ${layout}, ${fileCount} file(s) parse`,\n };\n}\n\n/**\n * Warns when a Workbox plugin is configured and no config excludes livelocale/ from its\n * navigation fallback. A bare mention of livelocale does not count: a Vite config imports\n * `livelocale/vite` and package.json lists the package. Returns null otherwise (PF-16: an ok\n * finding here would shadow the live `Service worker` probe in title lookups).\n */\nfunction checkServiceWorkerConfig(root: string): Finding | null {\n const files = SERVICE_WORKER_CONFIG_CANDIDATES.filter((rel) =>\n fs.existsSync(path.join(root, rel))\n ).map((rel) => ({ rel, text: readText(path.join(root, rel)) }));\n const pwa = files.find(({ text }) => /VitePWA\\s*\\(|workbox-webpack-plugin/.test(text));\n if (!pwa) return null;\n if (files.some(({ text }) => /navigateFallbackDenylist[\\s\\S]{0,300}?livelocale/.test(text))) {\n return null;\n }\n const plugin = /VitePWA\\s*\\(/.test(pwa.text) ? 'VitePWA' : 'workbox-webpack-plugin';\n return {\n level: 'warn',\n title: 'Service worker config',\n detail: `${pwa.rel} uses ${plugin}, and its navigation fallback would answer livelocale/index.html with your app's page. Add to its Workbox options: ${DENYLIST_LINE}`,\n };\n}\n\n// ─── Live checks ────────────────────────────────────────────────────────────\n\nasync function probe(\n fetchImpl: typeof fetch,\n url: string,\n token?: string\n): Promise<{ ok: true; res: Response } | { ok: false; error: string }> {\n try {\n // Preview deployments answer in cold starts and GitHub round trips; allow more time there.\n const signal =\n typeof AbortSignal.timeout === 'function' ? AbortSignal.timeout(15000) : undefined;\n const headers: Record<string, string> = token ? { Authorization: `Bearer ${token}` } : {};\n const res = await fetchImpl(url, { signal, redirect: 'manual', headers });\n return { ok: true, res };\n } catch (err: any) {\n return { ok: false, error: err?.message || String(err) };\n }\n}\n\n/**\n * Describes a redirect to a hosting provider's login page (Vercel Deployment\n * Protection, Netlify password protection, …), or returns null for any other response.\n */\nfunction loginWall(res: Response, origin: string): string | null {\n if (res.status < 300 || res.status >= 400) return null;\n const location = res.headers.get('location') || '';\n let target: URL;\n try {\n target = new URL(location, origin);\n } catch {\n return null;\n }\n if (target.origin === new URL(origin).origin) return null;\n if (/(^|\\.)vercel\\.com$/i.test(target.hostname)) {\n return 'Vercel Deployment Protection redirects visitors to a Vercel login. Turn off Vercel Authentication for preview deployments (Project Settings → Deployment Protection).';\n }\n return `The app redirects to ${target.host}, which looks like a hosting login wall. Allow the Studio through it or turn it off for this deployment.`;\n}\n\nasync function checkServerInfo(\n origin: string,\n fetchImpl: typeof fetch,\n token: string | undefined\n): Promise<Finding[]> {\n const res = await probe(fetchImpl, `${origin}${API_ROUTE}?action=info`, token);\n if (!res.ok || res.res.status !== 200) return [];\n let info: any = null;\n try {\n info = await res.res.json();\n } catch {}\n if (!info || typeof info.mode !== 'string') return [];\n const findings: Finding[] = [\n {\n level: 'ok',\n title: 'Server mode',\n detail: `${info.mode}${info.authRequired ? ', token required' : ''}${info.git ? ', git actions available' : ''}`,\n },\n ];\n for (const problem of Array.isArray(info.problems) ? info.problems : []) {\n findings.push({ level: 'fail', title: 'Repository access', detail: String(problem) });\n }\n return findings;\n}\n\nasync function checkLive(\n appOrigin: string,\n fetchImpl: typeof fetch,\n token: string | undefined\n): Promise<Finding[]> {\n const findings: Finding[] = [];\n const origin = appOrigin.replace(/\\/+$/, '');\n\n const api = await probe(fetchImpl, `${origin}${API_ROUTE}`, token);\n if (!api.ok) {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: `${origin} is not reachable (${api.error}). Is the dev server running?`,\n });\n } else {\n const { res } = api;\n let body: any = null;\n try {\n body = await res.json();\n } catch {}\n if (res.status === 200 && Array.isArray(body)) {\n findings.push({\n level: 'ok',\n title: 'Mutation API',\n detail: `${origin}${API_ROUTE} responded with ${body.length} locale(s)`,\n });\n findings.push(...(await checkServerInfo(origin, fetchImpl, token)));\n } else if (res.status === 401) {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: token\n ? 'The server rejected the access token. Check LIVELOCALE_TOKEN on the deployment.'\n : 'The server requires an access token (preview mode). Re-run with --token <token> or set LIVELOCALE_TOKEN.',\n });\n } else if (res.status === 403) {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: `Server refused the request: ${body?.error || 'HTTP 403'}`,\n });\n } else if (res.status === 404) {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: `HTTP 404 at ${origin}${API_ROUTE}. The route handler is not served; run npx livelocale init and restart the dev server.`,\n });\n } else if (res.status >= 300 && res.status < 400) {\n const wall = loginWall(res, origin);\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: wall\n ? `${wall} The Studio cannot reach the app through it.`\n : `HTTP ${res.status} redirect at ${API_ROUTE}; auth middleware is probably intercepting it. Exclude api/livelocale from the matcher.`,\n });\n } else {\n findings.push({\n level: 'fail',\n title: 'Mutation API',\n detail: `Unexpected HTTP ${res.status}: ${body?.error || 'no error body'}`,\n });\n }\n }\n\n const page = await probe(fetchImpl, `${origin}/`);\n const pageWall = page.ok ? loginWall(page.res, origin) : null;\n if (pageWall) {\n findings.push({ level: 'fail', title: 'Studio can embed the app', detail: pageWall });\n } else if (page.ok) {\n const csp = page.res.headers.get('content-security-policy') || '';\n const xfo = page.res.headers.get('x-frame-options') || '';\n const blockers: string[] = [];\n const frameAncestors = csp.match(/frame-ancestors[^;]*/i)?.[0];\n if (frameAncestors && !allowsStudio(frameAncestors.trim())) {\n blockers.push(`Content-Security-Policy: ${frameAncestors}`);\n }\n if (xfo) blockers.push(`X-Frame-Options: ${xfo}`);\n if (blockers.length > 0) {\n findings.push({\n level: 'warn',\n title: 'Studio can embed the app',\n detail: `${origin}/ sends ${blockers.join(' and ')}. Unless the Studio origin is allowed, the preview iframe will be blank.`,\n });\n } else {\n findings.push({\n level: 'ok',\n title: 'Studio can embed the app',\n detail: 'no frame-blocking headers',\n });\n }\n }\n\n return findings;\n}\n\n// ─── Share probes ───────────────────────────────────────────────────────────\n\n/** `<base>livelocale/index.html`, the link translators open. */\nexport function shareLinkFor(appBase: string): string {\n return `${appBase}${SHARE_DIR}/index.html`;\n}\n\n/**\n * Splits an http(s) app URL into its origin and its base: the query and hash are\n * dropped, a trailing `index.html` is dropped, and the path gains a trailing `/`.\n * Throws for anything that is not an http(s) URL.\n */\nexport function normalizeAppUrl(value: string): { origin: string; base: string } {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error(`Not an http(s) URL: ${value}`);\n }\n let pathname = url.pathname.replace(/index\\.html$/, '');\n if (!pathname.endsWith('/')) pathname += '/';\n return { origin: url.origin, base: `${url.origin}${pathname}` };\n}\n\nconst STUDIO_TITLE = 'LiveLocale · Studio';\nconst UPLOAD_HINT = 'Upload the livelocale/ folder from your build output.';\n\n/** One share probe's answer, read once so several findings can share it. */\ntype Fetched =\n | { url: string; error: string }\n | { url: string; status: number; headers: Headers; body: string; wall: string | null };\n\ntype Answer = Extract<Fetched, { status: number }>;\n\nfunction isAnswer(page: Fetched): page is Answer {\n return !('error' in page);\n}\n\nasync function fetchPage(fetchImpl: typeof fetch, url: string, origin: string): Promise<Fetched> {\n const res = await probe(fetchImpl, url);\n if (!res.ok) return { url, error: res.error };\n let body = '';\n try {\n body = await res.res.text();\n } catch {}\n return {\n url,\n status: res.res.status,\n headers: res.res.headers,\n body,\n wall: loginWall(res.res, origin),\n };\n}\n\n/** The answer itself, or the failing finding when the probe got no answer or hit a login wall. */\nfunction answered(title: string, page: Fetched): Answer | Finding {\n if (!isAnswer(page)) {\n return { level: 'fail', title, detail: `${page.url} is not reachable (${page.error}).` };\n }\n if (page.wall) return { level: 'fail', title, detail: page.wall };\n return page;\n}\n\nfunction parseJson(text: string): { ok: true; value: unknown } | { ok: false } {\n try {\n return { ok: true, value: JSON.parse(text) };\n } catch {\n return { ok: false };\n }\n}\n\nfunction checkStudioPage(studioPage: Fetched, root: Fetched): Finding {\n const title = 'Share Studio page';\n const studio = answered(title, studioPage);\n if ('level' in studio) return studio;\n if (studio.status === 200 && isAnswer(root) && root.status === 200 && studio.body === root.body) {\n return {\n level: 'fail',\n title,\n detail: `The host answered livelocale/index.html with your app's page (SPA fallback or service worker). ${UPLOAD_HINT}`,\n };\n }\n if (studio.status === 200 && studio.body.includes(STUDIO_TITLE)) {\n return { level: 'ok', title, detail: studio.url };\n }\n return {\n level: 'fail',\n title,\n detail: `${studio.url} answered HTTP ${studio.status} without the LiveLocale Studio. ${UPLOAD_HINT}`,\n };\n}\n\nfunction checkManifest(manifestPage: Fetched): Finding {\n const title = 'Share manifest';\n const manifest = answered(title, manifestPage);\n if ('level' in manifest) return manifest;\n if (manifest.status === 404) {\n return {\n level: 'fail',\n title,\n detail: `${manifest.url} answered HTTP 404; did the build run with share: true or livelocale pack?`,\n };\n }\n const parsed = manifest.status === 200 ? parseJson(manifest.body) : { ok: false as const };\n if (parsed.ok && isShareManifest(parsed.value)) {\n const m = parsed.value;\n return {\n level: 'ok',\n title,\n detail: `${m.locales.length} locale(s), source ${m.sourceLocale}, built from ${m.branch ?? 'an unknown branch'} @ ${m.base?.slice(0, 7) ?? 'an unknown commit'}`,\n };\n }\n return {\n level: 'fail',\n title,\n detail: `${manifest.url} answered HTTP ${manifest.status} without a LiveLocale share manifest (format 1). Rebuild with share: true or run livelocale pack.`,\n };\n}\n\nconst HEAD_OPEN = /<head(?=[\\s>])[^>]*>/i;\nconst HTML_OPEN = /<html(?=[\\s>])[^>]*>/i;\nconst DOCTYPE = /<!doctype\\b[^>]*>/i;\n\n/** The attributes of the first element in `<head>` when it is a `<script>`, else null. */\nfunction firstHeadScript(html: string): string | null {\n let start = 0;\n for (const pattern of [HEAD_OPEN, HTML_OPEN, DOCTYPE]) {\n const match = pattern.exec(html);\n if (match) {\n start = match.index + match[0].length;\n break;\n }\n }\n const rest = html.slice(start).replace(/^(?:\\s|<!--[\\s\\S]*?-->)*/, '');\n return /^<script\\b([^>]*)>/i.exec(rest)?.[1] ?? null;\n}\n\nfunction flagTagProblem(root: Fetched, base: string, flagUrl: string): string | null {\n const expected = `The first element in <head> of ${base} must be <script src=\"${flagUrl}\"></script> without async. Run livelocale pack on the build output again.`;\n if (!isAnswer(root) || root.status !== 200) return expected;\n const attrs = firstHeadScript(root.body);\n if (attrs === null || /(?:^|\\s)async(?=[\\s=]|$)/i.test(attrs)) return expected;\n const src = /(?:^|\\s)src\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'>]+))/i.exec(attrs);\n const value = src ? (src[1] ?? src[2] ?? src[3] ?? '') : '';\n try {\n if (src && new URL(value, base).href === flagUrl) return null;\n } catch {}\n return expected;\n}\n\nfunction checkFlagScript(flagPage: Fetched, root: Fetched, base: string): Finding {\n const title = 'Share flag script';\n const flag = answered(title, flagPage);\n if ('level' in flag) return flag;\n const problems: string[] = [];\n const type = flag.headers.get('content-type') || '';\n if (\n flag.status !== 200 ||\n !/javascript|ecmascript/i.test(type) ||\n !flag.body.startsWith(FLAG_SCRIPT_SIGNATURE)\n ) {\n problems.push(\n `${flag.url} answered HTTP ${flag.status} (${type || 'no content type'}) without the LiveLocale flag script. ${UPLOAD_HINT}`\n );\n }\n const tag = flagTagProblem(root, base, flag.url);\n if (tag) problems.push(tag);\n if (problems.length > 0) return { level: 'fail', title, detail: problems.join(' ') };\n return { level: 'ok', title, detail: `${flag.url} loads first in <head>` };\n}\n\n/** The sources of a CSP directive, or null when the policy does not set it. */\nfunction cspSources(csp: string, directive: string): string[] | null {\n for (const part of csp.split(';')) {\n const [name, ...sources] = part.trim().split(/\\s+/);\n if (name && name.toLowerCase() === directive) return sources;\n }\n return null;\n}\n\n/** True when the sources let the page's own origin in. */\nfunction allowsSelf(sources: string[], origin: string): boolean {\n return sources.some((s) => s === \"'self'\" || s === '*' || s.replace(/\\/+$/, '') === origin);\n}\n\nfunction checkShareFrameHeaders(pages: Fetched[], origin: string): Finding {\n const title = 'Share frame headers';\n const blockers: string[] = [];\n for (const page of pages) {\n const answer = answered(title, page);\n if ('level' in answer) return answer;\n const xfo = (answer.headers.get('x-frame-options') || '').trim();\n if (/^deny$/i.test(xfo)) blockers.push(`${page.url} sends X-Frame-Options: ${xfo}`);\n const ancestors = cspSources(\n answer.headers.get('content-security-policy') || '',\n 'frame-ancestors'\n );\n if (ancestors && (ancestors.includes(\"'none'\") || !allowsSelf(ancestors, origin))) {\n blockers.push(`${page.url} sends frame-ancestors ${ancestors.join(' ') || \"'none'\"}`);\n }\n }\n if (blockers.length > 0) {\n return {\n level: 'fail',\n title,\n detail: `${blockers.join('; ')}. The share Studio frames your app from the same origin; use X-Frame-Options: SAMEORIGIN or frame-ancestors 'self'.`,\n };\n }\n return { level: 'ok', title, detail: 'both pages can be framed by the same origin' };\n}\n\nfunction checkShareCsp(pages: Fetched[], origin: string): Finding {\n const title = 'Share CSP';\n const blocked: string[] = [];\n for (const page of pages) {\n const answer = answered(title, page);\n if ('level' in answer) return answer;\n const csp = answer.headers.get('content-security-policy') || '';\n const scriptSrc = cspSources(csp, 'script-src');\n const sources = scriptSrc ?? cspSources(csp, 'default-src');\n if (sources && !allowsSelf(sources, origin)) {\n blocked.push(`${page.url} (${scriptSrc ? 'script-src' : 'default-src'})`);\n }\n }\n if (blocked.length > 0) {\n return {\n level: 'warn',\n title,\n detail: `${blocked.join(', ')} leaves out 'self', so the browser may block livelocale/flag.js and the Studio's scripts. Add 'self' to script-src.`,\n };\n }\n return { level: 'ok', title, detail: \"scripts from 'self' are allowed\" };\n}\n\n/**\n * Worker URLs worth reading: the one the app HTML registers, then the usual file names, both\n * under the app base and at the origin root (`/sw.js`, `/service-worker.js`). The two are the\n * same for a root base; a project site can carry either.\n */\nfunction workerCandidates(root: Fetched, base: string): string[] {\n const urls: string[] = [];\n if (isAnswer(root)) {\n const registered = /serviceWorker\\s*\\.\\s*register\\s*\\(\\s*[\"'`]([^\"'`]+)[\"'`]/.exec(root.body);\n if (registered) {\n try {\n urls.push(new URL(registered[1]!, base).href);\n } catch {}\n }\n }\n const names = ['sw.js', 'service-worker.js'];\n for (const url of [\n ...names.map((name) => new URL(name, base).href),\n ...names.map((name) => new URL(`/${name}`, base).href),\n ]) {\n if (!urls.includes(url)) urls.push(url);\n }\n return urls;\n}\n\nasync function checkServiceWorker(\n fetchImpl: typeof fetch,\n root: Fetched,\n base: string,\n origin: string\n): Promise<Finding> {\n const title = 'Service worker';\n const found: string[] = [];\n for (const url of workerCandidates(root, base)) {\n const worker = await fetchPage(fetchImpl, url, origin);\n if (!isAnswer(worker)) continue;\n if (worker.wall) return { level: 'fail', title, detail: worker.wall };\n // A host's HTML fallback is not a worker.\n if (worker.status !== 200 || /html/i.test(worker.headers.get('content-type') || '')) continue;\n found.push(url);\n if (\n /createHandlerBoundToURL|navigateFallback/.test(worker.body) &&\n !worker.body.includes('livelocale')\n ) {\n return {\n level: 'warn',\n title,\n detail: `${url} answers navigations with the app shell, so livelocale/index.html would open your app. Add to your Workbox config: ${DENYLIST_LINE}`,\n };\n }\n }\n return {\n level: 'ok',\n title,\n detail: found.length > 0 ? `${found.join(', ')} leaves livelocale/ alone` : 'none found',\n };\n}\n\nasync function checkShare(\n origin: string,\n base: string,\n fetchImpl: typeof fetch,\n manifest: Fetched\n): Promise<Finding[]> {\n const shareUrl = (file: string) => `${base}${SHARE_DIR}/${file}`;\n const [root, studio, flag] = await Promise.all([\n fetchPage(fetchImpl, base, origin),\n fetchPage(fetchImpl, shareLinkFor(base), origin),\n fetchPage(fetchImpl, shareUrl(SHARE_FLAG_FILE), origin),\n ]);\n return [\n checkStudioPage(studio, root),\n checkManifest(manifest),\n checkFlagScript(flag, root, base),\n checkShareFrameHeaders([root, studio], origin),\n checkShareCsp([root, studio], origin),\n await checkServiceWorker(fetchImpl, root, base, origin),\n { level: 'ok', title: 'Share link', detail: shareLinkFor(base) },\n ];\n}\n\n/** True when the manifest URL answered 200 with JSON, which marks a share build. */\nfunction looksLikeShareBuild(manifest: Fetched): boolean {\n return isAnswer(manifest) && manifest.status === 200 && parseJson(manifest.body).ok;\n}\n\n// ─── Entry points ───────────────────────────────────────────────────────────\n\nexport async function runDoctor(options: DoctorOptions): Promise<Finding[]> {\n const root = path.resolve(options.projectDir);\n const findings: Finding[] = [\n checkRouteHandler(root),\n checkProvider(root),\n checkMiddleware(root),\n checkFrameHeaders(root),\n checkLocales(root, options.localesPath),\n ];\n const workerConfig = checkServiceWorkerConfig(root);\n if (workerConfig) findings.push(workerConfig);\n\n const appOrigin = options.appOrigin ?? (options.appBase && new URL(options.appBase).origin);\n if (appOrigin) {\n const fetchImpl = options.fetchImpl ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') {\n findings.push({\n level: 'warn',\n title: 'Mutation API',\n detail: 'Live checks need Node 18+ (global fetch).',\n });\n } else {\n const origin = appOrigin.replace(/\\/+$/, '');\n const base = options.appBase ?? `${origin}/`;\n const manifest = await fetchPage(\n fetchImpl,\n `${base}${SHARE_DIR}/${SHARE_MANIFEST_FILE}`,\n origin\n );\n if (options.share || looksLikeShareBuild(manifest)) {\n // A static share build has no mutation API and is framed by a same-origin Studio.\n findings.push(...(await checkShare(origin, base, fetchImpl, manifest)));\n } else {\n const token = options.token ?? process.env['LIVELOCALE_TOKEN'] ?? undefined;\n findings.push(...(await checkLive(origin, fetchImpl, token || undefined)));\n }\n }\n }\n\n return findings;\n}\n\nexport function hasFailures(findings: Finding[]): boolean {\n return findings.some((f) => f.level === 'fail');\n}\n\nconst GLYPH: Record<FindingLevel, string> = { ok: '✅', warn: '⚠️ ', fail: '❌' };\n\nexport function formatFindings(findings: Finding[]): string {\n const lines: string[] = [];\n for (const f of findings) {\n lines.push(`${GLYPH[f.level]} ${f.title}`);\n if (f.detail) lines.push(` ${f.detail}`);\n }\n return lines.join('\\n');\n}\n","/**\n * Shared validation rules for locale codes, translation keys, and values.\n *\n * Platform-agnostic: used by the server router, FileMutator, and the Studio\n * UI so that every layer enforces exactly the same contract.\n */\n\nexport const LOCALE_RE = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,4})?$/;\n\nexport const KEY_RE = /^[a-zA-Z0-9._-]+$/;\n\nexport const MAX_LOCALE_LENGTH = 10;\nexport const MAX_KEY_LENGTH = 200;\nexport const MAX_VALUE_LENGTH = 10000;\n\n/**\n * Object-prototype member names that must never be used as translation key\n * segments. Assigning through these bypasses own-property checks and can\n * pollute `Object.prototype` process-wide (prototype pollution).\n */\nexport const DANGEROUS_KEY_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Returns true if no segment of the dot-separated `key` is a dangerous\n * object-prototype member name.\n */\nexport function isSafeKeyPath(key: unknown): boolean {\n if (typeof key !== 'string') return false;\n return !key.split('.').some((segment) => DANGEROUS_KEY_SEGMENTS.has(segment));\n}\n\n/**\n * Returns true if `locale` is a 2-10 character code matching the loose\n * standard pattern (supports es-419, zh-Hans, eng, etc.).\n */\nexport function isValidLocaleFormat(locale: unknown): boolean {\n return (\n typeof locale === 'string' &&\n locale.length >= 2 &&\n locale.length <= MAX_LOCALE_LENGTH &&\n LOCALE_RE.test(locale)\n );\n}\n\n/**\n * Returns true if `key` is a 1-200 character dot-separated path containing\n * only alphanumerics, dots, underscores, or hyphens.\n */\nexport function isValidKeyFormat(key: unknown): boolean {\n return (\n typeof key === 'string' && key.length >= 1 && key.length <= MAX_KEY_LENGTH && KEY_RE.test(key)\n );\n}\n\n/**\n * Returns true if `value` is a string no longer than MAX_VALUE_LENGTH.\n */\nexport function isValidValueFormat(value: unknown): boolean {\n return typeof value === 'string' && value.length <= MAX_VALUE_LENGTH;\n}\n\n/**\n * Rejects locale identifiers that could escape the locales directory.\n */\nexport function isSafeLocaleSegment(locale: string): boolean {\n return !(\n locale.includes('..') ||\n locale.includes('/') ||\n locale.includes('\\\\') ||\n locale.includes('%') ||\n locale.includes('\\0')\n );\n}\n","/**\n * The share folder's `flag.js`: a classic ES5 script that static share builds load\n * first in `<head>` of every app page.\n *\n * It sets `window.__LIVELOCALE_FLAG__ = 'preview'` (the global `env.ts` reads) only\n * when the page is framed by a same-origin parent whose path is under the folder\n * `flag.js` itself is served from, which is the Studio folder whatever the app base\n * is. Visitors who open the site directly, or frame it from anywhere else, stay\n * `off`. It never overwrites a flag the page already set, never throws, and never\n * logs.\n *\n * Browser-safe, as tests/unit/core-browser-safe.test.ts checks.\n */\n\n/** The first line of `FLAG_SCRIPT`, which `doctor` uses to recognise a deployed `flag.js`. */\nexport const FLAG_SCRIPT_SIGNATURE = '/*! livelocale flag v1 */';\n\n/** The exact contents `pack` writes to `<base>livelocale/flag.js`. */\nexport const FLAG_SCRIPT = `${FLAG_SCRIPT_SIGNATURE}\n(function () {\n try {\n var me = document.currentScript;\n if (!me || !me.src || window.parent === window || window.__LIVELOCALE_FLAG__ !== undefined)\n return;\n var studio = new URL('.', me.src);\n var host = window.parent.location;\n if (\n host.origin === 'null' ||\n host.origin !== window.location.origin ||\n host.origin !== studio.origin\n )\n return;\n if (host.pathname.indexOf(studio.pathname) !== 0) return;\n window.__LIVELOCALE_FLAG__ = 'preview';\n } catch (e) {}\n})();\n`;\n","/**\n * The `lc1.` change link: the error type every codec step throws, base64url,\n * finding a token in pasted text, the fenced block GitHub issues carry, the\n * repository slug and branch name rules, the change-set schema with its caps,\n * and encoding and decoding through Web Streams deflate.\n *\n * Browser-safe, as tests/unit/core-browser-safe.test.ts checks.\n */\n\nimport {\n isSafeKeyPath,\n isValidKeyFormat,\n isValidLocaleFormat,\n isValidValueFormat,\n MAX_VALUE_LENGTH,\n} from './validate.js';\n\nexport const CHANGE_LINK_PREFIX = 'lc1.';\n\nexport const CHANGE_BLOCK_OPEN = '```livelocale';\n\nconst CHANGE_BLOCK_CLOSE = '```';\n\nexport type ChangeLinkErrorCode =\n | 'NOT_FOUND'\n | 'AMBIGUOUS'\n | 'UNSUPPORTED_VERSION'\n | 'CORRUPT'\n | 'TOO_LARGE'\n | 'TOO_MANY_EDITS'\n | 'INVALID'\n | 'UNSUPPORTED_ENVIRONMENT';\n\n/** A change link that cannot be found, read or written. Messages never echo payload text. */\nexport class ChangeLinkError extends Error {\n readonly code: ChangeLinkErrorCode;\n\n constructor(code: ChangeLinkErrorCode, message: string) {\n super(message);\n this.name = 'ChangeLinkError';\n this.code = code;\n }\n}\n\nconst CORRUPT_MESSAGE =\n 'This change link is damaged or incomplete. Ask the sender to send the file instead.';\n\nconst UNSUPPORTED_VERSION_MESSAGE =\n 'This change link was made by a newer LiveLocale. Update LiveLocale and try again.';\n\nconst BASE64URL_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\n/** `String.fromCharCode` takes one argument per byte, so bytes are spread a chunk at a time. */\nconst CHUNK_BYTES = 0x8000;\n\n/** RFC 4648 §5 base64url without padding. */\nexport function toBase64Url(bytes: Uint8Array): string {\n // One binary string, one btoa call: 0x8000 is not a multiple of 3, so\n // encoding chunk by chunk would put padding in the middle of the output.\n let binary = '';\n for (let i = 0; i < bytes.length; i += CHUNK_BYTES) {\n binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK_BYTES));\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Decodes canonical RFC 4648 §5 base64url without padding. Anything else\n * (another alphabet, `=`, an impossible length, or non-zero trailing bits)\n * throws `CORRUPT`, so a damaged link never decodes to different bytes.\n */\nexport function fromBase64Url(text: string): Uint8Array {\n if (!/^[A-Za-z0-9_-]*$/.test(text) || text.length % 4 === 1) {\n throw new ChangeLinkError('CORRUPT', CORRUPT_MESSAGE);\n }\n const tail = text.length % 4;\n if (tail !== 0) {\n // The last character of a 2- or 3-character group carries 4 or 2 unused bits.\n const unusedBits = tail === 2 ? 0x0f : 0x03;\n if ((BASE64URL_ALPHABET.indexOf(text[text.length - 1]!) & unusedBits) !== 0) {\n throw new ChangeLinkError('CORRUPT', CORRUPT_MESSAGE);\n }\n }\n const binary = atob(\n text.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat(tail === 0 ? 0 : 4 - tail)\n );\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\n/** The fenced block a GitHub issue carries: `CHANGE_BLOCK_OPEN`, the token, the closing fence. */\nexport function fencedChangeBlock(token: string): string {\n return `${CHANGE_BLOCK_OPEN}\\n${token}\\n${CHANGE_BLOCK_CLOSE}\\n`;\n}\n\n/**\n * The content of the first fenced `livelocale` block, up to the next line\n * that is exactly the closing fence (or the end of the text), with all\n * whitespace removed so lines a mail or chat app wrapped join up again.\n * Returns null when the text has no such block.\n */\nfunction fencedBlockContent(text: string): string | null {\n const open = new RegExp(`${CHANGE_BLOCK_OPEN}(?:\\\\r\\\\n|\\\\r|\\\\n)`).exec(text);\n if (!open) return null;\n const lines = text.slice(open.index + open[0].length).split(/\\r\\n|\\r|\\n/);\n const close = lines.indexOf(CHANGE_BLOCK_CLOSE);\n return (close < 0 ? lines : lines.slice(0, close)).join('').replace(/\\s+/g, '');\n}\n\n/**\n * Finds the one `lc1.` token in pasted text: a bare token, a Studio link, a\n * link rewritten by a mail scanner, chat markup, prose, or a GitHub issue's\n * fenced block (which wins over any other text). Returns `lc1.<data>`.\n *\n * Throws `AMBIGUOUS` for two different tokens, `UNSUPPORTED_VERSION` for a\n * newer `lcN.` token only, and `NOT_FOUND` otherwise.\n */\nexport function findChangeToken(text: string): string {\n const scope = (fencedBlockContent(text) ?? text).replace(/%23/gi, '#');\n\n const tokens = new Set<string>();\n for (const match of scope.matchAll(/(?:^|[^A-Za-z0-9_-])lc1\\.([A-Za-z0-9_-]+)/g)) {\n tokens.add(match[1]!);\n }\n\n if (tokens.size === 1) return CHANGE_LINK_PREFIX + [...tokens][0]!;\n if (tokens.size > 1) {\n throw new ChangeLinkError(\n 'AMBIGUOUS',\n 'This text holds more than one change link. Paste one link at a time.'\n );\n }\n if (/(?:^|[^A-Za-z0-9_-])lc(?:[2-9]|[1-9]\\d+)\\.[A-Za-z0-9_-]/.test(scope)) {\n throw new ChangeLinkError('UNSUPPORTED_VERSION', UNSUPPORTED_VERSION_MESSAGE);\n }\n throw new ChangeLinkError(\n 'NOT_FOUND',\n 'This is not a LiveLocale change link. A change link contains \"lc1.\".'\n );\n}\n\n/** A GitHub `owner/repo` slug. The repository part may not be `.` or `..`. */\nexport function isValidRepoSlug(slug: string): boolean {\n if (!/^[A-Za-z0-9][A-Za-z0-9-]{0,38}\\/[A-Za-z0-9._-]{1,100}$/.test(slug)) return false;\n const repo = slug.slice(slug.indexOf('/') + 1);\n return repo !== '.' && repo !== '..';\n}\n\nconst BRANCH_NAME_RE = /^(?!-)(?!.*\\.\\.)[^\\s\\x00-\\x1f\\x7f]{1,255}$/;\n\n/**\n * The one branch-name rule. The share manifest, build info and the change-set\n * schema all use it. `''` is not valid. A name never starts with `-` (so git\n * never reads it as an option) and never holds `..`, whitespace, control\n * characters or a lone UTF-16 surrogate. The schema rejects a lone surrogate\n * anywhere as broken text, so a name that passes here never fails a link.\n */\nexport function isValidBranchName(name: string): boolean {\n return BRANCH_NAME_RE.test(name) && !hasLoneSurrogate(name);\n}\n\nexport const CHANGE_LINK_VERSION = 1;\nexport const MAX_CHANGE_EDITS = 500;\nexport const MAX_BY_CHARS = 100;\nexport const MAX_NOTE_CHARS = 2_000;\n\n/** One proposed edit. `from` is null when the key is absent in that locale in the build. */\nexport interface ChangeEdit {\n locale: string;\n key: string;\n from: string | null;\n to: string;\n force: boolean;\n}\n\n/** The edits a translator sends, with the build they were made against. */\nexport interface ChangeSet {\n repo?: string;\n branch: string;\n base: string;\n src: string;\n by: string;\n note: string;\n edits: ChangeEdit[];\n}\n\n/** An edit on the wire. A forced edit carries a trailing `1`. */\nexport type ChangeEditTuple =\n | [locale: string, key: string, from: string | null, to: string]\n | [locale: string, key: string, from: string | null, to: string, force: 1];\n\n/** The JSON a change link carries. */\nexport interface ChangeWire {\n v: 1;\n repo?: string;\n branch: string;\n base: string;\n src: string;\n by: string;\n note: string;\n e: ChangeEditTuple[];\n}\n\n/** The wire form of a change set: no `repo` key when it is unset, and `1` appended only to forced edits. */\nexport function toWire(set: ChangeSet): ChangeWire {\n return {\n v: CHANGE_LINK_VERSION,\n ...(set.repo === undefined ? {} : { repo: set.repo }),\n branch: set.branch,\n base: set.base,\n src: set.src,\n by: set.by,\n note: set.note,\n e: set.edits.map(\n ({ locale, key, from, to, force }): ChangeEditTuple =>\n force ? [locale, key, from, to, 1] : [locale, key, from, to]\n ),\n };\n}\n\n/** Empty, or a full SHA-1 or SHA-256 commit id in lowercase hex. */\nconst BASE_SHA_RE = /^(?:[0-9a-f]{40}|[0-9a-f]{64})?$/;\n\nconst BY_FORBIDDEN_RE = /[\\x00-\\x1f\\x7f]/;\n\n/** Control characters other than tab, line feed and carriage return. */\nconst NOTE_FORBIDDEN_RE = /[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/;\n\n/** A high surrogate with no low one after it, or a low surrogate with no high one before it. */\nconst LONE_SURROGATE_RE =\n /[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:^|[^\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Reads an own property only, so no field ever comes from a prototype. */\nfunction own(obj: Record<string, unknown>, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : undefined;\n}\n\nfunction invalid(message: string): ChangeLinkError {\n return new ChangeLinkError('INVALID', message);\n}\n\nfunction hasLoneSurrogate(text: string | null | undefined): boolean {\n return typeof text === 'string' && LONE_SURROGATE_RE.test(text);\n}\n\nfunction parseEdit(entry: unknown, n: number): ChangeEdit {\n const fail = (problem: string) => invalid(`edit ${n}: ${problem}`);\n if (!Array.isArray(entry) || (entry.length !== 4 && entry.length !== 5)) {\n throw fail('is not a [locale, key, from, to] entry.');\n }\n const [locale, key, from, to, force] = entry as unknown[];\n if (typeof locale !== 'string' || !isValidLocaleFormat(locale)) {\n throw fail('the locale is not a locale code.');\n }\n if (typeof key !== 'string' || !isValidKeyFormat(key) || !isSafeKeyPath(key)) {\n throw fail('the key is not a valid translation key.');\n }\n if (from !== null && (typeof from !== 'string' || !isValidValueFormat(from))) {\n throw fail(`the current text is not text of at most ${MAX_VALUE_LENGTH} characters.`);\n }\n if (typeof to !== 'string' || !isValidValueFormat(to)) {\n throw fail(`the new text is not text of at most ${MAX_VALUE_LENGTH} characters.`);\n }\n if (entry.length === 5 && force !== 1) throw fail('the force flag must be 1.');\n return { locale, key, from, to, force: entry.length === 5 };\n}\n\n/**\n * Rejects two edits to one locale and key, and, within one locale, an edit\n * whose key is a dotted ancestor of another edit's key (`a.b` and `a.b.c`),\n * which would need both a text and a nested object at the same path.\n */\nfunction checkKeysDistinct(edits: ChangeEdit[]): void {\n const keysByLocale = new Map<string, Set<string>>();\n edits.forEach(({ locale, key }, i) => {\n let keys = keysByLocale.get(locale);\n if (!keys) keysByLocale.set(locale, (keys = new Set()));\n if (keys.has(key)) throw invalid(`edit ${i + 1}: an earlier edit changes the same key.`);\n keys.add(key);\n });\n edits.forEach(({ locale, key }, i) => {\n const keys = keysByLocale.get(locale)!;\n for (let dot = key.indexOf('.'); dot >= 0; dot = key.indexOf('.', dot + 1)) {\n if (keys.has(key.slice(0, dot))) {\n throw invalid(`edit ${i + 1}: another edit changes a key that contains this one.`);\n }\n }\n });\n}\n\n/**\n * Validates a decoded change link and returns it as a change set made of\n * fresh objects, ignoring unknown top-level fields. Throws\n * `UNSUPPORTED_VERSION` unless `v` is 1, `TOO_MANY_EDITS` above\n * `MAX_CHANGE_EDITS` edits, and `INVALID` for anything else outside the\n * schema; a bad entry's message starts with `edit <n>:` (1-based).\n */\nexport function parseChangeSet(value: unknown): ChangeSet {\n if (!isPlainObject(value)) throw invalid('This change link does not hold a change set.');\n if (own(value, 'v') !== CHANGE_LINK_VERSION) {\n throw new ChangeLinkError('UNSUPPORTED_VERSION', UNSUPPORTED_VERSION_MESSAGE);\n }\n\n const repo = own(value, 'repo');\n if (repo !== undefined && (typeof repo !== 'string' || !isValidRepoSlug(repo))) {\n throw invalid('The repository is not an owner/name slug.');\n }\n const branch = own(value, 'branch');\n if (typeof branch !== 'string' || (branch !== '' && !isValidBranchName(branch))) {\n throw invalid('The branch is not a valid branch name.');\n }\n const base = own(value, 'base');\n if (typeof base !== 'string' || !BASE_SHA_RE.test(base)) {\n throw invalid('The base is not a full commit id.');\n }\n const src = own(value, 'src');\n if (typeof src !== 'string' || !isValidLocaleFormat(src)) {\n throw invalid('The source locale is not a locale code.');\n }\n const by = own(value, 'by');\n if (typeof by !== 'string' || by.length > MAX_BY_CHARS || BY_FORBIDDEN_RE.test(by)) {\n throw invalid(`The name is not one line of at most ${MAX_BY_CHARS} characters.`);\n }\n const note = own(value, 'note');\n if (typeof note !== 'string' || note.length > MAX_NOTE_CHARS || NOTE_FORBIDDEN_RE.test(note)) {\n throw invalid(`The note is not plain text of at most ${MAX_NOTE_CHARS} characters.`);\n }\n\n const entries = own(value, 'e');\n if (!Array.isArray(entries)) throw invalid('This change link holds no list of edits.');\n if (entries.length > MAX_CHANGE_EDITS) {\n throw new ChangeLinkError(\n 'TOO_MANY_EDITS',\n `A change link holds at most ${MAX_CHANGE_EDITS} edits. Send the rest in another link.`\n );\n }\n if (entries.length === 0) throw invalid('This change link holds no edits.');\n // Array.from visits the holes of a sparse array, which map would skip.\n const edits = Array.from(entries, (entry: unknown, i) => parseEdit(entry, i + 1));\n checkKeysDistinct(edits);\n\n if ([repo, branch, base, src, by, note].some(hasLoneSurrogate)) {\n throw invalid('This change link holds broken text.');\n }\n edits.forEach(({ locale, key, from, to }, i) => {\n if ([locale, key, from, to].some(hasLoneSurrogate)) {\n throw invalid(`edit ${i + 1}: holds broken text.`);\n }\n });\n\n return { ...(repo === undefined ? {} : { repo }), branch, base, src, by, note, edits };\n}\n\n/** At most this many bytes of JSON after inflation, on encode and on decode. */\nexport const MAX_INFLATED_BYTES = 512 * 1024;\n\n/** A longer token is refused before any base64 or inflate work. */\nexport const MAX_TOKEN_CHARS = 1_000_000;\n\n/** Above this many link characters, Send offers a file instead of a link. */\nexport const CHANGE_LINK_FILE_THRESHOLD = 6_000;\n\n/** Compresses to the zlib format (RFC 1950). */\nexport type Deflater = (bytes: Uint8Array) => Promise<Uint8Array>;\n\n/**\n * Inflates the zlib format (RFC 1950). Throws `TOO_LARGE` once the output\n * passes `maxOutputLength`, and `CORRUPT` on bad or truncated data.\n */\nexport type Inflater = (bytes: Uint8Array, maxOutputLength: number) => Promise<Uint8Array>;\n\nconst TOO_LARGE_MESSAGE = `A change link holds at most ${MAX_INFLATED_BYTES / 1024} KB of text. Send the changes in smaller links.`;\n\nconst UNSUPPORTED_ENVIRONMENT_MESSAGE =\n 'This browser cannot create or read change links. Use a current Chrome, Edge or Firefox, or Safari 16.4 or later.';\n\n/**\n * Input is written to a stream this many bytes at a time. Browsers inflate a\n * written chunk whole before the reader sees any of it, so this bounds how far\n * past the cap a decompression bomb can grow (about 1,000 times this).\n */\nconst FEED_SLICE_BYTES = 4096;\n\n/**\n * Feeds `bytes` through a compression or decompression stream and collects\n * the output, throwing `TOO_LARGE` as soon as it passes `maxOutputLength`.\n * A failed read rejects with the stream's own error.\n */\nasync function pipeBytes(\n stream: CompressionStream | DecompressionStream,\n bytes: Uint8Array,\n maxOutputLength: number\n): Promise<Uint8Array> {\n // The copy keeps a caller's later change to `bytes` out of the stream.\n const input = new Uint8Array(bytes);\n const writer = stream.writable.getWriter();\n const reader = stream.readable.getReader();\n // Set once the reads below stop for any reason. The feeding loop checks it\n // before every write, so no slice is written after the reads stop, however\n // far ahead of the reads the runtime lets writes resolve.\n let stopped = false;\n // Runs alongside the reads below and is not awaited: a transform stream\n // takes more input only once its output is read. Each write waits for the\n // one before, so at most one slice is in flight. How many written slices\n // the stream buffers before inflating them is up to the runtime: a browser\n // takes the next one only once the reader asks for more output, Node's\n // zlib-backed stream up to its highWaterMark of input (16 KB or 64 KB). The\n // reads report the stream's error, so the loop's rejection is silenced.\n void (async () => {\n for (let at = 0; at < input.length; at += FEED_SLICE_BYTES) {\n if (stopped) return;\n await writer.write(input.subarray(at, at + FEED_SLICE_BYTES));\n }\n if (!stopped) await writer.close();\n })().catch(() => {});\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.length;\n if (total > maxOutputLength) throw new ChangeLinkError('TOO_LARGE', TOO_LARGE_MESSAGE);\n chunks.push(value);\n }\n } catch (err) {\n // Tear down both sides: the cancel discards inflated output not yet\n // read, the abort drops input written but not yet taken. Neither waits\n // on the other's pending work.\n stopped = true;\n void writer.abort(err).catch(() => {});\n await reader.cancel(err).catch(() => {});\n throw err;\n }\n\n const out = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n out.set(chunk, offset);\n offset += chunk.length;\n }\n return out;\n}\n\n/** Deflates with `CompressionStream('deflate')`. */\nexport const streamDeflate: Deflater = async (bytes) => {\n if (typeof globalThis.CompressionStream !== 'function') {\n throw new ChangeLinkError('UNSUPPORTED_ENVIRONMENT', UNSUPPORTED_ENVIRONMENT_MESSAGE);\n }\n return pipeBytes(new CompressionStream('deflate'), bytes, Infinity);\n};\n\n/**\n * Inflates with `DecompressionStream('deflate')`. Trailing data after the\n * zlib stream is rejected only where the runtime rejects it (browsers, Node\n * 24); `nodeInflate` checks it everywhere.\n */\nexport const streamInflate: Inflater = async (bytes, maxOutputLength) => {\n if (typeof globalThis.DecompressionStream !== 'function') {\n throw new ChangeLinkError('UNSUPPORTED_ENVIRONMENT', UNSUPPORTED_ENVIRONMENT_MESSAGE);\n }\n try {\n return await pipeBytes(new DecompressionStream('deflate'), bytes, maxOutputLength);\n } catch (err) {\n if (err instanceof ChangeLinkError) throw err;\n throw new ChangeLinkError('CORRUPT', CORRUPT_MESSAGE);\n }\n};\n\n/**\n * Encodes a change set as `lc1.<base64url>`. The set is validated against\n * the schema first, so every link this returns also decodes. Throws the\n * schema's codes, `TOO_LARGE` above `MAX_INFLATED_BYTES` of JSON, and\n * `UNSUPPORTED_ENVIRONMENT` without `CompressionStream`.\n */\nexport async function encodeChangeLink(\n set: ChangeSet,\n deflate: Deflater = streamDeflate\n): Promise<string> {\n // Serialize the validated copy, so the link holds exactly what was checked.\n const json = JSON.stringify(toWire(parseChangeSet(toWire(set))));\n const bytes = new TextEncoder().encode(json);\n if (bytes.length > MAX_INFLATED_BYTES) {\n throw new ChangeLinkError('TOO_LARGE', TOO_LARGE_MESSAGE);\n }\n return CHANGE_LINK_PREFIX + toBase64Url(await deflate(bytes));\n}\n\n/**\n * Decodes the one change link in `text`: a token, a Studio link, a change\n * file or a GitHub issue body. Throws `findChangeToken`'s and the schema's\n * codes, `TOO_LARGE` for a token over `MAX_TOKEN_CHARS` (before any other\n * work) or a payload over `MAX_INFLATED_BYTES`, and `CORRUPT` for anything\n * that does not decode to JSON.\n */\nexport async function decodeChangeLink(\n text: string,\n inflate: Inflater = streamInflate\n): Promise<ChangeSet> {\n const token = findChangeToken(text);\n if (token.length > MAX_TOKEN_CHARS) {\n throw new ChangeLinkError('TOO_LARGE', TOO_LARGE_MESSAGE);\n }\n try {\n const bytes = await inflate(\n fromBase64Url(token.slice(CHANGE_LINK_PREFIX.length)),\n MAX_INFLATED_BYTES\n );\n const json = new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n return parseChangeSet(JSON.parse(json));\n } catch (err) {\n if (err instanceof ChangeLinkError) throw err;\n throw new ChangeLinkError('CORRUPT', CORRUPT_MESSAGE);\n }\n}\n","/**\n * The share manifest contract: the names inside the share folder\n * (`<base>livelocale/`) and the shape of its `manifest.json`, which `pack`\n * writes and the static Studio and `doctor` read.\n *\n * Browser-safe, as tests/unit/core-browser-safe.test.ts checks.\n */\n\nimport { isValidBranchName, isValidRepoSlug } from './change-link.js';\nimport { LOCALE_RE } from './validate.js';\n\n/** The share folder under the app base. No underscore, because Jekyll drops such folders. */\nexport const SHARE_DIR = 'livelocale';\nexport const SHARE_MANIFEST_FILE = 'manifest.json';\nexport const SHARE_FLAG_FILE = 'flag.js';\nexport const SHARE_LOCALES_DIR = 'locales';\nexport const SHARE_MANIFEST_FORMAT = 1;\n\n/** `flat`: one `<code>.json` per locale; `namespaced`: one folder per locale, one file per namespace. */\nexport type LocalesLayout = 'flat' | 'namespaced';\n\nexport interface ShareManifest {\n format: 1;\n /** GitHub `owner/name`. The key is absent unless the build sets `exposeRepo`. */\n repo?: string;\n defaultBranch: string | null;\n /** The branch the site was built from. */\n branch: string | null;\n /** The commit the site was built from: lowercase hex, 40 or 64 characters. */\n base: string | null;\n /** Repo-relative POSIX path of the locales folder, `'.'` for the root. */\n localesPath: string;\n layout: LocalesLayout;\n /** Always one of `locales`. */\n sourceLocale: string;\n /** Sorted. Each code has one file at `./locales/<code>.json`. */\n locales: string[];\n /** The app base, such as `'/'` or `'/repo/'`; null when the app uses a relative base. */\n basePath: string | null;\n /** Sorted keys found in the code by KeyScanner. */\n codeKeys: string[];\n}\n\nconst BASE_SHA_RE = /^[0-9a-f]{40}([0-9a-f]{24})?$/;\n\n/** Reads an own property only, so no field ever comes from a prototype. */\nfunction own(obj: object, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(obj, key)\n ? (obj as Record<string, unknown>)[key]\n : undefined;\n}\n\n/** True for an array whose every slot passes `test`. A hole fails, which `every` would skip. */\nfunction isArrayOf<T>(value: unknown, test: (item: unknown) => item is T): value is T[] {\n if (!Array.isArray(value)) return false;\n for (let i = 0; i < value.length; i++) {\n if (!test(value[i])) return false;\n }\n return true;\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nfunction isLocaleCode(value: unknown): value is string {\n return typeof value === 'string' && LOCALE_RE.test(value);\n}\n\nfunction isNullOr(value: unknown, test: (text: string) => boolean): boolean {\n return value === null || (typeof value === 'string' && test(value));\n}\n\n/**\n * True when `value` is a format-1 share manifest. Unknown fields are ignored,\n * so a newer build can add fields. Both branches must pass `isValidBranchName`,\n * the rule the change-set schema applies to a link's branch, and an empty\n * locales list fails because the source locale must be one of them.\n */\nexport function isShareManifest(value: unknown): value is ShareManifest {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const repo = own(value, 'repo');\n const layout = own(value, 'layout');\n const locales = own(value, 'locales');\n const sourceLocale = own(value, 'sourceLocale');\n return (\n own(value, 'format') === SHARE_MANIFEST_FORMAT &&\n (repo === undefined || (typeof repo === 'string' && isValidRepoSlug(repo))) &&\n isNullOr(own(value, 'defaultBranch'), isValidBranchName) &&\n isNullOr(own(value, 'branch'), isValidBranchName) &&\n isNullOr(own(value, 'base'), (base) => BASE_SHA_RE.test(base)) &&\n typeof own(value, 'localesPath') === 'string' &&\n (layout === 'flat' || layout === 'namespaced') &&\n isArrayOf(locales, isLocaleCode) &&\n typeof sourceLocale === 'string' &&\n locales.includes(sourceLocale) &&\n isNullOr(own(value, 'basePath'), (path) => path.startsWith('/') && path.endsWith('/')) &&\n isArrayOf(own(value, 'codeKeys'), isString)\n );\n}\n\n/** The value itself when it is a share manifest, otherwise null (an HTML fallback page, say). */\nexport function parseShareManifest(value: unknown): ShareManifest | null {\n return isShareManifest(value) ? value : null;\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { LOCALE_RE } from '../core/validate.js';\nimport { comparePlaceholders, validateMessageSyntax } from '../core/placeholders.js';\nimport { KeyScanner } from '../server/key-scanner.js';\n\nexport type IssueKind =\n | 'invalid-json'\n | 'missing-in-locale'\n | 'missing-from-code'\n | 'placeholder-mismatch'\n | 'syntax'\n | 'empty'\n | 'unused';\n\nexport type IssueLevel = 'fail' | 'warn';\n\nexport interface CheckIssue {\n kind: IssueKind;\n level: IssueLevel;\n locale?: string;\n key?: string;\n /** Locale file (or folder) relative to the project, for invalid JSON. */\n file?: string;\n message: string;\n}\n\nexport interface CheckOptions {\n /** Project root to scan for source files. */\n projectDir: string;\n /** Locales directory, absolute or relative to `projectDir`. Defaults to `locales`. */\n localesPath?: string;\n /** Locale the others are compared against. Defaults to `en` when present, else the first locale. */\n sourceLocale?: string;\n /** Report keys that exist in locale files but are never referenced in code. Defaults to true. */\n unused?: boolean;\n /** Treat warnings (unused and empty values) as failures. */\n strict?: boolean;\n}\n\nexport interface CheckReport {\n localesDir: string;\n sourceLocale: string | null;\n locales: string[];\n codeKeyCount: number;\n issues: CheckIssue[];\n}\n\n/** i18next plural suffixes; `t('items')` resolves `items_one`, `items_other`, … at run time. */\nconst PLURAL_SUFFIX_RE = /_(?:ordinal_)?(?:zero|one|two|few|many|other)$/;\n\nconst KIND_ORDER: IssueKind[] = [\n 'invalid-json',\n 'syntax',\n 'missing-from-code',\n 'missing-in-locale',\n 'placeholder-mismatch',\n 'empty',\n 'unused',\n];\n\nconst KIND_TITLE: Record<IssueKind, string> = {\n 'invalid-json': 'Locale files that are not valid JSON',\n syntax: 'Broken ICU message syntax',\n 'missing-from-code': 'Keys used in code but missing from a locale',\n 'missing-in-locale': 'Keys missing compared to the source locale',\n 'placeholder-mismatch': 'Placeholders that differ from the source locale',\n empty: 'Empty translations',\n unused: 'Keys never referenced in code',\n};\n\ninterface LocaleData {\n /** Leaf key → value. Non-string leaves (numbers, arrays) are kept but not validated. */\n leaves: Map<string, unknown>;\n /** Every intermediate object path, so `t.home` counts as a reference to `home.*`. */\n branches: Set<string>;\n}\n\nfunction listLocales(localesDir: string): string[] {\n const locales = new Set<string>();\n for (const item of fs.readdirSync(localesDir, { withFileTypes: true })) {\n if (item.isDirectory() && LOCALE_RE.test(item.name)) locales.add(item.name);\n else if (item.isFile() && item.name.endsWith('.json')) {\n const name = path.basename(item.name, '.json');\n if (LOCALE_RE.test(name)) locales.add(name);\n }\n }\n return Array.from(locales).sort();\n}\n\nfunction flatten(obj: unknown, prefix: string, data: LocaleData): void {\n if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return;\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const full = prefix ? `${prefix}.${key}` : key;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n data.branches.add(full);\n flatten(value, full, data);\n } else {\n data.leaves.set(full, value);\n }\n }\n}\n\n/**\n * Reads one locale the way the runtime does: a flat `{locale}.json`, or every\n * `*.json` inside `{locale}/` merged under its file name as the namespace.\n */\nfunction readLocale(\n localesDir: string,\n locale: string,\n projectDir: string,\n issues: CheckIssue[]\n): LocaleData {\n const data: LocaleData = { leaves: new Map(), branches: new Set() };\n const rel = (p: string) => path.relative(projectDir, p).split(path.sep).join('/');\n const parse = (file: string): unknown => {\n try {\n return JSON.parse(fs.readFileSync(file, 'utf-8'));\n } catch (err: any) {\n issues.push({\n kind: 'invalid-json',\n level: 'fail',\n locale,\n file: rel(file),\n message: err?.message ?? String(err),\n });\n return undefined;\n }\n };\n\n const dir = path.join(localesDir, locale);\n if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {\n for (const file of fs.readdirSync(dir).sort()) {\n if (!file.endsWith('.json')) continue;\n const ns = path.basename(file, '.json');\n const parsed = parse(path.join(dir, file));\n if (parsed === undefined) continue;\n data.branches.add(ns);\n flatten(parsed, ns, data);\n }\n } else {\n flatten(parse(path.join(localesDir, `${locale}.json`)), '', data);\n }\n return data;\n}\n\n/** True when `key` resolves in `data`: as a leaf, an object, or an i18next plural family. */\nfunction hasKey(data: LocaleData, key: string): boolean {\n if (data.leaves.has(key) || data.branches.has(key)) return true;\n for (const leaf of data.leaves.keys()) {\n if (leaf.startsWith(`${key}_`) && PLURAL_SUFFIX_RE.test(leaf)) return true;\n }\n return false;\n}\n\n/** True when a locale key is reached by some code reference (directly, via a parent object, or as a plural form). */\nfunction isReferenced(key: string, codeKeys: Set<string>): boolean {\n const base = key.replace(PLURAL_SUFFIX_RE, '');\n for (const candidate of base === key ? [key] : [key, base]) {\n if (codeKeys.has(candidate)) return true;\n let dot = candidate.lastIndexOf('.');\n while (dot > 0) {\n if (codeKeys.has(candidate.slice(0, dot))) return true;\n dot = candidate.lastIndexOf('.', dot - 1);\n }\n }\n return false;\n}\n\n/**\n * Read-only consistency check of a project's translations, meant for CI:\n * missing keys, broken ICU syntax, placeholder drift between locales, empty\n * values, and keys nothing references.\n */\nexport async function runCheck(options: CheckOptions): Promise<CheckReport> {\n const projectDir = path.resolve(options.projectDir);\n const localesDir = path.resolve(projectDir, options.localesPath ?? 'locales');\n const issues: CheckIssue[] = [];\n const strict = options.strict ?? false;\n const warn: IssueLevel = strict ? 'fail' : 'warn';\n\n if (!fs.existsSync(localesDir) || !fs.statSync(localesDir).isDirectory()) {\n throw new Error(`Locales directory not found: ${localesDir}`);\n }\n\n const locales = listLocales(localesDir);\n const data = new Map(locales.map((l) => [l, readLocale(localesDir, l, projectDir, issues)]));\n\n const sourceLocale =\n options.sourceLocale ?? (locales.includes('en') ? 'en' : (locales[0] ?? null));\n if (sourceLocale && !data.has(sourceLocale)) {\n throw new Error(\n `Source locale \"${sourceLocale}\" not found in ${localesDir} (found: ${locales.join(', ') || 'none'}).`\n );\n }\n\n const scanner = new KeyScanner({ requireEnabled: false });\n const codeKeys = new Set(await scanner.scanSourceKeys(projectDir));\n\n for (const [locale, localeData] of data) {\n for (const [key, value] of localeData.leaves) {\n if (typeof value !== 'string') continue;\n const error = validateMessageSyntax(value);\n if (error) {\n issues.push({ kind: 'syntax', level: 'fail', locale, key, message: error });\n }\n if (value.trim() === '') {\n issues.push({ kind: 'empty', level: warn, locale, key, message: 'Value is empty.' });\n }\n }\n\n for (const key of codeKeys) {\n if (!hasKey(localeData, key)) {\n issues.push({\n kind: 'missing-from-code',\n level: 'fail',\n locale,\n key,\n message: `Used in code but not defined in ${locale}.`,\n });\n }\n }\n }\n\n if (sourceLocale) {\n const source = data.get(sourceLocale)!;\n for (const [locale, localeData] of data) {\n if (locale === sourceLocale) continue;\n for (const [key, sourceValue] of source.leaves) {\n if (!localeData.leaves.has(key)) {\n // Keys the code uses are already reported as missing-from-code, and plural\n // families differ legitimately between languages (Arabic has six forms).\n if (codeKeys.has(key) || PLURAL_SUFFIX_RE.test(key)) continue;\n issues.push({\n kind: 'missing-in-locale',\n level: 'fail',\n locale,\n key,\n message: `Defined in ${sourceLocale} but not in ${locale}.`,\n });\n continue;\n }\n\n const value = localeData.leaves.get(key);\n if (typeof sourceValue !== 'string' || typeof value !== 'string' || value === '') continue;\n const cmp = comparePlaceholders(sourceValue, value);\n if (!cmp.ok) {\n const parts: string[] = [];\n if (cmp.missing.length) parts.push(`missing ${cmp.missing.join(', ')}`);\n if (cmp.extra.length) parts.push(`extra ${cmp.extra.join(', ')}`);\n issues.push({\n kind: 'placeholder-mismatch',\n level: 'fail',\n locale,\n key,\n message: `${parts.join('; ')} (compared to ${sourceLocale}).`,\n });\n }\n }\n }\n\n if (options.unused ?? true) {\n for (const key of source.leaves.keys()) {\n if (!isReferenced(key, codeKeys)) {\n issues.push({\n kind: 'unused',\n level: warn,\n locale: sourceLocale,\n key,\n message: 'Not referenced in code (dynamic keys cannot be detected).',\n });\n }\n }\n }\n }\n\n issues.sort(\n (a, b) =>\n KIND_ORDER.indexOf(a.kind) - KIND_ORDER.indexOf(b.kind) ||\n (a.locale ?? '').localeCompare(b.locale ?? '') ||\n (a.key ?? a.file ?? '').localeCompare(b.key ?? b.file ?? '')\n );\n\n return {\n localesDir,\n sourceLocale,\n locales,\n codeKeyCount: codeKeys.size,\n issues,\n };\n}\n\nexport function hasCheckFailures(report: CheckReport): boolean {\n return report.issues.some((i) => i.level === 'fail');\n}\n\n/** Human-readable report, grouped by issue kind, with at most `limit` lines per group. */\nexport function formatCheckReport(report: CheckReport, limit = 25): string {\n const lines: string[] = [];\n for (const kind of KIND_ORDER) {\n const group = report.issues.filter((i) => i.kind === kind);\n if (group.length === 0) continue;\n const glyph = group.some((i) => i.level === 'fail') ? '✖' : '⚠';\n lines.push(`${glyph} ${KIND_TITLE[kind]} (${group.length})`);\n for (const issue of group.slice(0, limit)) {\n const where = issue.key\n ? `${issue.locale ? `[${issue.locale}] ` : ''}${issue.key}`\n : (issue.file ?? issue.locale ?? '');\n lines.push(` ${where} — ${issue.message}`);\n }\n if (group.length > limit) lines.push(` …and ${group.length - limit} more`);\n }\n return lines.join('\\n');\n}\n","/**\n * Placeholder analysis for translation messages.\n *\n * Understands the formats the supported libraries use:\n * - ICU MessageFormat (next-intl, react-intl, FormatJS): `{name}`, `{count, number}`,\n * `{count, plural, one {…} other {…}}`, apostrophe quoting.\n * - i18next: `{{name}}`, `{{count, number}}`, nesting `$t(key)`.\n * - printf-style: `%s`, `%d`, `%1$s`.\n * - rich-text tags (react-intl, next-intl `t.rich`, i18next `<Trans>`): `<b>…</b>`, `<0>…</0>`.\n *\n * A placeholder token is a canonical string such as `{name}`, `{{name}}`, `%s` or `<b>`,\n * so two messages can be compared as sets.\n */\n\nconst PLURAL_TYPES = new Set(['plural', 'select', 'selectordinal']);\n\ninterface ParseResult {\n args: Set<string>;\n error: string | null;\n}\n\n/**\n * Removes ICU apostrophe-quoted spans (`'{'`, `'{literal}'`) and turns `''`\n * into a plain apostrophe so the structural scan only sees real syntax.\n */\nfunction unquoteIcu(message: string): string {\n let out = '';\n let i = 0;\n while (i < message.length) {\n const ch = message[i]!;\n if (ch !== \"'\") {\n out += ch;\n i += 1;\n continue;\n }\n if (message[i + 1] === \"'\") {\n out += \"'\";\n i += 2;\n continue;\n }\n const next = message[i + 1];\n if (next === '{' || next === '}' || next === '#' || next === '|') {\n // Quoted span: skip to the closing single apostrophe (doubled ones are literal).\n let j = i + 1;\n while (j < message.length) {\n if (message[j] === \"'\") {\n if (message[j + 1] === \"'\") {\n j += 2;\n continue;\n }\n break;\n }\n j += 1;\n }\n i = j + 1;\n continue;\n }\n out += ch;\n i += 1;\n }\n return out;\n}\n\n/** Recursive-descent walk over ICU structure collecting argument names and the first error. */\nfunction parseIcu(message: string): ParseResult {\n const args = new Set<string>();\n let pos = 0;\n let error: string | null = null;\n\n const fail = (msg: string) => {\n if (!error) error = msg;\n };\n\n const parseMessage = (depth: number): void => {\n while (pos < message.length) {\n const ch = message[pos]!;\n if (ch === '{') {\n pos += 1;\n parseArgument(depth + 1);\n } else if (ch === '}') {\n if (depth === 0) {\n fail('Unbalanced braces: unexpected \"}\"');\n pos += 1;\n } else {\n return; // caller consumes the brace\n }\n } else {\n pos += 1;\n }\n }\n if (depth > 0) fail('Unbalanced braces: missing \"}\"');\n };\n\n const readUntil = (stops: string[]): string => {\n let out = '';\n while (pos < message.length && !stops.includes(message[pos]!)) {\n out += message[pos]!;\n pos += 1;\n }\n return out;\n };\n\n const parseArgument = (depth: number): void => {\n const name = readUntil([',', '}']).trim();\n if (name && !name.includes('{')) args.add(name);\n if (pos >= message.length) {\n fail('Unbalanced braces: missing \"}\"');\n return;\n }\n if (message[pos] === '}') {\n pos += 1;\n return;\n }\n pos += 1; // ','\n const type = readUntil([',', '}']).trim();\n if (pos >= message.length) {\n fail('Unbalanced braces: missing \"}\"');\n return;\n }\n if (message[pos] === '}') {\n pos += 1;\n return;\n }\n pos += 1; // ','\n\n if (PLURAL_TYPES.has(type)) {\n let hasOther = false;\n while (pos < message.length) {\n // skip whitespace\n while (pos < message.length && /\\s/.test(message[pos]!)) pos += 1;\n if (message[pos] === '}') {\n pos += 1;\n if (!hasOther) fail(`\"${name}\" (${type}) has no \"other\" branch`);\n return;\n }\n const selector = readUntil(['{', '}', ' ', '\\t', '\\n']).trim();\n while (pos < message.length && /\\s/.test(message[pos]!)) pos += 1;\n if (message[pos] !== '{') {\n fail(`\"${name}\" (${type}): expected \"{\" after \"${selector}\"`);\n return;\n }\n if (selector === 'other') hasOther = true;\n pos += 1;\n parseMessage(depth + 1);\n if (message[pos] === '}') pos += 1;\n }\n fail('Unbalanced braces: missing \"}\"');\n return;\n }\n\n // number/date/time style, or unknown: skip to the matching brace\n let level = 1;\n while (pos < message.length && level > 0) {\n if (message[pos] === '{') level += 1;\n else if (message[pos] === '}') level -= 1;\n pos += 1;\n }\n if (level > 0) fail('Unbalanced braces: missing \"}\"');\n };\n\n parseMessage(0);\n return { args, error };\n}\n\nconst I18NEXT_RE = /\\{\\{\\s*([^{}]*?)\\s*\\}\\}/g;\nconst NESTING_RE = /\\$t\\([^)]*\\)/g;\nconst PRINTF_RE = /%(?:\\d+\\$)?[-+ 0#]*\\d*(?:\\.\\d+)?[sdifgxXoc]/g;\nconst TAG_RE = /<\\/?([A-Za-z][\\w-]*|\\d+)\\b[^<>]*>/g;\n\n/** Returns the sorted, de-duplicated placeholder tokens found in `message`. */\nexport function extractPlaceholders(message: string): string[] {\n if (typeof message !== 'string' || message === '') return [];\n const tokens = new Set<string>();\n\n // i18next interpolation first, then blank it out so the ICU scan does not see `{{`.\n const withoutI18next = message.replace(I18NEXT_RE, (_m, inner: string) => {\n const name = inner.split(',')[0]!.trim();\n if (name) tokens.add(`{{${name}}}`);\n return ' ';\n });\n\n for (const m of withoutI18next.match(NESTING_RE) ?? []) tokens.add(m);\n for (const m of withoutI18next.replace(/%%/g, '').match(PRINTF_RE) ?? []) tokens.add(m);\n for (const m of withoutI18next.matchAll(TAG_RE)) tokens.add(`<${m[1]}>`);\n\n const icu = parseIcu(unquoteIcu(withoutI18next.replace(TAG_RE, ' ')));\n for (const arg of icu.args) tokens.add(`{${arg}}`);\n\n return Array.from(tokens).sort();\n}\n\nexport interface PlaceholderComparison {\n ok: boolean;\n /** Present in the reference but not in the value. */\n missing: string[];\n /** Present in the value but not in the reference. */\n extra: string[];\n}\n\n/** Compares placeholder sets; an empty reference is compatible with anything. */\nexport function comparePlaceholders(\n reference: string | undefined | null,\n value: string\n): PlaceholderComparison {\n if (!reference) return { ok: true, missing: [], extra: [] };\n const ref = new Set(extractPlaceholders(reference));\n const val = new Set(extractPlaceholders(value));\n const missing = Array.from(ref).filter((t) => !val.has(t));\n const extra = Array.from(val).filter((t) => !ref.has(t));\n return { ok: missing.length === 0 && extra.length === 0, missing, extra };\n}\n\n/** Returns a description of the first ICU structural problem, or null when the message is sound. */\nexport function validateMessageSyntax(message: string): string | null {\n if (typeof message !== 'string') return null;\n const prepared = unquoteIcu(message.replace(I18NEXT_RE, ' ').replace(TAG_RE, ' '));\n return parseIcu(prepared).error;\n}\n","import { promises as fs } from 'fs';\nimport * as path from 'path';\nimport { isSafeLocaleSegment } from '../core/validate.js';\nimport { getDisabledReason } from '../core/env.js';\nimport { parseGitignore, type GitignoreMatcher } from '../core/gitignore.js';\n\nconst IGNORE_DIRS = new Set([\n 'node_modules',\n '.next',\n 'dist',\n 'build',\n '.git',\n 'coverage',\n 'test-results',\n 'out',\n '.idea',\n '.vscode',\n '.turbo',\n '.cache',\n]);\n\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);\n\n/** Files above this size are almost certainly bundles or fixtures, not components. */\nconst MAX_SOURCE_BYTES = 1_000_000;\n\nconst PROP_RE = /\\bt(?:\\??\\.[a-zA-Z0-9_]+)+/g;\nconst IGNORE_PROPS = new Set([\n 'toString',\n 'length',\n 'constructor',\n 'prototype',\n 'map',\n 'forEach',\n 'filter',\n 'reduce',\n 'call',\n 'apply',\n 'bind',\n 'name',\n 'displayName',\n 'raw',\n 'rich',\n 'markup',\n 'has',\n]);\n\nconst KEY_SHAPE = /^[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)*$/;\nconst DECL = String.raw`(?:const|let|var)\\s+`;\n/** A string literal in any quote style; read the value with `stringArg(match)`. */\nconst STR = String.raw`(?:'(?<s1>[^']*)'|\"(?<s2>[^\"]*)\"|\\x60(?<s3>[^\\x60]*)\\x60)`;\nconst stringArg = (m: RegExpMatchArray): string | undefined =>\n m.groups?.['s1'] ?? m.groups?.['s2'] ?? m.groups?.['s3'];\n\n/** Translator-method names whose first argument is a key. */\nconst METHODS = String.raw`(?:\\.(?:rich|raw|markup|has))?`;\n\n/**\n * Maps translator variable names to their key prefix (namespace) from the\n * declarations in a file:\n * const t = useTranslations('home') // next-intl (also getTranslations, await)\n * const { t } = useTranslation('auth') // react-i18next\n * const t = wrapTranslationEngine(x, { keyPrefix: 'auth' })\n * const t = wrapNextIntl(x, 'checkout')\n * Scope is not tracked; the last declaration of a name in the file wins.\n */\nfunction namespaceBindings(content: string): Map<string, string> {\n const map = new Map<string, string>();\n\n const hookRe = new RegExp(\n DECL +\n String.raw`(?<name>\\w+)\\s*=\\s*(?:await\\s+)?(?:useTranslations|getTranslations)\\(\\s*(?:` +\n STR +\n String.raw`)?\\s*\\)`,\n 'g'\n );\n for (const m of content.matchAll(hookRe)) map.set(m.groups!['name']!, stringArg(m) ?? '');\n\n const wrapNextIntlRe = new RegExp(\n DECL + String.raw`(?<name>\\w+)\\s*=\\s*wrapNextIntl\\([^;]*?,\\s*` + STR + String.raw`\\s*\\)`,\n 'g'\n );\n for (const m of content.matchAll(wrapNextIntlRe)) {\n map.set(m.groups!['name']!, stringArg(m) ?? '');\n }\n\n const wrapEngineRe = new RegExp(\n DECL + String.raw`(?<name>\\w+)\\s*=\\s*wrapTranslationEngine\\([^;]*?keyPrefix:\\s*` + STR,\n 'g'\n );\n for (const m of content.matchAll(wrapEngineRe)) {\n map.set(m.groups!['name']!, stringArg(m) ?? '');\n }\n\n const i18nextRe = new RegExp(\n DECL + String.raw`\\{(?<bindings>[^}]*)\\}\\s*=\\s*useTranslation\\(\\s*(?:` + STR + String.raw`)?`,\n 'g'\n );\n for (const m of content.matchAll(i18nextRe)) {\n const binding = /\\bt\\s*(?::\\s*(\\w+))?/.exec(m.groups!['bindings']!);\n if (binding) map.set(binding[1] ?? 't', stringArg(m) ?? '');\n }\n\n return map;\n}\n\n/** Extracts translation key references from one source file's text. */\nexport function extractKeys(content: string): string[] {\n const keys = new Set<string>();\n const bindings = namespaceBindings(content);\n const translators = new Set<string>(['t', ...bindings.keys()]);\n\n for (const name of translators) {\n const prefix = bindings.get(name) ?? '';\n const callRe = new RegExp(String.raw`\\b` + name + METHODS + String.raw`\\(\\s*` + STR, 'g');\n for (const m of content.matchAll(callRe)) {\n const key = stringArg(m);\n if (!key || key.includes('${') || !KEY_SHAPE.test(key)) continue;\n keys.add(prefix ? `${prefix}.${key}` : key);\n }\n }\n\n let match: RegExpExecArray | null;\n PROP_RE.lastIndex = 0;\n while ((match = PROP_RE.exec(content)) !== null) {\n const clean = match[0].replace(/\\bt/, '').replace(/\\?/g, '');\n const segments = clean\n .split('.')\n .map((seg) => seg.trim())\n .filter(Boolean);\n if (segments.length > 0 && !segments.some((seg) => IGNORE_PROPS.has(seg))) {\n keys.add(segments.join('.'));\n }\n }\n\n return Array.from(keys).sort();\n}\n\ninterface CachedFile<T> {\n mtimeMs: number;\n size: number;\n value: T;\n}\n\nconst NO_IGNORES: GitignoreMatcher = { ignores: () => false };\n\n/**\n * Read-only analysis of translation keys: scans the codebase for `t(...)`\n * references and compiles the set of keys present in locale files.\n *\n * Scans are incremental: each source file's extracted keys are cached by\n * mtime and size, so a rescan only re-reads files that changed. The project's\n * root `.gitignore` is honoured in addition to the built-in ignore list.\n */\nexport interface KeyScannerOptions {\n /**\n * Refuse to scan unless LiveLocale is enabled (development or preview mode).\n * Defaults to true; read-only tooling such as `check` turns it off so it can run in CI.\n */\n requireEnabled?: boolean;\n}\n\nexport class KeyScanner {\n private fileCache = new Map<string, CachedFile<string[]>>();\n private gitignoreCache: CachedFile<GitignoreMatcher> | null = null;\n private readonly requireEnabled: boolean;\n\n constructor(options: KeyScannerOptions = {}) {\n this.requireEnabled = options.requireEnabled ?? true;\n }\n\n private assertEnabled(): void {\n if (!this.requireEnabled) return;\n const reason = getDisabledReason();\n if (reason !== null) {\n throw new Error(\n `[livelocale] KeyScanner can only be executed in development mode (${reason}).`\n );\n }\n }\n\n private async loadGitignore(projectRoot: string): Promise<GitignoreMatcher> {\n const gitignorePath = path.join(projectRoot, '.gitignore');\n let stat;\n try {\n stat = await fs.stat(gitignorePath);\n } catch {\n this.gitignoreCache = null;\n return NO_IGNORES;\n }\n const hit = this.gitignoreCache;\n if (hit && hit.mtimeMs === stat.mtimeMs && hit.size === stat.size) {\n return hit.value;\n }\n try {\n const content = await fs.readFile(gitignorePath, 'utf-8');\n const matcher = parseGitignore(content);\n this.gitignoreCache = { mtimeMs: stat.mtimeMs, size: stat.size, value: matcher };\n return matcher;\n } catch {\n return NO_IGNORES;\n }\n }\n\n /**\n * Scans the project (the parent directory of `basePath`) for translation key references.\n */\n async scanCodebaseKeys(basePath: string): Promise<string[]> {\n return this.scanSourceKeys(path.dirname(path.resolve(basePath)));\n }\n\n /** Scans every source file under `projectRoot` for translation key references. */\n async scanSourceKeys(projectRoot: string): Promise<string[]> {\n this.assertEnabled();\n\n projectRoot = path.resolve(projectRoot);\n const gitignore = await this.loadGitignore(projectRoot);\n const keysSet = new Set<string>();\n const seen = new Set<string>();\n\n const toRel = (fullPath: string) =>\n path.relative(projectRoot, fullPath).split(path.sep).join('/');\n\n const scanDir = async (dir: string): Promise<void> => {\n let items;\n try {\n items = await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const item of items) {\n const fullPath = path.join(dir, item.name);\n\n if (item.isDirectory()) {\n if (IGNORE_DIRS.has(item.name)) continue;\n if (gitignore.ignores(toRel(fullPath), true)) continue;\n await scanDir(fullPath);\n continue;\n }\n\n if (!item.isFile()) continue;\n if (!SOURCE_EXTENSIONS.has(path.extname(item.name))) continue;\n if (item.name.endsWith('.d.ts')) continue;\n if (gitignore.ignores(toRel(fullPath), false)) continue;\n\n let stat;\n try {\n stat = await fs.stat(fullPath);\n } catch {\n continue;\n }\n if (stat.size > MAX_SOURCE_BYTES) continue;\n\n seen.add(fullPath);\n const cached = this.fileCache.get(fullPath);\n if (cached && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) {\n for (const k of cached.value) keysSet.add(k);\n continue;\n }\n\n try {\n const content = await fs.readFile(fullPath, 'utf-8');\n const keys = extractKeys(content);\n this.fileCache.set(fullPath, { mtimeMs: stat.mtimeMs, size: stat.size, value: keys });\n for (const k of keys) keysSet.add(k);\n } catch {}\n }\n };\n\n await scanDir(projectRoot);\n\n // Forget files that disappeared so the cache cannot grow without bound.\n for (const cachedPath of this.fileCache.keys()) {\n if (!seen.has(cachedPath)) this.fileCache.delete(cachedPath);\n }\n\n return Array.from(keysSet).sort();\n }\n\n /**\n * Scans all locale files/folders to compile the set of all keys currently in locales.\n */\n async scanLocalesKeys(\n basePath: string,\n listLocales: (base: string) => Promise<string[]>\n ): Promise<string[]> {\n this.assertEnabled();\n\n const locales = await listLocales(basePath);\n const keysSet = new Set<string>();\n\n for (const locale of locales) {\n try {\n const resolvedBasePath = path.resolve(basePath);\n const localePath = path.resolve(resolvedBasePath, locale);\n\n let isDir = false;\n try {\n const stats = await fs.stat(localePath);\n isDir = stats.isDirectory();\n } catch {}\n\n let data: Record<string, any> = {};\n\n if (isDir) {\n const files = await fs.readdir(localePath);\n for (const file of files) {\n if (file.endsWith('.json')) {\n const ns = path.basename(file, '.json');\n try {\n const content = await fs.readFile(path.join(localePath, file), 'utf-8');\n data[ns] = JSON.parse(content);\n } catch {}\n }\n }\n } else {\n try {\n if (!isSafeLocaleSegment(locale)) {\n continue;\n }\n const filePath = path.resolve(resolvedBasePath, `${locale}.json`);\n if (filePath.startsWith(resolvedBasePath)) {\n const content = await fs.readFile(filePath, 'utf-8');\n data = JSON.parse(content);\n }\n } catch {}\n }\n\n const flatten = (obj: any, prefix = '') => {\n if (!obj || typeof obj !== 'object') return;\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n const newKey = prefix ? `${prefix}.${key}` : key;\n if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {\n flatten(obj[key], newKey);\n } else {\n keysSet.add(newKey);\n }\n }\n }\n };\n\n flatten(data);\n } catch {}\n }\n\n return Array.from(keysSet).sort();\n }\n\n /**\n * Returns merged lists of keys from codebase and existing locale files.\n */\n async getKeysMetadata(\n basePath: string,\n listLocales: (base: string) => Promise<string[]>\n ): Promise<{ allKeys: string[]; codeKeys: string[] }> {\n const codeKeys = await this.scanCodebaseKeys(basePath);\n const localeKeys = await this.scanLocalesKeys(basePath, listLocales);\n const allKeys = Array.from(new Set([...codeKeys, ...localeKeys])).sort();\n return {\n allKeys,\n codeKeys,\n };\n }\n}\n","/**\n * Single source of truth for \"is LiveLocale active right now, and in which mode?\".\n *\n * Modes:\n * - `development`: NODE_ENV is `development` (the default, zero-config mode).\n * - `preview`: explicitly opted in with `LIVELOCALE=preview` (server) or\n * `NEXT_PUBLIC_LIVELOCALE=preview` (client bundles). Works in production builds so a\n * preview deployment can be edited through a hosted Studio. The mutation API then\n * requires a bearer token (see the router).\n * - `off`: everything else.\n *\n * Rules, in order:\n * 1. `LIVELOCALE=off|0|false` (or `NEXT_PUBLIC_LIVELOCALE=off`) always wins → off.\n * 2. `LIVELOCALE=preview` / `NEXT_PUBLIC_LIVELOCALE=preview` → preview.\n * 3. `NODE_ENV` must be `development`, otherwise off.\n * 4. `LIVELOCALE=force` skips rule 5.\n * 5. On the server, a known hosting platform (Vercel preview/production, Netlify,\n * Kubernetes, Render, Fly.io, Railway, Heroku) → off, so a mis-configured staging\n * deploy cannot leak watermarks. A one-time warning is logged.\n *\n * `process.env.NODE_ENV` and `process.env.NEXT_PUBLIC_LIVELOCALE` are referenced as\n * literal member expressions so Next.js and Vite can inline them in browser bundles.\n */\n\nexport type LiveLocaleMode = 'off' | 'development' | 'preview';\n\nconst OFF_VALUES = new Set(['off', '0', 'false']);\n\nlet warnedDeployed = false;\n\n/** Test hook: forget that the deployed-platform warning was already printed. */\nexport function resetEnvWarnings(): void {\n warnedDeployed = false;\n}\n\nfunction readNodeEnv(): string | undefined {\n try {\n return process.env.NODE_ENV;\n } catch {\n return undefined;\n }\n}\n\n/** Set by the Vite plugin (and usable by any host) to mirror the server flag into the page. */\nexport const BROWSER_FLAG_GLOBAL = '__LIVELOCALE_FLAG__';\n\nfunction readPublicFlag(): string | undefined {\n let value: string | undefined;\n try {\n value = process.env.NEXT_PUBLIC_LIVELOCALE;\n } catch {\n value = undefined;\n }\n if (value) return value;\n try {\n const g = globalThis as any;\n const fromGlobal = g.window?.[BROWSER_FLAG_GLOBAL] ?? g[BROWSER_FLAG_GLOBAL];\n return typeof fromGlobal === 'string' ? fromGlobal : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readEnv(name: string): string | undefined {\n if (typeof process === 'undefined' || !process.env) return undefined;\n const value = process.env[name];\n return value === '' ? undefined : value;\n}\n\n/** Returns a human-readable platform name when running on a known hosting platform. */\nexport function detectDeployedPlatform(): string | null {\n if (typeof window !== 'undefined') return null; // browser: nothing to detect\n const vercelEnv = readEnv('VERCEL_ENV');\n if (vercelEnv === 'production' || vercelEnv === 'preview')\n return `Vercel (VERCEL_ENV=${vercelEnv})`;\n const netlifyContext = readEnv('CONTEXT');\n if (readEnv('NETLIFY') === 'true' && netlifyContext && netlifyContext !== 'dev') {\n return `Netlify (CONTEXT=${netlifyContext})`;\n }\n if (readEnv('KUBERNETES_SERVICE_HOST')) return 'Kubernetes';\n if (readEnv('RENDER') === 'true') return 'Render';\n if (readEnv('FLY_APP_NAME')) return 'Fly.io';\n if (readEnv('RAILWAY_ENVIRONMENT')) return 'Railway';\n if (readEnv('DYNO')) return 'Heroku';\n return null;\n}\n\nfunction evaluate(): { mode: LiveLocaleMode; reason: string | null } {\n const flag = (readEnv('LIVELOCALE') ?? '').toLowerCase();\n const publicFlag = (readPublicFlag() ?? '').toLowerCase();\n\n if (OFF_VALUES.has(flag)) return { mode: 'off', reason: 'LIVELOCALE kill switch is set' };\n if (OFF_VALUES.has(publicFlag)) {\n return { mode: 'off', reason: 'NEXT_PUBLIC_LIVELOCALE kill switch is set' };\n }\n\n if (flag === 'preview' || publicFlag === 'preview') return { mode: 'preview', reason: null };\n\n const nodeEnv = readNodeEnv();\n if (nodeEnv !== 'development') {\n return {\n mode: 'off',\n reason: `NODE_ENV is \"${nodeEnv ?? 'undefined'}\" (must be \"development\", or set LIVELOCALE=preview)`,\n };\n }\n\n if (flag === 'force') return { mode: 'development', reason: null };\n\n const platform = detectDeployedPlatform();\n if (platform) {\n if (!warnedDeployed) {\n warnedDeployed = true;\n console.warn(\n `[livelocale] Disabled: deployed environment detected (${platform}) while NODE_ENV=development. ` +\n `Set LIVELOCALE=force to override, LIVELOCALE=preview for a hosted preview, or LIVELOCALE=off to silence this warning.`\n );\n }\n return { mode: 'off', reason: `deployed environment detected (${platform})` };\n }\n\n return { mode: 'development', reason: null };\n}\n\n/** The active mode: `off`, `development`, or `preview`. */\nexport function getLiveLocaleMode(): LiveLocaleMode {\n return evaluate().mode;\n}\n\n/**\n * Returns `null` when LiveLocale should be active, otherwise a short reason\n * suitable for error messages and logs.\n */\nexport function getDisabledReason(): string | null {\n return evaluate().reason;\n}\n\n/** True when watermarking, the mutation API, and the client scanner should run. */\nexport function isLiveLocaleEnabled(): boolean {\n return evaluate().mode !== 'off';\n}\n","/**\n * A small, dependency-free `.gitignore` matcher covering the patterns that\n * matter for skipping generated code during key scanning: directory rules\n * (`build/`), anchored rules (`/dist`), globs (`*.log`, `**\\/tmp`,\n * `docs/**\\/*.snap`) and negation (`!keep.log`). Last matching rule wins, and a\n * path whose ancestor directory is ignored is ignored too.\n */\n\nexport interface GitignoreMatcher {\n /** `relPath` is relative to the directory holding the .gitignore, using `/` separators. */\n ignores(relPath: string, isDir: boolean): boolean;\n}\n\ninterface Rule {\n regex: RegExp;\n negated: boolean;\n dirOnly: boolean;\n}\n\nfunction globToRegexSource(pattern: string): string {\n let out = '';\n let i = 0;\n while (i < pattern.length) {\n const ch = pattern[i]!;\n if (ch === '*') {\n if (pattern[i + 1] === '*') {\n // `**/` → any number of directories (including none); `**` elsewhere → anything\n if (pattern[i + 2] === '/') {\n out += '(?:.*/)?';\n i += 3;\n } else {\n out += '.*';\n i += 2;\n }\n } else {\n out += '[^/]*';\n i += 1;\n }\n } else if (ch === '?') {\n out += '[^/]';\n i += 1;\n } else {\n out += /[.+^${}()|[\\]\\\\]/.test(ch) ? `\\\\${ch}` : ch;\n i += 1;\n }\n }\n return out;\n}\n\nfunction compileRule(rawLine: string): Rule | null {\n let line = rawLine.replace(/\\r$/, '');\n if (!line.trim() || line.trimStart().startsWith('#')) return null;\n // Trailing spaces are ignored unless escaped\n line = line.replace(/(?<!\\\\)\\s+$/, '');\n\n let negated = false;\n if (line.startsWith('!')) {\n negated = true;\n line = line.slice(1);\n }\n\n let dirOnly = false;\n if (line.endsWith('/')) {\n dirOnly = true;\n line = line.slice(0, -1);\n }\n\n let anchored = false;\n if (line.startsWith('/')) {\n anchored = true;\n line = line.slice(1);\n } else if (line.includes('/')) {\n anchored = true;\n }\n\n if (!line) return null;\n\n const body = globToRegexSource(line);\n const regex = anchored ? new RegExp(`^${body}$`) : new RegExp(`(?:^|/)${body}$`);\n return { regex, negated, dirOnly };\n}\n\nexport function parseGitignore(content: string): GitignoreMatcher {\n const rules: Rule[] = [];\n for (const line of content.split('\\n')) {\n const rule = compileRule(line);\n if (rule) rules.push(rule);\n }\n\n const matchOne = (relPath: string, isDir: boolean): boolean => {\n let ignored = false;\n for (const rule of rules) {\n if (rule.dirOnly && !isDir) continue;\n if (rule.regex.test(relPath)) ignored = !rule.negated;\n }\n return ignored;\n };\n\n return {\n ignores(relPath: string, isDir: boolean): boolean {\n if (rules.length === 0) return false;\n const normalized = relPath.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/^\\/+/, '');\n if (!normalized) return false;\n if (matchOne(normalized, isDir)) return true;\n\n // An ignored ancestor directory ignores everything beneath it.\n const segments = normalized.split('/');\n for (let i = 1; i < segments.length; i++) {\n if (matchOne(segments.slice(0, i).join('/'), true)) return true;\n }\n return false;\n },\n };\n}\n","import { spawn } from 'child_process';\nimport { existsSync, readFileSync, statSync, promises as fs } from 'fs';\nimport * as path from 'path';\nimport { FLAG_SCRIPT } from '../core/flag-script.js';\nimport { LOCALE_RE } from '../core/validate.js';\nimport {\n SHARE_DIR,\n SHARE_FLAG_FILE,\n SHARE_LOCALES_DIR,\n SHARE_MANIFEST_FILE,\n SHARE_MANIFEST_FORMAT,\n type LocalesLayout,\n type ShareManifest,\n} from '../core/share-manifest.js';\nimport { resolveBuildInfo, type GitRunner } from './build-info.js';\nimport { parseGitignore } from '../core/gitignore.js';\nimport { detectBuildTarget, findExportBlockingRoute, outputCandidates } from './build-target.js';\nimport { KeyScanner } from './key-scanner.js';\nimport { moduleDir } from './module-dir.js';\nimport { PackError } from './pack-error.js';\nimport {\n basePathOf,\n flagSrcFor,\n injectFlagScript,\n normalizeBase,\n shareUrlPathFor,\n} from './share-html.js';\n\nexport interface ShareDataOptions {\n projectDir: string;\n /** The locales folder, relative to `projectDir`. Defaults to `locales`. */\n localesPath?: string;\n sourceLocale?: string;\n exposeRepo?: boolean;\n basePath: string | null;\n env?: NodeJS.ProcessEnv;\n git?: GitRunner;\n}\n\nexport interface ShareData {\n manifest: ShareManifest;\n /** Each locale's merged nested dictionary; namespaces are top-level keys. */\n dictionaries: Record<string, Record<string, unknown>>;\n warnings: string[];\n}\n\nconst NO_REPO_WARNING =\n 'exposeRepo is on but no GitHub repository was found; the manifest has no repo.';\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction toPosix(relative: string): string {\n return relative.split(path.sep).join('/') || '.';\n}\n\n/** True when `child` is `parent` or inside it. */\nfunction isInside(parent: string, child: string): boolean {\n const rel = path.relative(parent, child);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n}\n\n/** Sets an own property, so a `__proto__` name never reaches the prototype. */\nfunction defineOwn(target: Record<string, unknown>, key: string, value: unknown): void {\n Object.defineProperty(target, key, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n}\n\n/** Reads one JSON file whose root must be a plain object. Never goes through FileMutator. */\nasync function readJsonObject(file: string, projectDir: string): Promise<Record<string, unknown>> {\n const shown = toPosix(path.relative(projectDir, file));\n let parsed: unknown;\n try {\n parsed = JSON.parse(await fs.readFile(file, 'utf-8'));\n } catch (error) {\n throw new PackError(\n 'INVALID_LOCALE_FILE',\n `${shown} is not a JSON object: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n if (!isPlainObject(parsed)) {\n const kind = Array.isArray(parsed) ? 'an array' : parsed === null ? 'null' : typeof parsed;\n throw new PackError(\n 'INVALID_LOCALE_FILE',\n `${shown} is not a JSON object: the root is ${kind}`\n );\n }\n return parsed;\n}\n\n/**\n * Collects what the share folder needs: the manifest (build info, locales,\n * layout, code keys) and every locale's dictionary, read straight from disk.\n */\nexport async function collectShareData(options: ShareDataOptions): Promise<ShareData> {\n const projectDir = path.resolve(options.projectDir);\n const localesDir = path.resolve(projectDir, options.localesPath ?? 'locales');\n const warnings: string[] = [];\n\n let entries;\n try {\n if (!(await fs.stat(localesDir)).isDirectory()) throw new Error('not a directory');\n entries = await fs.readdir(localesDir, { withFileTypes: true });\n } catch {\n throw new PackError(\n 'LOCALES_NOT_FOUND',\n `Locales directory not found: ${localesDir}. Pass --locales <path>.`\n );\n }\n\n const dirLocales = new Set<string>();\n const fileLocales = new Set<string>();\n for (const entry of entries) {\n if (entry.isDirectory() && LOCALE_RE.test(entry.name)) {\n dirLocales.add(entry.name);\n } else if (entry.isFile() && entry.name.endsWith('.json')) {\n const code = entry.name.slice(0, -'.json'.length);\n if (LOCALE_RE.test(code)) fileLocales.add(code);\n }\n }\n const locales = [...new Set([...dirLocales, ...fileLocales])].sort();\n if (locales.length === 0) {\n throw new PackError(\n 'NO_LOCALES',\n `No locale files in ${localesDir} (expected en.json or en/*.json).`\n );\n }\n const layout: LocalesLayout = dirLocales.size > 0 ? 'namespaced' : 'flat';\n\n const sourceLocale = options.sourceLocale ?? (locales.includes('en') ? 'en' : locales[0]!);\n if (!locales.includes(sourceLocale)) {\n throw new PackError(\n 'SOURCE_LOCALE_NOT_FOUND',\n `Source locale \"${sourceLocale}\" not found in ${localesDir} (found: ${locales.join(', ')}).`\n );\n }\n\n const dictionaries: Record<string, Record<string, unknown>> = {};\n for (const locale of locales) {\n let dictionary: Record<string, unknown>;\n if (dirLocales.has(locale)) {\n dictionary = {};\n const folder = path.join(localesDir, locale);\n const files = (await fs.readdir(folder, { withFileTypes: true }))\n .filter((file) => file.isFile() && file.name.endsWith('.json'))\n .map((file) => file.name)\n .sort();\n for (const file of files) {\n const namespace = file.slice(0, -'.json'.length);\n defineOwn(dictionary, namespace, await readJsonObject(path.join(folder, file), projectDir));\n }\n } else {\n dictionary = await readJsonObject(path.join(localesDir, `${locale}.json`), projectDir);\n }\n defineOwn(dictionaries, locale, dictionary);\n }\n\n const info = await resolveBuildInfo({\n cwd: projectDir,\n env: options.env,\n git: options.git,\n includeRepo: options.exposeRepo === true,\n });\n const root =\n info.gitRoot !== null && isInside(info.gitRoot, localesDir) ? info.gitRoot : projectDir;\n const codeKeys = await new KeyScanner({ requireEnabled: false }).scanSourceKeys(projectDir);\n\n if (options.exposeRepo === true && info.repo === null) warnings.push(NO_REPO_WARNING);\n\n const manifest: ShareManifest = {\n format: SHARE_MANIFEST_FORMAT,\n ...(options.exposeRepo === true && info.repo !== null ? { repo: info.repo } : {}),\n defaultBranch: info.defaultBranch,\n branch: info.branch,\n base: info.base,\n localesPath: toPosix(path.relative(root, localesDir)),\n layout,\n sourceLocale,\n locales,\n basePath: options.basePath,\n codeKeys: [...codeKeys].sort(),\n };\n\n return { manifest, dictionaries, warnings };\n}\n\nexport const RELATIVE_BASE_WARNING =\n 'The app base is relative (./), so flag.js is linked per HTML file. Pages served by a client-side route fallback cannot load it; build with an absolute base (--base /path/) if the app has such routes.';\n\nexport interface PackOptions extends Omit<ShareDataOptions, 'basePath'> {\n /** The build output folder: absolute, or relative to `projectDir`. */\n outDir: string;\n /** The raw app base (`/`, `/app/`, `./`). Defaults to the detected stack's base, else `/`. */\n base?: string;\n /** `'auto'` (default) skips injection for Next projects or when `<outDir>/_next` exists. */\n injectHtml?: boolean | 'auto';\n /** The built Studio. Defaults to `resolveStudioDir()`. */\n studioDir?: string;\n}\n\nexport interface PackResult {\n shareDir: string;\n manifest: ShareManifest;\n /** POSIX paths relative to the output folder, sorted. */\n htmlInjected: string[];\n shareUrlPath: string;\n warnings: string[];\n}\n\n/** Where the built Studio may sit: beside the bundle in `dist/`, or `dist/studio` from source. */\nexport function defaultStudioCandidates(): string[] {\n const here = moduleDir();\n return [path.resolve(here, '../studio'), path.resolve(here, '../../dist/studio')];\n}\n\nfunction isDirectory(target: string): boolean {\n try {\n return statSync(target).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** The first candidate that holds a built Studio (`index.html` and `assets/`), or null. */\nexport function resolveStudioDir(candidates: string[] = defaultStudioCandidates()): string | null {\n for (const dir of candidates) {\n if (existsSync(path.join(dir, 'index.html')) && isDirectory(path.join(dir, 'assets'))) {\n return dir;\n }\n }\n return null;\n}\n\n/** True when `shareDir` is absent, or holds a `manifest.json` with a numeric `format`. */\nasync function ownsShareDir(shareDir: string): Promise<boolean> {\n try {\n await fs.lstat(shareDir);\n } catch {\n return true;\n }\n try {\n const manifest: unknown = JSON.parse(\n await fs.readFile(path.join(shareDir, SHARE_MANIFEST_FILE), 'utf-8')\n );\n return isPlainObject(manifest) && typeof manifest['format'] === 'number';\n } catch {\n return false;\n }\n}\n\n/** Every `*.html` file under `outDir` outside the share folder, skipping symlinks. POSIX, sorted. */\nasync function findHtmlFiles(outDir: string, shareDir: string): Promise<string[]> {\n const found: string[] = [];\n const walk = async (dir: string): Promise<void> => {\n for (const entry of await fs.readdir(dir, { withFileTypes: true })) {\n if (entry.isSymbolicLink()) continue;\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (full !== shareDir) await walk(full);\n } else if (entry.isFile() && entry.name.toLowerCase().endsWith('.html')) {\n found.push(toPosix(path.relative(outDir, full)));\n }\n }\n };\n await walk(outDir);\n return found.sort();\n}\n\n/**\n * Writes the share folder (`<outDir>/livelocale/`): the Studio, `manifest.json`, the locale\n * dictionaries and `flag.js`, then links `flag.js` from every app HTML file. Everything is\n * validated before the first write, and nothing outside the share folder is written except\n * the flag tag in HTML.\n */\nexport async function packOutput(options: PackOptions): Promise<PackResult> {\n const {\n outDir: outOption,\n base: baseOption,\n injectHtml = 'auto',\n studioDir: studioOption,\n ...shareOptions\n } = options;\n const projectDir = path.resolve(options.projectDir);\n const outDir = path.resolve(projectDir, outOption);\n if (!isDirectory(outDir)) {\n throw new PackError(\n 'OUT_DIR_NOT_FOUND',\n `Build output not found: ${outDir}. Run your build first.`\n );\n }\n\n const target = detectBuildTarget(projectDir);\n const base = normalizeBase(baseOption ?? target.base ?? '/');\n\n const candidates =\n studioOption !== undefined\n ? [path.resolve(projectDir, studioOption)]\n : defaultStudioCandidates();\n const studioDir = resolveStudioDir(candidates);\n if (studioDir === null) {\n throw new PackError(\n 'STUDIO_NOT_FOUND',\n `LiveLocale Studio files are missing from the installed package (looked in ${candidates.join(', ')}). Reinstall livelocale.`\n );\n }\n\n const data = await collectShareData({ ...shareOptions, projectDir, basePath: basePathOf(base) });\n\n const shareDir = path.join(outDir, SHARE_DIR);\n if (!(await ownsShareDir(shareDir))) {\n throw new PackError(\n 'SHARE_DIR_TAKEN',\n `${toPosix(path.relative(projectDir, outDir))}/${SHARE_DIR}/ already exists and was not written by LiveLocale. Move it away and run again.`\n );\n }\n\n await fs.rm(shareDir, { recursive: true, force: true });\n await fs.cp(studioDir, shareDir, { recursive: true });\n await fs.writeFile(\n path.join(shareDir, SHARE_MANIFEST_FILE),\n JSON.stringify(data.manifest, null, 2) + '\\n',\n 'utf-8'\n );\n const localesDir = path.join(shareDir, SHARE_LOCALES_DIR);\n await fs.mkdir(localesDir, { recursive: true });\n for (const locale of data.manifest.locales) {\n await fs.writeFile(\n path.join(localesDir, `${locale}.json`),\n JSON.stringify(data.dictionaries[locale]),\n 'utf-8'\n );\n }\n await fs.writeFile(path.join(shareDir, SHARE_FLAG_FILE), FLAG_SCRIPT, 'utf-8');\n\n const inject =\n injectHtml === 'auto'\n ? target.kind !== 'next' && !existsSync(path.join(outDir, '_next'))\n : injectHtml;\n const htmlInjected = inject ? await findHtmlFiles(outDir, shareDir) : [];\n for (const rel of htmlInjected) {\n const file = path.join(outDir, ...rel.split('/'));\n const html = await fs.readFile(file, 'utf-8');\n const injected = injectFlagScript(html, flagSrcFor(base, rel));\n if (injected !== html) await fs.writeFile(file, injected, 'utf-8');\n }\n\n const warnings = [...data.warnings];\n if (base.kind === 'relative') warnings.push(RELATIVE_BASE_WARNING);\n\n return {\n shareDir,\n manifest: data.manifest,\n htmlInjected,\n shareUrlPath: shareUrlPathFor(base),\n warnings,\n };\n}\n\n/** Command-line options shared by `livelocale pack` and `livelocale build`. */\nexport interface ShareCliArgs {\n positional: string[];\n dir: string;\n locales?: string;\n source?: string;\n base?: string;\n out?: string;\n exposeRepo: boolean;\n inject: boolean;\n preview: boolean;\n command: string[];\n}\n\nconst VALUE_OPTIONS = {\n '--dir': 'dir',\n '--locales': 'locales',\n '--source': 'source',\n '--base': 'base',\n '--out': 'out',\n} as const;\n\n/**\n * Parses `pack`/`build` arguments (`argv` excludes the command name). Tokens after the first\n * `--` go to `command` verbatim. Throws `PackError('USAGE')` for an unknown option or a\n * missing value.\n */\nexport function parseShareArgs(argv: string[]): ShareCliArgs {\n const args: ShareCliArgs = {\n positional: [],\n dir: '.',\n locales: undefined,\n source: undefined,\n base: undefined,\n out: undefined,\n exposeRepo: false,\n inject: true,\n preview: false,\n command: [],\n };\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (arg === '--') {\n args.command = argv.slice(i + 1);\n break;\n }\n if (Object.prototype.hasOwnProperty.call(VALUE_OPTIONS, arg)) {\n const value = argv[i + 1];\n if (value === undefined || value.startsWith('--')) {\n throw new PackError('USAGE', `${arg} needs a value.`);\n }\n args[VALUE_OPTIONS[arg as keyof typeof VALUE_OPTIONS]] = value;\n i++;\n } else if (arg === '--expose-repo') {\n args.exposeRepo = true;\n } else if (arg === '--no-inject') {\n args.inject = false;\n } else if (arg === '--preview') {\n args.preview = true;\n } else if (arg.startsWith('-') && arg !== '-') {\n throw new PackError('USAGE', `Unknown option \"${arg}\".`);\n } else {\n args.positional.push(arg);\n }\n }\n return args;\n}\n\n/** Runs one command and resolves with its exit code. */\nexport type RunCommand = (\n command: string,\n args: string[],\n options: { cwd: string; env: NodeJS.ProcessEnv }\n) => Promise<number>;\n\nconst WINDOWS_NEEDS_QUOTES = /[\\s\"&|<>^()]/;\n\n/**\n * Quotes one argument for a Windows command line: wrapped in double quotes when it is empty or\n * holds whitespace, a quote or a cmd.exe operator; quotes are escaped with `\\`, and backslashes\n * before a quote (or the closing quote) are doubled.\n */\nexport function quoteWindowsArg(arg: string): string {\n if (arg !== '' && !WINDOWS_NEEDS_QUOTES.test(arg)) return arg;\n let out = '\"';\n let backslashes = 0;\n for (const ch of arg) {\n if (ch === '\\\\') {\n backslashes++;\n continue;\n }\n if (ch === '\"') {\n out += '\\\\'.repeat(backslashes * 2 + 1) + '\"';\n } else {\n out += '\\\\'.repeat(backslashes) + ch;\n }\n backslashes = 0;\n }\n return out + '\\\\'.repeat(backslashes * 2) + '\"';\n}\n\n/**\n * Runs the command with inherited stdio. On Windows it runs one quoted command line through the\n * shell, so `.cmd` shims such as `next` and `vite` resolve. A missing program resolves with 127.\n */\nexport const spawnInherit: RunCommand = (command, args, { cwd, env }) =>\n new Promise((resolve, reject) => {\n const child =\n process.platform === 'win32'\n ? spawn([command, ...args].map(quoteWindowsArg).join(' '), {\n cwd,\n env,\n stdio: 'inherit',\n shell: true,\n })\n : spawn(command, args, { cwd, env, stdio: 'inherit' });\n child.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'ENOENT') resolve(127);\n else reject(error);\n });\n child.on('close', (code) => resolve(code ?? 1));\n });\n\nexport interface BuildCommandOptions extends Omit<PackOptions, 'outDir' | 'injectHtml'> {\n /** The build command and its arguments. */\n command: string[];\n /** Run the command with `LIVELOCALE=preview` and `NEXT_PUBLIC_LIVELOCALE=preview`. */\n preview?: boolean;\n /** The static build output folder. Defaults to the first fresh `outputCandidates` entry. */\n outDir?: string;\n /** Defaults to `spawnInherit`. */\n run?: RunCommand;\n /** Defaults to `Date.now`. */\n now?: () => number;\n}\n\nexport interface BuildResult {\n exitCode: number;\n pack: PackResult | null;\n /** This command's own warnings, then every `pack.warnings` entry. */\n warnings: string[];\n}\n\nexport const BUILD_USAGE = 'Usage: livelocale build [--preview] -- <your build command>';\nconst NEXT_PREVIEW_WARNING =\n 'Next.js pages have no watermarks without --preview; the Studio will open but nothing is editable.';\nconst NEXT_GITIGNORE_WARNING =\n 'Add public/livelocale/ to .gitignore; it is generated on every build.';\n/** How much older than the build start a fresh `index.html` may be (coarse file-system clocks). */\nconst FRESH_SLACK_MS = 2000;\n\nfunction gitignoresShareDir(projectDir: string): boolean {\n let content: string;\n try {\n content = readFileSync(path.join(projectDir, '.gitignore'), 'utf-8');\n } catch {\n return false;\n }\n return parseGitignore(content).ignores(`public/${SHARE_DIR}`, true);\n}\n\nfunction freshOutput(projectDir: string, candidates: string[], startMs: number): string | null {\n for (const candidate of candidates) {\n try {\n const stat = statSync(path.join(projectDir, candidate, 'index.html'));\n if (stat.isFile() && stat.mtimeMs >= startMs - FRESH_SLACK_MS) return candidate;\n } catch {\n // not built here\n }\n }\n return null;\n}\n\n/**\n * `livelocale build`: runs the build command and packs its output. Next.js projects are packed\n * into `public/` first (Next copies it into the build); static stacks are packed after a\n * successful build, into `outDir` or the freshly written output folder.\n */\nexport async function runBuildCommand(options: BuildCommandOptions): Promise<BuildResult> {\n const {\n command,\n preview = false,\n outDir,\n run = spawnInherit,\n now = Date.now,\n ...packOptions\n } = options;\n if (command.length === 0) throw new PackError('USAGE', BUILD_USAGE);\n const projectDir = path.resolve(options.projectDir);\n const target = detectBuildTarget(projectDir);\n const env = options.env ?? process.env;\n const childEnv = preview\n ? { ...env, LIVELOCALE: 'preview', NEXT_PUBLIC_LIVELOCALE: 'preview' }\n : env;\n const runBuild = () => run(command[0]!, command.slice(1), { cwd: projectDir, env: childEnv });\n\n if (target.kind === 'next') {\n const blocking = target.staticExport ? findExportBlockingRoute(projectDir) : null;\n if (blocking !== null) {\n throw new PackError(\n 'NEXT_EXPORT_POST_ROUTE',\n `Next.js static export (output: 'export') cannot build ${blocking}: it exports POST, and export mode only allows GET route handlers. The share link does not need this route. Delete ${blocking} (or move it out of this build) and run again.`\n );\n }\n await fs.mkdir(path.join(projectDir, 'public'), { recursive: true });\n const pack = await packOutput({\n ...packOptions,\n projectDir,\n outDir: 'public',\n injectHtml: false,\n });\n const warnings: string[] = [];\n if (!preview) warnings.push(NEXT_PREVIEW_WARNING);\n if (!gitignoresShareDir(projectDir)) warnings.push(NEXT_GITIGNORE_WARNING);\n const exitCode = await runBuild();\n return { exitCode, pack, warnings: [...warnings, ...pack.warnings] };\n }\n\n const startMs = now();\n const exitCode = await runBuild();\n if (exitCode !== 0) return { exitCode, pack: null, warnings: [] };\n\n const candidates = outputCandidates(target);\n const output = outDir ?? freshOutput(projectDir, candidates, startMs);\n if (output === null) {\n throw new PackError(\n 'OUTPUT_NOT_FOUND',\n `Could not find the build output (looked for a fresh index.html in ${candidates.map((c) => `${c}/`).join(', ')}). Pass --out <dir>.`\n );\n }\n const pack = await packOutput({ ...packOptions, projectDir, outDir: output, injectHtml: 'auto' });\n return { exitCode, pack, warnings: [...pack.warnings] };\n}\n","import { execFile } from 'child_process';\nimport { readFileSync } from 'fs';\nimport * as path from 'path';\nimport { isValidBranchName, isValidRepoSlug } from '../core/change-link.js';\n\n/** Runs git with `args` in `cwd`. Resolves to trimmed stdout, or null on any failure. */\nexport type GitRunner = (args: string[], cwd: string) => Promise<string | null>;\n\n/** The default runner: no shell, no window, and git never prompts for credentials. */\nexport const runGit: GitRunner = (args, cwd) =>\n new Promise((resolve) => {\n try {\n execFile(\n 'git',\n args,\n { cwd, windowsHide: true, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } },\n (error, stdout) => resolve(error ? null : String(stdout).trim())\n );\n } catch {\n resolve(null);\n }\n });\n\nexport interface BuildInfoOptions {\n cwd: string;\n env?: NodeJS.ProcessEnv;\n git?: GitRunner;\n /** Only when true is the repository slug resolved (and `git remote` called). */\n includeRepo?: boolean;\n}\n\nexport interface BuildInfo {\n repo: string | null;\n defaultBranch: string | null;\n branch: string | null;\n base: string | null;\n gitRoot: string | null;\n}\n\nconst SHA_RE = /^[0-9a-f]{40}([0-9a-f]{24})?$/i;\n\ntype Candidate = string | null | undefined | (() => Promise<string | null | undefined>);\n\n/** The first candidate that `accept` maps to a non-null value wins; later ones are never evaluated. */\nasync function firstValid(\n candidates: Candidate[],\n accept: (value: string) => string | null\n): Promise<string | null> {\n for (const candidate of candidates) {\n const value = typeof candidate === 'function' ? await candidate() : candidate;\n if (typeof value !== 'string' || value === '') continue;\n const accepted = accept(value);\n if (accepted !== null) return accepted;\n }\n return null;\n}\n\nconst asBranch = (value: string): string | null => (isValidBranchName(value) ? value : null);\nconst asSha = (value: string): string | null => (SHA_RE.test(value) ? value.toLowerCase() : null);\nconst asSlug = (value: string): string | null => (isValidRepoSlug(value) ? value : null);\n\nfunction readEvent(eventPath: string | undefined): Record<string, unknown> {\n if (!eventPath) return {};\n try {\n const parsed: unknown = JSON.parse(readFileSync(eventPath, 'utf-8'));\n return isRecord(parsed) ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Reads a nested string from a parsed event payload, or undefined. */\nfunction pick(obj: unknown, ...keys: string[]): string | undefined {\n let current = obj;\n for (const key of keys) {\n if (!isRecord(current)) return undefined;\n current = current[key];\n }\n return typeof current === 'string' ? current : undefined;\n}\n\n/**\n * Resolves the repository, branch, commit and default branch of the build from\n * CI variables first and the local git checkout second. An empty or invalid\n * value from one source falls through to the next.\n */\nexport async function resolveBuildInfo(options: BuildInfoOptions): Promise<BuildInfo> {\n const { cwd, env = process.env, git = runGit, includeRepo = false } = options;\n const event = readEvent(env.GITHUB_EVENT_PATH);\n const isPullRequest =\n env.GITHUB_EVENT_NAME === 'pull_request' || env.GITHUB_EVENT_NAME === 'pull_request_target';\n const netlify = env.NETLIFY === 'true';\n const gitlab = env.GITLAB_CI === 'true';\n\n const branch = await firstValid(\n [\n env.GITHUB_HEAD_REF,\n env.GITHUB_REF_TYPE === 'branch' ? env.GITHUB_REF_NAME : null,\n env.VERCEL_GIT_COMMIT_REF,\n env.CF_PAGES_BRANCH,\n netlify ? env.BRANCH : null,\n gitlab ? env.CI_COMMIT_REF_NAME : null,\n async () => {\n const head = await git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd);\n return head === 'HEAD' ? null : head;\n },\n ],\n asBranch\n );\n\n const base = await firstValid(\n [\n isPullRequest ? pick(event, 'pull_request', 'head', 'sha') : null,\n env.GITHUB_SHA,\n env.VERCEL_GIT_COMMIT_SHA,\n env.CF_PAGES_COMMIT_SHA,\n netlify ? env.COMMIT_REF : null,\n gitlab ? env.CI_COMMIT_SHA : null,\n () => git(['rev-parse', 'HEAD'], cwd),\n ],\n asSha\n );\n\n const defaultBranch = await firstValid(\n [\n pick(event, 'repository', 'default_branch'),\n async () => {\n const ref = await git(['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'], cwd);\n return ref?.startsWith('origin/') ? ref.slice('origin/'.length) : null;\n },\n ],\n asBranch\n );\n\n const githubCom =\n env.GITHUB_SERVER_URL === undefined ||\n env.GITHUB_SERVER_URL === '' ||\n env.GITHUB_SERVER_URL === 'https://github.com';\n const repo = includeRepo\n ? await firstValid(\n [\n githubCom ? env.GITHUB_REPOSITORY : null,\n env.VERCEL_GIT_PROVIDER === 'github' &&\n env.VERCEL_GIT_REPO_OWNER &&\n env.VERCEL_GIT_REPO_SLUG\n ? `${env.VERCEL_GIT_REPO_OWNER}/${env.VERCEL_GIT_REPO_SLUG}`\n : null,\n netlify && env.REPOSITORY_URL ? parseGitHubSlug(env.REPOSITORY_URL) : null,\n async () => {\n const remote = await git(['remote', 'get-url', 'origin'], cwd);\n return remote ? parseGitHubSlug(remote) : null;\n },\n ],\n asSlug\n )\n : null;\n\n const top = await git(['rev-parse', '--show-toplevel'], cwd);\n const gitRoot = top ? path.resolve(top) : null;\n\n return { repo, defaultBranch, branch, base, gitRoot };\n}\n\n/**\n * The `owner/repo` slug of a github.com remote, or null. Accepts https, http,\n * ssh and git URLs and the scp-like `git@github.com:owner/repo` form, with or\n * without `.git` and a trailing slash. Credentials in the URL are discarded\n * here and never returned.\n */\nexport function parseGitHubSlug(remote: string): string | null {\n const text = remote.trim();\n let repoPath: string;\n const scp = /^[A-Za-z0-9._-]+@github\\.com:(.*)$/i.exec(text);\n if (scp) {\n repoPath = scp[1] ?? '';\n } else {\n let url: URL;\n try {\n url = new URL(text);\n } catch {\n return null;\n }\n if (!['https:', 'http:', 'ssh:', 'git:'].includes(url.protocol)) return null;\n if (url.hostname.toLowerCase() !== 'github.com') return null;\n repoPath = url.pathname;\n }\n const trimmed = repoPath\n .replace(/^\\/+/, '')\n .replace(/\\/+$/, '')\n .replace(/\\.git$/i, '');\n return isValidRepoSlug(trimmed) ? trimmed : null;\n}\n","import { existsSync, readFileSync } from 'fs';\nimport * as path from 'path';\n\n/** Next.js config file names, in the order they are read. */\nexport const NEXT_CONFIG_FILES = [\n 'next.config.js',\n 'next.config.mjs',\n 'next.config.cjs',\n 'next.config.ts',\n 'next.config.mts',\n];\n\nconst VITE_CONFIG_FILES = [\n 'vite.config.js',\n 'vite.config.mjs',\n 'vite.config.cjs',\n 'vite.config.ts',\n 'vite.config.mts',\n];\n\nexport type BuildTarget =\n | { kind: 'next'; staticExport: boolean; base: string | null } // base = Next basePath\n | { kind: 'cra'; base: string | null } // from package.json homepage ('./' for '.')\n | { kind: 'vite'; base: string | null } // from vite.config base (site path or './')\n | { kind: 'other'; base: null };\n\nconst OUTPUT_EXPORT = /\\boutput\\s*:\\s*['\"`]export['\"`]/;\nconst BASE_PATH = /\\bbasePath\\s*:\\s*['\"`](\\/[^'\"`]*)['\"`]/;\n/** Vite `base`: a site path ('/repo/') or a relative base ('./', ''). Full URLs are not a site path. */\nconst VITE_BASE = /\\bbase\\s*:\\s*['\"`](\\/[^'\"`]*|\\.\\/?|)['\"`]/;\nconst EXPORTS_POST =\n /export\\s+(?:const|let|var|async\\s+function|function)\\s+POST\\b|export\\s*\\{[^}]*\\bPOST\\b[^}]*\\}/;\n\ninterface PackageJson {\n dependencies?: Record<string, unknown>;\n devDependencies?: Record<string, unknown>;\n homepage?: unknown;\n}\n\nfunction readText(file: string): string | null {\n try {\n return readFileSync(file, 'utf-8');\n } catch {\n return null;\n }\n}\n\nfunction readPackageJson(projectDir: string): PackageJson {\n const text = readText(path.join(projectDir, 'package.json'));\n if (text === null) return {};\n try {\n const parsed: unknown = JSON.parse(text);\n return parsed && typeof parsed === 'object' ? (parsed as PackageJson) : {};\n } catch {\n return {};\n }\n}\n\nfunction hasDependency(pkg: PackageJson, name: string): boolean {\n return Boolean(pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]);\n}\n\nfunction firstExisting(projectDir: string, names: string[]): string | null {\n for (const name of names) {\n const file = path.join(projectDir, name);\n if (existsSync(file)) return file;\n }\n return null;\n}\n\n/** Removes block comments and whole-line `//` comments so commented-out options never match. */\nfunction stripComments(source: string): string {\n return source\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .split('\\n')\n .filter((line) => !line.trimStart().startsWith('//'))\n .join('\\n');\n}\n\nfunction craBase(homepage: unknown): string | null {\n if (typeof homepage !== 'string') return null;\n const value = homepage.trim();\n if (value === '.' || value === './') return './';\n if (value.startsWith('/')) return value;\n try {\n return new URL(value).pathname;\n } catch {\n return null;\n }\n}\n\n/** Detects the project's build stack. The first match wins: Next, CRA, Vite, then other. */\nexport function detectBuildTarget(projectDir: string): BuildTarget {\n const pkg = readPackageJson(projectDir);\n\n const nextConfig = firstExisting(projectDir, NEXT_CONFIG_FILES);\n if (nextConfig || hasDependency(pkg, 'next')) {\n const source = stripComments((nextConfig && readText(nextConfig)) ?? '');\n return {\n kind: 'next',\n staticExport: OUTPUT_EXPORT.test(source),\n base: BASE_PATH.exec(source)?.[1] ?? null,\n };\n }\n\n if (hasDependency(pkg, 'react-scripts')) return { kind: 'cra', base: craBase(pkg.homepage) };\n\n if (hasDependency(pkg, 'vite') || firstExisting(projectDir, VITE_CONFIG_FILES)) {\n const viteConfig = firstExisting(projectDir, VITE_CONFIG_FILES);\n const source = stripComments((viteConfig && readText(viteConfig)) ?? '');\n return { kind: 'vite', base: VITE_BASE.exec(source)?.[1] ?? null };\n }\n\n return { kind: 'other', base: null };\n}\n\nconst ROUTE_DIRS = ['app', 'src/app'];\nconst ROUTE_EXTENSIONS = ['ts', 'js', 'mjs', 'tsx', 'jsx'];\n\n/**\n * Finds a LiveLocale Next route that exports POST, which `output: 'export'` cannot build.\n * Returns its POSIX path relative to the project, or null.\n */\nexport function findExportBlockingRoute(projectDir: string): string | null {\n for (const dir of ROUTE_DIRS) {\n for (const ext of ROUTE_EXTENSIONS) {\n const rel = `${dir}/api/livelocale/route.${ext}`;\n const source = readText(path.join(projectDir, rel));\n if (source !== null && EXPORTS_POST.test(source)) return rel;\n }\n }\n return null;\n}\n\n/** Output folders to look for, most likely first. */\nexport function outputCandidates(target: BuildTarget): string[] {\n return target.kind === 'cra' ? ['build', 'dist', 'out'] : ['dist', 'build', 'out'];\n}\n","/** Every reason `livelocale pack`, `livelocale build` or the Vite share step can stop. */\nexport type PackErrorCode =\n | 'USAGE'\n | 'BAD_BASE'\n | 'LOCALES_NOT_FOUND'\n | 'NO_LOCALES'\n | 'SOURCE_LOCALE_NOT_FOUND'\n | 'INVALID_LOCALE_FILE'\n | 'OUT_DIR_NOT_FOUND'\n | 'STUDIO_NOT_FOUND'\n | 'SHARE_DIR_TAKEN'\n | 'NEXT_EXPORT_POST_ROUTE'\n | 'OUTPUT_NOT_FOUND';\n\n/** A pack failure with a stable code and a message that names the fix. */\nexport class PackError extends Error {\n readonly code: PackErrorCode;\n\n constructor(code: PackErrorCode, message: string) {\n super(message);\n this.name = 'PackError';\n this.code = code;\n }\n}\n","import { SHARE_DIR, SHARE_FLAG_FILE } from '../core/share-manifest.js';\nimport { PackError } from './pack-error.js';\n\n/** Where the app's HTML is served from: a site path such as `/app/`, or relative (`./`). */\nexport type AppBase = { kind: 'absolute'; path: string } | { kind: 'relative' };\n\n/** A URL scheme (`https:`) or a protocol-relative start (`//`). */\nconst FULL_URL = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\n/** A Windows drive path (`C:/...`), which Git Bash/MSYS makes from a `/repo/` argument. */\nconst WINDOWS_PATH = /^[A-Za-z]:[\\\\/]/;\n/** One path segment: unreserved characters, a few safe sub-delimiters and valid percent escapes. */\nconst SEGMENT = /^(?:[A-Za-z0-9._~@+-]|%[0-9A-Fa-f]{2})+$/;\n\n/**\n * Turns `--base` / `shareBase` into an `AppBase`. `''`, `.` and `./` are relative; a path\n * starting with `/` is absolute and always ends in `/`. Anything else throws `BAD_BASE`.\n */\nexport function normalizeBase(value: string): AppBase {\n if (value === '' || value === '.' || value === './') return { kind: 'relative' };\n if (WINDOWS_PATH.test(value)) {\n throw new PackError(\n 'BAD_BASE',\n `The app base \"${value}\" is a Windows path. Your shell (Git Bash/MSYS) probably converted a site path such as /repo/ into it. Run the command with MSYS_NO_PATHCONV=1, or from an npm script, and pass the site path, for example --base /app/.`\n );\n }\n if (FULL_URL.test(value)) {\n throw new PackError(\n 'BAD_BASE',\n `The app base \"${value}\" is a full URL. Pass the path your HTML is served from, for example --base /app/ (shareBase in the Vite plugin).`\n );\n }\n const notASitePath = () =>\n new PackError(\n 'BAD_BASE',\n `The app base \"${value}\" is not a site path. Use \"/\", \"/app/\" or \"./\".`\n );\n if (!value.startsWith('/')) throw notASitePath();\n const segments = value.slice(1).split('/');\n if (segments[segments.length - 1] === '') segments.pop();\n for (const segment of segments) {\n if (segment === '.' || segment === '..' || !SEGMENT.test(segment)) throw notASitePath();\n }\n return { kind: 'absolute', path: segments.length === 0 ? '/' : `/${segments.join('/')}/` };\n}\n\n/** The manifest's `basePath`: the absolute path, or null for a relative base. */\nexport function basePathOf(base: AppBase): string | null {\n return base.kind === 'absolute' ? base.path : null;\n}\n\n/** The `src` of the flag tag for the HTML file at `htmlRelPath` (POSIX, relative to the output root). */\nexport function flagSrcFor(base: AppBase, htmlRelPath: string): string {\n const file = `${SHARE_DIR}/${SHARE_FLAG_FILE}`;\n if (base.kind === 'absolute') return `${base.path}${file}`;\n const depth = htmlRelPath.split('/').length - 1;\n return depth === 0 ? `./${file}` : `${'../'.repeat(depth)}${file}`;\n}\n\n/** The share link's path: `<base>livelocale/index.html`, relative when the base is. */\nexport function shareUrlPathFor(base: AppBase): string {\n const page = `${SHARE_DIR}/index.html`;\n return base.kind === 'absolute' ? `${base.path}${page}` : page;\n}\n\nconst EXISTING_FLAG_TAG = /<script\\b[^>]*\\bsrc=\"[^\"]*livelocale\\/flag\\.js\"[^>]*>\\s*<\\/script>/gi;\nconst HEAD_OPEN = /<head(?=[\\s>])[^>]*>/i;\nconst HTML_OPEN = /<html(?=[\\s>])[^>]*>/i;\nconst DOCTYPE = /<!doctype\\b[^>]*>/i;\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Puts `<script src=\"…\"></script>` first in `<head>`, replacing any earlier flag tag, so running\n * it twice changes nothing. Without a `<head>` it goes after `<html…>`, then after the doctype,\n * then at the start.\n */\nexport function injectFlagScript(html: string, src: string): string {\n const tag = `<script src=\"${escapeAttribute(src)}\"></script>`;\n const cleaned = html.replace(EXISTING_FLAG_TAG, '');\n for (const pattern of [HEAD_OPEN, HTML_OPEN, DOCTYPE]) {\n const match = pattern.exec(cleaned);\n if (match) {\n const end = match.index + match[0].length;\n return cleaned.slice(0, end) + tag + cleaned.slice(end);\n }\n }\n return tag + cleaned;\n}\n","/** The `livelocale apply` command: argument parsing and the terminal entry point. */\n\nimport * as path from 'path';\nimport { ApplyInputError, readApplyInput } from './link-input.js';\nimport { runLocalApply } from './local.js';\n\nexport interface ApplyArgs {\n input?: string;\n clipboard: boolean;\n pr: boolean;\n force: boolean;\n dryRun: boolean;\n dir: string;\n locales?: string;\n source?: string;\n}\n\nconst VALUE_OPTIONS = { '--dir': 'dir', '--locales': 'locales', '--source': 'source' } as const;\nconst FLAG_OPTIONS = {\n '--clipboard': 'clipboard',\n '--pr': 'pr',\n '--force': 'force',\n '--dry-run': 'dryRun',\n} as const;\n\n/** Parses the arguments after `apply`. Throws `ApplyInputError` on bad combinations. */\nexport function parseApplyArgs(argv: string[]): ApplyArgs {\n const args: ApplyArgs = {\n input: undefined,\n clipboard: false,\n pr: false,\n force: false,\n dryRun: false,\n dir: '.',\n locales: undefined,\n source: undefined,\n };\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (Object.prototype.hasOwnProperty.call(VALUE_OPTIONS, arg)) {\n const value = argv[i + 1];\n if (value === undefined || value.startsWith('--')) {\n throw new ApplyInputError(`${arg} needs a value.`);\n }\n args[VALUE_OPTIONS[arg as keyof typeof VALUE_OPTIONS]] = value;\n i++;\n } else if (Object.prototype.hasOwnProperty.call(FLAG_OPTIONS, arg)) {\n args[FLAG_OPTIONS[arg as keyof typeof FLAG_OPTIONS]] = true;\n } else if (arg.startsWith('-') && arg !== '-') {\n throw new ApplyInputError(`Unknown option \"${arg}\".`);\n } else if (args.input !== undefined) {\n throw new ApplyInputError('Pass one change link, file or \"-\".');\n } else {\n args.input = arg;\n }\n }\n if (args.clipboard && args.input !== undefined) {\n throw new ApplyInputError('Pass the link or --clipboard, not both.');\n }\n return args;\n}\n\n/** Runs `livelocale apply` and sets `process.exitCode`. Every error is one `❌` line. */\nexport async function runApplyCommand(argv: string[]): Promise<void> {\n try {\n const args = parseApplyArgs(argv);\n const input = await readApplyInput(args.input, {\n cwd: process.cwd(),\n clipboard: args.clipboard,\n });\n const result = await runLocalApply({\n projectDir: path.resolve(args.dir),\n localesPath: args.locales,\n sourceLocale: args.source,\n input,\n force: args.force,\n dryRun: args.dryRun,\n pr: args.pr,\n });\n process.exitCode = result.exitCode;\n } catch (err) {\n console.error(`❌ ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n}\n","import { execFile } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n/** The largest input `apply` reads from an argument, a file, stdin or the clipboard. */\nexport const MAX_APPLY_INPUT_BYTES = 1_048_576;\n\nconst TOO_LARGE_MESSAGE = 'The input is larger than 1 MB.';\nconst NO_INPUT_MESSAGE =\n 'Pass the change link, a file that holds it, \"-\" to read stdin, or --clipboard. ' +\n '(cmd.exe cuts arguments at 8,191 characters; use --clipboard or a file for long links.)';\nconst NO_CLIPBOARD_MESSAGE =\n 'Could not read the clipboard. Save the change link to a file and pass the file instead.';\n\n/** A problem with what `apply` was asked to read. Its message is safe to print. */\nexport class ApplyInputError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ApplyInputError';\n }\n}\n\nexport interface ApplyInputOptions {\n /** Relative file paths resolve against this directory. */\n cwd: string;\n /** Read the clipboard instead of the argument. */\n clipboard?: boolean;\n /** Read for `-`. Defaults to `process.stdin`. */\n stdin?: NodeJS.ReadableStream;\n /** Defaults to {@link readClipboard}. */\n readClipboard?: () => Promise<string>;\n}\n\nfunction checkSize(text: string): string {\n if (Buffer.byteLength(text, 'utf8') > MAX_APPLY_INPUT_BYTES) {\n throw new ApplyInputError(TOO_LARGE_MESSAGE);\n }\n return text;\n}\n\nasync function readStream(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of stream) {\n const bytes = typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : Buffer.from(chunk);\n size += bytes.length;\n if (size > MAX_APPLY_INPUT_BYTES) throw new ApplyInputError(TOO_LARGE_MESSAGE);\n chunks.push(bytes);\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n\n/** The file `arg` names when it is an existing file under `cwd`, else null. */\nfunction existingFile(arg: string, cwd: string): string | null {\n try {\n const resolved = path.resolve(cwd, arg);\n return fs.statSync(resolved, { throwIfNoEntry: false })?.isFile() ? resolved : null;\n } catch {\n // A link is rarely a valid path (too long, or characters the OS rejects).\n return null;\n }\n}\n\n/**\n * Returns the raw text that holds the link; decodeChangeLink finds the token\n * (fenced block first). `-` reads stdin, an existing file (relative to `cwd`)\n * is read, and any other argument is the text itself.\n */\nexport async function readApplyInput(\n arg: string | undefined,\n options: ApplyInputOptions\n): Promise<string> {\n if (options.clipboard) return checkSize(await (options.readClipboard ?? readClipboard)());\n if (arg === undefined || arg === '') throw new ApplyInputError(NO_INPUT_MESSAGE);\n if (arg === '-') return readStream(options.stdin ?? process.stdin);\n\n const file = existingFile(arg, options.cwd);\n if (file === null) return checkSize(arg);\n if (fs.statSync(file).size > MAX_APPLY_INPUT_BYTES) throw new ApplyInputError(TOO_LARGE_MESSAGE);\n return checkSize(fs.readFileSync(file, 'utf8'));\n}\n\ntype ClipboardCommand = [command: string, args: string[]];\n\nfunction clipboardCommands(platform: NodeJS.Platform): ClipboardCommand[] {\n if (platform === 'win32') {\n return [\n ['powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', 'Get-Clipboard -Raw']],\n ];\n }\n if (platform === 'darwin') return [['pbpaste', []]];\n return [\n ['wl-paste', ['--no-newline']],\n ['xclip', ['-selection', 'clipboard', '-o']],\n ['xsel', ['--clipboard', '--output']],\n ];\n}\n\nconst TOO_LARGE = Symbol('too large');\n\n/** Resolves to stdout, null when the command fails, or TOO_LARGE. */\nfunction run(\n execFileImpl: typeof execFile,\n [command, args]: ClipboardCommand\n): Promise<string | null | typeof TOO_LARGE> {\n return new Promise((resolve) => {\n try {\n execFileImpl(\n command,\n args,\n { encoding: 'utf8', windowsHide: true, maxBuffer: MAX_APPLY_INPUT_BYTES + 1 },\n (error, stdout) => {\n const code = (error as NodeJS.ErrnoException | null)?.code;\n if (code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER') resolve(TOO_LARGE);\n else resolve(error ? null : String(stdout));\n }\n );\n } catch {\n resolve(null);\n }\n });\n}\n\n/**\n * Reads the system clipboard: PowerShell on Windows, `pbpaste` on macOS, and\n * `wl-paste`, then `xclip`, then `xsel` on Linux. Throws `ApplyInputError`\n * when no command works or the text is larger than 1 MB.\n */\nexport async function readClipboard(\n execFileImpl: typeof execFile = execFile,\n platform: NodeJS.Platform = process.platform\n): Promise<string> {\n for (const command of clipboardCommands(platform)) {\n const text = await run(execFileImpl, command);\n if (text === TOO_LARGE) throw new ApplyInputError(TOO_LARGE_MESSAGE);\n if (text !== null) return checkSize(text);\n }\n throw new ApplyInputError(NO_CLIPBOARD_MESSAGE);\n}\n","/**\n * `livelocale apply` into the working tree: decodes a change link, plans every\n * edit against the project's own locale files and writes the edits that pass.\n */\n\nimport { execFile, spawn } from 'child_process';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { decodeChangeLink } from '../../core/change-link.js';\nimport { nodeInflate } from '../../core/change-link-node.js';\nimport { planApply, type ApplyPlan, type LocaleTarget } from '../../core/apply-plan.js';\nimport { isValidLocaleFormat } from '../../core/validate.js';\nimport { FileMutator } from '../../server/file-mutator.js';\nimport { GitClient } from '../../server/git-client.js';\nimport { runCheck } from '../check.js';\nimport { ApplyInputError } from './link-input.js';\nimport {\n renderCommitMessage,\n renderPullRequestBody,\n renderTerminalSummary,\n summarizeCheck,\n} from './report.js';\n\n/** Runs git with `args` in `cwd` and resolves with stdout; throws on a non-zero exit. */\nexport type GitExec = (\n args: string[],\n cwd: string,\n opts?: { inherit?: boolean }\n) => Promise<string>;\n\n/** Runs the GitHub CLI with `args` in `cwd` and resolves with stdout. */\nexport type GhExec = (args: string[], cwd: string) => Promise<string>;\n\nexport interface LocalApplyOptions {\n projectDir: string;\n /** Locales directory relative to the project (default `locales`). */\n localesPath?: string;\n /** Default: `en` when present, else the first locale. */\n sourceLocale?: string;\n /** Text that holds the link (from readApplyInput). */\n input: string;\n force?: boolean;\n dryRun?: boolean;\n pr?: boolean;\n log?: (line: string) => void;\n exec?: { git?: GitExec; gh?: GhExec };\n /** The clock for the branch name. Default `() => new Date()`. */\n now?: () => Date;\n}\n\nexport interface LocalApplyResult {\n plan: ApplyPlan;\n /** Project-relative POSIX paths of the locale files written. */\n written: string[];\n branch?: string;\n prUrl?: string;\n exitCode: 0 | 1;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nasync function readTarget(\n mutator: FileMutator,\n localesDir: string,\n locale: string\n): Promise<LocaleTarget> {\n if (!isValidLocaleFormat(locale)) return null;\n const dir = path.join(localesDir, locale);\n let layout: 'flat' | 'namespaced';\n if (fs.statSync(dir, { throwIfNoEntry: false })?.isDirectory()) {\n layout = 'namespaced';\n } else if (fs.statSync(`${dir}.json`, { throwIfNoEntry: false })?.isFile()) {\n layout = 'flat';\n } else {\n return null;\n }\n const dict: unknown = await mutator.readLocale(localesDir, locale);\n if (!isPlainObject(dict)) {\n throw new Error(`The \"${locale}\" locale file is not a JSON object.`);\n }\n return { layout, dict };\n}\n\n/** The file `updateLocaleKey` writes for `key`, relative to the project, in POSIX form. */\nfunction fileFor(\n localesPath: string,\n layout: 'flat' | 'namespaced',\n locale: string,\n key: string\n): string {\n const rel =\n layout === 'flat'\n ? path.join(localesPath, `${locale}.json`)\n : path.join(localesPath, locale, `${key.slice(0, key.indexOf('.'))}.json`);\n return path.normalize(rel).split(path.sep).join('/');\n}\n\nconst PR_TITLE = 'i18n: LiveLocale changes';\nconst GITHUB_REMOTE_RE = /github\\.com[:/]([\\w.-]+\\/[\\w.-]+?)(?:\\.git)?$/;\n\n/** Runs git without a shell or a credential prompt; `inherit` streams its output to the user. */\nconst defaultGit: GitExec = (args, cwd, opts) => {\n const env = { ...process.env, GIT_TERMINAL_PROMPT: '0' };\n if (opts?.inherit) {\n return new Promise((resolve, reject) => {\n const child = spawn('git', args, { cwd, env, stdio: 'inherit', windowsHide: true });\n child.on('error', reject);\n child.on('close', (code) =>\n code === 0 ? resolve('') : reject(new Error(`git ${args[0]} failed (exit ${code}).`))\n );\n });\n }\n return new Promise((resolve, reject) => {\n execFile(\n 'git',\n args,\n { cwd, env, windowsHide: true, maxBuffer: 16 * 1024 * 1024 },\n (error, stdout) => (error ? reject(error) : resolve(String(stdout)))\n );\n });\n};\n\n/** Runs the GitHub CLI without a shell. */\nconst defaultGh: GhExec = (args, cwd) =>\n new Promise((resolve, reject) => {\n execFile('gh', args, { cwd, windowsHide: true }, (error, stdout, stderr) =>\n error ? reject(Object.assign(error, { stderr: String(stderr) })) : resolve(String(stdout))\n );\n });\n\n/** `YYYYMMDD-HHmmss` in UTC. */\nfunction utcStamp(date: Date): string {\n const p = (n: number) => String(n).padStart(2, '0');\n return (\n `${date.getUTCFullYear()}${p(date.getUTCMonth() + 1)}${p(date.getUTCDate())}-` +\n `${p(date.getUTCHours())}${p(date.getUTCMinutes())}${p(date.getUTCSeconds())}`\n );\n}\n\n/** Resolves with the command's stdout, or null when it fails. */\nasync function tryRun(run: () => Promise<string>): Promise<string | null> {\n try {\n return await run();\n } catch {\n return null;\n }\n}\n\n/** The first free `livelocale/apply-<stamp>[-n]` name, locally and at origin's push URL. */\nasync function pickBranchName(git: GitExec, root: string, stamp: string): Promise<string> {\n const pushUrl = (\n await tryRun(() => git(['remote', 'get-url', '--push', 'origin'], root))\n )?.trim();\n const taken = async (name: string): Promise<boolean> => {\n const local = await tryRun(() =>\n git(['rev-parse', '--verify', '--quiet', `refs/heads/${name}`], root)\n );\n if (local !== null) return true;\n if (!pushUrl) return false;\n // A failing ls-remote counts as \"no such branch\": the push never forces, so it still fails.\n const remote = await tryRun(() =>\n git(['ls-remote', '--heads', pushUrl, `refs/heads/${name}`], root)\n );\n return remote !== null && remote.trim() !== '';\n };\n const base = `livelocale/apply-${stamp}`;\n let name = base;\n for (let n = 2; await taken(name); n++) name = `${base}-${n}`;\n return name;\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** Writes every `apply` edit and returns the project-relative files written. */\nasync function writeEdits(\n mutator: FileMutator,\n plan: ApplyPlan,\n targets: Map<string, LocaleTarget>,\n localesDir: string,\n localesPath: string\n): Promise<string[]> {\n const written: string[] = [];\n for (const edit of plan.edits) {\n if (edit.status !== 'apply') continue;\n await mutator.updateLocaleKey(localesDir, edit.locale, edit.key, edit.to);\n const file = fileFor(localesPath, targets.get(edit.locale)!.layout, edit.locale, edit.key);\n if (!written.includes(file)) written.push(file);\n }\n return written;\n}\n\nfunction exitCodeFor(plan: ApplyPlan): 0 | 1 {\n const c = plan.counts;\n return c.conflict + c.invalid + c['needs-force'] > 0 ? 1 : 0;\n}\n\n/** The repository root and current branch; refuses a detached HEAD or a dirty locales folder. */\nasync function preparePullRequest(\n git: GitExec,\n projectDir: string,\n localesDir: string\n): Promise<{ root: string; original: string }> {\n const top = (await tryRun(() => git(['rev-parse', '--show-toplevel'], projectDir)))?.trim();\n if (!top) throw new ApplyInputError('apply --pr needs a git repository.');\n const root = path.resolve(top);\n const original = (\n await tryRun(() => git(['symbolic-ref', '--quiet', '--short', 'HEAD'], root))\n )?.trim();\n if (!original) throw new ApplyInputError('Check out a branch first.');\n const status = await new GitClient().status(localesDir);\n if (status.changes.length > 0) {\n const rel = path.relative(root, localesDir).split(path.sep).join('/') || '.';\n throw new ApplyInputError(\n `Commit or stash the changes under ${rel} first; apply --pr commits everything in that folder.`\n );\n }\n return { root, original };\n}\n\n/**\n * Runs `gh pr create`. Undefined when gh is missing or fails (not logged in, a pull\n * request already exists, ...): the branch is already pushed, so the caller prints the\n * manual fallback instead of failing.\n */\nasync function createPullRequest(\n log: (line: string) => void,\n gh: GhExec,\n root: string,\n base: string,\n head: string,\n body: string\n): Promise<string | undefined> {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'livelocale-pr-'));\n const bodyFile = path.join(tmpDir, 'body.md');\n try {\n fs.writeFileSync(bodyFile, body, 'utf-8');\n const out = await gh(\n [\n 'pr',\n 'create',\n '--base',\n base,\n '--head',\n head,\n '--title',\n PR_TITLE,\n '--body-file',\n bodyFile,\n ],\n root\n );\n const lines = out\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean);\n return lines[lines.length - 1];\n } catch (err) {\n if ((err as NodeJS.ErrnoException | undefined)?.code !== 'ENOENT') {\n const stderr = (err as { stderr?: unknown } | undefined)?.stderr;\n const reason =\n typeof stderr === 'string' && stderr.trim() ? stderr.trim() : errorMessage(err);\n log(`gh could not open the pull request: ${reason}`);\n }\n return undefined;\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n}\n\n/**\n * Plans the link's edits against `<projectDir>/<localesPath>` and writes every\n * `apply` edit (unless `dryRun`). Logs the terminal summary only, never values.\n * With `pr`, writes them on a new `livelocale/apply-<stamp>` branch, commits,\n * pushes, opens a pull request with `gh` when origin is GitHub, and switches back.\n * Throws `ChangeLinkError` for a damaged link.\n */\nexport async function runLocalApply(options: LocalApplyOptions): Promise<LocalApplyResult> {\n const log = options.log ?? ((line: string) => console.log(line));\n const set = await decodeChangeLink(options.input, nodeInflate);\n\n const localesPath = options.localesPath ?? 'locales';\n const localesDir = path.resolve(options.projectDir, localesPath);\n if (!fs.statSync(localesDir, { throwIfNoEntry: false })?.isDirectory()) {\n throw new ApplyInputError(`No locales folder at ${localesPath}.`);\n }\n\n const pr = options.pr === true && options.dryRun !== true;\n const git = options.exec?.git ?? defaultGit;\n const repo = pr ? await preparePullRequest(git, options.projectDir, localesDir) : undefined;\n if (repo && set.branch !== '' && set.branch !== repo.original) {\n log(\n `The link was made from the branch \\`${set.branch}\\`; the pull request targets \\`${repo.original}\\`.`\n );\n }\n\n // The local developer runs this, so the CLI-only option is allowed here.\n // Quiet: the terminal summary is the only output.\n const mutator = new FileMutator({ requireEnabled: false, quiet: true });\n let sourceLocale = options.sourceLocale;\n if (sourceLocale === undefined) {\n const locales = await mutator.listLocales(localesDir);\n sourceLocale = locales.includes('en') ? 'en' : (locales[0] ?? 'en');\n }\n if (set.src !== sourceLocale) {\n log(\n `The link says the source locale is \\`${set.src}\\`; using \\`${sourceLocale}\\` (pass --source to change).`\n );\n }\n\n const targets = new Map<string, LocaleTarget>();\n for (const locale of new Set([sourceLocale, ...set.edits.map((e) => e.locale)])) {\n targets.set(locale, await readTarget(mutator, localesDir, locale));\n }\n\n const plan = planApply({\n edits: set.edits,\n sourceLocale,\n targets,\n allowForce: options.force === true,\n });\n const exitCode = exitCodeFor(plan);\n\n if (!repo || plan.counts.apply === 0) {\n const written =\n repo || options.dryRun\n ? []\n : await writeEdits(mutator, plan, targets, localesDir, localesPath);\n log(renderTerminalSummary(plan));\n return { plan, written, exitCode };\n }\n\n const { root, original } = repo;\n const now = options.now ?? (() => new Date());\n const branch = await pickBranchName(git, root, utcStamp(now()));\n await git(['switch', '-c', branch], root);\n\n try {\n const written = await writeEdits(mutator, plan, targets, localesDir, localesPath);\n log(renderTerminalSummary(plan));\n\n let checkSummary: string;\n try {\n const report = await runCheck({\n projectDir: options.projectDir,\n localesPath: localesDir,\n sourceLocale,\n unused: false,\n });\n const edited = plan.edits\n .filter((edit) => edit.status === 'apply')\n .map((edit): [string, string] => [edit.locale, edit.key]);\n checkSummary = summarizeCheck(report, edited);\n } catch (err) {\n checkSummary = `Check could not run: ${errorMessage(err)}`;\n }\n\n await new GitClient().commit(localesDir, renderCommitMessage({ plan, by: set.by }));\n await git(['push', '-u', 'origin', branch], root, { inherit: true });\n\n const remote = (await tryRun(() => git(['remote', 'get-url', 'origin'], root)))?.trim();\n const slug = remote ? GITHUB_REMOTE_RE.exec(remote)?.[1] : undefined;\n let prUrl: string | undefined;\n if (slug) {\n const body = renderPullRequestBody({\n plan,\n by: set.by,\n note: set.note,\n checkSummary,\n target: { branch: original, isDefault: false, reason: 'local' },\n });\n prUrl = await createPullRequest(\n log,\n options.exec?.gh ?? defaultGh,\n root,\n original,\n branch,\n body\n );\n }\n if (prUrl) {\n log(`Opened ${prUrl}`);\n } else {\n log(`Pushed ${branch}. Open a pull/merge request from it into ${original}.`);\n if (slug) log(`https://github.com/${slug}/compare/${original}...${branch}?expand=1`);\n }\n\n await git(['switch', original], root);\n return { plan, written, branch, prUrl, exitCode };\n } catch (err) {\n log(`You are on ${branch}; your changes are committed there.`);\n throw err;\n }\n}\n","/**\n * The Node inflater for `lc1.` change links, used by `livelocale apply`.\n *\n * Node-only: nothing under `src/studio` or `src/client` may import this file,\n * as tests/unit/core-browser-safe.test.ts checks. Browser code uses\n * `streamInflate` from `./change-link.js`.\n */\n\nimport { inflateSync } from 'zlib';\nimport { ChangeLinkError, type Inflater, MAX_INFLATED_BYTES } from './change-link.js';\n\n/** The same copy `decodeChangeLink` shows for a damaged link. */\nconst CORRUPT_MESSAGE =\n 'This change link is damaged or incomplete. Ask the sender to send the file instead.';\n\n/** The same copy `decodeChangeLink` shows for a payload over the cap. */\nconst TOO_LARGE_MESSAGE = `A change link holds at most ${MAX_INFLATED_BYTES / 1024} KB of text. Send the changes in smaller links.`;\n\n/** What `inflateSync` returns with `info: true`. Node's typings describe only the plain Buffer. */\ntype InflateInfo = { buffer: Buffer; engine: { bytesWritten: number } };\n\n/**\n * Inflates the zlib format with `zlib.inflateSync`, which stops once the\n * output passes `maxOutputLength` instead of growing past it. Throws\n * `TOO_LARGE` above the cap, and `CORRUPT` on bad, truncated or empty data\n * and on bytes after the end of the zlib stream, which `inflateSync` would\n * otherwise ignore.\n */\nexport const nodeInflate: Inflater = async (bytes, maxOutputLength) => {\n let result: InflateInfo;\n try {\n result = inflateSync(bytes, { maxOutputLength, info: true }) as unknown as InflateInfo;\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ERR_BUFFER_TOO_LARGE') {\n throw new ChangeLinkError('TOO_LARGE', TOO_LARGE_MESSAGE);\n }\n throw new ChangeLinkError('CORRUPT', CORRUPT_MESSAGE);\n }\n if (result.engine.bytesWritten !== bytes.length) {\n throw new ChangeLinkError('CORRUPT', CORRUPT_MESSAGE);\n }\n return result.buffer;\n};\n","/**\n * Zero-Width Watermarking Encoder/Decoder\n *\n * Maps translation keys into invisible Unicode zero-width characters and\n * prepends them as a binary watermark onto the translation string.\n *\n * Delimiters:\n * \\u200C – Zero-Width Non-Joiner (ZWNJ) → boundary start/end marker\n * \\u200B – Zero-Width Space (ZWS) → binary bit 0\n * \\u200D – Zero-Width Joiner (ZWJ) → binary bit 1\n *\n * The delimiters touch the visible text, so they must be non-joining: a ZWJ\n * there is \"join-causing\" and makes the first Arabic letter take its connected\n * form, as if a hidden letter came before it. Bits never touch a letter.\n *\n * The watermark is strictly prepended so it survives downstream truncation\n * (e.g., text.substring()) that removes only from the right.\n */\n\nconst DELIM = '\\u200C'; // ZWNJ – boundary delimiter (non-joining)\nconst BIT_0 = '\\u200B'; // ZWS – represents bit 0\nconst BIT_1 = '\\u200D'; // ZWJ – represents bit 1\n\n/** First character of every watermark; a cheap pre-check before decoding. */\nexport const WATERMARK_DELIMITER = DELIM;\n\nconst ZW_RE = /[\\u200B\\u200C\\u200D]/g;\n\n/** A complete watermark anywhere in a string: delimiter, whole bytes of bits, delimiter. */\nconst WATERMARK_RE = /\\u200C(?:[\\u200B\\u200D]{8})+\\u200C/g;\n\n/** Encodes a translation key as an invisible watermark prefix on `text`. */\nexport function encodeKey(text: string, key: string): string {\n const bytes = new TextEncoder().encode(key);\n let bits = '';\n for (const byte of bytes) {\n bits += byte.toString(2).padStart(8, '0');\n }\n\n let watermark = DELIM;\n for (const bit of bits) {\n watermark += bit === '0' ? BIT_0 : BIT_1;\n }\n watermark += DELIM;\n\n return watermark + text;\n}\n\n/**\n * Decodes a watermark prefix from `text`.\n *\n * Returns `{ key, cleanText }` where `cleanText` is the original visible\n * text with the watermark stripped. If no valid watermark is found,\n * returns `null`.\n */\nexport function decodeKey(text: string): { key: string; cleanText: string } | null {\n if (!text.startsWith(DELIM)) return null;\n\n const end = text.indexOf(DELIM, 1);\n if (end === -1) return null;\n\n const bitsStr = text.slice(1, end);\n // Validate: every char must be a known ZW bit\n for (const ch of bitsStr) {\n if (ch !== BIT_0 && ch !== BIT_1) return null;\n }\n\n if (bitsStr.length !== 0 && bitsStr.length % 8 !== 0) return null;\n\n const bytes: number[] = [];\n for (let i = 0; i < bitsStr.length; i += 8) {\n let byte = 0;\n for (let j = 0; j < 8; j++) {\n byte = (byte << 1) | (bitsStr[i + j] === BIT_1 ? 1 : 0);\n }\n bytes.push(byte);\n }\n\n try {\n const key = new TextDecoder().decode(new Uint8Array(bytes));\n const cleanText = text.slice(end + 1);\n return { key, cleanText };\n } catch {\n return null;\n }\n}\n\n/**\n * Strips a valid watermark *prefix* from `text`, leaving any legitimate\n * zero-width characters inside the visible text untouched.\n *\n * ZWNJ (\\u200C) and ZWSP (\\u200B) are valid orthography in Persian, Urdu,\n * Thai, and other scripts — a blanket removal would silently corrupt real\n * translations. Only the decoded watermark prefix is removed.\n */\nexport function stripWatermark(text: string): string {\n const decoded = decodeKey(text);\n if (decoded) return decoded.cleanText;\n return text;\n}\n\n/**\n * Aggressively removes every zero-width character from `text`.\n *\n * This also removes ZWNJ and ZWSP that Persian, Urdu and Thai text needs, so\n * prefer `removeWatermarks` for user-visible text and `stripWatermark` for\n * translation content.\n */\nexport function sanitizeZeroWidth(text: string): string {\n return text.replace(ZW_RE, '');\n}\n\n/**\n * Removes every complete watermark from `text`, wherever it occurs, and keeps\n * all other zero-width characters. Persian and Urdu use ZWNJ inside words and\n * Thai uses ZWSP, so stripping every zero-width character would corrupt them.\n */\nexport function removeWatermarks(text: string): string {\n return text.replace(WATERMARK_RE, '');\n}\n\n/** True when `text` contains at least one complete watermark. */\nexport function containsWatermark(text: string): boolean {\n WATERMARK_RE.lastIndex = 0;\n const found = WATERMARK_RE.test(text);\n WATERMARK_RE.lastIndex = 0;\n return found;\n}\n\n/**\n * Returns true if `text` begins with a valid watermark prefix.\n */\nexport function hasWatermark(text: string): boolean {\n return text.startsWith(DELIM);\n}\n\n/**\n * Deeply strips watermark prefixes from a value: strings are cleaned with\n * `stripWatermark`, arrays and plain objects are rebuilt with cleaned members,\n * everything else is returned as-is. The input is never mutated.\n *\n * Use it wherever a translated string must be compared, measured, serialized\n * or handed to code that is not display-only, e.g. `unwrap(t('yes')) === 'Yes'`.\n */\nexport function unwrap<T>(value: T): T {\n if (typeof value === 'string') return stripWatermark(value) as T;\n if (Array.isArray(value)) return value.map((item) => unwrap(item)) as T;\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>)) {\n out[key] = unwrap((value as Record<string, unknown>)[key]);\n }\n return out as T;\n }\n return value;\n}\n","import { DANGEROUS_KEY_SEGMENTS } from './validate.js';\n\n/** RULE SRV-003: deeper key paths are rejected to keep recursion bounded. */\nexport const MAX_KEY_DEPTH = 30;\n\n/**\n * Sets `value` at the dot-separated `keyPath` inside `obj`, creating\n * intermediate objects as needed. Rejects paths deeper than `MAX_KEY_DEPTH`\n * and any segment that could pollute `Object.prototype` (RULE SEC-005).\n */\nexport function setNestedProperty(obj: Record<string, any>, keyPath: string, value: string): void {\n const keys = keyPath.split('.');\n\n if (keys.length > MAX_KEY_DEPTH) {\n throw new Error(\n `[livelocale] Key depth limit exceeded. Maximum depth is ${MAX_KEY_DEPTH} levels.`\n );\n }\n\n if (keys.some((k) => DANGEROUS_KEY_SEGMENTS.has(k))) {\n throw new Error(\n `[livelocale] Forbidden key segment in path: \"${keyPath}\". Segment names like __proto__, constructor, and prototype are not allowed.`\n );\n }\n\n let current = obj;\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i]!;\n\n if (i === keys.length - 1) {\n current[key] = value;\n return;\n }\n\n if (\n !(key in current) ||\n current[key] === null ||\n typeof current[key] !== 'object' ||\n Array.isArray(current[key])\n ) {\n current[key] = {};\n }\n\n current = current[key];\n }\n}\n\n/** The outcome of reading a dotted key without writing to it. */\nexport type KeyLookup =\n | { state: 'string'; value: string }\n | { state: 'missing' }\n | { state: 'occupied' };\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasOwn(obj: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\n/**\n * Reads the string at the dot-separated `keyPath` inside `dict` through own\n * properties only, following the same nested walk `setNestedProperty` writes\n * through.\n *\n * - `string`: the path leads to a string value.\n * - `missing`: a segment is absent, or `dict` is not a plain object. Writing\n * here creates the key.\n * - `occupied`: a write would overwrite data or create a duplicate the app\n * never reads. That is an intermediate value that is not a plain object, a\n * final value that is not a string, or, at any level, an own property named\n * exactly like the rest of the dotted path (a literal key such as `\"a.b\"`).\n */\nexport function lookupKey(dict: unknown, keyPath: string): KeyLookup {\n if (!isPlainObject(dict)) return { state: 'missing' };\n\n const segments = keyPath.split('.');\n const leaf = segments.length - 1;\n let current = dict;\n\n for (let i = 0; i < leaf; i++) {\n if (hasOwn(current, segments.slice(i).join('.'))) return { state: 'occupied' };\n\n const segment = segments[i]!;\n if (!hasOwn(current, segment)) return { state: 'missing' };\n\n const next = current[segment];\n if (!isPlainObject(next)) return { state: 'occupied' };\n current = next;\n }\n\n const key = segments[leaf]!;\n if (!hasOwn(current, key)) return { state: 'missing' };\n\n const value = current[key];\n return typeof value === 'string' ? { state: 'string', value } : { state: 'occupied' };\n}\n\n/**\n * Detects the indentation unit of an existing JSON document so rewrites keep\n * the project's style (tabs, 2 or 4 spaces). Defaults to two spaces.\n */\nexport function detectJsonIndent(content: string): string {\n const match = /^([ \\t]+)\"/m.exec(content);\n if (!match) return ' ';\n const ws = match[1]!;\n return ws.includes('\\t') ? '\\t' : ws;\n}\n\n/**\n * Serializes `data` the way the original `content` was formatted: same\n * indentation unit and the same presence or absence of a trailing newline.\n * New documents get two spaces and a trailing newline.\n */\nexport function stringifyLike(data: unknown, content: string | null): string {\n const indent = content === null ? ' ' : detectJsonIndent(content);\n const trailing = content === null || content.endsWith('\\n') ? '\\n' : '';\n return JSON.stringify(data, null, indent) + trailing;\n}\n\n/** Flattens a nested dictionary into dot-separated leaf keys. */\nexport function flattenKeys(obj: unknown, prefix = '', out: Set<string> = new Set()): Set<string> {\n if (!obj || typeof obj !== 'object') return out;\n for (const key of Object.keys(obj as Record<string, unknown>)) {\n const value = (obj as Record<string, unknown>)[key];\n const full = prefix ? `${prefix}.${key}` : key;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n flattenKeys(value, full, out);\n } else {\n out.add(full);\n }\n }\n return out;\n}\n","/**\n * The write rules every translation save must pass, in one browser-safe place.\n *\n * The mutation router, the Studio's static transport and `livelocale apply`\n * all call `validateWrite`, so a value accepted by one is accepted by all.\n * `validateEdit` adds what a write needs when its caller holds the locale\n * files: the reference from the source locale and the structure guard.\n */\n\nimport { lookupKey } from './json-path.js';\nimport { comparePlaceholders, validateMessageSyntax } from './placeholders.js';\nimport {\n isSafeKeyPath,\n isValidKeyFormat,\n isValidLocaleFormat,\n isValidValueFormat,\n} from './validate.js';\n\nexport type WriteRuleCode =\n | 'INVALID_LOCALE_FORMAT'\n | 'INVALID_KEY_FORMAT'\n | 'INVALID_VALUE_FORMAT'\n | 'MESSAGE_SYNTAX'\n | 'PLACEHOLDER_MISMATCH'\n | 'KEY_NOT_A_STRING';\n\nexport interface WriteAccepted {\n ok: true;\n locale: string;\n key: string;\n value: string;\n}\n\nexport interface WriteRejected {\n ok: false;\n /** 422 means that `force` would let the write through. */\n status: 400 | 409 | 422;\n code: WriteRuleCode;\n error: string;\n /** Only for PLACEHOLDER_MISMATCH. */\n details?: { missing: string[]; extra: string[] };\n}\n\nexport type WriteVerdict = WriteAccepted | WriteRejected;\n\nexport interface WriteRuleOptions {\n /** Text whose placeholders the value must keep. null, undefined or '' skips the parity check. */\n reference?: string | null;\n /** Skips only the 422 rules (syntax and parity). The format rules always apply. */\n force?: boolean;\n}\n\nconst reject = (\n status: WriteRejected['status'],\n code: WriteRuleCode,\n error: string\n): WriteRejected => ({\n ok: false,\n status,\n code,\n error,\n});\n\n/**\n * Checks one write in a fixed order: locale, key format, key safety, value,\n * then (unless forced) message syntax and placeholder parity. Returns the\n * first rule that fails, or the narrowed write.\n */\nexport function validateWrite(\n input: { locale: unknown; key: unknown; value: unknown },\n options: WriteRuleOptions = {}\n): WriteVerdict {\n const { locale, key, value } = input;\n\n if (!isValidLocaleFormat(locale)) {\n return reject(400, 'INVALID_LOCALE_FORMAT', 'Invalid locale string parameter.');\n }\n\n if (!isValidKeyFormat(key)) {\n return reject(\n 400,\n 'INVALID_KEY_FORMAT',\n 'Invalid key path. Must be 1-200 characters containing alphanumeric, dots, underscores, or hyphens.'\n );\n }\n\n if (!isSafeKeyPath(key)) {\n return reject(\n 400,\n 'INVALID_KEY_FORMAT',\n 'Forbidden key path: segments like __proto__, constructor, or prototype are not allowed.'\n );\n }\n\n if (!isValidValueFormat(value)) {\n return reject(\n 400,\n 'INVALID_VALUE_FORMAT',\n 'Invalid value. Must be a string less than 10000 characters.'\n );\n }\n\n const accepted: WriteAccepted = {\n ok: true,\n locale: locale as string,\n key: key as string,\n value: value as string,\n };\n\n // RULE SRV-007: PLACEHOLDER SAFETY — a translation must keep the placeholders\n // of its reference and stay structurally valid, unless the author forces it.\n if (options.force === true) return accepted;\n\n const syntaxError = validateMessageSyntax(accepted.value);\n if (syntaxError) {\n return reject(422, 'MESSAGE_SYNTAX', `Message syntax: ${syntaxError}.`);\n }\n\n // An empty, null or undefined reference is compatible with any value.\n const comparison = comparePlaceholders(options.reference, accepted.value);\n if (!comparison.ok) {\n const parts: string[] = [];\n if (comparison.missing.length) parts.push(`missing ${comparison.missing.join(', ')}`);\n if (comparison.extra.length) parts.push(`unexpected ${comparison.extra.join(', ')}`);\n return {\n ...reject(\n 422,\n 'PLACEHOLDER_MISMATCH',\n `Placeholders differ from the reference: ${parts.join('; ')}.`\n ),\n details: { missing: comparison.missing, extra: comparison.extra },\n };\n }\n\n return accepted;\n}\n\n/** The locale files an edit is checked against. */\nexport interface SourceContext {\n /** apply: its --source argument; Studio: manifest.sourceLocale. */\n sourceLocale: string;\n /** The source-locale dictionary as stored (namespaces merged under their names). */\n source: Record<string, unknown>;\n /** The edit locale's dictionary; omitted when that locale has no file. */\n target?: Record<string, unknown>;\n}\n\n/** The string at `key` in ctx.source, else null. For a source-locale edit this is its current text. */\nexport function sourceReference(key: string, ctx: SourceContext): string | null {\n const found = lookupKey(ctx.source, key);\n return found.state === 'string' ? found.value : null;\n}\n\n/**\n * Checks one edit against the locale files: the format rules, then the\n * structure guard (409, which `force` cannot override), then message syntax\n * and placeholder parity against `sourceReference` unless `options.force`.\n * The reference is always recomputed here; any `reference` or `force`\n * carried on `edit` is ignored.\n */\nexport function validateEdit(\n edit: { locale: string; key: string; value: string },\n ctx: SourceContext,\n options?: { force?: boolean }\n): WriteVerdict {\n const { locale, key, value } = edit;\n const input = { locale, key, value };\n\n // `force` skips only the 422 rules, so this runs the format rules alone.\n const format = validateWrite(input, { force: true });\n if (!format.ok) return format;\n\n const dict = locale === ctx.sourceLocale ? ctx.source : (ctx.target ?? {});\n if (lookupKey(dict, key).state === 'occupied') {\n return reject(\n 409,\n 'KEY_NOT_A_STRING',\n `Cannot save \"${key}\" in ${locale}: it would replace translations that are not a single text.`\n );\n }\n\n return validateWrite(input, {\n reference: sourceReference(key, ctx),\n force: options?.force === true,\n });\n}\n\nexport type ContentRiskFlag = 'markup' | 'javascript-url' | 'new-url' | 'bidi-control';\n\nexport const RISK_FLAG_MESSAGES: Record<ContentRiskFlag, string> = {\n markup: 'Adds markup that the source text does not have.',\n 'javascript-url': 'Adds a javascript:, vbscript: or data: link.',\n 'new-url': 'Adds a web address that the source text does not have.',\n 'bidi-control': 'Contains invisible text-direction control characters.',\n};\n\n// Global patterns are only ever read through String.match and String.matchAll,\n// which never leave state behind on a shared regex. No lookbehind: the core\n// must run in every browser the Studio supports.\nconst TAG_PATTERN = /<\\/?([A-Za-z][\\w-]*)\\b[^<>]*>/g;\nconst SCRIPT_LINK_PATTERNS = [/\\b(?:javascript|vbscript)\\s*:/i, /\\bdata:[a-z]+\\/[\\w.+-]+/i];\nconst URL_PATTERN = /\\b(?:https?:\\/\\/|www\\.)[^\\s<>\"')]+/gi;\n// U+202A-U+202E (embeddings and overrides) and U+2066-U+2069 (isolates).\n// LRM and RLM are ordinary Arabic and Hebrew typography, so they are left out.\nconst BIDI_CONTROL_PATTERN = /[\\u202A-\\u202E\\u2066-\\u2069]/g;\n\n/** Tag names are case-insensitive in HTML, so `<B>` and `<b>` are one name. */\nconst tagNames = (text: string): string[] =>\n Array.from(text.matchAll(TAG_PATTERN), (m) => m[1]!.toLowerCase());\n\nconst allMatches = (pattern: RegExp, text: string): string[] => text.match(pattern) ?? [];\n\n/** True when `found` holds an item that `known` lacks. */\nconst hasNew = (known: string[], found: string[]): boolean => {\n const set = new Set(known);\n return found.some((item) => !set.has(item));\n};\n\n/**\n * Flags only what `value` adds compared with `reference`, in the order of\n * the union above, each at most once. A missing reference (a key the source\n * locale lacks) counts as empty, so everything in `value` is new. This only\n * reports; what a flag blocks, if anything, is the caller's decision.\n */\nexport function detectRiskFlags(reference: string | undefined, value: string): ContentRiskFlag[] {\n const ref = reference ?? '';\n const flags: ContentRiskFlag[] = [];\n\n if (hasNew(tagNames(ref), tagNames(value))) flags.push('markup');\n\n // Each pattern is checked on its own, so a reference holding a data: link\n // does not excuse a new javascript: link.\n if (SCRIPT_LINK_PATTERNS.some((pattern) => pattern.test(value) && !pattern.test(ref))) {\n flags.push('javascript-url');\n }\n\n if (hasNew(allMatches(URL_PATTERN, ref), allMatches(URL_PATTERN, value))) flags.push('new-url');\n\n if (hasNew(allMatches(BIDI_CONTROL_PATTERN, ref), allMatches(BIDI_CONTROL_PATTERN, value))) {\n flags.push('bidi-control');\n }\n\n return flags;\n}\n","/**\n * The apply planner shared by the Studio's Review mode and `livelocale apply`.\n *\n * It decides, for every edit of a change link, what applying it to the\n * target's locale files would do. Every edit is re-validated against the\n * target's own source locale, and a per-key 3-way check compares the link's\n * `from` with the current value. Nothing is written here and nothing is\n * normalized: text is compared by exact code units.\n */\n\nimport { containsWatermark } from '../client/watermark.js';\nimport type { ChangeEdit } from './change-link.js';\nimport { lookupKey } from './json-path.js';\nimport {\n detectRiskFlags,\n RISK_FLAG_MESSAGES,\n sourceReference,\n validateEdit,\n type ContentRiskFlag,\n type SourceContext,\n type WriteRuleCode,\n} from './save-rules.js';\n\nexport type EditStatus = 'apply' | 'already' | 'conflict' | 'invalid' | 'needs-force';\n\nexport type RiskFlag = ContentRiskFlag | 'new-key' | 'forced';\n\n/** The one copy for every flag, shared by Review rows and the PR/issue tables. */\nexport const FLAG_MESSAGES: Record<RiskFlag, string> = {\n ...RISK_FLAG_MESSAGES,\n forced: 'Saved with “Save anyway”.',\n 'new-key': 'Adds a key the source locale does not have.',\n};\n\nexport type PlanCode =\n | WriteRuleCode\n | 'UNKNOWN_LOCALE'\n | 'UNKNOWN_NAMESPACE'\n | 'CONTAINS_WATERMARK'\n | 'CHANGED_ON_TARGET'\n | 'REMOVED_ON_TARGET';\n\nexport interface PlannedEdit extends ChangeEdit {\n status: EditStatus;\n code?: PlanCode;\n message?: string;\n current?: string;\n flags: RiskFlag[];\n}\n\nexport interface ApplyPlan {\n edits: PlannedEdit[];\n counts: Record<EditStatus, number>;\n}\n\n/** One locale's file on the target; null when that locale has no file. */\nexport type LocaleTarget = {\n layout: 'flat' | 'namespaced';\n dict: Record<string, unknown>;\n} | null;\n\nexport interface PlanInput {\n edits: readonly ChangeEdit[];\n sourceLocale: string;\n targets: ReadonlyMap<string, LocaleTarget>;\n /** A maintainer allowed force: `--force` locally, `/livelocale apply --force` on GitHub. */\n allowForce: boolean;\n}\n\ntype Outcome = Pick<PlannedEdit, 'status' | 'code' | 'message' | 'current'>;\n\n/** True when the key's first segment is already a namespace object in `dict`. */\nfunction inExistingNamespace(dict: Record<string, unknown>, key: string): boolean {\n const dot = key.indexOf('.');\n if (dot === -1) return false;\n\n const namespace = key.slice(0, dot);\n if (!Object.prototype.hasOwnProperty.call(dict, namespace)) return false;\n\n const value = dict[namespace];\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction planEdit(\n edit: ChangeEdit,\n input: PlanInput,\n source: Record<string, unknown>\n): PlannedEdit {\n const { locale, key, from, to, force } = edit;\n const base = { locale, key, from, to, force };\n const invalid = (code: PlanCode, message: string): PlannedEdit => ({\n ...base,\n status: 'invalid',\n code,\n message,\n flags: [],\n });\n\n // 1. Locale.\n const target = input.targets.get(locale);\n if (!target) return invalid('UNKNOWN_LOCALE', `No \"${locale}\" locale file on the target.`);\n\n // 2. Namespace.\n if (target.layout === 'namespaced' && !inExistingNamespace(target.dict, key)) {\n return invalid(\n 'UNKNOWN_NAMESPACE',\n `\"${key}\" is not in an existing namespace file of ${locale}.`\n );\n }\n\n // 3. Watermark.\n if (containsWatermark(to)) {\n return invalid('CONTAINS_WATERMARK', 'The new text contains LiveLocale watermark characters.');\n }\n\n const ctx: SourceContext = { sourceLocale: input.sourceLocale, source, target: target.dict };\n const reference = sourceReference(key, ctx);\n const flags: RiskFlag[] = [];\n // 7. Risk flags, for every edit that is not invalid.\n const planned = (outcome: Outcome): PlannedEdit => ({\n ...base,\n ...outcome,\n flags: [...flags, ...detectRiskFlags(reference ?? from ?? undefined, to)],\n });\n\n // 4. Already done.\n const found = lookupKey(target.dict, key);\n if (found.state === 'string' && found.value === to) {\n return planned({ status: 'already', current: found.value });\n }\n\n // 5. Validation. The client's force only counts when a maintainer allows it,\n // and it never overrides a 400 or 409.\n const verdict = validateEdit({ locale, key, value: to }, ctx, { force: false });\n if (!verdict.ok) {\n if (verdict.status !== 422 || !force) return invalid(verdict.code, verdict.error);\n if (!input.allowForce) {\n return planned({ status: 'needs-force', code: verdict.code, message: verdict.error });\n }\n flags.push('forced');\n }\n\n // 6. Three-way check. validateEdit refused an occupied key, so the key is\n // either missing or holds a string here.\n const current = found.state === 'string' ? found.value : undefined;\n if (current === undefined) {\n if (from !== null) {\n return planned({\n status: 'conflict',\n code: 'REMOVED_ON_TARGET',\n message: 'Removed on the target since the link was made.',\n });\n }\n if (reference === null) flags.push('new-key');\n return planned({ status: 'apply' });\n }\n if (current === from) return planned({ status: 'apply' });\n return planned({\n status: 'conflict',\n code: 'CHANGED_ON_TARGET',\n message: 'Changed on the target since the link was made.',\n current,\n });\n}\n\n/**\n * Plans every edit against the target's locale files, in order: locale,\n * namespace, watermark, already done, validation, 3-way check, risk flags.\n * Throws Error(`Source locale \"${s}\" has no locale file on the target.`) when\n * targets.get(sourceLocale) is missing or null.\n */\nexport function planApply(input: PlanInput): ApplyPlan {\n const source = input.targets.get(input.sourceLocale);\n if (!source) {\n throw new Error(`Source locale \"${input.sourceLocale}\" has no locale file on the target.`);\n }\n\n const edits = input.edits.map((edit) => planEdit(edit, input, source.dict));\n const counts: Record<EditStatus, number> = {\n apply: 0,\n already: 0,\n conflict: 0,\n invalid: 0,\n 'needs-force': 0,\n };\n for (const edit of edits) counts[edit.status] += 1;\n\n return { edits, counts };\n}\n","import { promises as fs } from 'fs';\nimport * as path from 'path';\nimport { isSafeLocaleSegment } from '../core/validate.js';\nimport { LOCALE_RE } from '../core/validate.js';\nimport { DANGEROUS_KEY_SEGMENTS } from '../core/validate.js';\nimport { resolveSafeLocalePath } from '../core/safe-path.js';\nimport { setNestedProperty, detectJsonIndent } from '../core/json-path.js';\nimport { KeyScanner } from './key-scanner.js';\nimport { getDisabledReason } from '../core/env.js';\n\nexport { detectJsonIndent };\n\nclass FileMutex {\n private queue: Promise<any> = Promise.resolve();\n\n async acquire<T>(fn: () => Promise<T>): Promise<T> {\n const next = this.queue.then(fn);\n // Suppress errors on the main queue chain to prevent locking up the mutex\n this.queue = next.then(\n () => {},\n () => {}\n );\n return next;\n }\n}\n\nexport interface FileMutatorOptions {\n /** Refuse to run unless LiveLocale is enabled. Default true; only CLI tooling passes false. */\n requireEnabled?: boolean;\n /** Skip the console line each `updateLocaleKey` write prints. Default false. */\n quiet?: boolean;\n}\n\nexport class FileMutator {\n private fileLocks = new Map<string, FileMutex>();\n private readonly requireEnabled: boolean;\n private readonly quiet: boolean;\n private readonly scanner: KeyScanner;\n\n constructor(options: FileMutatorOptions = {}) {\n this.requireEnabled = options.requireEnabled ?? true;\n this.quiet = options.quiet ?? false;\n this.scanner = new KeyScanner({ requireEnabled: this.requireEnabled });\n }\n\n private assertEnabled(): void {\n if (!this.requireEnabled) return;\n const reason = getDisabledReason();\n if (reason !== null) {\n throw new Error(\n `[livelocale] FileMutator can only be executed in development mode (${reason}).`\n );\n }\n }\n\n /**\n * Helper to serialize execution per file path\n */\n private async withLock<T>(filePath: string, fn: () => Promise<T>): Promise<T> {\n let lock = this.fileLocks.get(filePath);\n if (!lock) {\n lock = new FileMutex();\n this.fileLocks.set(filePath, lock);\n }\n return lock.acquire(fn);\n }\n\n /**\n * Updates a locale JSON file on disk atomically and safely.\n * Enforces development mode checks, path traversal mitigation, key depth restrictions,\n * structural JSON validation, and concurrency serialization.\n */\n async updateLocaleKey(\n basePath: string,\n locale: string,\n keyPath: string,\n newValue: string\n ): Promise<void> {\n // RULE GEN-001: DEVELOPMENT-ONLY ENFORCEMENT\n this.assertEnabled();\n\n // RULE SRV-002: PATH TRAVERSAL PREVENTION\n // Reject any locale string containing invalid characters\n if (!isSafeLocaleSegment(locale)) {\n throw new Error(\n `[livelocale] Path traversal attempt detected in locale identifier: \"${locale}\"`\n );\n }\n\n const resolvedBasePath = path.resolve(basePath);\n const localeDir = path.resolve(resolvedBasePath, locale);\n\n let filePath = '';\n let mutationKeyPath = keyPath;\n let isNamespaceDir = false;\n\n try {\n const stats = await fs.stat(localeDir);\n if (stats.isDirectory()) {\n isNamespaceDir = true;\n }\n } catch {}\n\n if (isNamespaceDir) {\n const firstDot = keyPath.indexOf('.');\n if (firstDot !== -1) {\n const namespace = keyPath.substring(0, firstDot);\n if (DANGEROUS_KEY_SEGMENTS.has(namespace)) {\n throw new Error(\n `[livelocale] Forbidden namespace segment in path: \"${namespace}\". Segment names like __proto__, constructor, and prototype are not allowed.`\n );\n }\n mutationKeyPath = keyPath.substring(firstDot + 1);\n filePath = path.resolve(localeDir, `${namespace}.json`);\n } else {\n filePath = path.resolve(localeDir, `${keyPath}.json`);\n mutationKeyPath = '';\n }\n } else {\n filePath = path.resolve(resolvedBasePath, `${locale}.json`);\n }\n\n if (!filePath.startsWith(resolvedBasePath)) {\n throw new Error(\n `[livelocale] Path traversal attempt: Resolved file path must start with basePath.`\n );\n }\n\n // Perform atomic operation within a file lock to guarantee concurrency safety (RULE SRV-006)\n await this.withLock(filePath, async () => {\n let currentData: Record<string, any> = {};\n // Formatting of the existing file, preserved on rewrite (git-friendly diffs).\n let indent = ' ';\n let trailingNewline = '\\n';\n\n try {\n const fileContent = await fs.readFile(filePath, 'utf-8');\n indent = detectJsonIndent(fileContent);\n trailingNewline = fileContent.endsWith('\\n') ? '\\n' : '';\n try {\n const parsed = JSON.parse(fileContent);\n\n // RULE SRV-004: JSON PARSE VALIDATION\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('Root must be an object');\n }\n currentData = parsed;\n } catch (parseError: any) {\n throw new Error(\n `[livelocale] Invalid locale file: root must be an object. Code: INVALID_LOCALE. Original error: ${parseError.message}`\n );\n }\n } catch (err: any) {\n // If file does not exist, initialize it as empty object\n if (err.code !== 'ENOENT') {\n throw new Error(\n `[livelocale] Failed to read locale file at ${filePath}. Operation: read. Original error: ${err.message}`\n );\n }\n }\n\n // Update nested property using safe array traversal (RULE SEC-003 & RULE SRV-003)\n if (mutationKeyPath) {\n setNestedProperty(currentData, mutationKeyPath, newValue);\n } else {\n // Root value mutation inside split JSON files (rare but possible: e.g. key has no dot)\n throw new Error(\n '[livelocale] Invalid namespace key path: must contain at least one nested key.'\n );\n }\n\n // RULE SEC-004: VALIDATE JSON BEFORE WRITE\n let stringified: string;\n try {\n stringified = JSON.stringify(currentData, null, indent);\n JSON.parse(stringified); // Paranoid check\n stringified += trailingNewline;\n } catch (err: any) {\n throw new Error(\n `[livelocale] Produced JSON is invalid or has circular references. Original error: ${err.message}`\n );\n }\n\n // RULE SRV-001: ATOMIC WRITES ONLY\n const tempPath = `${filePath}.tmp`;\n try {\n await fs.writeFile(tempPath, stringified, 'utf-8');\n } catch (err: any) {\n throw new Error(\n `[livelocale] Failed to write temp file at ${tempPath}. Operation: write. Original error: ${err.message}`\n );\n }\n\n try {\n await fs.rename(tempPath, filePath);\n } catch (err: any) {\n // Attempt clean up of temp file\n try {\n await fs.unlink(tempPath);\n } catch {\n // Ignore unlink error to bubble original rename error\n }\n throw new Error(\n `[livelocale] Failed to rename temp file to target at ${filePath}. Operation: rename. Original error: ${err.message}`\n );\n }\n\n // RULE SEC-001: NEVER LOG TRANSLATION VALUES\n if (!this.quiet) {\n console.log(`[livelocale] Updated key '${keyPath}' in locale '${locale}'`);\n }\n });\n }\n\n /**\n * Returns the full dictionary for a locale: a flat `{locale}.json`, or every\n * `*.json` inside the `{locale}/` folder merged under its namespace.\n */\n async readLocale(basePath: string, locale: string): Promise<Record<string, any>> {\n this.assertEnabled();\n const localePath = path.resolve(basePath, locale);\n let isDir = false;\n try {\n isDir = (await fs.stat(localePath)).isDirectory();\n } catch {}\n\n if (isDir) {\n const merged: Record<string, any> = {};\n for (const file of await fs.readdir(localePath)) {\n if (!file.endsWith('.json')) continue;\n try {\n merged[path.basename(file, '.json')] = JSON.parse(\n await fs.readFile(path.join(localePath, file), 'utf-8')\n );\n } catch {}\n }\n return merged;\n }\n\n const filePath = resolveSafeLocalePath(basePath, locale);\n return JSON.parse(await fs.readFile(filePath, 'utf-8'));\n }\n\n /**\n * Lists all locale codes dynamically scanned from the locales directory.\n */\n async listLocales(basePath: string): Promise<string[]> {\n this.assertEnabled();\n\n const resolvedBasePath = path.resolve(basePath);\n const items = await fs.readdir(resolvedBasePath, { withFileTypes: true });\n const localesSet = new Set<string>();\n\n for (const item of items) {\n if (item.isDirectory()) {\n if (LOCALE_RE.test(item.name)) {\n localesSet.add(item.name);\n }\n } else if (item.isFile() && item.name.endsWith('.json')) {\n const name = path.basename(item.name, '.json');\n if (LOCALE_RE.test(name)) {\n localesSet.add(name);\n }\n }\n }\n\n return Array.from(localesSet).sort();\n }\n\n /**\n * Adds a new locale directory/file based on current repository structure.\n */\n async addLocale(basePath: string, locale: string): Promise<void> {\n this.assertEnabled();\n\n if (!isSafeLocaleSegment(locale)) {\n throw new Error(\n `[livelocale] Path traversal attempt detected in locale identifier: \"${locale}\"`\n );\n }\n\n if (!LOCALE_RE.test(locale)) {\n throw new Error(`[livelocale] Invalid locale format: \"${locale}\"`);\n }\n\n const resolvedBasePath = path.resolve(basePath);\n const localePath = path.resolve(resolvedBasePath, locale);\n\n if (!localePath.startsWith(resolvedBasePath)) {\n throw new Error(\n `[livelocale] Path traversal attempt: Resolved file path must start with basePath.`\n );\n }\n\n // Check if directory or file already exists\n let exists = false;\n try {\n await fs.stat(localePath);\n exists = true;\n } catch {}\n try {\n await fs.stat(`${localePath}.json`);\n exists = true;\n } catch {}\n\n if (exists) {\n throw new Error(`[livelocale] Locale \"${locale}\" already exists.`);\n }\n\n // Scan basePath for layout detection: if we find any directories matching locale regex,\n // we use folder-based namespaces.\n const items = await fs.readdir(resolvedBasePath, { withFileTypes: true });\n let referenceDir: string | null = null;\n for (const item of items) {\n if (item.isDirectory() && LOCALE_RE.test(item.name)) {\n referenceDir = item.name;\n break;\n }\n }\n\n if (referenceDir) {\n // Create folder-based layout: create directory and write empty namespace files corresponding\n // to those in referenceDir\n await fs.mkdir(localePath, { recursive: true });\n const refPath = path.resolve(resolvedBasePath, referenceDir);\n const files = await fs.readdir(refPath);\n for (const file of files) {\n if (file.endsWith('.json')) {\n await fs.writeFile(path.join(localePath, file), '{}', 'utf-8');\n }\n }\n } else {\n // Flat layout: write empty json file\n await fs.writeFile(`${localePath}.json`, '{}', 'utf-8');\n }\n\n console.log(`[livelocale] Added locale '${locale}'`);\n }\n\n /**\n * Renames an existing locale (directory or file) to a new name.\n */\n async renameLocale(basePath: string, oldLocale: string, newLocale: string): Promise<void> {\n this.assertEnabled();\n\n if (!isSafeLocaleSegment(oldLocale) || !isSafeLocaleSegment(newLocale)) {\n throw new Error('[livelocale] Path traversal attempt detected');\n }\n\n if (!LOCALE_RE.test(oldLocale) || !LOCALE_RE.test(newLocale)) {\n throw new Error(`[livelocale] Invalid locale format`);\n }\n\n const resolvedBasePath = path.resolve(basePath);\n const oldPath = path.resolve(resolvedBasePath, oldLocale);\n const newPath = path.resolve(resolvedBasePath, newLocale);\n\n if (!oldPath.startsWith(resolvedBasePath) || !newPath.startsWith(resolvedBasePath)) {\n throw new Error('[livelocale] Path traversal attempt');\n }\n\n let isDir = false;\n let exists = false;\n try {\n const stats = await fs.stat(oldPath);\n isDir = stats.isDirectory();\n exists = true;\n } catch {}\n\n let isFile = false;\n if (!exists) {\n try {\n await fs.stat(`${oldPath}.json`);\n isFile = true;\n exists = true;\n } catch {}\n }\n\n if (!exists) {\n throw new Error(`[livelocale] Locale \"${oldLocale}\" does not exist.`);\n }\n\n // Check if new path already exists\n let newExists = false;\n try {\n await fs.stat(newPath);\n newExists = true;\n } catch {}\n try {\n await fs.stat(`${newPath}.json`);\n newExists = true;\n } catch {}\n\n if (newExists) {\n throw new Error(`[livelocale] Target locale \"${newLocale}\" already exists.`);\n }\n\n if (isDir) {\n await fs.rename(oldPath, newPath);\n } else if (isFile) {\n await fs.rename(`${oldPath}.json`, `${newPath}.json`);\n }\n\n console.log(`[livelocale] Renamed locale '${oldLocale}' to '${newLocale}'`);\n }\n\n /**\n * Deletes an existing locale (directory or file).\n */\n async deleteLocale(basePath: string, locale: string): Promise<void> {\n this.assertEnabled();\n\n if (!isSafeLocaleSegment(locale)) {\n throw new Error('[livelocale] Path traversal attempt detected');\n }\n\n if (!LOCALE_RE.test(locale)) {\n throw new Error(`[livelocale] Invalid locale format`);\n }\n\n const resolvedBasePath = path.resolve(basePath);\n const localePath = path.resolve(resolvedBasePath, locale);\n\n if (!localePath.startsWith(resolvedBasePath)) {\n throw new Error('[livelocale] Path traversal attempt');\n }\n\n let isDir = false;\n let exists = false;\n try {\n const stats = await fs.stat(localePath);\n isDir = stats.isDirectory();\n exists = true;\n } catch {}\n\n let isFile = false;\n if (!exists) {\n try {\n await fs.stat(`${localePath}.json`);\n isFile = true;\n exists = true;\n } catch {}\n }\n\n if (!exists) {\n throw new Error(`[livelocale] Locale \"${locale}\" does not exist.`);\n }\n\n if (isDir) {\n await fs.rm(localePath, { recursive: true, force: true });\n } else if (isFile) {\n await fs.unlink(`${localePath}.json`);\n }\n\n console.log(`[livelocale] Deleted locale '${locale}'`);\n }\n\n /**\n * Scans codebase directory recursively for references to translation keys.\n * Delegates to the composed KeyScanner (SRP).\n */\n async scanCodebaseKeys(basePath: string): Promise<string[]> {\n return this.scanner.scanCodebaseKeys(basePath);\n }\n\n /**\n * Scans all locale files/folders to compile the set of all keys currently in locales.\n */\n async scanLocalesKeys(basePath: string): Promise<string[]> {\n return this.scanner.scanLocalesKeys(basePath, this.listLocales.bind(this));\n }\n\n /**\n * Returns merged lists of keys from codebase and existing locale files.\n */\n async getKeysMetadata(basePath: string): Promise<{ allKeys: string[]; codeKeys: string[] }> {\n return this.scanner.getKeysMetadata(basePath, this.listLocales.bind(this));\n }\n}\n","import * as path from 'path';\nimport { isSafeLocaleSegment } from './validate.js';\n\n/**\n * Resolves a locale code to a safe `{locale}.json` path inside `basePath`,\n * rejecting path traversal attempts.\n */\nexport function resolveSafeLocalePath(basePath: string, locale: string): string {\n if (!isSafeLocaleSegment(locale)) {\n throw new Error('Path traversal attempt');\n }\n const resolvedBasePath = path.resolve(basePath);\n const filePath = path.resolve(resolvedBasePath, `${locale}.json`);\n if (!filePath.startsWith(resolvedBasePath)) {\n throw new Error('Path traversal attempt');\n }\n return filePath;\n}\n","import { execFile } from 'child_process';\nimport { promisify } from 'util';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { GitGateway, GitStatus, GitChange, GitChangeStatus } from './router.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** Diffs larger than this are truncated so the Studio never receives megabytes of JSON. */\nconst MAX_DIFF_BYTES = 200_000;\n\nfunction mapStatus(xy: string): GitChangeStatus {\n if (xy === '??') return 'added';\n const code = xy.trim()[0] ?? '';\n switch (code) {\n case 'M':\n return 'modified';\n case 'A':\n return 'added';\n case 'D':\n return 'deleted';\n case 'R':\n return 'renamed';\n default:\n return 'modified';\n }\n}\n\n/**\n * Thin wrapper over the `git` CLI, scoped to the locales directory. Every\n * command receives arguments as an array (no shell), and every path argument\n * is the locales directory relative to the repository root, so the Studio can\n * only ever stage, commit, or discard translation files.\n */\nexport class GitClient implements GitGateway {\n private async git(cwd: string, args: string[]): Promise<string> {\n const { stdout } = await execFileAsync('git', args, {\n cwd,\n maxBuffer: 16 * 1024 * 1024,\n windowsHide: true,\n env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },\n });\n return stdout;\n }\n\n /** Resolves the repository root and the locales path relative to it (forward slashes). */\n private async locate(\n localesPath: string\n ): Promise<{ root: string; rel: string; absolute: string } | null> {\n const absolute = path.resolve(localesPath);\n const cwd = fs.existsSync(absolute) ? absolute : path.dirname(absolute);\n if (!fs.existsSync(cwd)) return null;\n try {\n const root = (await this.git(cwd, ['rev-parse', '--show-toplevel'])).trim();\n if (!root) return null;\n const rel = path.relative(root, absolute).split(path.sep).join('/');\n if (rel.startsWith('..')) return null; // locales directory lives outside the repo\n return { root: path.resolve(root), rel: rel || '.', absolute };\n } catch {\n return null;\n }\n }\n\n async status(localesPath: string): Promise<GitStatus> {\n const loc = await this.locate(localesPath);\n if (!loc) return { isRepo: false, branch: null, changes: [] };\n\n let branch: string | null = null;\n try {\n branch = (await this.git(loc.root, ['rev-parse', '--abbrev-ref', 'HEAD'])).trim() || null;\n } catch {\n branch = null; // fresh repository without commits\n }\n\n const changes: GitChange[] = [];\n try {\n const out = await this.git(loc.root, [\n 'status',\n '--porcelain=v1',\n '--untracked-files=all',\n '--',\n loc.rel,\n ]);\n for (const line of out.split('\\n')) {\n if (line.length < 4) continue;\n const xy = line.slice(0, 2);\n let file = line.slice(3).trim();\n const arrow = file.indexOf(' -> ');\n if (arrow !== -1) file = file.slice(arrow + 4);\n if (file.startsWith('\"') && file.endsWith('\"')) file = file.slice(1, -1);\n changes.push({ path: file, status: mapStatus(xy) });\n }\n } catch {}\n\n return { isRepo: true, branch, changes, mode: 'local', pullRequestUrl: null };\n }\n\n async diff(localesPath: string): Promise<string> {\n const loc = await this.locate(localesPath);\n if (!loc) return '';\n\n let out = '';\n try {\n out = await this.git(loc.root, ['diff', '--no-color', '--', loc.rel]);\n } catch {}\n\n // Untracked files are not part of `git diff`; synthesize an all-additions hunk.\n try {\n const untracked = await this.git(loc.root, [\n 'ls-files',\n '--others',\n '--exclude-standard',\n '--',\n loc.rel,\n ]);\n for (const file of untracked\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean)) {\n const full = path.join(loc.root, file);\n let content = '';\n try {\n content = fs.readFileSync(full, 'utf-8');\n } catch {\n continue;\n }\n const lines = content.split('\\n');\n if (lines[lines.length - 1] === '') lines.pop();\n out +=\n `diff --git a/${file} b/${file}\\nnew file mode 100644\\n--- /dev/null\\n+++ b/${file}\\n` +\n `@@ -0,0 +1,${lines.length} @@\\n` +\n lines.map((l) => `+${l}`).join('\\n') +\n '\\n';\n }\n } catch {}\n\n if (Buffer.byteLength(out, 'utf-8') > MAX_DIFF_BYTES) {\n out = out.slice(0, MAX_DIFF_BYTES) + '\\n… diff truncated …\\n';\n }\n return out;\n }\n\n async commit(localesPath: string, message: string): Promise<{ hash: string }> {\n const loc = await this.locate(localesPath);\n if (!loc) throw new Error('Not a git repository.');\n\n const status = await this.status(localesPath);\n if (status.changes.length === 0) {\n throw new Error(`No changes to commit under ${loc.rel}.`);\n }\n\n await this.git(loc.root, ['add', '-A', '--', loc.rel]);\n await this.git(loc.root, ['commit', '-q', '-m', message, '--', loc.rel]);\n const hash = (await this.git(loc.root, ['rev-parse', '--short', 'HEAD'])).trim();\n return { hash };\n }\n\n async discard(localesPath: string): Promise<void> {\n const loc = await this.locate(localesPath);\n if (!loc) throw new Error('Not a git repository.');\n\n try {\n await this.git(loc.root, ['checkout', '--', loc.rel]);\n } catch {\n // No tracked files under the locales directory yet; nothing to restore.\n }\n await this.git(loc.root, ['clean', '-fd', '--', loc.rel]);\n }\n}\n","/**\n * The reports `livelocale apply` writes: the pull request body, the commit\n * message and the terminal summary.\n *\n * Every piece of translator text (values, `by`, `note`, check messages) is\n * escaped so it can never mention a user, link an issue, inject markup or\n * break the table. The terminal summary never contains values (SEC-001).\n */\n\nimport {\n FLAG_MESSAGES,\n type ApplyPlan,\n type EditStatus,\n type PlannedEdit,\n} from '../../core/apply-plan.js';\nimport type { CheckReport } from '../check.js';\n\nconst DEFAULT_SPAN_LENGTH = 120;\nconst DEFAULT_TABLE_ROWS = 100;\nconst MAX_BODY_CHARS = 60_000;\nconst MAX_NOTE_CHARS = 2_000;\nconst MAX_NAME_CHARS = 64;\nconst MAX_CHECK_LINES = 50;\nconst MAX_CHECK_SUMMARY_CHARS = 10_000;\n/** Room the table never uses, so the separators around it always fit. */\nconst BODY_MARGIN = 200;\n\nconst STATUS_LABELS: Record<EditStatus, string> = {\n apply: 'applied',\n already: 'already done',\n conflict: 'conflict',\n 'needs-force': 'needs --force',\n invalid: 'rejected',\n};\n\nconst BIDI_CONTROL_RE = /[‪-‮⁦-⁩]/g;\n// Every CommonMark line ending: a lone CR ends a table row just like LF does.\nconst NEWLINE_RE = /\\r\\n|\\r|\\n/g;\n// Control characters left after newlines are mapped (tab is kept: it is harmless in a span).\nconst SPAN_CONTROL_RE = /[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]/g;\nconst CONTROL_RE = /[\\u0000-\\u001f\\u007f-\\u009f]/g;\n\n/** Cuts `text` to `max` code units without leaving half a surrogate pair. */\nfunction cut(text: string, max: number): string {\n if (text.length <= max) return text;\n let out = text.slice(0, max);\n const last = out.charCodeAt(out.length - 1);\n if (last >= 0xd800 && last <= 0xdbff) out = out.slice(0, -1);\n return out;\n}\n\n/**\n * Cuts `text` to at most `max` characters by dropping whole lines from the end\n * and adding a `…` line, so a code span is never cut in half.\n */\nfunction cutLines(text: string, max: number): string {\n if (text.length <= max) return text;\n const kept: string[] = [];\n let length = 0;\n for (const line of text.split('\\n')) {\n const added = (kept.length > 0 ? 1 : 0) + line.length;\n // Leave room for the \"\\n…\" line.\n if (length + added + 2 > max) break;\n kept.push(line);\n length += added;\n }\n return [...kept, '…'].join('\\n');\n}\n\nfunction longestBacktickRun(text: string): number {\n let longest = 0;\n for (const run of text.match(/`+/g) ?? []) longest = Math.max(longest, run.length);\n return longest;\n}\n\nfunction codePointLabel(ch: string): string {\n return `⟨U+${ch.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}⟩`;\n}\n\n/** Renders translator text as one inline code span that is safe in a table cell. */\nexport function codeSpan(text: string, maxLength: number = DEFAULT_SPAN_LENGTH): string {\n const truncated = text.length > maxLength ? `${cut(text, maxLength)}…` : text;\n const content = truncated\n .replace(NEWLINE_RE, '⏎')\n .replace(BIDI_CONTROL_RE, codePointLabel)\n .replace(SPAN_CONTROL_RE, codePointLabel)\n .replace(/\\|/g, '\\\\|');\n if (content === '') return '` `';\n\n const fence = '`'.repeat(longestBacktickRun(content) + 1);\n const pad = /^[` ]|[` ]$/.test(content) ? ' ' : '';\n return `${fence}${pad}${content}${pad}${fence}`;\n}\n\n/** Cleans a translator name for a commit trailer; undefined when nothing is left. */\nexport function sanitizeName(name: string | undefined): string | undefined {\n if (name === undefined) return undefined;\n const cleaned = name\n .replace(NEWLINE_RE, ' ')\n .replace(CONTROL_RE, '')\n .replace(/[@#<>]/g, '')\n .trim();\n const result = cut(cleaned, MAX_NAME_CHARS).trim();\n return result === '' ? undefined : result;\n}\n\nexport interface TargetInfo {\n branch: string;\n isDefault: boolean;\n requested?: string;\n reason: 'link' | 'default' | 'not-allowed' | 'local';\n}\n\nexport interface ReportContext {\n plan: ApplyPlan;\n by?: string;\n note?: string;\n target: TargetInfo;\n issueNumber?: number;\n checkSummary?: string;\n runUrl?: string;\n}\n\nconst NO_CHECK_PROBLEMS = '✅ `livelocale check`: no problems in the changed keys.';\n\n/** Summarizes a `livelocale check` report, listing only problems in the edited keys. */\nexport function summarizeCheck(\n report: CheckReport,\n edited: Array<[locale: string, key: string]>\n): string {\n const changed = new Set(edited.map(([locale, key]) => `${locale}\\u0000${key}`));\n const mine = report.issues.filter(\n (issue) =>\n issue.locale !== undefined &&\n issue.key !== undefined &&\n changed.has(`${issue.locale}\\u0000${issue.key}`)\n );\n if (mine.length === 0) return NO_CHECK_PROBLEMS;\n\n const lines = [`⚠ \\`livelocale check\\` found ${mine.length} problem(s) in the changed keys:`, ''];\n for (const issue of mine.slice(0, MAX_CHECK_LINES)) {\n lines.push(\n `- ${codeSpan(issue.locale ?? '')} ${codeSpan(issue.key ?? '')}: ${codeSpan(issue.message)}`\n );\n }\n if (mine.length > MAX_CHECK_LINES) lines.push(`- …and ${mine.length - MAX_CHECK_LINES} more`);\n\n const others = report.issues.length - mine.length;\n if (others > 0) {\n lines.push('', `(${others} other problem(s) already in the repository are not shown.)`);\n }\n return lines.join('\\n');\n}\n\nfunction checksCell(edit: PlannedEdit): string {\n const parts: string[] = edit.flags.map((flag) => FLAG_MESSAGES[flag]);\n if ((edit.status === 'invalid' || edit.status === 'needs-force') && edit.message) {\n parts.push(codeSpan(edit.message));\n }\n return parts.join('; ');\n}\n\nfunction renderRow(edit: PlannedEdit): string {\n const before = edit.from === null ? '—' : codeSpan(edit.from);\n const after =\n edit.status === 'conflict'\n ? `now: ${edit.current === undefined ? '(removed)' : codeSpan(edit.current)}`\n : codeSpan(edit.to);\n const cells = [\n STATUS_LABELS[edit.status],\n codeSpan(edit.locale),\n codeSpan(edit.key),\n before,\n after,\n checksCell(edit),\n ];\n return `| ${cells.join(' | ')} |`;\n}\n\n/** Renders rows until `limit` rows or `maxChars` characters, whichever comes first. */\nfunction renderTable(plan: ApplyPlan, limit: number, maxChars: number): string {\n const lines = [\n '| Status | Locale | Key | Before | After | Checks |',\n '| --- | --- | --- | --- | --- | --- |',\n ];\n const moreLine = (n: number) => `\\n\\n…and ${n} more`;\n // Reserve room for the widest \"…and N more\" line.\n let length = lines.join('\\n').length + moreLine(plan.edits.length).length;\n let shown = 0;\n for (const edit of plan.edits) {\n if (shown >= limit) break;\n const row = renderRow(edit);\n if (length + row.length + 1 > maxChars) break;\n lines.push(row);\n length += row.length + 1;\n shown += 1;\n }\n\n const rest = plan.edits.length - shown;\n return lines.join('\\n') + (rest > 0 ? moreLine(rest) : '');\n}\n\n/** The before/after table of a plan, with the checks the PR reviewer must see. */\nexport function renderChangesTable(plan: ApplyPlan, limit: number = DEFAULT_TABLE_ROWS): string {\n return renderTable(plan, limit, MAX_BODY_CHARS - BODY_MARGIN);\n}\n\nfunction fencedNote(note: string): string {\n const text = cut(note, MAX_NOTE_CHARS);\n const fence = '`'.repeat(Math.max(3, longestBacktickRun(text) + 1));\n return `${fence}text\\n${text}\\n${fence}`;\n}\n\nfunction closingLine(ctx: ReportContext): string | undefined {\n if (ctx.issueNumber === undefined) return undefined;\n if (ctx.target.isDefault) return `Closes #${ctx.issueNumber}`;\n return `Refs #${ctx.issueNumber}. LiveLocale closes the issue when this pull request is merged or closed.`;\n}\n\n/** The pull request body; never longer than 60,000 characters. */\nexport function renderPullRequestBody(ctx: ReportContext): string {\n const head: string[] = ['Applies translations sent with a LiveLocale change link.'];\n if (ctx.by?.trim()) head.push(`Translated by ${codeSpan(ctx.by)}`);\n if (ctx.target.reason === 'not-allowed' && ctx.target.requested !== undefined) {\n head.push(\n `The link was made from ${codeSpan(ctx.target.requested)}, which is not in the allowed branches, so this targets ${codeSpan(ctx.target.branch)}.`\n );\n }\n if (ctx.note?.trim()) head.push(fencedNote(ctx.note));\n\n const tail: string[] = [];\n if (ctx.checkSummary) tail.push(cutLines(ctx.checkSummary, MAX_CHECK_SUMMARY_CHARS));\n if (ctx.runUrl) tail.push(`Run log: ${ctx.runUrl}`);\n const closing = closingLine(ctx);\n if (closing) tail.push(closing);\n\n const fixed = [...head, ...tail].join('\\n\\n').length;\n const table = renderTable(ctx.plan, DEFAULT_TABLE_ROWS, MAX_BODY_CHARS - BODY_MARGIN - fixed);\n return [...head, table, ...tail].join('\\n\\n');\n}\n\n/** The commit message, with a sanitized `Translated-by:` trailer. */\nexport function renderCommitMessage(input: {\n plan: ApplyPlan;\n by?: string;\n issueNumber?: number;\n runId?: string;\n}): string {\n let subject = 'i18n: apply LiveLocale changes';\n if (input.issueNumber !== undefined) subject += ` (#${input.issueNumber})`;\n else if (input.runId !== undefined) subject += ` (run ${input.runId})`;\n\n const applied = input.plan.edits.filter((edit) => edit.status === 'apply');\n const locales = [...new Set(applied.map((edit) => edit.locale))].sort();\n const parts = [subject, `${applied.length} translation(s) in ${locales.join(', ')}.`];\n\n const name = sanitizeName(input.by);\n if (name) parts.push(`Translated-by: ${name}`);\n return parts.join('\\n\\n');\n}\n\n/** The terminal summary: counts, then one status line per edit. Never contains values. */\nexport function renderTerminalSummary(plan: ApplyPlan): string {\n const c = plan.counts;\n const lines = [\n `Applied ${c.apply} · already done ${c.already} · conflicts ${c.conflict} · needs --force ${c['needs-force']} · rejected ${c.invalid}`,\n ];\n for (const edit of plan.edits) {\n lines.push(`${STATUS_LABELS[edit.status]} ${edit.locale} ${edit.key}`);\n }\n return lines.join('\\n');\n}\n"],"mappings":"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","names":["fs","path","path","fs","path","BASE_SHA_RE","own","path","invalid","fs","path","path","fs","listLocales","flatten","import_child_process","import_fs","path","import_fs","path","resolve","import_fs","path","readText","firstExisting","HEAD_OPEN","HTML_OPEN","DOCTYPE","isPlainObject","relative","fs","resolve","reject","run","pack","exitCode","path","import_child_process","fs","path","TOO_LARGE_MESSAGE","resolve","import_child_process","fs","path","CORRUPT_MESSAGE","TOO_LARGE_MESSAGE","isPlainObject","invalid","import_fs","path","path","fs","import_child_process","fs","path","MAX_NOTE_CHARS","run","MAX_NOTE_CHARS","isPlainObject","resolve","reject","run","name","VALUE_OPTIONS","resolve","transformReactI18next","run"]}