livelocale 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.cjs +56 -12
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +55 -12
- package/dist/client/index.js.map +1 -1
- package/dist/codemod/index.cjs +0 -0
- package/dist/codemod/index.js +0 -0
- package/dist/react/index.cjs +57 -14
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +57 -14
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +8 -2
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +7 -2
- package/dist/server/index.js.map +1 -1
- package/dist/studio/assets/{index-D7ifnqy5.js → index-D6D5nPQI.js} +1 -1
- package/dist/studio/assets/{index-Zh0KtFUH.css → index-z0sbyt6N.css} +1 -1
- package/dist/studio/index.html +2 -2
- package/dist/{wrap-CsOtHp8r.d.cts → wrap-2qVxLN9Q.d.cts} +10 -18
- package/dist/{wrap-CsOtHp8r.d.ts → wrap-2qVxLN9Q.d.ts} +10 -18
- package/package.json +1 -1
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/file-mutator.ts","../../src/core/validate.ts","../../src/core/safe-path.ts","../../src/core/json-path.ts","../../src/server/key-scanner.ts","../../src/core/env.ts","../../src/core/gitignore.ts","../../src/server/git-client.ts","../../src/server/github-gateway.ts","../../src/core/placeholders.ts","../../src/server/router.ts","../../src/server/node-body.ts","../../src/server/next-handler.ts","../../src/server/translations.ts","../../src/client/watermark.ts","../../src/client/wrap.ts","../../src/core/deep-merge.ts","../../src/core/json-cache.ts"],"sourcesContent":["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\nfunction assertEnabled(component: string): void {\n const reason = getDisabledReason();\n if (reason !== null) {\n throw new Error(\n `[livelocale] ${component} can only be executed in development mode (${reason}).`\n );\n }\n}\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 class FileMutator {\n private fileLocks = new Map<string, FileMutex>();\n private scanner = new KeyScanner();\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 assertEnabled('FileMutator');\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 console.log(`[livelocale] Updated key '${keyPath}' in locale '${locale}'`);\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 assertEnabled('FileMutator');\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 assertEnabled('FileMutator');\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 assertEnabled('FileMutator');\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 assertEnabled('FileMutator');\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 assertEnabled('FileMutator');\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","/**\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 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 { 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/**\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","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 { 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","import type {\n MutationGateway,\n GitGateway,\n GitStatus,\n GitChange,\n GitChangeStatus,\n} from './router.js';\nimport {\n LOCALE_RE,\n isSafeLocaleSegment,\n isValidLocaleFormat,\n isSafeKeyPath,\n DANGEROUS_KEY_SEGMENTS,\n} from '../core/validate.js';\nimport { setNestedProperty, stringifyLike, flattenKeys } from '../core/json-path.js';\n\nexport interface GitHubGatewayConfig {\n /** `owner/name` */\n repo: string;\n /** Branch that receives one commit per save; created from `baseBranch` on first use. */\n branch: string;\n /** Pull-request target and the source for creating `branch`. Defaults to `main`. */\n baseBranch?: string;\n /** Token with `contents: write` and `pull_requests: write` on the repository. */\n token: string;\n /** Defaults to `https://api.github.com`; set for GitHub Enterprise Server. */\n apiBase?: string;\n /** Injectable fetch for tests. */\n fetchImpl?: typeof fetch;\n}\n\n/** A gateway that is both the translation store and the review workflow. */\nexport interface GitHubGateway extends MutationGateway, GitGateway {}\n\ninterface ContentFile {\n type: 'file';\n path: string;\n sha: string;\n content: string;\n encoding: string;\n}\n\ninterface ContentEntry {\n type: 'file' | 'dir' | string;\n name: string;\n path: string;\n}\n\ntype Contents = ContentFile | ContentEntry[] | null;\n\n/** A non-2xx answer from the GitHub REST API. */\nclass GitHubApiError extends Error {\n constructor(\n message: string,\n readonly status: number\n ) {\n super(message);\n this.name = 'GitHubApiError';\n }\n}\n\n/** Attempts per save when another writer changed the file between our read and our write. */\nconst MAX_WRITE_ATTEMPTS = 4;\n\n/**\n * True when a contents write lost a race: GitHub answers 409 when the blob sha\n * we sent is stale, and 422 when a file we thought was new now exists.\n */\nconst isWriteConflict = (err: unknown) =>\n err instanceof GitHubApiError &&\n (err.status === 409 || (err.status === 422 && /sha/i.test(err.message)));\n\nconst encodePath = (p: string) => p.split('/').map(encodeURIComponent).join('/');\n\nconst normalizeDir = (p: string) =>\n p.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/^\\/+/, '').replace(/\\/+$/, '');\n\nfunction mapCompareStatus(status: string): GitChangeStatus {\n switch (status) {\n case 'added':\n case 'copied':\n return 'added';\n case 'removed':\n return 'deleted';\n case 'renamed':\n return 'renamed';\n default:\n return 'modified';\n }\n}\n\n/**\n * Stores translations in a GitHub repository branch through the REST API, so\n * a hosted Studio can edit a preview deployment with no local checkout:\n * every save is a commit on `branch`, `commit` opens (or reuses) a pull\n * request to `baseBranch`, and `discard` resets the branch to base.\n *\n * Only paths under the locales directory are ever read or written.\n */\nexport function createGitHubGateway(config: GitHubGatewayConfig): GitHubGateway {\n const repo = config.repo;\n const branch = config.branch;\n const baseBranch = config.baseBranch ?? 'main';\n const apiBase = (config.apiBase ?? 'https://api.github.com').replace(/\\/+$/, '');\n const fetchImpl = config.fetchImpl ?? globalThis.fetch;\n const owner = repo.split('/')[0] ?? '';\n\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) {\n throw new Error(`[livelocale] github.repo must be \"owner/name\", got \"${repo}\".`);\n }\n if (typeof fetchImpl !== 'function') {\n throw new Error('[livelocale] The GitHub gateway needs a global fetch (Node 18+).');\n }\n\n // ─── Low-level API ───────────────────────────────────────────────────────\n\n async function api<T = any>(\n method: string,\n path: string,\n options: { body?: unknown; query?: Record<string, string>; allow404?: boolean } = {}\n ): Promise<{ status: number; data: T | null }> {\n const url = new URL(`${apiBase}/repos/${repo}${path}`);\n for (const [k, v] of Object.entries(options.query ?? {})) url.searchParams.set(k, v);\n const response = await fetchImpl(url.toString(), {\n method,\n headers: {\n Authorization: `Bearer ${config.token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n ...(options.body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n },\n body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n });\n let data: any = null;\n try {\n data = await response.json();\n } catch {}\n if (response.status === 404 && options.allow404) return { status: 404, data: null };\n if (!response.ok) {\n const detail = data?.message || 'request failed';\n const hint = /not accessible by/i.test(detail)\n ? ' The token lacks a permission: give it \"Contents\" and \"Pull requests\" with \"Read and write\" on this repository.'\n : '';\n throw new GitHubApiError(\n `GitHub API ${response.status} on ${method} ${path}: ${detail}.${hint}`,\n response.status\n );\n }\n return { status: response.status, data };\n }\n\n /** Raw status of a request that is expected to fail validation; never throws on 4xx. */\n async function probeStatus(method: string, path: string, body?: unknown): Promise<number> {\n const response = await fetchImpl(`${apiBase}/repos/${repo}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${config.token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n try {\n await response.arrayBuffer();\n } catch {}\n return response.status;\n }\n\n async function refSha(name: string): Promise<string | null> {\n const res = await api<{ object: { sha: string } }>(\n 'GET',\n `/git/ref/heads/${encodeURIComponent(name)}`,\n { allow404: true }\n );\n return res.data?.object?.sha ?? null;\n }\n\n let branchReady: Promise<void> | null = null;\n function ensureBranch(): Promise<void> {\n if (!branchReady) {\n branchReady = (async () => {\n if (await refSha(branch)) return;\n const base = await refSha(baseBranch);\n if (!base) throw new Error(`Base branch \"${baseBranch}\" does not exist in ${repo}.`);\n await api('POST', '/git/refs', { body: { ref: `refs/heads/${branch}`, sha: base } });\n })().catch((err) => {\n branchReady = null;\n throw err;\n });\n }\n return branchReady;\n }\n\n async function getContents(path: string): Promise<Contents> {\n await ensureBranch();\n const res = await api<Contents>('GET', `/contents/${encodePath(path)}`, {\n query: { ref: branch },\n allow404: true,\n });\n return res.data;\n }\n\n async function readFile(path: string): Promise<{ text: string; sha: string } | null> {\n const contents = await getContents(path);\n if (!contents || Array.isArray(contents) || contents.type !== 'file') return null;\n const text = Buffer.from(contents.content.replace(/\\n/g, ''), 'base64').toString('utf-8');\n return { text, sha: contents.sha };\n }\n\n async function putFile(path: string, text: string, message: string, sha?: string): Promise<void> {\n await ensureBranch();\n await api('PUT', `/contents/${encodePath(path)}`, {\n body: {\n message,\n content: Buffer.from(text, 'utf-8').toString('base64'),\n branch,\n ...(sha ? { sha } : {}),\n },\n });\n }\n\n async function deleteFile(path: string, message: string, sha: string): Promise<void> {\n await api('DELETE', `/contents/${encodePath(path)}`, { body: { message, sha, branch } });\n }\n\n // Saves to one file are queued in this process, and a save that still loses\n // a race (another serverless instance, another Studio) re-reads and retries.\n const fileQueues = new Map<string, Promise<unknown>>();\n function withFileLock<T>(path: string, fn: () => Promise<T>): Promise<T> {\n const previous = fileQueues.get(path) ?? Promise.resolve();\n const next = previous.then(fn, fn);\n const settled = next.then(\n () => {},\n () => {}\n );\n fileQueues.set(path, settled);\n settled.then(() => {\n if (fileQueues.get(path) === settled) fileQueues.delete(path);\n });\n return next;\n }\n\n async function retryOnConflict<T>(fn: () => Promise<T>): Promise<T> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await fn();\n } catch (err) {\n if (!isWriteConflict(err) || attempt >= MAX_WRITE_ATTEMPTS) throw err;\n await new Promise((resolve) => setTimeout(resolve, 150 * attempt));\n }\n }\n }\n\n // ─── Locale layout helpers ───────────────────────────────────────────────\n\n const flatPath = (base: string, locale: string) => `${normalizeDir(base)}/${locale}.json`;\n const dirPath = (base: string, locale: string) => `${normalizeDir(base)}/${locale}`;\n\n function assertLocale(locale: string): void {\n if (!isValidLocaleFormat(locale) || !isSafeLocaleSegment(locale)) {\n throw new Error(`[livelocale] Invalid locale \"${locale}\".`);\n }\n }\n\n async function namespaceFiles(base: string, locale: string): Promise<string[] | null> {\n const contents = await getContents(dirPath(base, locale));\n if (!contents || !Array.isArray(contents)) return null;\n return contents.filter((e) => e.type === 'file' && e.name.endsWith('.json')).map((e) => e.name);\n }\n\n // ─── MutationGateway ─────────────────────────────────────────────────────\n\n async function listLocales(basePath: string): Promise<string[]> {\n const contents = await getContents(normalizeDir(basePath));\n if (!contents || !Array.isArray(contents)) return [];\n const set = new Set<string>();\n for (const entry of contents) {\n if (entry.type === 'dir' && LOCALE_RE.test(entry.name)) set.add(entry.name);\n if (entry.type === 'file' && entry.name.endsWith('.json')) {\n const code = entry.name.slice(0, -5);\n if (LOCALE_RE.test(code)) set.add(code);\n }\n }\n return Array.from(set).sort();\n }\n\n async function readLocale(basePath: string, locale: string): Promise<Record<string, any>> {\n assertLocale(locale);\n const files = await namespaceFiles(basePath, locale);\n if (files) {\n const merged: Record<string, any> = {};\n for (const file of files) {\n const f = await readFile(`${dirPath(basePath, locale)}/${file}`);\n if (!f) continue;\n try {\n merged[file.slice(0, -5)] = JSON.parse(f.text);\n } catch {}\n }\n return merged;\n }\n const flat = await readFile(flatPath(basePath, locale));\n if (!flat) throw new Error(`Locale \"${locale}\" not found on branch ${branch}.`);\n return JSON.parse(flat.text);\n }\n\n async function updateLocaleKey(\n basePath: string,\n locale: string,\n keyPath: string,\n value: string\n ): Promise<void> {\n assertLocale(locale);\n if (!isSafeKeyPath(keyPath)) {\n throw new Error(`[livelocale] Forbidden key segment in path: \"${keyPath}\".`);\n }\n\n let filePath: string;\n let mutationKeyPath = keyPath;\n const files = await namespaceFiles(basePath, locale);\n if (files) {\n const firstDot = keyPath.indexOf('.');\n if (firstDot === -1) {\n throw new Error(\n '[livelocale] Invalid namespace key path: must contain at least one nested key.'\n );\n }\n const ns = keyPath.slice(0, firstDot);\n if (DANGEROUS_KEY_SEGMENTS.has(ns)) {\n throw new Error(`[livelocale] Forbidden namespace segment in path: \"${ns}\".`);\n }\n filePath = `${dirPath(basePath, locale)}/${ns}.json`;\n mutationKeyPath = keyPath.slice(firstDot + 1);\n } else {\n filePath = flatPath(basePath, locale);\n }\n\n await withFileLock(filePath, () =>\n retryOnConflict(async () => {\n const existing = await readFile(filePath);\n let data: Record<string, any> = {};\n if (existing) {\n const parsed = JSON.parse(existing.text);\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('[livelocale] Invalid locale file: root must be an object.');\n }\n data = parsed;\n }\n setNestedProperty(data, mutationKeyPath, value);\n await putFile(\n filePath,\n stringifyLike(data, existing?.text ?? null),\n `i18n(${locale}): update ${keyPath}`,\n existing?.sha\n );\n })\n );\n }\n\n async function localeExists(basePath: string, locale: string): Promise<boolean> {\n if (await namespaceFiles(basePath, locale)) return true;\n return (await readFile(flatPath(basePath, locale))) !== null;\n }\n\n async function addLocale(basePath: string, locale: string): Promise<void> {\n assertLocale(locale);\n if (await localeExists(basePath, locale)) {\n throw new Error(`[livelocale] Locale \"${locale}\" already exists.`);\n }\n // Mirror the existing layout: if any locale is a folder, create a folder.\n const contents = await getContents(normalizeDir(basePath));\n const referenceDir = Array.isArray(contents)\n ? contents.find((e) => e.type === 'dir' && LOCALE_RE.test(e.name))?.name\n : undefined;\n if (referenceDir) {\n const files = (await namespaceFiles(basePath, referenceDir)) ?? [];\n for (const file of files) {\n await putFile(`${dirPath(basePath, locale)}/${file}`, '{}\\n', `i18n: add locale ${locale}`);\n }\n } else {\n await putFile(flatPath(basePath, locale), '{}\\n', `i18n: add locale ${locale}`);\n }\n }\n\n async function renameLocale(\n basePath: string,\n oldLocale: string,\n newLocale: string\n ): Promise<void> {\n assertLocale(oldLocale);\n assertLocale(newLocale);\n if (!(await localeExists(basePath, oldLocale))) {\n throw new Error(`[livelocale] Locale \"${oldLocale}\" does not exist.`);\n }\n if (await localeExists(basePath, newLocale)) {\n throw new Error(`[livelocale] Target locale \"${newLocale}\" already exists.`);\n }\n const message = `i18n: rename locale ${oldLocale} to ${newLocale}`;\n const files = await namespaceFiles(basePath, oldLocale);\n if (files) {\n for (const file of files) {\n const f = await readFile(`${dirPath(basePath, oldLocale)}/${file}`);\n if (!f) continue;\n await putFile(`${dirPath(basePath, newLocale)}/${file}`, f.text, message);\n await deleteFile(`${dirPath(basePath, oldLocale)}/${file}`, message, f.sha);\n }\n return;\n }\n const flat = await readFile(flatPath(basePath, oldLocale));\n if (!flat) return;\n await putFile(flatPath(basePath, newLocale), flat.text, message);\n await deleteFile(flatPath(basePath, oldLocale), message, flat.sha);\n }\n\n async function deleteLocale(basePath: string, locale: string): Promise<void> {\n assertLocale(locale);\n const message = `i18n: delete locale ${locale}`;\n const files = await namespaceFiles(basePath, locale);\n if (files) {\n for (const file of files) {\n const f = await readFile(`${dirPath(basePath, locale)}/${file}`);\n if (f) await deleteFile(`${dirPath(basePath, locale)}/${file}`, message, f.sha);\n }\n return;\n }\n const flat = await readFile(flatPath(basePath, locale));\n if (!flat) throw new Error(`[livelocale] Locale \"${locale}\" does not exist.`);\n await deleteFile(flatPath(basePath, locale), message, flat.sha);\n }\n\n async function getKeysMetadata(\n basePath: string\n ): Promise<{ allKeys: string[]; codeKeys: string[] }> {\n const keys = new Set<string>();\n for (const locale of await listLocales(basePath)) {\n try {\n flattenKeys(await readLocale(basePath, locale), '', keys);\n } catch {}\n }\n // Scanning source for t('…') references would need a checkout; preview mode\n // reports locale keys only.\n return { allKeys: Array.from(keys).sort(), codeKeys: [] };\n }\n\n // ─── GitGateway ──────────────────────────────────────────────────────────\n\n async function compareFiles(\n basePath: string\n ): Promise<{ filename: string; status: string; patch?: string }[]> {\n await ensureBranch();\n const res = await api<{ files?: { filename: string; status: string; patch?: string }[] }>(\n 'GET',\n `/compare/${encodeURIComponent(baseBranch)}...${encodeURIComponent(branch)}`\n );\n const prefix = `${normalizeDir(basePath)}/`;\n return (res.data?.files ?? []).filter((f) => f.filename.startsWith(prefix));\n }\n\n async function openPullRequestUrl(): Promise<string | null> {\n const res = await api<{ html_url: string }[]>('GET', '/pulls', {\n query: { head: `${owner}:${branch}`, base: baseBranch, state: 'open' },\n });\n return res.data?.[0]?.html_url ?? null;\n }\n\n async function status(basePath: string): Promise<GitStatus> {\n const files = await compareFiles(basePath);\n const changes: GitChange[] = files.map((f) => ({\n path: f.filename,\n status: mapCompareStatus(f.status),\n }));\n return {\n isRepo: true,\n branch,\n changes,\n mode: 'github',\n pullRequestUrl: await openPullRequestUrl(),\n };\n }\n\n async function diff(basePath: string): Promise<string> {\n const files = await compareFiles(basePath);\n return files\n .map(\n (f) =>\n `diff --git a/${f.filename} b/${f.filename}\\n--- a/${f.filename}\\n+++ b/${f.filename}\\n${f.patch ?? '(binary or too large)'}\\n`\n )\n .join('');\n }\n\n async function commit(basePath: string, message: string): Promise<{ hash: string }> {\n const files = await compareFiles(basePath);\n if (files.length === 0) {\n throw new Error(`No changes to propose under ${normalizeDir(basePath)} on ${branch}.`);\n }\n const existing = await openPullRequestUrl();\n if (existing) return { hash: existing };\n const res = await api<{ html_url: string }>('POST', '/pulls', {\n body: {\n title: message,\n head: branch,\n base: baseBranch,\n body: 'Translation changes proposed from the LiveLocale Studio.',\n },\n });\n return { hash: res.data!.html_url };\n }\n\n async function discard(): Promise<void> {\n const base = await refSha(baseBranch);\n if (!base) throw new Error(`Base branch \"${baseBranch}\" does not exist in ${repo}.`);\n await ensureBranch();\n await api('PATCH', `/git/refs/heads/${encodeURIComponent(branch)}`, {\n body: { sha: base, force: true },\n });\n }\n\n /**\n * Verifies the token, the repository, the base branch, and write access.\n * Write access is probed with deliberately empty requests: GitHub answers\n * 422 (validation failed) when the token has the permission and 403 when it\n * does not, so nothing is created either way.\n */\n async function checkAccess(): Promise<string[]> {\n if (!config.token) {\n return ['No GitHub token configured (github.token / GITHUB_TOKEN is empty).'];\n }\n const repoStatus = await probeStatus('GET', '');\n if (repoStatus === 401) return ['The GitHub token is invalid or expired.'];\n if (repoStatus === 404 || repoStatus === 403) {\n return [`Repository ${repo} was not found, or the token has no access to it.`];\n }\n if (repoStatus >= 400) return [`GitHub answered HTTP ${repoStatus} for ${repo}.`];\n\n const problems: string[] = [];\n if (!(await refSha(baseBranch))) {\n problems.push(`Base branch \"${baseBranch}\" does not exist in ${repo}.`);\n }\n if ((await probeStatus('POST', '/git/blobs', {})) === 403) {\n problems.push(\n `The token cannot write to ${repo}: give it \"Contents: Read and write\" so saves can be committed.`\n );\n }\n if ((await probeStatus('POST', '/pulls', {})) === 403) {\n problems.push(\n `The token cannot open pull requests in ${repo}: give it \"Pull requests: Read and write\".`\n );\n }\n return problems;\n }\n\n return {\n checkAccess,\n listLocales,\n readLocale,\n updateLocaleKey,\n addLocale,\n renameLocale,\n deleteLocale,\n getKeysMetadata,\n status,\n diff,\n commit,\n discard,\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 { getDisabledReason, getLiveLocaleMode } from '../core/env.js';\nimport { comparePlaceholders, validateMessageSyntax } from '../core/placeholders.js';\nimport {\n isValidKeyFormat,\n isValidLocaleFormat,\n isValidValueFormat,\n isSafeKeyPath,\n} from '../core/validate.js';\n\n/**\n * Platform-agnostic port for translation file operations. The Next.js and\n * Vite adapters both depend on this narrow contract (DIP) instead of the\n * concrete FileMutator implementation.\n */\nexport interface MutationGateway {\n updateLocaleKey(basePath: string, locale: string, key: string, value: string): Promise<void>;\n listLocales(basePath: string): Promise<string[]>;\n /** Full dictionary for one locale (namespace folders merged). Rejects when missing. */\n readLocale(basePath: string, locale: string): Promise<Record<string, any>>;\n addLocale(basePath: string, locale: string): Promise<void>;\n renameLocale(basePath: string, locale: string, newLocale: string): Promise<void>;\n deleteLocale(basePath: string, locale: string): Promise<void>;\n getKeysMetadata(basePath: string): Promise<{ allKeys: string[]; codeKeys: string[] }>;\n}\n\nexport type GitChangeStatus = 'modified' | 'added' | 'deleted' | 'renamed';\n\nexport interface GitChange {\n /** Path relative to the repository root, forward slashes. */\n path: string;\n status: GitChangeStatus;\n}\n\nexport interface GitStatus {\n isRepo: boolean;\n branch: string | null;\n changes: GitChange[];\n /** `local` = git CLI on the developer machine, `github` = branch + pull request via API. */\n mode?: 'local' | 'github';\n /** Open pull request for the branch, when the gateway knows about one. */\n pullRequestUrl?: string | null;\n}\n\n/**\n * Optional port for version-control operations scoped to the locales\n * directory. Implemented by `GitClient`; absent when git integration is off.\n */\nexport interface GitGateway {\n status(localesPath: string): Promise<GitStatus>;\n diff(localesPath: string): Promise<string>;\n commit(localesPath: string, message: string): Promise<{ hash: string }>;\n discard(localesPath: string): Promise<void>;\n /**\n * Optional self-test of credentials and permissions. Returns human-readable\n * problems (empty when everything needed is in place). Reported by `?action=info`.\n */\n checkAccess?(): Promise<string[]>;\n}\n\nexport interface RouterRequest {\n method: string;\n url: string;\n origin: string;\n /** Raw request body for body-carrying methods; parsed by the router. */\n bodyText?: string;\n /** Value of the Authorization header, if any. */\n authorization?: string;\n /** Value of the Content-Type header (lowercased), if any. */\n contentType?: string;\n}\n\nexport interface RouterResponse {\n status: number;\n headers: Record<string, string>;\n body: string | null;\n}\n\nexport interface MutationRouterOptions {\n localesPath: string;\n allowedOrigins?: string[];\n /** Enables the `git` read action and the `commit` / `discard` write actions. */\n git?: GitGateway;\n /**\n * When set, every request except CORS preflight must carry\n * `Authorization: Bearer <authToken>`. Mandatory in preview mode.\n */\n authToken?: string;\n}\n\nexport interface MutationRouter {\n handle(request: RouterRequest): Promise<RouterResponse>;\n}\n\nconst DEFAULT_ALLOWED_ORIGINS = ['http://localhost:3010', 'http://127.0.0.1:3010'];\n\n/** Maximum accepted request body size (1 MB) — far above any realistic payload. */\nexport const MAX_BODY_BYTES = 1_000_000;\n\n/** Commit messages longer than this are rejected. */\nexport const MAX_COMMIT_MESSAGE_LENGTH = 500;\n\n/** Any localhost origin (any port) is trusted — remote websites are not. */\nconst LOCALHOST_ORIGIN_RE = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(:\\d+)?$/;\n\n/** Constant-time string comparison so token checks do not leak length or prefix. */\nfunction safeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n\nfunction bearerToken(authorization: string | undefined): string | null {\n if (!authorization) return null;\n const match = /^Bearer\\s+(.+)$/i.exec(authorization.trim());\n return match ? match[1]!.trim() : null;\n}\n\nconst json = (\n status: number,\n headers: Record<string, string>,\n payload: unknown\n): RouterResponse => ({\n status,\n headers,\n body: JSON.stringify(payload),\n});\n\n/**\n * The single implementation of the livelocale mutation API.\n *\n * Both the Next.js route handler and the Vite dev-server middleware are thin\n * adapters over this router, so validation, CORS, and error handling live in\n * exactly one place (OCP).\n */\nexport function createMutationRouter(\n mutator: MutationGateway,\n options: MutationRouterOptions\n): MutationRouter {\n // Extra origins may be supplied at run time (GitHub Codespaces, Gitpod,\n // custom HTTPS dev hostnames) without touching code:\n // LIVELOCALE_ALLOWED_ORIGINS=\"https://abc-3010.app.github.dev,https://studio.dev.local\"\n const envOrigins = (process.env['LIVELOCALE_ALLOWED_ORIGINS'] || '')\n .split(',')\n .map((o) => o.trim())\n .filter(Boolean);\n const allowedOrigins = [...(options.allowedOrigins || DEFAULT_ALLOWED_ORIGINS), ...envOrigins];\n const localesPath = options.localesPath;\n const git = options.git;\n const authToken = options.authToken && options.authToken.length > 0 ? options.authToken : null;\n\n const isOriginAllowed = (origin: string): boolean =>\n allowedOrigins.includes(origin) || LOCALHOST_ORIGIN_RE.test(origin);\n\n const resolveAllowedOrigin = (origin: string): string => {\n return isOriginAllowed(origin) ? origin : allowedOrigins[0] || '';\n };\n\n const corsHeaders = (origin: string): Record<string, string> => ({\n 'Access-Control-Allow-Origin': resolveAllowedOrigin(origin),\n 'Access-Control-Allow-Methods': 'POST, OPTIONS, GET',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n 'Content-Type': 'application/json',\n });\n\n // A passing access check is remembered; a failing one is re-run on every\n // `info` call so fixing the token takes effect without a restart.\n let accessOk = false;\n async function accessProblems(): Promise<string[]> {\n if (!git?.checkAccess || accessOk) return [];\n try {\n const problems = await git.checkAccess();\n accessOk = problems.length === 0;\n return problems;\n } catch (err: any) {\n return [`Could not verify repository access: ${err?.message || err}`];\n }\n }\n\n // ─── GET: Fetch locale dictionary, list locales, or fetch keys metadata ───\n\n async function handleGet(\n urlObj: URL,\n basePath: string,\n headers: Record<string, string>\n ): Promise<RouterResponse> {\n const locale = urlObj.searchParams.get('locale');\n const action = urlObj.searchParams.get('action');\n\n if (action === 'info') {\n return json(200, headers, {\n mode: getLiveLocaleMode(),\n authRequired: authToken !== null,\n git: Boolean(git),\n problems: await accessProblems(),\n });\n }\n\n if (action === 'git') {\n if (!git) {\n return json(200, headers, {\n available: false,\n isRepo: false,\n branch: null,\n changes: [],\n diff: '',\n });\n }\n try {\n const status = await git.status(basePath);\n const diff = status.isRepo && status.changes.length > 0 ? await git.diff(basePath) : '';\n return json(200, headers, { available: true, ...status, diff });\n } catch (err: any) {\n return json(500, headers, {\n error: `Failed to read git status: ${err.message}`,\n code: 'GIT_STATUS_FAILED',\n });\n }\n }\n\n if (action === 'keys') {\n try {\n const metadata = await mutator.getKeysMetadata(basePath);\n return json(200, headers, metadata);\n } catch (err: any) {\n return json(500, headers, {\n error: `Failed to fetch keys metadata: ${err.message}`,\n code: 'KEYS_METADATA_FAILED',\n });\n }\n }\n\n if (!locale) {\n try {\n const localesList = await mutator.listLocales(basePath);\n return json(200, headers, localesList);\n } catch (err: any) {\n return json(500, headers, {\n error: `Failed to list locales: ${err.message}`,\n code: 'LIST_LOCALES_FAILED',\n });\n }\n }\n\n if (!isValidLocaleFormat(locale)) {\n return json(400, headers, {\n error: 'Invalid locale string parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n\n try {\n return json(200, headers, await mutator.readLocale(basePath, locale));\n } catch (readErr: any) {\n return json(404, headers, {\n error: `Failed to load locale: ${readErr.message}`,\n code: 'LOCALE_LOAD_FAILED',\n });\n }\n }\n\n // ─── POST: Mutate a translation key or manage locales ────────────────────\n\n async function handlePost(\n bodyText: string | undefined,\n basePath: string,\n headers: Record<string, string>\n ): Promise<RouterResponse> {\n let body: any;\n try {\n body = JSON.parse(bodyText ?? '');\n } catch {\n return json(400, headers, {\n error: 'Invalid JSON request body',\n code: 'BAD_REQUEST',\n });\n }\n\n const { locale, key, value, action, newLocale, message, reference, force } = body || {};\n\n if (action === 'commit' || action === 'discard') {\n if (!git) {\n return json(501, headers, {\n error: 'Git integration is not enabled for this handler.',\n code: 'GIT_UNAVAILABLE',\n });\n }\n if (action === 'commit') {\n const text = typeof message === 'string' ? message.trim() : '';\n if (!text || text.length > MAX_COMMIT_MESSAGE_LENGTH) {\n return json(400, headers, {\n error: `Commit message must be 1-${MAX_COMMIT_MESSAGE_LENGTH} characters.`,\n code: 'INVALID_COMMIT_MESSAGE',\n });\n }\n try {\n const result = await git.commit(basePath, text);\n return json(200, headers, { success: true, hash: result.hash });\n } catch (err: any) {\n return json(409, headers, { error: err.message, code: 'GIT_COMMIT_FAILED' });\n }\n }\n try {\n await git.discard(basePath);\n return json(200, headers, { success: true });\n } catch (err: any) {\n return json(500, headers, { error: err.message, code: 'GIT_DISCARD_FAILED' });\n }\n }\n\n if (action === 'addLocale') {\n if (!isValidLocaleFormat(locale)) {\n return json(400, headers, {\n error: 'Invalid locale string parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n await mutator.addLocale(basePath, locale);\n return json(200, headers, { success: true, locale });\n }\n\n if (action === 'renameLocale') {\n if (!isValidLocaleFormat(locale) || !isValidLocaleFormat(newLocale)) {\n return json(400, headers, {\n error: 'Invalid oldLocale or newLocale parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n await mutator.renameLocale(basePath, locale, newLocale);\n return json(200, headers, { success: true, locale, newLocale });\n }\n\n if (action === 'deleteLocale') {\n if (!isValidLocaleFormat(locale)) {\n return json(400, headers, {\n error: 'Invalid locale string parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n await mutator.deleteLocale(basePath, locale);\n return json(200, headers, { success: true, locale });\n }\n\n if (!isValidLocaleFormat(locale)) {\n return json(400, headers, {\n error: 'Invalid locale string parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n\n if (!isValidKeyFormat(key)) {\n return json(400, headers, {\n error:\n 'Invalid key path. Must be 1-200 characters containing alphanumeric, dots, underscores, or hyphens.',\n code: 'INVALID_KEY_FORMAT',\n });\n }\n\n if (!isSafeKeyPath(key)) {\n return json(400, headers, {\n error:\n 'Forbidden key path: segments like __proto__, constructor, or prototype are not allowed.',\n code: 'INVALID_KEY_FORMAT',\n });\n }\n\n if (!isValidValueFormat(value)) {\n return json(400, headers, {\n error: 'Invalid value. Must be a string less than 10000 characters.',\n code: 'INVALID_VALUE_FORMAT',\n });\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 (force !== true) {\n const syntaxError = validateMessageSyntax(value);\n if (syntaxError) {\n return json(422, headers, {\n error: `Message syntax: ${syntaxError}.`,\n code: 'MESSAGE_SYNTAX',\n });\n }\n if (typeof reference === 'string') {\n const comparison = comparePlaceholders(reference, 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 json(422, headers, {\n error: `Placeholders differ from the reference: ${parts.join('; ')}.`,\n code: 'PLACEHOLDER_MISMATCH',\n details: { missing: comparison.missing, extra: comparison.extra },\n });\n }\n }\n }\n\n await mutator.updateLocaleKey(basePath, locale, key, value);\n\n return json(200, headers, { success: true, key, locale });\n }\n\n return {\n async handle(request: RouterRequest): Promise<RouterResponse> {\n const headers = corsHeaders(request.origin);\n\n // RULE GEN-001: DEVELOPMENT-ONLY ENFORCEMENT\n const disabledReason = getDisabledReason();\n if (disabledReason !== null) {\n return json(403, headers, {\n error: `Forbidden: LiveLocale is disabled — ${disabledReason}. It only runs in development mode.`,\n code: 'FORBIDDEN',\n });\n }\n\n // Preflight never carries credentials; let it through so the browser can\n // learn that Authorization is an allowed header.\n if (request.method === 'OPTIONS') {\n return { status: 204, headers, body: null };\n }\n\n // RULE SEC-011: PREVIEW MODE REQUIRES A TOKEN — the API is reachable from the\n // internet in this mode, so refuse to serve anything without one configured.\n if (getLiveLocaleMode() === 'preview' && !authToken) {\n return json(403, headers, {\n error:\n 'Preview mode requires an access token. Set LIVELOCALE_TOKEN (or pass authToken) on the server.',\n code: 'PREVIEW_TOKEN_REQUIRED',\n });\n }\n\n // RULE SEC-012: BEARER AUTH — when a token is configured, every request needs it.\n if (authToken) {\n const presented = bearerToken(request.authorization);\n if (!presented || !safeEqual(presented, authToken)) {\n return json(401, headers, {\n error: 'Unauthorized: a valid Authorization: Bearer token is required.',\n code: 'UNAUTHORIZED',\n });\n }\n }\n\n // RULE SEC-006: CSRF PREVENTION — hard-reject writes from disallowed origins\n // (browsers always send Origin on cross-origin POSTs, including no-cors ones).\n if (request.method === 'POST' && request.origin && !isOriginAllowed(request.origin)) {\n return json(403, headers, {\n error: 'Forbidden: request origin is not allowed.',\n code: 'FORBIDDEN_ORIGIN',\n });\n }\n\n // RULE SEC-006: require a JSON content type on writes so the no-cors\n // \"text/plain\" CSRF vector cannot bypass validation via simple requests.\n if (\n request.method === 'POST' &&\n request.contentType &&\n !request.contentType.includes('application/json')\n ) {\n return json(415, headers, {\n error: 'Content-Type must be application/json.',\n code: 'UNSUPPORTED_MEDIA_TYPE',\n });\n }\n\n try {\n if (request.method === 'GET') {\n const urlObj = new URL(request.url, 'http://localhost');\n return await handleGet(urlObj, localesPath, headers);\n }\n\n if (request.method === 'POST') {\n return await handlePost(request.bodyText, localesPath, headers);\n }\n\n // Unsupported method\n return json(405, headers, {\n error: 'Method Not Allowed',\n code: 'METHOD_NOT_ALLOWED',\n });\n } catch (err: any) {\n return json(500, headers, {\n error: err.message || 'Internal Server Error',\n code: 'INTERNAL_ERROR',\n });\n }\n },\n };\n}\n","/**\n * Minimal structural type for a Node `http.IncomingMessage`-like request.\n * Used by the Pages Router adapter and the Vite middleware so neither needs\n * to import `next` or `vite` types.\n */\nexport interface NodeRequestLike {\n method?: string;\n url?: string;\n headers: Record<string, string | string[] | undefined>;\n on(event: 'data', cb: (chunk: Buffer | string) => void): unknown;\n on(event: 'end', cb: () => void): unknown;\n on(event: 'error', cb: (err: Error) => void): unknown;\n destroy?(): void;\n}\n\n/** Minimal structural type for a Node `http.ServerResponse`-like response. */\nexport interface NodeResponseLike {\n statusCode: number;\n setHeader(name: string, value: string): unknown;\n end(chunk?: string): unknown;\n}\n\nexport class BodyTooLargeError extends Error {\n readonly code = 'BODY_TOO_LARGE';\n constructor() {\n super('Request body too large.');\n this.name = 'BodyTooLargeError';\n }\n}\n\n/**\n * Buffers a Node request body as UTF-8 text, rejecting with\n * `BodyTooLargeError` as soon as `maxBytes` is exceeded (RULE SEC-007).\n */\nexport function readNodeBody(req: NodeRequestLike, maxBytes: number): Promise<string> {\n return new Promise((resolve, reject) => {\n let bodyText = '';\n let settled = false;\n req.on('data', (chunk) => {\n if (settled) return;\n bodyText += chunk.toString();\n if (Buffer.byteLength(bodyText, 'utf-8') > maxBytes) {\n settled = true;\n reject(new BodyTooLargeError());\n req.destroy?.();\n }\n });\n req.on('end', () => {\n if (settled) return;\n settled = true;\n resolve(bodyText);\n });\n req.on('error', (err) => {\n if (settled) return;\n settled = true;\n reject(err);\n });\n });\n}\n\n/** Returns the first value of a possibly multi-valued Node header, lowercased name expected. */\nexport function headerValue(\n headers: Record<string, string | string[] | undefined>,\n name: string\n): string {\n const raw = headers[name];\n if (Array.isArray(raw)) return raw[0] ?? '';\n return raw ?? '';\n}\n","import { FileMutator } from './file-mutator.js';\nimport { GitClient } from './git-client.js';\nimport { createGitHubGateway, type GitHubGatewayConfig } from './github-gateway.js';\nimport { createMutationRouter, MAX_BODY_BYTES, type RouterResponse } from './router.js';\nimport {\n readNodeBody,\n headerValue,\n BodyTooLargeError,\n type NodeRequestLike,\n type NodeResponseLike,\n} from './node-body.js';\n\nexport interface HandlerConfig {\n /** Locales directory: absolute on disk, or repository-relative when `github` is set. */\n localesPath: string;\n allowedOrigins?: string[];\n /**\n * Expose git status, commit, and discard for the locales directory to the\n * Studio. Requires the `git` CLI on PATH. Defaults to `true`.\n */\n git?: boolean;\n /**\n * Bearer token required on every request. Defaults to the `LIVELOCALE_TOKEN`\n * environment variable. Mandatory in preview mode.\n */\n authToken?: string;\n /**\n * Store translations on a GitHub branch instead of the local filesystem\n * (preview mode for hosted editing). Each save becomes a commit; the\n * Studio's commit action opens a pull request.\n */\n github?: GitHubGatewayConfig;\n}\n\n/**\n * A handler that works as both a Next.js App Router route handler\n * (`(request: Request) => Promise<Response>`) and a Pages Router API route\n * (`(req, res) => Promise<void>`). The shape is detected per call.\n */\nexport interface LiveLocaleHandler {\n (request: Request): Promise<Response>;\n (req: NodeRequestLike, res: NodeResponseLike): Promise<void>;\n}\n\nconst TOO_LARGE: RouterResponse = {\n status: 413,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'Request body too large.', code: 'BODY_TOO_LARGE' }),\n};\n\nfunction isNodeResponse(value: unknown): value is NodeResponseLike {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as NodeResponseLike).setHeader === 'function' &&\n typeof (value as NodeResponseLike).end === 'function'\n );\n}\n\n/**\n * Creates a Next.js route handler (App Router or Pages Router) backed by the\n * unified mutation router. Handles GET, POST, and OPTIONS requests.\n */\nexport function createLiveLocaleHandler(config: HandlerConfig): LiveLocaleHandler {\n const github = config.github ? createGitHubGateway(config.github) : null;\n const mutator = github ?? new FileMutator();\n const git = github ?? (config.git === false ? undefined : new GitClient());\n const router = createMutationRouter(mutator, {\n localesPath: config.localesPath,\n allowedOrigins: config.allowedOrigins,\n git,\n authToken: config.authToken ?? process.env['LIVELOCALE_TOKEN'],\n });\n\n // ─── App Router: Web Request / Response ──────────────────────────────────\n\n async function handleWeb(request: Request): Promise<Response> {\n // RULE SEC-007: BODY SIZE CAP — reject oversized bodies before buffering\n const contentLength = Number(request.headers.get('content-length') || 0);\n if (contentLength > MAX_BODY_BYTES) {\n return toWebResponse(TOO_LARGE);\n }\n\n let bodyText: string | undefined;\n if (request.method === 'POST') {\n bodyText = await request.text().catch(() => '');\n if (Buffer.byteLength(bodyText, 'utf-8') > MAX_BODY_BYTES) {\n return toWebResponse(TOO_LARGE);\n }\n }\n\n const result = await router.handle({\n method: request.method,\n url: request.url,\n origin: request.headers.get('origin') || '',\n contentType: request.headers.get('content-type') || '',\n authorization: request.headers.get('authorization') || undefined,\n bodyText,\n });\n\n return toWebResponse(result);\n }\n\n // ─── Pages Router: Node IncomingMessage / ServerResponse ─────────────────\n\n async function handleNode(req: NodeRequestLike, res: NodeResponseLike): Promise<void> {\n const method = req.method || 'GET';\n let result: RouterResponse;\n\n try {\n const contentLength = Number(headerValue(req.headers, 'content-length') || 0);\n if (contentLength > MAX_BODY_BYTES) {\n throw new BodyTooLargeError();\n }\n\n result = await router.handle({\n method,\n url: req.url || '/',\n origin: headerValue(req.headers, 'origin'),\n contentType: headerValue(req.headers, 'content-type'),\n authorization: headerValue(req.headers, 'authorization') || undefined,\n bodyText: method === 'POST' ? await readNodeBody(req, MAX_BODY_BYTES) : undefined,\n });\n } catch (err: any) {\n result =\n err instanceof BodyTooLargeError\n ? TOO_LARGE\n : {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n error: err?.message || 'Internal Server Error',\n code: 'INTERNAL_ERROR',\n }),\n };\n }\n\n for (const [name, value] of Object.entries(result.headers)) {\n res.setHeader(name, value);\n }\n res.statusCode = result.status;\n res.end(result.body ?? '');\n }\n\n function liveLocaleHandler(request: Request): Promise<Response>;\n function liveLocaleHandler(req: NodeRequestLike, res: NodeResponseLike): Promise<void>;\n function liveLocaleHandler(\n reqOrRequest: Request | NodeRequestLike,\n res?: NodeResponseLike\n ): Promise<Response> | Promise<void> {\n if (isNodeResponse(res)) {\n return handleNode(reqOrRequest as NodeRequestLike, res);\n }\n return handleWeb(reqOrRequest as Request);\n }\n\n return liveLocaleHandler;\n}\n\nfunction toWebResponse(result: RouterResponse): Response {\n return new Response(result.body, { status: result.status, headers: result.headers });\n}\n","import { readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { wrapTranslationEngine } from '../client/wrap.js';\nimport { deepMerge } from '../core/deep-merge.js';\nimport { isLiveLocaleEnabled } from '../core/env.js';\nimport { readJsonCached } from '../core/json-cache.js';\n\nexport interface CreateTranslationsOptions {\n /**\n * Directory containing locale JSON files.\n * @default `process.cwd() + '/locales'`\n */\n localesDir?: string;\n\n /**\n * List of accepted locale codes. Any locale not in this list falls back to\n * `fallbackLocale` to prevent path-traversal attacks.\n * @default `['en']`\n */\n supportedLocales?: string[];\n\n /**\n * Locale to use when the requested locale is unsupported or its file is\n * missing.\n * @default `'en'`\n */\n fallbackLocale?: string;\n}\n\nfunction isDirectory(p: string): boolean {\n try {\n return statSync(p).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** Reads every `*.json` in `dir` into `{ [namespace]: data }`, skipping unparsable files. */\nfunction readNamespaceDir(dir: string): Record<string, any> {\n const out: Record<string, any> = {};\n for (const file of readdirSync(dir)) {\n if (!file.endsWith('.json')) continue;\n try {\n out[file.slice(0, -5)] = readJsonCached(join(dir, file));\n } catch {}\n }\n return out;\n}\n\n/**\n * Loads a locale JSON file and returns a type-safe translation object that\n * is automatically watermarked in development (for zero-migration studio\n * integration) and returned as-is in production.\n *\n * File parses are cached by mtime and size (see `core/json-cache.ts`), so\n * repeated server renders cost one `stat` per file instead of a read and parse.\n *\n * This is the recommended entry-point for Server Components — no manual\n * `wrapTranslationEngine` call needed.\n *\n * @example\n * ```tsx\n * // app/page.tsx\n * import { createTranslations } from 'livelocale/server';\n *\n * export default async function Page({ searchParams }) {\n * const { locale = 'en' } = await searchParams;\n * const t = createTranslations(locale, {\n * supportedLocales: ['en', 'ar', 'es'],\n * });\n * return <h1>{t.home?.title}</h1>;\n * }\n * ```\n */\nexport function createTranslations(\n locale: string,\n options: CreateTranslationsOptions = {}\n): Record<string, any> {\n const {\n localesDir = join(process.cwd(), 'locales'),\n supportedLocales = ['en'],\n fallbackLocale = 'en',\n } = options;\n\n // SECURITY: reject locales not in the allow-list to prevent path traversal\n const safeLocale = supportedLocales.includes(locale) ? locale : fallbackLocale;\n\n const loadFlatFile = (dir: string, loc: string, fallback: string): Record<string, any> => {\n try {\n return readJsonCached(join(dir, `${loc}.json`));\n } catch {\n try {\n return readJsonCached(join(dir, `${fallback}.json`));\n } catch {\n return {};\n }\n }\n };\n\n const localePath = join(localesDir, safeLocale);\n let data: Record<string, any> = {};\n\n if (isDirectory(localePath)) {\n try {\n data = readNamespaceDir(localePath);\n } catch {\n data = loadFlatFile(localesDir, safeLocale, fallbackLocale);\n }\n } else {\n data = loadFlatFile(localesDir, safeLocale, fallbackLocale);\n }\n\n // In development, merge every other locale into a fallback dictionary so\n // untranslated keys still render (and stay editable) in the Studio.\n let fallbackData: Record<string, any> = {};\n if (isLiveLocaleEnabled()) {\n try {\n for (const entry of readdirSync(localesDir)) {\n if (entry.startsWith('.') || entry === safeLocale) continue;\n const entryPath = join(localesDir, entry);\n\n if (isDirectory(entryPath)) {\n try {\n const namespaces = readNamespaceDir(entryPath);\n for (const ns of Object.keys(namespaces)) {\n fallbackData[ns] = deepMerge(fallbackData[ns] || {}, namespaces[ns]);\n }\n } catch {}\n } else if (entry.endsWith('.json')) {\n if (entry.slice(0, -5) === safeLocale) continue;\n try {\n fallbackData = deepMerge(fallbackData, readJsonCached(entryPath));\n } catch {}\n }\n }\n } catch {}\n }\n\n return wrapTranslationEngine(data, { fallback: fallbackData });\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 * \\u200D – Zero-Width Joiner (ZWJ) → boundary start/end marker\n * \\u200B – Zero-Width Space (ZWS) → binary bit 0\n * \\u200C – Zero-Width Non-Joiner (ZWNJ) → binary bit 1\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 = '\\u200D'; // ZWJ – boundary delimiter\nconst BIT_0 = '\\u200B'; // ZWS – represents bit 0\nconst BIT_1 = '\\u200C'; // ZWNJ – represents bit 1\n\nconst ZW_RE = /[\\u200B\\u200C\\u200D]/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 * Use only for clipboard/form sanitization where no visible text should ever\n * contain ZW characters. Do NOT use on translation content destined for\n * locale files — prefer `stripWatermark`.\n */\nexport function sanitizeZeroWidth(text: string): string {\n return text.replace(ZW_RE, '');\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 { encodeKey } from './watermark.js';\nimport { isLiveLocaleEnabled } from '../core/env.js';\n\nexport interface WrapOptions {\n /**\n * A dot-separated key prefix to prepend to all resolved key paths.\n *\n * Use this when wrapping a namespaced translation function (e.g.\n * react-i18next `useTranslation('home')` or next-intl `useTranslations('home')`)\n * so that the watermarked key matches the actual path in your locale JSON file.\n *\n * @example\n * const { t: rawT } = useTranslation('home');\n * const t = wrapTranslationEngine(rawT, { keyPrefix: 'home' });\n * // t('title') encodes as 'home.title' — matches the JSON structure\n */\n keyPrefix?: string;\n\n /**\n * Optional fallback translations to use when the target key is missing.\n */\n fallback?: Record<string, any>;\n}\n\n/**\n * Helper that extracts a dot-notated key string from an argument (string or object descriptor).\n */\nfunction extractKey(arg: unknown, keyPrefix: string): string {\n if (typeof arg === 'string') {\n return keyPrefix ? `${keyPrefix}.${arg}` : arg;\n }\n if (arg && typeof arg === 'object') {\n const obj = arg as Record<string, any>;\n if (typeof obj.id === 'string' && obj.id.trim() !== '') {\n return keyPrefix ? `${keyPrefix}.${obj.id}` : obj.id;\n }\n if (typeof obj.key === 'string' && obj.key.trim() !== '') {\n return keyPrefix ? `${keyPrefix}.${obj.key}` : obj.key;\n }\n }\n return keyPrefix;\n}\n\n/**\n * Wraps any translation function or record (e.g. from next-intl, react-i18next,\n * FormatJS, or a plain locale object loaded server-side) with a JavaScript Proxy\n * that automatically encodes translation keys as invisible zero-width watermark\n * prefixes in development. In production the proxy is transparent — the original\n * engine is returned as-is.\n */\nexport function wrapTranslationEngine<T extends object>(engine: T, options: WrapOptions = {}): T {\n if (!isLiveLocaleEnabled()) {\n return engine;\n }\n\n return buildProxy(engine, options.keyPrefix ?? '', options);\n}\n\n/**\n * Dedicated convenience wrapper for `next-intl` (App Router and Pages Router).\n * Automatically wraps `useTranslations(namespace)` or `getTranslations(namespace)`.\n *\n * @example\n * ```tsx\n * const t = wrapNextIntl(useTranslations('auth'), 'auth');\n * return <h1>{t('login.title')}</h1>;\n * ```\n */\nexport function wrapNextIntl<T extends object>(t: T, namespace?: string): T {\n return wrapTranslationEngine(t, { keyPrefix: namespace });\n}\n\nfunction getNestedProperty(obj: any, path: string): any {\n if (!obj || typeof obj !== 'object') return undefined;\n if (path in obj) {\n return obj[path];\n }\n const parts = path.split('.');\n let current = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n current = current[part];\n }\n return current;\n}\n\nfunction buildProxy<T extends object>(target: T, keyPrefix: string, options: WrapOptions): T {\n return new Proxy(target, {\n get(obj, prop: string | symbol) {\n if (typeof prop !== 'string') {\n const val = Reflect.get(obj, prop);\n return typeof val === 'object' && val !== null\n ? buildProxy(val as object, keyPrefix, options)\n : val;\n }\n\n let val = Reflect.get(obj, prop);\n const fullKey = keyPrefix ? `${keyPrefix}.${prop}` : prop;\n\n // If val is missing, try looking it up in fallback\n const fallbackObj =\n options.fallback ??\n (typeof window !== 'undefined' ? (window as any).__livelocale_fallback__ : undefined);\n if (val === undefined && fallbackObj) {\n const fbVal = getNestedProperty(fallbackObj, fullKey);\n if (fbVal !== undefined) {\n val = fbVal;\n }\n }\n\n // Leaf string value – encode it with its full key path\n if (typeof val === 'string') {\n return encodeKey(val, fullKey);\n }\n\n // Function (e.g. t() or t.raw() or t.rich() from next-intl) – wrap the call result\n if (typeof val === 'function') {\n return (...args: unknown[]) => {\n const result = (val as (...args: unknown[]) => unknown).apply(obj, args);\n const calledKey = extractKey(args[0], fullKey);\n\n let resolvedValue = result;\n const isMissing =\n resolvedValue === undefined ||\n resolvedValue === null ||\n resolvedValue === '' ||\n (typeof resolvedValue === 'string' &&\n (resolvedValue === args[0] || resolvedValue === calledKey));\n\n if (isMissing && fallbackObj && calledKey) {\n const fbVal = getNestedProperty(fallbackObj, calledKey);\n if (fbVal !== undefined) {\n resolvedValue = fbVal;\n }\n }\n\n if (typeof resolvedValue === 'string' && calledKey) {\n return encodeKey(resolvedValue, calledKey);\n }\n return resolvedValue;\n };\n }\n\n // Nested object – recurse with updated key path\n if (typeof val === 'object' && val !== null) {\n return buildProxy(val as object, fullKey, options);\n }\n\n return val;\n },\n\n // Allow the proxy to be called directly (e.g. t('key') or t('key', { name: 'value' }))\n apply(target: any, thisArg, args: unknown[]) {\n const result = Reflect.apply(target, thisArg, args);\n const calledKey = extractKey(args[0], keyPrefix);\n\n const fallbackObj =\n options.fallback ??\n (typeof window !== 'undefined' ? (window as any).__livelocale_fallback__ : undefined);\n let resolvedValue = result;\n const isMissing =\n resolvedValue === undefined ||\n resolvedValue === null ||\n resolvedValue === '' ||\n (typeof resolvedValue === 'string' &&\n (resolvedValue === args[0] || resolvedValue === calledKey));\n\n if (isMissing && fallbackObj && calledKey) {\n const fbVal = getNestedProperty(fallbackObj, calledKey);\n if (fbVal !== undefined) {\n resolvedValue = fbVal;\n }\n }\n\n if (typeof resolvedValue === 'string' && calledKey) {\n return encodeKey(resolvedValue, calledKey);\n }\n return resolvedValue;\n },\n });\n}\n","/**\n * Recursively merges `source` into `target`.\n *\n * Arrays and primitives in `source` replace `target` values; plain objects\n * are merged depth-first.\n */\nexport function deepMerge(target: any, source: any): any {\n if (typeof target !== 'object' || target === null) return source;\n if (typeof source !== 'object' || source === null) return target;\n\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (key in target) {\n result[key] = deepMerge(target[key], source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n}\n","import { readFileSync, statSync } from 'fs';\n\ninterface CacheEntry {\n mtimeMs: number;\n size: number;\n data: unknown;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\n/** Drops every cached parse. Exposed for tests and for tooling that rewrites locale files. */\nexport function clearJsonCache(): void {\n cache.clear();\n}\n\n/**\n * Reads and parses a JSON file, reusing the previous parse while the file's\n * mtime and size are unchanged. One `stat` per call replaces a full read and\n * parse on every server render. Throws like `readFileSync` / `JSON.parse` do.\n *\n * Callers must treat the returned object as read-only: it is shared between calls.\n */\nexport function readJsonCached(filePath: string): any {\n let mtimeMs: number | undefined;\n let size: number | undefined;\n try {\n const stat = statSync(filePath);\n if (typeof stat?.mtimeMs === 'number') {\n mtimeMs = stat.mtimeMs;\n size = stat.size;\n }\n } catch {\n // Missing file: fall through so readFileSync raises the real error.\n }\n\n if (mtimeMs !== undefined) {\n const hit = cache.get(filePath);\n if (hit && hit.mtimeMs === mtimeMs && hit.size === size) {\n return hit.data;\n }\n }\n\n const data = JSON.parse(readFileSync(filePath, 'utf-8'));\n if (mtimeMs !== undefined && size !== undefined) {\n cache.set(filePath, { mtimeMs, size, data });\n }\n return data;\n}\n"],"mappings":"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","names":["fs","path","path","fs","fs","path","path","resolve","resolve","statSync","join","path","val","target","readFileSync","readFileSync","statSync","join"]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/file-mutator.ts","../../src/core/validate.ts","../../src/core/safe-path.ts","../../src/core/json-path.ts","../../src/server/key-scanner.ts","../../src/core/env.ts","../../src/core/gitignore.ts","../../src/server/git-client.ts","../../src/server/github-gateway.ts","../../src/core/placeholders.ts","../../src/server/router.ts","../../src/server/node-body.ts","../../src/server/next-handler.ts","../../src/server/translations.ts","../../src/client/watermark.ts","../../src/client/wrap.ts","../../src/core/deep-merge.ts","../../src/core/json-cache.ts"],"sourcesContent":["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\nfunction assertEnabled(component: string): void {\n const reason = getDisabledReason();\n if (reason !== null) {\n throw new Error(\n `[livelocale] ${component} can only be executed in development mode (${reason}).`\n );\n }\n}\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 class FileMutator {\n private fileLocks = new Map<string, FileMutex>();\n private scanner = new KeyScanner();\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 assertEnabled('FileMutator');\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 console.log(`[livelocale] Updated key '${keyPath}' in locale '${locale}'`);\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 assertEnabled('FileMutator');\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 assertEnabled('FileMutator');\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 assertEnabled('FileMutator');\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 assertEnabled('FileMutator');\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 assertEnabled('FileMutator');\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","/**\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 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 { 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/**\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","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 { 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","import type {\n MutationGateway,\n GitGateway,\n GitStatus,\n GitChange,\n GitChangeStatus,\n} from './router.js';\nimport {\n LOCALE_RE,\n isSafeLocaleSegment,\n isValidLocaleFormat,\n isSafeKeyPath,\n DANGEROUS_KEY_SEGMENTS,\n} from '../core/validate.js';\nimport { setNestedProperty, stringifyLike, flattenKeys } from '../core/json-path.js';\n\nexport interface GitHubGatewayConfig {\n /** `owner/name` */\n repo: string;\n /** Branch that receives one commit per save; created from `baseBranch` on first use. */\n branch: string;\n /** Pull-request target and the source for creating `branch`. Defaults to `main`. */\n baseBranch?: string;\n /** Token with `contents: write` and `pull_requests: write` on the repository. */\n token: string;\n /** Defaults to `https://api.github.com`; set for GitHub Enterprise Server. */\n apiBase?: string;\n /** Injectable fetch for tests. */\n fetchImpl?: typeof fetch;\n}\n\n/** A gateway that is both the translation store and the review workflow. */\nexport interface GitHubGateway extends MutationGateway, GitGateway {}\n\ninterface ContentFile {\n type: 'file';\n path: string;\n sha: string;\n content: string;\n encoding: string;\n}\n\ninterface ContentEntry {\n type: 'file' | 'dir' | string;\n name: string;\n path: string;\n}\n\ntype Contents = ContentFile | ContentEntry[] | null;\n\n/** A non-2xx answer from the GitHub REST API. */\nclass GitHubApiError extends Error {\n constructor(\n message: string,\n readonly status: number\n ) {\n super(message);\n this.name = 'GitHubApiError';\n }\n}\n\n/** Attempts per save when another writer changed the file between our read and our write. */\nconst MAX_WRITE_ATTEMPTS = 4;\n\n/**\n * True when a contents write lost a race: GitHub answers 409 when the blob sha\n * we sent is stale, and 422 when a file we thought was new now exists.\n */\nconst isWriteConflict = (err: unknown) =>\n err instanceof GitHubApiError &&\n (err.status === 409 || (err.status === 422 && /sha/i.test(err.message)));\n\nconst encodePath = (p: string) => p.split('/').map(encodeURIComponent).join('/');\n\nconst normalizeDir = (p: string) =>\n p.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/^\\/+/, '').replace(/\\/+$/, '');\n\nfunction mapCompareStatus(status: string): GitChangeStatus {\n switch (status) {\n case 'added':\n case 'copied':\n return 'added';\n case 'removed':\n return 'deleted';\n case 'renamed':\n return 'renamed';\n default:\n return 'modified';\n }\n}\n\n/**\n * Stores translations in a GitHub repository branch through the REST API, so\n * a hosted Studio can edit a preview deployment with no local checkout:\n * every save is a commit on `branch`, `commit` opens (or reuses) a pull\n * request to `baseBranch`, and `discard` resets the branch to base.\n *\n * Only paths under the locales directory are ever read or written.\n */\nexport function createGitHubGateway(config: GitHubGatewayConfig): GitHubGateway {\n const repo = config.repo;\n const branch = config.branch;\n const baseBranch = config.baseBranch ?? 'main';\n const apiBase = (config.apiBase ?? 'https://api.github.com').replace(/\\/+$/, '');\n const fetchImpl = config.fetchImpl ?? globalThis.fetch;\n const owner = repo.split('/')[0] ?? '';\n\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) {\n throw new Error(`[livelocale] github.repo must be \"owner/name\", got \"${repo}\".`);\n }\n if (typeof fetchImpl !== 'function') {\n throw new Error('[livelocale] The GitHub gateway needs a global fetch (Node 18+).');\n }\n\n // ─── Low-level API ───────────────────────────────────────────────────────\n\n async function api<T = any>(\n method: string,\n path: string,\n options: { body?: unknown; query?: Record<string, string>; allow404?: boolean } = {}\n ): Promise<{ status: number; data: T | null }> {\n const url = new URL(`${apiBase}/repos/${repo}${path}`);\n for (const [k, v] of Object.entries(options.query ?? {})) url.searchParams.set(k, v);\n const response = await fetchImpl(url.toString(), {\n method,\n headers: {\n Authorization: `Bearer ${config.token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n ...(options.body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n },\n body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n });\n let data: any = null;\n try {\n data = await response.json();\n } catch {}\n if (response.status === 404 && options.allow404) return { status: 404, data: null };\n if (!response.ok) {\n const detail = data?.message || 'request failed';\n const hint = /not accessible by/i.test(detail)\n ? ' The token lacks a permission: give it \"Contents\" and \"Pull requests\" with \"Read and write\" on this repository.'\n : '';\n throw new GitHubApiError(\n `GitHub API ${response.status} on ${method} ${path}: ${detail}.${hint}`,\n response.status\n );\n }\n return { status: response.status, data };\n }\n\n /** Raw status of a request that is expected to fail validation; never throws on 4xx. */\n async function probeStatus(method: string, path: string, body?: unknown): Promise<number> {\n const response = await fetchImpl(`${apiBase}/repos/${repo}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${config.token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n try {\n await response.arrayBuffer();\n } catch {}\n return response.status;\n }\n\n async function refSha(name: string): Promise<string | null> {\n const res = await api<{ object: { sha: string } }>(\n 'GET',\n `/git/ref/heads/${encodeURIComponent(name)}`,\n { allow404: true }\n );\n return res.data?.object?.sha ?? null;\n }\n\n let branchReady: Promise<void> | null = null;\n function ensureBranch(): Promise<void> {\n if (!branchReady) {\n branchReady = (async () => {\n if (await refSha(branch)) return;\n const base = await refSha(baseBranch);\n if (!base) throw new Error(`Base branch \"${baseBranch}\" does not exist in ${repo}.`);\n await api('POST', '/git/refs', { body: { ref: `refs/heads/${branch}`, sha: base } });\n })().catch((err) => {\n branchReady = null;\n throw err;\n });\n }\n return branchReady;\n }\n\n async function getContents(path: string): Promise<Contents> {\n await ensureBranch();\n const res = await api<Contents>('GET', `/contents/${encodePath(path)}`, {\n query: { ref: branch },\n allow404: true,\n });\n return res.data;\n }\n\n async function readFile(path: string): Promise<{ text: string; sha: string } | null> {\n const contents = await getContents(path);\n if (!contents || Array.isArray(contents) || contents.type !== 'file') return null;\n const text = Buffer.from(contents.content.replace(/\\n/g, ''), 'base64').toString('utf-8');\n return { text, sha: contents.sha };\n }\n\n async function putFile(path: string, text: string, message: string, sha?: string): Promise<void> {\n await ensureBranch();\n await api('PUT', `/contents/${encodePath(path)}`, {\n body: {\n message,\n content: Buffer.from(text, 'utf-8').toString('base64'),\n branch,\n ...(sha ? { sha } : {}),\n },\n });\n }\n\n async function deleteFile(path: string, message: string, sha: string): Promise<void> {\n await api('DELETE', `/contents/${encodePath(path)}`, { body: { message, sha, branch } });\n }\n\n // Saves to one file are queued in this process, and a save that still loses\n // a race (another serverless instance, another Studio) re-reads and retries.\n const fileQueues = new Map<string, Promise<unknown>>();\n function withFileLock<T>(path: string, fn: () => Promise<T>): Promise<T> {\n const previous = fileQueues.get(path) ?? Promise.resolve();\n const next = previous.then(fn, fn);\n const settled = next.then(\n () => {},\n () => {}\n );\n fileQueues.set(path, settled);\n settled.then(() => {\n if (fileQueues.get(path) === settled) fileQueues.delete(path);\n });\n return next;\n }\n\n async function retryOnConflict<T>(fn: () => Promise<T>): Promise<T> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await fn();\n } catch (err) {\n if (!isWriteConflict(err) || attempt >= MAX_WRITE_ATTEMPTS) throw err;\n await new Promise((resolve) => setTimeout(resolve, 150 * attempt));\n }\n }\n }\n\n // ─── Locale layout helpers ───────────────────────────────────────────────\n\n const flatPath = (base: string, locale: string) => `${normalizeDir(base)}/${locale}.json`;\n const dirPath = (base: string, locale: string) => `${normalizeDir(base)}/${locale}`;\n\n function assertLocale(locale: string): void {\n if (!isValidLocaleFormat(locale) || !isSafeLocaleSegment(locale)) {\n throw new Error(`[livelocale] Invalid locale \"${locale}\".`);\n }\n }\n\n async function namespaceFiles(base: string, locale: string): Promise<string[] | null> {\n const contents = await getContents(dirPath(base, locale));\n if (!contents || !Array.isArray(contents)) return null;\n return contents.filter((e) => e.type === 'file' && e.name.endsWith('.json')).map((e) => e.name);\n }\n\n // ─── MutationGateway ─────────────────────────────────────────────────────\n\n async function listLocales(basePath: string): Promise<string[]> {\n const contents = await getContents(normalizeDir(basePath));\n if (!contents || !Array.isArray(contents)) return [];\n const set = new Set<string>();\n for (const entry of contents) {\n if (entry.type === 'dir' && LOCALE_RE.test(entry.name)) set.add(entry.name);\n if (entry.type === 'file' && entry.name.endsWith('.json')) {\n const code = entry.name.slice(0, -5);\n if (LOCALE_RE.test(code)) set.add(code);\n }\n }\n return Array.from(set).sort();\n }\n\n async function readLocale(basePath: string, locale: string): Promise<Record<string, any>> {\n assertLocale(locale);\n const files = await namespaceFiles(basePath, locale);\n if (files) {\n const merged: Record<string, any> = {};\n for (const file of files) {\n const f = await readFile(`${dirPath(basePath, locale)}/${file}`);\n if (!f) continue;\n try {\n merged[file.slice(0, -5)] = JSON.parse(f.text);\n } catch {}\n }\n return merged;\n }\n const flat = await readFile(flatPath(basePath, locale));\n if (!flat) throw new Error(`Locale \"${locale}\" not found on branch ${branch}.`);\n return JSON.parse(flat.text);\n }\n\n async function updateLocaleKey(\n basePath: string,\n locale: string,\n keyPath: string,\n value: string\n ): Promise<void> {\n assertLocale(locale);\n if (!isSafeKeyPath(keyPath)) {\n throw new Error(`[livelocale] Forbidden key segment in path: \"${keyPath}\".`);\n }\n\n let filePath: string;\n let mutationKeyPath = keyPath;\n const files = await namespaceFiles(basePath, locale);\n if (files) {\n const firstDot = keyPath.indexOf('.');\n if (firstDot === -1) {\n throw new Error(\n '[livelocale] Invalid namespace key path: must contain at least one nested key.'\n );\n }\n const ns = keyPath.slice(0, firstDot);\n if (DANGEROUS_KEY_SEGMENTS.has(ns)) {\n throw new Error(`[livelocale] Forbidden namespace segment in path: \"${ns}\".`);\n }\n filePath = `${dirPath(basePath, locale)}/${ns}.json`;\n mutationKeyPath = keyPath.slice(firstDot + 1);\n } else {\n filePath = flatPath(basePath, locale);\n }\n\n await withFileLock(filePath, () =>\n retryOnConflict(async () => {\n const existing = await readFile(filePath);\n let data: Record<string, any> = {};\n if (existing) {\n const parsed = JSON.parse(existing.text);\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('[livelocale] Invalid locale file: root must be an object.');\n }\n data = parsed;\n }\n setNestedProperty(data, mutationKeyPath, value);\n await putFile(\n filePath,\n stringifyLike(data, existing?.text ?? null),\n `i18n(${locale}): update ${keyPath}`,\n existing?.sha\n );\n })\n );\n }\n\n async function localeExists(basePath: string, locale: string): Promise<boolean> {\n if (await namespaceFiles(basePath, locale)) return true;\n return (await readFile(flatPath(basePath, locale))) !== null;\n }\n\n async function addLocale(basePath: string, locale: string): Promise<void> {\n assertLocale(locale);\n if (await localeExists(basePath, locale)) {\n throw new Error(`[livelocale] Locale \"${locale}\" already exists.`);\n }\n // Mirror the existing layout: if any locale is a folder, create a folder.\n const contents = await getContents(normalizeDir(basePath));\n const referenceDir = Array.isArray(contents)\n ? contents.find((e) => e.type === 'dir' && LOCALE_RE.test(e.name))?.name\n : undefined;\n if (referenceDir) {\n const files = (await namespaceFiles(basePath, referenceDir)) ?? [];\n for (const file of files) {\n await putFile(`${dirPath(basePath, locale)}/${file}`, '{}\\n', `i18n: add locale ${locale}`);\n }\n } else {\n await putFile(flatPath(basePath, locale), '{}\\n', `i18n: add locale ${locale}`);\n }\n }\n\n async function renameLocale(\n basePath: string,\n oldLocale: string,\n newLocale: string\n ): Promise<void> {\n assertLocale(oldLocale);\n assertLocale(newLocale);\n if (!(await localeExists(basePath, oldLocale))) {\n throw new Error(`[livelocale] Locale \"${oldLocale}\" does not exist.`);\n }\n if (await localeExists(basePath, newLocale)) {\n throw new Error(`[livelocale] Target locale \"${newLocale}\" already exists.`);\n }\n const message = `i18n: rename locale ${oldLocale} to ${newLocale}`;\n const files = await namespaceFiles(basePath, oldLocale);\n if (files) {\n for (const file of files) {\n const f = await readFile(`${dirPath(basePath, oldLocale)}/${file}`);\n if (!f) continue;\n await putFile(`${dirPath(basePath, newLocale)}/${file}`, f.text, message);\n await deleteFile(`${dirPath(basePath, oldLocale)}/${file}`, message, f.sha);\n }\n return;\n }\n const flat = await readFile(flatPath(basePath, oldLocale));\n if (!flat) return;\n await putFile(flatPath(basePath, newLocale), flat.text, message);\n await deleteFile(flatPath(basePath, oldLocale), message, flat.sha);\n }\n\n async function deleteLocale(basePath: string, locale: string): Promise<void> {\n assertLocale(locale);\n const message = `i18n: delete locale ${locale}`;\n const files = await namespaceFiles(basePath, locale);\n if (files) {\n for (const file of files) {\n const f = await readFile(`${dirPath(basePath, locale)}/${file}`);\n if (f) await deleteFile(`${dirPath(basePath, locale)}/${file}`, message, f.sha);\n }\n return;\n }\n const flat = await readFile(flatPath(basePath, locale));\n if (!flat) throw new Error(`[livelocale] Locale \"${locale}\" does not exist.`);\n await deleteFile(flatPath(basePath, locale), message, flat.sha);\n }\n\n async function getKeysMetadata(\n basePath: string\n ): Promise<{ allKeys: string[]; codeKeys: string[] }> {\n const keys = new Set<string>();\n for (const locale of await listLocales(basePath)) {\n try {\n flattenKeys(await readLocale(basePath, locale), '', keys);\n } catch {}\n }\n // Scanning source for t('…') references would need a checkout; preview mode\n // reports locale keys only.\n return { allKeys: Array.from(keys).sort(), codeKeys: [] };\n }\n\n // ─── GitGateway ──────────────────────────────────────────────────────────\n\n async function compareFiles(\n basePath: string\n ): Promise<{ filename: string; status: string; patch?: string }[]> {\n await ensureBranch();\n const res = await api<{ files?: { filename: string; status: string; patch?: string }[] }>(\n 'GET',\n `/compare/${encodeURIComponent(baseBranch)}...${encodeURIComponent(branch)}`\n );\n const prefix = `${normalizeDir(basePath)}/`;\n return (res.data?.files ?? []).filter((f) => f.filename.startsWith(prefix));\n }\n\n async function openPullRequestUrl(): Promise<string | null> {\n const res = await api<{ html_url: string }[]>('GET', '/pulls', {\n query: { head: `${owner}:${branch}`, base: baseBranch, state: 'open' },\n });\n return res.data?.[0]?.html_url ?? null;\n }\n\n async function status(basePath: string): Promise<GitStatus> {\n const files = await compareFiles(basePath);\n const changes: GitChange[] = files.map((f) => ({\n path: f.filename,\n status: mapCompareStatus(f.status),\n }));\n return {\n isRepo: true,\n branch,\n changes,\n mode: 'github',\n pullRequestUrl: await openPullRequestUrl(),\n };\n }\n\n async function diff(basePath: string): Promise<string> {\n const files = await compareFiles(basePath);\n return files\n .map(\n (f) =>\n `diff --git a/${f.filename} b/${f.filename}\\n--- a/${f.filename}\\n+++ b/${f.filename}\\n${f.patch ?? '(binary or too large)'}\\n`\n )\n .join('');\n }\n\n async function commit(basePath: string, message: string): Promise<{ hash: string }> {\n const files = await compareFiles(basePath);\n if (files.length === 0) {\n throw new Error(`No changes to propose under ${normalizeDir(basePath)} on ${branch}.`);\n }\n const existing = await openPullRequestUrl();\n if (existing) return { hash: existing };\n const res = await api<{ html_url: string }>('POST', '/pulls', {\n body: {\n title: message,\n head: branch,\n base: baseBranch,\n body: 'Translation changes proposed from the LiveLocale Studio.',\n },\n });\n return { hash: res.data!.html_url };\n }\n\n async function discard(): Promise<void> {\n const base = await refSha(baseBranch);\n if (!base) throw new Error(`Base branch \"${baseBranch}\" does not exist in ${repo}.`);\n await ensureBranch();\n await api('PATCH', `/git/refs/heads/${encodeURIComponent(branch)}`, {\n body: { sha: base, force: true },\n });\n }\n\n /**\n * Verifies the token, the repository, the base branch, and write access.\n * Write access is probed with deliberately empty requests: GitHub answers\n * 422 (validation failed) when the token has the permission and 403 when it\n * does not, so nothing is created either way.\n */\n async function checkAccess(): Promise<string[]> {\n if (!config.token) {\n return ['No GitHub token configured (github.token / GITHUB_TOKEN is empty).'];\n }\n const repoStatus = await probeStatus('GET', '');\n if (repoStatus === 401) return ['The GitHub token is invalid or expired.'];\n if (repoStatus === 404 || repoStatus === 403) {\n return [`Repository ${repo} was not found, or the token has no access to it.`];\n }\n if (repoStatus >= 400) return [`GitHub answered HTTP ${repoStatus} for ${repo}.`];\n\n const problems: string[] = [];\n if (!(await refSha(baseBranch))) {\n problems.push(`Base branch \"${baseBranch}\" does not exist in ${repo}.`);\n }\n if ((await probeStatus('POST', '/git/blobs', {})) === 403) {\n problems.push(\n `The token cannot write to ${repo}: give it \"Contents: Read and write\" so saves can be committed.`\n );\n }\n if ((await probeStatus('POST', '/pulls', {})) === 403) {\n problems.push(\n `The token cannot open pull requests in ${repo}: give it \"Pull requests: Read and write\".`\n );\n }\n return problems;\n }\n\n return {\n checkAccess,\n listLocales,\n readLocale,\n updateLocaleKey,\n addLocale,\n renameLocale,\n deleteLocale,\n getKeysMetadata,\n status,\n diff,\n commit,\n discard,\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 { getDisabledReason, getLiveLocaleMode } from '../core/env.js';\nimport { comparePlaceholders, validateMessageSyntax } from '../core/placeholders.js';\nimport {\n isValidKeyFormat,\n isValidLocaleFormat,\n isValidValueFormat,\n isSafeKeyPath,\n} from '../core/validate.js';\n\n/**\n * Platform-agnostic port for translation file operations. The Next.js and\n * Vite adapters both depend on this narrow contract (DIP) instead of the\n * concrete FileMutator implementation.\n */\nexport interface MutationGateway {\n updateLocaleKey(basePath: string, locale: string, key: string, value: string): Promise<void>;\n listLocales(basePath: string): Promise<string[]>;\n /** Full dictionary for one locale (namespace folders merged). Rejects when missing. */\n readLocale(basePath: string, locale: string): Promise<Record<string, any>>;\n addLocale(basePath: string, locale: string): Promise<void>;\n renameLocale(basePath: string, locale: string, newLocale: string): Promise<void>;\n deleteLocale(basePath: string, locale: string): Promise<void>;\n getKeysMetadata(basePath: string): Promise<{ allKeys: string[]; codeKeys: string[] }>;\n}\n\nexport type GitChangeStatus = 'modified' | 'added' | 'deleted' | 'renamed';\n\nexport interface GitChange {\n /** Path relative to the repository root, forward slashes. */\n path: string;\n status: GitChangeStatus;\n}\n\nexport interface GitStatus {\n isRepo: boolean;\n branch: string | null;\n changes: GitChange[];\n /** `local` = git CLI on the developer machine, `github` = branch + pull request via API. */\n mode?: 'local' | 'github';\n /** Open pull request for the branch, when the gateway knows about one. */\n pullRequestUrl?: string | null;\n}\n\n/**\n * Optional port for version-control operations scoped to the locales\n * directory. Implemented by `GitClient`; absent when git integration is off.\n */\nexport interface GitGateway {\n status(localesPath: string): Promise<GitStatus>;\n diff(localesPath: string): Promise<string>;\n commit(localesPath: string, message: string): Promise<{ hash: string }>;\n discard(localesPath: string): Promise<void>;\n /**\n * Optional self-test of credentials and permissions. Returns human-readable\n * problems (empty when everything needed is in place). Reported by `?action=info`.\n */\n checkAccess?(): Promise<string[]>;\n}\n\nexport interface RouterRequest {\n method: string;\n url: string;\n origin: string;\n /** Raw request body for body-carrying methods; parsed by the router. */\n bodyText?: string;\n /** Value of the Authorization header, if any. */\n authorization?: string;\n /** Value of the Content-Type header (lowercased), if any. */\n contentType?: string;\n}\n\nexport interface RouterResponse {\n status: number;\n headers: Record<string, string>;\n body: string | null;\n}\n\nexport interface MutationRouterOptions {\n localesPath: string;\n allowedOrigins?: string[];\n /** Enables the `git` read action and the `commit` / `discard` write actions. */\n git?: GitGateway;\n /**\n * When set, every request except CORS preflight must carry\n * `Authorization: Bearer <authToken>`. Mandatory in preview mode.\n */\n authToken?: string;\n}\n\nexport interface MutationRouter {\n handle(request: RouterRequest): Promise<RouterResponse>;\n}\n\nconst DEFAULT_ALLOWED_ORIGINS = ['http://localhost:3010', 'http://127.0.0.1:3010'];\n\n/** Maximum accepted request body size (1 MB) — far above any realistic payload. */\nexport const MAX_BODY_BYTES = 1_000_000;\n\n/** Commit messages longer than this are rejected. */\nexport const MAX_COMMIT_MESSAGE_LENGTH = 500;\n\n/** Any localhost origin (any port) is trusted — remote websites are not. */\nconst LOCALHOST_ORIGIN_RE = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(:\\d+)?$/;\n\n/** Constant-time string comparison so token checks do not leak length or prefix. */\nfunction safeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n\nfunction bearerToken(authorization: string | undefined): string | null {\n if (!authorization) return null;\n const match = /^Bearer\\s+(.+)$/i.exec(authorization.trim());\n return match ? match[1]!.trim() : null;\n}\n\nconst json = (\n status: number,\n headers: Record<string, string>,\n payload: unknown\n): RouterResponse => ({\n status,\n headers,\n body: JSON.stringify(payload),\n});\n\n/**\n * The single implementation of the livelocale mutation API.\n *\n * Both the Next.js route handler and the Vite dev-server middleware are thin\n * adapters over this router, so validation, CORS, and error handling live in\n * exactly one place (OCP).\n */\nexport function createMutationRouter(\n mutator: MutationGateway,\n options: MutationRouterOptions\n): MutationRouter {\n // Extra origins may be supplied at run time (GitHub Codespaces, Gitpod,\n // custom HTTPS dev hostnames) without touching code:\n // LIVELOCALE_ALLOWED_ORIGINS=\"https://abc-3010.app.github.dev,https://studio.dev.local\"\n const envOrigins = (process.env['LIVELOCALE_ALLOWED_ORIGINS'] || '')\n .split(',')\n .map((o) => o.trim())\n .filter(Boolean);\n const allowedOrigins = [...(options.allowedOrigins || DEFAULT_ALLOWED_ORIGINS), ...envOrigins];\n const localesPath = options.localesPath;\n const git = options.git;\n const authToken = options.authToken && options.authToken.length > 0 ? options.authToken : null;\n\n const isOriginAllowed = (origin: string): boolean =>\n allowedOrigins.includes(origin) || LOCALHOST_ORIGIN_RE.test(origin);\n\n const resolveAllowedOrigin = (origin: string): string => {\n return isOriginAllowed(origin) ? origin : allowedOrigins[0] || '';\n };\n\n const corsHeaders = (origin: string): Record<string, string> => ({\n 'Access-Control-Allow-Origin': resolveAllowedOrigin(origin),\n 'Access-Control-Allow-Methods': 'POST, OPTIONS, GET',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n 'Content-Type': 'application/json',\n });\n\n // A passing access check is remembered; a failing one is re-run on every\n // `info` call so fixing the token takes effect without a restart.\n let accessOk = false;\n async function accessProblems(): Promise<string[]> {\n if (!git?.checkAccess || accessOk) return [];\n try {\n const problems = await git.checkAccess();\n accessOk = problems.length === 0;\n return problems;\n } catch (err: any) {\n return [`Could not verify repository access: ${err?.message || err}`];\n }\n }\n\n // ─── GET: Fetch locale dictionary, list locales, or fetch keys metadata ───\n\n async function handleGet(\n urlObj: URL,\n basePath: string,\n headers: Record<string, string>\n ): Promise<RouterResponse> {\n const locale = urlObj.searchParams.get('locale');\n const action = urlObj.searchParams.get('action');\n\n if (action === 'info') {\n return json(200, headers, {\n mode: getLiveLocaleMode(),\n authRequired: authToken !== null,\n git: Boolean(git),\n problems: await accessProblems(),\n });\n }\n\n if (action === 'git') {\n if (!git) {\n return json(200, headers, {\n available: false,\n isRepo: false,\n branch: null,\n changes: [],\n diff: '',\n });\n }\n try {\n const status = await git.status(basePath);\n const diff = status.isRepo && status.changes.length > 0 ? await git.diff(basePath) : '';\n return json(200, headers, { available: true, ...status, diff });\n } catch (err: any) {\n return json(500, headers, {\n error: `Failed to read git status: ${err.message}`,\n code: 'GIT_STATUS_FAILED',\n });\n }\n }\n\n if (action === 'keys') {\n try {\n const metadata = await mutator.getKeysMetadata(basePath);\n return json(200, headers, metadata);\n } catch (err: any) {\n return json(500, headers, {\n error: `Failed to fetch keys metadata: ${err.message}`,\n code: 'KEYS_METADATA_FAILED',\n });\n }\n }\n\n if (!locale) {\n try {\n const localesList = await mutator.listLocales(basePath);\n return json(200, headers, localesList);\n } catch (err: any) {\n return json(500, headers, {\n error: `Failed to list locales: ${err.message}`,\n code: 'LIST_LOCALES_FAILED',\n });\n }\n }\n\n if (!isValidLocaleFormat(locale)) {\n return json(400, headers, {\n error: 'Invalid locale string parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n\n try {\n return json(200, headers, await mutator.readLocale(basePath, locale));\n } catch (readErr: any) {\n return json(404, headers, {\n error: `Failed to load locale: ${readErr.message}`,\n code: 'LOCALE_LOAD_FAILED',\n });\n }\n }\n\n // ─── POST: Mutate a translation key or manage locales ────────────────────\n\n async function handlePost(\n bodyText: string | undefined,\n basePath: string,\n headers: Record<string, string>\n ): Promise<RouterResponse> {\n let body: any;\n try {\n body = JSON.parse(bodyText ?? '');\n } catch {\n return json(400, headers, {\n error: 'Invalid JSON request body',\n code: 'BAD_REQUEST',\n });\n }\n\n const { locale, key, value, action, newLocale, message, reference, force } = body || {};\n\n if (action === 'commit' || action === 'discard') {\n if (!git) {\n return json(501, headers, {\n error: 'Git integration is not enabled for this handler.',\n code: 'GIT_UNAVAILABLE',\n });\n }\n if (action === 'commit') {\n const text = typeof message === 'string' ? message.trim() : '';\n if (!text || text.length > MAX_COMMIT_MESSAGE_LENGTH) {\n return json(400, headers, {\n error: `Commit message must be 1-${MAX_COMMIT_MESSAGE_LENGTH} characters.`,\n code: 'INVALID_COMMIT_MESSAGE',\n });\n }\n try {\n const result = await git.commit(basePath, text);\n return json(200, headers, { success: true, hash: result.hash });\n } catch (err: any) {\n return json(409, headers, { error: err.message, code: 'GIT_COMMIT_FAILED' });\n }\n }\n try {\n await git.discard(basePath);\n return json(200, headers, { success: true });\n } catch (err: any) {\n return json(500, headers, { error: err.message, code: 'GIT_DISCARD_FAILED' });\n }\n }\n\n if (action === 'addLocale') {\n if (!isValidLocaleFormat(locale)) {\n return json(400, headers, {\n error: 'Invalid locale string parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n await mutator.addLocale(basePath, locale);\n return json(200, headers, { success: true, locale });\n }\n\n if (action === 'renameLocale') {\n if (!isValidLocaleFormat(locale) || !isValidLocaleFormat(newLocale)) {\n return json(400, headers, {\n error: 'Invalid oldLocale or newLocale parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n await mutator.renameLocale(basePath, locale, newLocale);\n return json(200, headers, { success: true, locale, newLocale });\n }\n\n if (action === 'deleteLocale') {\n if (!isValidLocaleFormat(locale)) {\n return json(400, headers, {\n error: 'Invalid locale string parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n await mutator.deleteLocale(basePath, locale);\n return json(200, headers, { success: true, locale });\n }\n\n if (!isValidLocaleFormat(locale)) {\n return json(400, headers, {\n error: 'Invalid locale string parameter.',\n code: 'INVALID_LOCALE_FORMAT',\n });\n }\n\n if (!isValidKeyFormat(key)) {\n return json(400, headers, {\n error:\n 'Invalid key path. Must be 1-200 characters containing alphanumeric, dots, underscores, or hyphens.',\n code: 'INVALID_KEY_FORMAT',\n });\n }\n\n if (!isSafeKeyPath(key)) {\n return json(400, headers, {\n error:\n 'Forbidden key path: segments like __proto__, constructor, or prototype are not allowed.',\n code: 'INVALID_KEY_FORMAT',\n });\n }\n\n if (!isValidValueFormat(value)) {\n return json(400, headers, {\n error: 'Invalid value. Must be a string less than 10000 characters.',\n code: 'INVALID_VALUE_FORMAT',\n });\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 (force !== true) {\n const syntaxError = validateMessageSyntax(value);\n if (syntaxError) {\n return json(422, headers, {\n error: `Message syntax: ${syntaxError}.`,\n code: 'MESSAGE_SYNTAX',\n });\n }\n if (typeof reference === 'string') {\n const comparison = comparePlaceholders(reference, 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 json(422, headers, {\n error: `Placeholders differ from the reference: ${parts.join('; ')}.`,\n code: 'PLACEHOLDER_MISMATCH',\n details: { missing: comparison.missing, extra: comparison.extra },\n });\n }\n }\n }\n\n await mutator.updateLocaleKey(basePath, locale, key, value);\n\n return json(200, headers, { success: true, key, locale });\n }\n\n return {\n async handle(request: RouterRequest): Promise<RouterResponse> {\n const headers = corsHeaders(request.origin);\n\n // RULE GEN-001: DEVELOPMENT-ONLY ENFORCEMENT\n const disabledReason = getDisabledReason();\n if (disabledReason !== null) {\n return json(403, headers, {\n error: `Forbidden: LiveLocale is disabled — ${disabledReason}. It only runs in development mode.`,\n code: 'FORBIDDEN',\n });\n }\n\n // Preflight never carries credentials; let it through so the browser can\n // learn that Authorization is an allowed header.\n if (request.method === 'OPTIONS') {\n return { status: 204, headers, body: null };\n }\n\n // RULE SEC-011: PREVIEW MODE REQUIRES A TOKEN — the API is reachable from the\n // internet in this mode, so refuse to serve anything without one configured.\n if (getLiveLocaleMode() === 'preview' && !authToken) {\n return json(403, headers, {\n error:\n 'Preview mode requires an access token. Set LIVELOCALE_TOKEN (or pass authToken) on the server.',\n code: 'PREVIEW_TOKEN_REQUIRED',\n });\n }\n\n // RULE SEC-012: BEARER AUTH — when a token is configured, every request needs it.\n if (authToken) {\n const presented = bearerToken(request.authorization);\n if (!presented || !safeEqual(presented, authToken)) {\n return json(401, headers, {\n error: 'Unauthorized: a valid Authorization: Bearer token is required.',\n code: 'UNAUTHORIZED',\n });\n }\n }\n\n // RULE SEC-006: CSRF PREVENTION — hard-reject writes from disallowed origins\n // (browsers always send Origin on cross-origin POSTs, including no-cors ones).\n if (request.method === 'POST' && request.origin && !isOriginAllowed(request.origin)) {\n return json(403, headers, {\n error: 'Forbidden: request origin is not allowed.',\n code: 'FORBIDDEN_ORIGIN',\n });\n }\n\n // RULE SEC-006: require a JSON content type on writes so the no-cors\n // \"text/plain\" CSRF vector cannot bypass validation via simple requests.\n if (\n request.method === 'POST' &&\n request.contentType &&\n !request.contentType.includes('application/json')\n ) {\n return json(415, headers, {\n error: 'Content-Type must be application/json.',\n code: 'UNSUPPORTED_MEDIA_TYPE',\n });\n }\n\n try {\n if (request.method === 'GET') {\n const urlObj = new URL(request.url, 'http://localhost');\n return await handleGet(urlObj, localesPath, headers);\n }\n\n if (request.method === 'POST') {\n return await handlePost(request.bodyText, localesPath, headers);\n }\n\n // Unsupported method\n return json(405, headers, {\n error: 'Method Not Allowed',\n code: 'METHOD_NOT_ALLOWED',\n });\n } catch (err: any) {\n return json(500, headers, {\n error: err.message || 'Internal Server Error',\n code: 'INTERNAL_ERROR',\n });\n }\n },\n };\n}\n","/**\n * Minimal structural type for a Node `http.IncomingMessage`-like request.\n * Used by the Pages Router adapter and the Vite middleware so neither needs\n * to import `next` or `vite` types.\n */\nexport interface NodeRequestLike {\n method?: string;\n url?: string;\n headers: Record<string, string | string[] | undefined>;\n on(event: 'data', cb: (chunk: Buffer | string) => void): unknown;\n on(event: 'end', cb: () => void): unknown;\n on(event: 'error', cb: (err: Error) => void): unknown;\n destroy?(): void;\n}\n\n/** Minimal structural type for a Node `http.ServerResponse`-like response. */\nexport interface NodeResponseLike {\n statusCode: number;\n setHeader(name: string, value: string): unknown;\n end(chunk?: string): unknown;\n}\n\nexport class BodyTooLargeError extends Error {\n readonly code = 'BODY_TOO_LARGE';\n constructor() {\n super('Request body too large.');\n this.name = 'BodyTooLargeError';\n }\n}\n\n/**\n * Buffers a Node request body as UTF-8 text, rejecting with\n * `BodyTooLargeError` as soon as `maxBytes` is exceeded (RULE SEC-007).\n */\nexport function readNodeBody(req: NodeRequestLike, maxBytes: number): Promise<string> {\n return new Promise((resolve, reject) => {\n let bodyText = '';\n let settled = false;\n req.on('data', (chunk) => {\n if (settled) return;\n bodyText += chunk.toString();\n if (Buffer.byteLength(bodyText, 'utf-8') > maxBytes) {\n settled = true;\n reject(new BodyTooLargeError());\n req.destroy?.();\n }\n });\n req.on('end', () => {\n if (settled) return;\n settled = true;\n resolve(bodyText);\n });\n req.on('error', (err) => {\n if (settled) return;\n settled = true;\n reject(err);\n });\n });\n}\n\n/** Returns the first value of a possibly multi-valued Node header, lowercased name expected. */\nexport function headerValue(\n headers: Record<string, string | string[] | undefined>,\n name: string\n): string {\n const raw = headers[name];\n if (Array.isArray(raw)) return raw[0] ?? '';\n return raw ?? '';\n}\n","import { FileMutator } from './file-mutator.js';\nimport { GitClient } from './git-client.js';\nimport { createGitHubGateway, type GitHubGatewayConfig } from './github-gateway.js';\nimport { createMutationRouter, MAX_BODY_BYTES, type RouterResponse } from './router.js';\nimport {\n readNodeBody,\n headerValue,\n BodyTooLargeError,\n type NodeRequestLike,\n type NodeResponseLike,\n} from './node-body.js';\n\nexport interface HandlerConfig {\n /** Locales directory: absolute on disk, or repository-relative when `github` is set. */\n localesPath: string;\n allowedOrigins?: string[];\n /**\n * Expose git status, commit, and discard for the locales directory to the\n * Studio. Requires the `git` CLI on PATH. Defaults to `true`.\n */\n git?: boolean;\n /**\n * Bearer token required on every request. Defaults to the `LIVELOCALE_TOKEN`\n * environment variable. Mandatory in preview mode.\n */\n authToken?: string;\n /**\n * Store translations on a GitHub branch instead of the local filesystem\n * (preview mode for hosted editing). Each save becomes a commit; the\n * Studio's commit action opens a pull request.\n */\n github?: GitHubGatewayConfig;\n}\n\n/**\n * A handler that works as both a Next.js App Router route handler\n * (`(request: Request) => Promise<Response>`) and a Pages Router API route\n * (`(req, res) => Promise<void>`). The shape is detected per call.\n */\nexport interface LiveLocaleHandler {\n (request: Request): Promise<Response>;\n (req: NodeRequestLike, res: NodeResponseLike): Promise<void>;\n}\n\nconst TOO_LARGE: RouterResponse = {\n status: 413,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ error: 'Request body too large.', code: 'BODY_TOO_LARGE' }),\n};\n\nfunction isNodeResponse(value: unknown): value is NodeResponseLike {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as NodeResponseLike).setHeader === 'function' &&\n typeof (value as NodeResponseLike).end === 'function'\n );\n}\n\n/**\n * Creates a Next.js route handler (App Router or Pages Router) backed by the\n * unified mutation router. Handles GET, POST, and OPTIONS requests.\n */\nexport function createLiveLocaleHandler(config: HandlerConfig): LiveLocaleHandler {\n const github = config.github ? createGitHubGateway(config.github) : null;\n const mutator = github ?? new FileMutator();\n const git = github ?? (config.git === false ? undefined : new GitClient());\n const router = createMutationRouter(mutator, {\n localesPath: config.localesPath,\n allowedOrigins: config.allowedOrigins,\n git,\n authToken: config.authToken ?? process.env['LIVELOCALE_TOKEN'],\n });\n\n // ─── App Router: Web Request / Response ──────────────────────────────────\n\n async function handleWeb(request: Request): Promise<Response> {\n // RULE SEC-007: BODY SIZE CAP — reject oversized bodies before buffering\n const contentLength = Number(request.headers.get('content-length') || 0);\n if (contentLength > MAX_BODY_BYTES) {\n return toWebResponse(TOO_LARGE);\n }\n\n let bodyText: string | undefined;\n if (request.method === 'POST') {\n bodyText = await request.text().catch(() => '');\n if (Buffer.byteLength(bodyText, 'utf-8') > MAX_BODY_BYTES) {\n return toWebResponse(TOO_LARGE);\n }\n }\n\n const result = await router.handle({\n method: request.method,\n url: request.url,\n origin: request.headers.get('origin') || '',\n contentType: request.headers.get('content-type') || '',\n authorization: request.headers.get('authorization') || undefined,\n bodyText,\n });\n\n return toWebResponse(result);\n }\n\n // ─── Pages Router: Node IncomingMessage / ServerResponse ─────────────────\n\n async function handleNode(req: NodeRequestLike, res: NodeResponseLike): Promise<void> {\n const method = req.method || 'GET';\n let result: RouterResponse;\n\n try {\n const contentLength = Number(headerValue(req.headers, 'content-length') || 0);\n if (contentLength > MAX_BODY_BYTES) {\n throw new BodyTooLargeError();\n }\n\n result = await router.handle({\n method,\n url: req.url || '/',\n origin: headerValue(req.headers, 'origin'),\n contentType: headerValue(req.headers, 'content-type'),\n authorization: headerValue(req.headers, 'authorization') || undefined,\n bodyText: method === 'POST' ? await readNodeBody(req, MAX_BODY_BYTES) : undefined,\n });\n } catch (err: any) {\n result =\n err instanceof BodyTooLargeError\n ? TOO_LARGE\n : {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n error: err?.message || 'Internal Server Error',\n code: 'INTERNAL_ERROR',\n }),\n };\n }\n\n for (const [name, value] of Object.entries(result.headers)) {\n res.setHeader(name, value);\n }\n res.statusCode = result.status;\n res.end(result.body ?? '');\n }\n\n function liveLocaleHandler(request: Request): Promise<Response>;\n function liveLocaleHandler(req: NodeRequestLike, res: NodeResponseLike): Promise<void>;\n function liveLocaleHandler(\n reqOrRequest: Request | NodeRequestLike,\n res?: NodeResponseLike\n ): Promise<Response> | Promise<void> {\n if (isNodeResponse(res)) {\n return handleNode(reqOrRequest as NodeRequestLike, res);\n }\n return handleWeb(reqOrRequest as Request);\n }\n\n return liveLocaleHandler;\n}\n\nfunction toWebResponse(result: RouterResponse): Response {\n return new Response(result.body, { status: result.status, headers: result.headers });\n}\n","import { readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { wrapTranslationEngine } from '../client/wrap.js';\nimport { deepMerge } from '../core/deep-merge.js';\nimport { isLiveLocaleEnabled } from '../core/env.js';\nimport { readJsonCached } from '../core/json-cache.js';\n\nexport interface CreateTranslationsOptions {\n /**\n * Directory containing locale JSON files.\n * @default `process.cwd() + '/locales'`\n */\n localesDir?: string;\n\n /**\n * List of accepted locale codes. Any locale not in this list falls back to\n * `fallbackLocale` to prevent path-traversal attacks.\n * @default `['en']`\n */\n supportedLocales?: string[];\n\n /**\n * Locale to use when the requested locale is unsupported or its file is\n * missing.\n * @default `'en'`\n */\n fallbackLocale?: string;\n}\n\nfunction isDirectory(p: string): boolean {\n try {\n return statSync(p).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** Reads every `*.json` in `dir` into `{ [namespace]: data }`, skipping unparsable files. */\nfunction readNamespaceDir(dir: string): Record<string, any> {\n const out: Record<string, any> = {};\n for (const file of readdirSync(dir)) {\n if (!file.endsWith('.json')) continue;\n try {\n out[file.slice(0, -5)] = readJsonCached(join(dir, file));\n } catch {}\n }\n return out;\n}\n\n/**\n * Loads a locale JSON file and returns a type-safe translation object that\n * is automatically watermarked in development (for zero-migration studio\n * integration) and returned as-is in production.\n *\n * File parses are cached by mtime and size (see `core/json-cache.ts`), so\n * repeated server renders cost one `stat` per file instead of a read and parse.\n *\n * This is the recommended entry-point for Server Components — no manual\n * `wrapTranslationEngine` call needed.\n *\n * @example\n * ```tsx\n * // app/page.tsx\n * import { createTranslations } from 'livelocale/server';\n *\n * export default async function Page({ searchParams }) {\n * const { locale = 'en' } = await searchParams;\n * const t = createTranslations(locale, {\n * supportedLocales: ['en', 'ar', 'es'],\n * });\n * return <h1>{t.home?.title}</h1>;\n * }\n * ```\n */\nexport function createTranslations(\n locale: string,\n options: CreateTranslationsOptions = {}\n): Record<string, any> {\n const {\n localesDir = join(process.cwd(), 'locales'),\n supportedLocales = ['en'],\n fallbackLocale = 'en',\n } = options;\n\n // SECURITY: reject locales not in the allow-list to prevent path traversal\n const safeLocale = supportedLocales.includes(locale) ? locale : fallbackLocale;\n\n const loadFlatFile = (dir: string, loc: string, fallback: string): Record<string, any> => {\n try {\n return readJsonCached(join(dir, `${loc}.json`));\n } catch {\n try {\n return readJsonCached(join(dir, `${fallback}.json`));\n } catch {\n return {};\n }\n }\n };\n\n const localePath = join(localesDir, safeLocale);\n let data: Record<string, any> = {};\n\n if (isDirectory(localePath)) {\n try {\n data = readNamespaceDir(localePath);\n } catch {\n data = loadFlatFile(localesDir, safeLocale, fallbackLocale);\n }\n } else {\n data = loadFlatFile(localesDir, safeLocale, fallbackLocale);\n }\n\n // In development, merge every other locale into a fallback dictionary so\n // untranslated keys still render (and stay editable) in the Studio.\n let fallbackData: Record<string, any> = {};\n if (isLiveLocaleEnabled()) {\n try {\n for (const entry of readdirSync(localesDir)) {\n if (entry.startsWith('.') || entry === safeLocale) continue;\n const entryPath = join(localesDir, entry);\n\n if (isDirectory(entryPath)) {\n try {\n const namespaces = readNamespaceDir(entryPath);\n for (const ns of Object.keys(namespaces)) {\n fallbackData[ns] = deepMerge(fallbackData[ns] || {}, namespaces[ns]);\n }\n } catch {}\n } else if (entry.endsWith('.json')) {\n if (entry.slice(0, -5) === safeLocale) continue;\n try {\n fallbackData = deepMerge(fallbackData, readJsonCached(entryPath));\n } catch {}\n }\n }\n } catch {}\n }\n\n return wrapTranslationEngine(data, { fallback: fallbackData });\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 { encodeKey } from './watermark.js';\nimport { isLiveLocaleEnabled } from '../core/env.js';\n\nexport interface WrapOptions {\n /**\n * A dot-separated key prefix to prepend to all resolved key paths.\n *\n * Use this when wrapping a namespaced translation function (e.g.\n * react-i18next `useTranslation('home')` or next-intl `useTranslations('home')`)\n * so that the watermarked key matches the actual path in your locale JSON file.\n *\n * @example\n * const { t: rawT } = useTranslation('home');\n * const t = wrapTranslationEngine(rawT, { keyPrefix: 'home' });\n * // t('title') encodes as 'home.title' — matches the JSON structure\n */\n keyPrefix?: string;\n\n /**\n * Optional fallback translations to use when the target key is missing.\n */\n fallback?: Record<string, any>;\n}\n\n/**\n * Helper that extracts a dot-notated key string from an argument (string or object descriptor).\n */\nfunction extractKey(arg: unknown, keyPrefix: string): string {\n if (typeof arg === 'string') {\n return keyPrefix ? `${keyPrefix}.${arg}` : arg;\n }\n if (arg && typeof arg === 'object') {\n const obj = arg as Record<string, any>;\n if (typeof obj.id === 'string' && obj.id.trim() !== '') {\n return keyPrefix ? `${keyPrefix}.${obj.id}` : obj.id;\n }\n if (typeof obj.key === 'string' && obj.key.trim() !== '') {\n return keyPrefix ? `${keyPrefix}.${obj.key}` : obj.key;\n }\n }\n return keyPrefix;\n}\n\n/**\n * Wraps any translation function or record (e.g. from next-intl, react-i18next,\n * FormatJS, or a plain locale object loaded server-side) with a JavaScript Proxy\n * that automatically encodes translation keys as invisible zero-width watermark\n * prefixes in development. In production the proxy is transparent — the original\n * engine is returned as-is.\n */\nexport function wrapTranslationEngine<T extends object>(engine: T, options: WrapOptions = {}): T {\n if (!isLiveLocaleEnabled()) {\n return engine;\n }\n\n return buildProxy(engine, options.keyPrefix ?? '', options);\n}\n\n/**\n * Dedicated convenience wrapper for `next-intl` (App Router and Pages Router).\n * Automatically wraps `useTranslations(namespace)` or `getTranslations(namespace)`.\n *\n * @example\n * ```tsx\n * const t = wrapNextIntl(useTranslations('auth'), 'auth');\n * return <h1>{t('login.title')}</h1>;\n * ```\n */\nexport function wrapNextIntl<T extends object>(t: T, namespace?: string): T {\n return wrapTranslationEngine(t, { keyPrefix: namespace });\n}\n\nfunction getNestedProperty(obj: any, path: string): any {\n if (!obj || typeof obj !== 'object') return undefined;\n if (path in obj) {\n return obj[path];\n }\n const parts = path.split('.');\n let current = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n current = current[part];\n }\n return current;\n}\n\nfunction buildProxy<T extends object>(target: T, keyPrefix: string, options: WrapOptions): T {\n return new Proxy(target, {\n get(obj, prop: string | symbol) {\n if (typeof prop !== 'string') {\n const val = Reflect.get(obj, prop);\n return typeof val === 'object' && val !== null\n ? buildProxy(val as object, keyPrefix, options)\n : val;\n }\n\n let val = Reflect.get(obj, prop);\n const fullKey = keyPrefix ? `${keyPrefix}.${prop}` : prop;\n\n // If val is missing, try looking it up in fallback\n const fallbackObj =\n options.fallback ??\n (typeof window !== 'undefined' ? (window as any).__livelocale_fallback__ : undefined);\n if (val === undefined && fallbackObj) {\n const fbVal = getNestedProperty(fallbackObj, fullKey);\n if (fbVal !== undefined) {\n val = fbVal;\n }\n }\n\n // Leaf string value – encode it with its full key path\n if (typeof val === 'string') {\n return encodeKey(val, fullKey);\n }\n\n // Function (e.g. t() or t.raw() or t.rich() from next-intl) – wrap the call result\n if (typeof val === 'function') {\n return (...args: unknown[]) => {\n const result = (val as (...args: unknown[]) => unknown).apply(obj, args);\n const calledKey = extractKey(args[0], fullKey);\n\n let resolvedValue = result;\n const isMissing =\n resolvedValue === undefined ||\n resolvedValue === null ||\n resolvedValue === '' ||\n (typeof resolvedValue === 'string' &&\n (resolvedValue === args[0] || resolvedValue === calledKey));\n\n if (isMissing && fallbackObj && calledKey) {\n const fbVal = getNestedProperty(fallbackObj, calledKey);\n if (fbVal !== undefined) {\n resolvedValue = fbVal;\n }\n }\n\n if (typeof resolvedValue === 'string' && calledKey) {\n return encodeKey(resolvedValue, calledKey);\n }\n return resolvedValue;\n };\n }\n\n // Nested object – recurse with updated key path\n if (typeof val === 'object' && val !== null) {\n return buildProxy(val as object, fullKey, options);\n }\n\n return val;\n },\n\n // Allow the proxy to be called directly (e.g. t('key') or t('key', { name: 'value' }))\n apply(target: any, thisArg, args: unknown[]) {\n const result = Reflect.apply(target, thisArg, args);\n const calledKey = extractKey(args[0], keyPrefix);\n\n const fallbackObj =\n options.fallback ??\n (typeof window !== 'undefined' ? (window as any).__livelocale_fallback__ : undefined);\n let resolvedValue = result;\n const isMissing =\n resolvedValue === undefined ||\n resolvedValue === null ||\n resolvedValue === '' ||\n (typeof resolvedValue === 'string' &&\n (resolvedValue === args[0] || resolvedValue === calledKey));\n\n if (isMissing && fallbackObj && calledKey) {\n const fbVal = getNestedProperty(fallbackObj, calledKey);\n if (fbVal !== undefined) {\n resolvedValue = fbVal;\n }\n }\n\n if (typeof resolvedValue === 'string' && calledKey) {\n return encodeKey(resolvedValue, calledKey);\n }\n return resolvedValue;\n },\n });\n}\n","/**\n * Recursively merges `source` into `target`.\n *\n * Arrays and primitives in `source` replace `target` values; plain objects\n * are merged depth-first.\n */\nexport function deepMerge(target: any, source: any): any {\n if (typeof target !== 'object' || target === null) return source;\n if (typeof source !== 'object' || source === null) return target;\n\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (key in target) {\n result[key] = deepMerge(target[key], source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n}\n","import { readFileSync, statSync } from 'fs';\n\ninterface CacheEntry {\n mtimeMs: number;\n size: number;\n data: unknown;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\n/** Drops every cached parse. Exposed for tests and for tooling that rewrites locale files. */\nexport function clearJsonCache(): void {\n cache.clear();\n}\n\n/**\n * Reads and parses a JSON file, reusing the previous parse while the file's\n * mtime and size are unchanged. One `stat` per call replaces a full read and\n * parse on every server render. Throws like `readFileSync` / `JSON.parse` do.\n *\n * Callers must treat the returned object as read-only: it is shared between calls.\n */\nexport function readJsonCached(filePath: string): any {\n let mtimeMs: number | undefined;\n let size: number | undefined;\n try {\n const stat = statSync(filePath);\n if (typeof stat?.mtimeMs === 'number') {\n mtimeMs = stat.mtimeMs;\n size = stat.size;\n }\n } catch {\n // Missing file: fall through so readFileSync raises the real error.\n }\n\n if (mtimeMs !== undefined) {\n const hit = cache.get(filePath);\n if (hit && hit.mtimeMs === mtimeMs && hit.size === size) {\n return hit.data;\n }\n }\n\n const data = JSON.parse(readFileSync(filePath, 'utf-8'));\n if (mtimeMs !== undefined && size !== undefined) {\n cache.set(filePath, { mtimeMs, size, data });\n }\n return data;\n}\n"],"mappings":"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","names":["fs","path","path","fs","fs","path","path","resolve","resolve","statSync","join","path","val","target","readFileSync","readFileSync","statSync","join"]}
|