@takuhon/cli 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -3
- package/dist/index.js +276 -13
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +19 -0
- package/dist/init.js +44 -36
- package/dist/init.js.map +1 -1
- package/package.json +6 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/build-command.ts","../src/backup.ts","../src/site.ts","../src/build-html.ts","../src/dev-command.ts","../src/export-command.ts","../src/import-command.ts","../src/migrate-command.ts","../src/restore-command.ts","../src/validate-command.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * `@takuhon/cli` entry point — the `takuhon` command.\n *\n * Exposes `--version` / `--help`, the local profile commands (`validate`,\n * `migrate`, `restore`, `export`, `import`, `build`, `dev`), and a pointer to\n * `create-takuhon` for scaffolding. The `sync` subcommand lands in a subsequent\n * release.\n *\n * `main` is pure (returns an exit code, never calls `process.exit`); the only\n * place that exits the process is {@link run}, invoked either when this module\n * is the entry script or by the bare-name `takuhon` package's `bin.mjs`, which\n * imports and calls `run()`. Keeping `process.exit` at that single boundary\n * lets tests import this module without terminating the test runner.\n */\n\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { stdin, stdout } from 'node:process';\nimport { createInterface } from 'node:readline/promises';\nimport { fileURLToPath } from 'node:url';\n\nimport { runBuild } from './build-command.js';\nimport { runDev } from './dev-command.js';\nimport { runExport } from './export-command.js';\nimport { runImport } from './import-command.js';\nimport { runMigrate } from './migrate-command.js';\nimport { runRestore } from './restore-command.js';\nimport { runValidate } from './validate-command.js';\n\n// Source the reported version from package.json (read at runtime relative to\n// this module) so `takuhon --version` can never drift from the published\n// release — there is no hand-maintained version literal to fall out of sync.\nconst pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as {\n version: string;\n};\nconst VERSION = pkg.version;\n\nconst HELP = `takuhon ${VERSION}\n\nTakuhon — open-source portable profile API server.\n\nUsage:\n takuhon --version Show the installed CLI version\n takuhon --help Show this help\n\nCommands:\n takuhon validate [path] Validate a takuhon.json (default: ./takuhon.json)\n takuhon migrate [path] [--to <v>] Forward-migrate a takuhon.json to a newer schema\n version (default target: latest). Backs up first.\n Add --out <file> to write elsewhere, --dry-run to preview.\n takuhon restore --from <backup> Restore a profile from a backup (prompts before\n overwriting; pass --yes to skip).\n takuhon export [path] [--output <f>] Serialise a takuhon.json to stdout (or --output file).\n takuhon import <file> [path] Import an exported profile into a takuhon.json,\n migrating to the current schema version. Backs up first.\n takuhon build [path] [--output <d>] Render a takuhon.json into a static site (HTML +\n JSON-LD, one page per locale). --base-url <url> adds\n absolute canonical/hreflang links.\n takuhon dev [path] [--port <n>] Serve a takuhon.json as a local static preview,\n re-rendered on each request (default port: 4321).\n --base-url <url> adds canonical/hreflang links.\n\nScaffolding a new profile project:\n npx create-takuhon my-profile\n npx create-takuhon my-profile --license CC-BY-4.0\n\nThe sync subcommand is planned for a future release.\nTrack progress at:\n\n https://github.com/takuhon-dev/takuhon\n`;\n\nasync function main(argv: readonly string[]): Promise<number> {\n const first = argv[0];\n\n if (first === '--version' || first === '-v') {\n process.stdout.write(`${VERSION}\\n`);\n return 0;\n }\n\n if (first === undefined || first === '--help' || first === '-h') {\n process.stdout.write(HELP);\n return 0;\n }\n\n if (first === 'validate') {\n return emit(runValidate(argv.slice(1)));\n }\n\n if (first === 'migrate') {\n return emit(runMigrate(argv.slice(1)));\n }\n\n if (first === 'export') {\n return emit(runExport(argv.slice(1)));\n }\n\n if (first === 'build') {\n return emit(runBuild(argv.slice(1)));\n }\n\n if (first === 'dev') {\n // `dev` runs a long-lived server and streams its own output, so it does not\n // go through `emit` (a one-shot result writer); it returns the exit code\n // directly and resolves only on graceful shutdown.\n return runDev(argv.slice(1));\n }\n\n if (first === 'import') {\n return emit(runImport(argv.slice(1)));\n }\n\n if (first === 'restore') {\n // Only offer an interactive prompt on a real TTY; otherwise `runRestore`\n // refuses to overwrite without `--yes`, which is the safe default for\n // pipelines.\n const confirm = stdin.isTTY ? promptConfirm : undefined;\n return emit(await runRestore(argv.slice(1), { confirm }));\n }\n\n process.stderr.write(\n `takuhon: unknown command '${first}'\\n` +\n `Run \\`takuhon --help\\` for usage. For scaffolding a new project, use \\`create-takuhon\\`.\\n`,\n );\n return 2;\n}\n\n/** Write a command outcome's streams and return its exit code. */\nfunction emit(outcome: { code: number; stdout: string; stderr: string }): number {\n if (outcome.stdout) process.stdout.write(outcome.stdout);\n if (outcome.stderr) process.stderr.write(outcome.stderr);\n return outcome.code;\n}\n\n/** Interactive [y/N] confirmation used by `restore` on a TTY. */\nasync function promptConfirm(message: string): Promise<boolean> {\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n const answer = await rl.question(`${message} `);\n return /^y(es)?$/i.test(answer.trim());\n } finally {\n rl.close();\n }\n}\n\n/**\n * Process entry point: run {@link main} and exit with its code. This is the\n * only function that calls `process.exit`. Exported so the bare-name\n * `takuhon` package can invoke it after importing this module.\n */\nexport async function run(argv: readonly string[] = process.argv.slice(2)): Promise<void> {\n try {\n process.exit(await main(argv));\n } catch (error) {\n process.stderr.write(`takuhon: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n}\n\n/** True when this module was started directly (`node …/index.js`). */\nfunction isEntrypoint(): boolean {\n const entry = process.argv[1];\n if (entry === undefined) return false;\n try {\n return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url));\n } catch {\n return false;\n }\n}\n\nif (isEntrypoint()) {\n void run();\n}\n","/**\n * `takuhon build [path] [--output <dir>] [--base-url <url>]` — render a\n * `takuhon.json` into a deployable static site (Spec §13 Static Edition).\n *\n * Mirrors the other command runners: {@link runBuild} is a pure function that\n * reads the source itself and returns its output as strings plus an exit code.\n * The render pipeline reuses `@takuhon/core` only: validate → normalize →\n * `applyPublicPrivacyFilter` (so the static site honours `meta.privacy` exactly\n * like the live API) → for each available locale `resolveLocale` →\n * {@link renderProfileHtml}. The default locale is written to `<dir>/index.html`\n * and every other locale to `<dir>/<locale>/index.html`.\n *\n * Canonical / hreflang links require absolute URLs, so they are emitted only\n * when `--base-url` is supplied; the human locale switcher always uses\n * depth-correct relative links. Asset files are referenced by URL as-is and\n * never copied (out of scope; assets are remote per the schema). Writes are\n * atomic via {@link writeFileAtomic}.\n *\n * Exit codes:\n * 0 — site generated (or `--help`)\n * 1 — the source was read but is not a valid takuhon profile\n * 2 — the command could not run: bad arguments, a missing/unreadable file,\n * a non-JSON file, or a failed write\n */\n\nimport { mkdirSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nimport { applyPublicPrivacyFilter, normalize, validate } from '@takuhon/core';\n\nimport { writeFileAtomic } from './backup.js';\nimport { generateSite } from './site.js';\n\nconst DEFAULT_PATH = 'takuhon.json';\nconst DEFAULT_OUTPUT = 'dist';\n\nconst USAGE = `Usage: takuhon build [path] [--output <dir>] [--base-url <url>]\n\nRender a takuhon.json into a static site (one HTML page per locale, with\nbuild-time Schema.org JSON-LD). With no path, builds ./takuhon.json.\n\nOptions:\n --output <dir> Output directory (default: ${DEFAULT_OUTPUT}). The default\n locale is written to <dir>/index.html and each other locale\n to <dir>/<locale>/index.html.\n --base-url <url> Site origin (e.g. https://me.example). Enables absolute\n canonical and hreflang links; without it those are omitted.\n\nThe public privacy filter is applied (meta.privacy is honoured). Asset URLs are\nreferenced as-is and are not copied. The output directory is written into, not\ncleaned — use a dedicated/empty directory so stale pages do not linger.\n\nExit codes: 0 = built, 1 = source is not a valid profile,\n2 = bad arguments / file missing / unreadable / not JSON / write failed.\n`;\n\nexport interface BuildOutcome {\n readonly code: number;\n readonly stdout: string;\n readonly stderr: string;\n}\n\ninterface ParsedArgs {\n path: string;\n output: string;\n baseUrl?: string;\n}\n\n/**\n * Run `takuhon build` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"build\"`).\n */\nexport function runBuild(args: readonly string[] = []): BuildOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon build --help\\` for usage.\\n`,\n };\n }\n\n return buildSite(parsed);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let output: string | undefined;\n let baseUrl: string | undefined;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--output' || arg === '--base-url') {\n const value = args[i + 1];\n if (value === undefined || value === '' || value.startsWith('-')) {\n return { error: `takuhon: \\`${arg}\\` requires a value.` };\n }\n if (arg === '--output') output = value;\n else baseUrl = value;\n i++;\n continue;\n }\n if (arg.startsWith('--output=')) {\n const value = arg.slice('--output='.length);\n if (value === '') return { error: 'takuhon: `--output` requires a value.' };\n output = value;\n continue;\n }\n if (arg.startsWith('--base-url=')) {\n const value = arg.slice('--base-url='.length);\n if (value === '') return { error: 'takuhon: `--base-url` requires a value.' };\n baseUrl = value;\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`build\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `build` takes at most one path argument.' };\n }\n path = arg;\n }\n\n if (baseUrl !== undefined && !isHttpUrl(baseUrl)) {\n return { error: 'takuhon: `--base-url` must be an absolute http(s) URL.' };\n }\n\n return {\n path: path ?? DEFAULT_PATH,\n output: output ?? DEFAULT_OUTPUT,\n // Drop any trailing slash so URL joins are predictable.\n baseUrl: baseUrl?.replace(/\\/+$/, ''),\n };\n}\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nfunction buildSite(parsed: ParsedArgs): BuildOutcome {\n const { path, output, baseUrl } = parsed;\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: cannot read '${path}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${path}' is not valid JSON: ${detail}\\n` };\n }\n\n const result = validate(data);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${path}' is not a valid takuhon profile; refusing to build:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n const filtered = applyPublicPrivacyFilter(normalize(result.data));\n\n const written: string[] = [];\n try {\n for (const page of generateSite(filtered, { baseUrl })) {\n const outFile = join(output, page.file);\n mkdirSync(dirname(outFile), { recursive: true });\n writeFileAtomic(outFile, page.html);\n written.push(outFile);\n }\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: failed to write the site: ${detail}\\n` };\n }\n\n const summary = written.map((w) => ` ${w}`).join('\\n');\n return {\n code: 0,\n stdout: `built ${written.length} page${written.length === 1 ? '' : 's'} from ${path}:\\n${summary}\\n`,\n stderr: '',\n };\n}\n","/**\n * Local backup helpers shared by `takuhon migrate` and `takuhon restore`.\n *\n * Backups are written to a `.takuhon-backups/` directory co-located with the\n * profile file being mutated, rather than a `~/.takuhon/backups/{slug}/`\n * tree: a local `takuhon.json` operated on by path has no guaranteed slug,\n * and the restore flow documented in operational-lifecycle §4.1 / §4.3 reads\n * and writes `.takuhon-backups/...` relative to the working file. Keeping the\n * backups beside the source also mirrors the Vercel / Static adapter layout\n * (§3.1), which is the closest analogue for a local file workflow.\n *\n * Naming follows §3.1 (`takuhon-backup-v{version}-{timestamp}.json`) and the\n * pre-restore convention of §4.1 (`pre-restore-{timestamp}.json`). Timestamps\n * are ISO 8601 basic format in UTC at second precision; {@link createBackup}\n * implements the §3.3 overwrite guard by falling back to millisecond\n * precision when a same-second name already exists.\n */\n\nimport { mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';\nimport { basename, dirname, join } from 'node:path';\n\n/** Directory (relative to the target file) that holds local backups. */\nexport const BACKUP_DIR_NAME = '.takuhon-backups';\n\n/**\n * Thrown by {@link createBackup} when a backup cannot be written without\n * overwriting an existing file even after disambiguating with milliseconds.\n */\nexport class BackupError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'BackupError';\n }\n}\n\n/**\n * Format `date` as a compact ISO 8601 basic-format UTC timestamp.\n *\n * @example\n * compactTimestamp(new Date('2026-05-11T12:00:00.123Z')) // \"20260511T120000Z\"\n * compactTimestamp(new Date('2026-05-11T12:00:00.123Z'), true) // \"20260511T120000.123Z\"\n */\nexport function compactTimestamp(date: Date, withMillis = false): string {\n const iso = date.toISOString(); // e.g. \"2026-05-11T12:00:00.123Z\"\n const trimmed = withMillis ? iso : iso.replace(/\\.\\d{3}Z$/, 'Z');\n // Drop the extended-format separators; the millisecond `.` (if kept) stays.\n return trimmed.replace(/[-:]/g, '');\n}\n\n/** Build the migration pre-backup filename for a given source `version`. */\nexport function migrateBackupName(version: string, date: Date, withMillis = false): string {\n return `takuhon-backup-v${version}-${compactTimestamp(date, withMillis)}.json`;\n}\n\n/** Build the pre-restore backup filename (operational-lifecycle §4.1). */\nexport function preRestoreName(date: Date, withMillis = false): string {\n return `pre-restore-${compactTimestamp(date, withMillis)}.json`;\n}\n\n/** Build the pre-import backup filename (operational-lifecycle §5.3 step 3). */\nexport function preImportName(date: Date, withMillis = false): string {\n return `pre-import-${compactTimestamp(date, withMillis)}.json`;\n}\n\n/** Resolve the `.takuhon-backups/` directory beside `targetPath`. */\nexport function backupDirFor(targetPath: string): string {\n return join(dirname(targetPath), BACKUP_DIR_NAME);\n}\n\n/**\n * Write `content` into `.takuhon-backups/` beside `targetPath`, returning the\n * path actually written.\n *\n * `name(withMillis)` yields the second-precision filename when `false` and a\n * millisecond-precision variant when `true`. The directory is created if\n * absent and writes use the `wx` flag so an existing file is never\n * overwritten (operational-lifecycle §3.3): a same-second collision retries\n * once at millisecond precision, and a further collision throws\n * {@link BackupError}.\n */\nexport function createBackup(params: {\n targetPath: string;\n content: string;\n name: (withMillis: boolean) => string;\n}): string {\n const dir = backupDirFor(params.targetPath);\n mkdirSync(dir, { recursive: true });\n\n const primary = join(dir, params.name(false));\n try {\n writeFileSync(primary, params.content, { flag: 'wx' });\n return primary;\n } catch (error) {\n if (!isAlreadyExists(error)) throw error;\n }\n\n const fallback = join(dir, params.name(true));\n try {\n writeFileSync(fallback, params.content, { flag: 'wx' });\n return fallback;\n } catch (error) {\n if (isAlreadyExists(error)) {\n throw new BackupError(\n `backup target already exists and could not be disambiguated: ${fallback}`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return (\n typeof error === 'object' && error !== null && (error as { code?: unknown }).code === 'EEXIST'\n );\n}\n\n/**\n * Write `content` to `target` atomically: stage it in a sibling temp file and\n * `rename` it into place. A `rename` within a directory is atomic, so a reader\n * never observes a half-written profile and an interrupted write (crash,\n * ENOSPC) cannot truncate the existing file — it is replaced whole or not at\n * all. The temp file is removed on failure. Pairs with the backup-before-write\n * ordering in the migrate / restore commands.\n */\nexport function writeFileAtomic(target: string, content: string): void {\n const tmp = join(dirname(target), `.${basename(target)}.${process.pid}.tmp`);\n try {\n writeFileSync(tmp, content, 'utf8');\n renameSync(tmp, target);\n } catch (error) {\n rmSync(tmp, { force: true });\n throw error;\n }\n}\n","/**\n * Shared static-site generation for `takuhon build` and `takuhon dev`.\n *\n * {@link generateSite} turns one validated, normalized, privacy-filtered profile\n * into the full set of pages the static surface exposes: one per available\n * locale. `build` writes each page's {@link SitePage.file} to disk; `dev` serves\n * each page's {@link SitePage.route} from memory. Keeping the per-locale loop,\n * the locale switcher links, and the canonical/hreflang logic here means both\n * commands share a single source of truth for the site's structure — the only\n * difference between them is disk write vs. in-memory serve.\n *\n * This reuses `@takuhon/core` only (validate/normalize/resolve happen upstream;\n * this module just resolves each locale and renders), so it stays bundler-free\n * and unit-testable as a pure function.\n */\n\nimport type { NormalizedTakuhon } from '@takuhon/core';\nimport { resolveLocale } from '@takuhon/core';\n\nimport { renderProfileHtml, type Alternate, type LocaleLink } from './build-html.js';\n\n/** One generated page: a serve route, a relative output file, and its HTML. */\nexport interface SitePage {\n /** URL path used by `dev` (default locale at `/`, others at `/<locale>/`). */\n readonly route: string;\n /** Output path used by `build`, relative to the output dir. */\n readonly file: string;\n /** Rendered HTML document. */\n readonly html: string;\n}\n\nexport interface GenerateOptions {\n /**\n * Site origin (e.g. `https://me.example`). When set, pages carry absolute\n * canonical + hreflang links; when absent those are omitted (the human locale\n * switcher is always relative either way).\n */\n readonly baseUrl?: string;\n}\n\n/**\n * Generate every page for a profile: the default locale first, then the rest,\n * de-duplicated. Schema.org JSON-LD is emitted unless `settings.enableJsonLd`\n * is explicitly `false`.\n */\nexport function generateSite(\n profile: NormalizedTakuhon,\n options: GenerateOptions = {},\n): SitePage[] {\n const { baseUrl } = options;\n const defaultLocale = profile.settings.defaultLocale;\n // Default locale first, then the rest, de-duplicated.\n const locales = [...new Set([defaultLocale, ...profile.settings.availableLocales])];\n const jsonLd = profile.settings.enableJsonLd !== false;\n\n return locales.map((locale) => {\n const localized = resolveLocale(profile, locale);\n const isDefault = locale === defaultLocale;\n\n const localeNav: LocaleLink[] = locales.map((to) => ({\n locale: to,\n href: localeHref(locale, to, defaultLocale),\n current: to === locale,\n }));\n const canonicalUrl = baseUrl ? absoluteUrl(baseUrl, locale, defaultLocale) : undefined;\n const alternates: Alternate[] = baseUrl ? buildAlternates(baseUrl, locales, defaultLocale) : [];\n\n const html = renderProfileHtml({ localized, canonicalUrl, alternates, localeNav, jsonLd });\n return {\n route: isDefault ? '/' : `/${locale}/`,\n file: isDefault ? 'index.html' : `${locale}/index.html`,\n html,\n };\n });\n}\n\n/** Absolute URL for a locale's page (default locale lives at the site root). */\nfunction absoluteUrl(baseUrl: string, locale: string, defaultLocale: string): string {\n return locale === defaultLocale ? `${baseUrl}/` : `${baseUrl}/${locale}/`;\n}\n\n/** hreflang alternates for every locale plus an `x-default` pointing at the default. */\nfunction buildAlternates(\n baseUrl: string,\n locales: readonly string[],\n defaultLocale: string,\n): Alternate[] {\n const alternates: Alternate[] = locales.map((locale) => ({\n hreflang: locale,\n href: absoluteUrl(baseUrl, locale, defaultLocale),\n }));\n alternates.push({\n hreflang: 'x-default',\n href: absoluteUrl(baseUrl, defaultLocale, defaultLocale),\n });\n return alternates;\n}\n\n/**\n * Depth-correct relative link from the page for `from` to the page for `to`,\n * for the human locale switcher. Always relative (independent of `baseUrl`)\n * so the switcher works regardless of where the site is hosted: the default\n * locale lives at the root, every other locale one directory deep.\n */\nfunction localeHref(from: string, to: string, defaultLocale: string): string {\n const fromRoot = from === defaultLocale;\n const toRoot = to === defaultLocale;\n if (fromRoot) return toRoot ? './' : `${to}/`;\n return toRoot ? '../' : `../${to}/`;\n}\n","/**\n * Pure HTML rendering for `takuhon build`.\n *\n * {@link renderProfileHtml} turns one locale-resolved {@link LocalizedTakuhon}\n * into a complete, self-contained static HTML document: semantic markup for\n * every profile section, an inline stylesheet, optional Schema.org JSON-LD,\n * and the `<head>` metadata (`<title>`, description, canonical, hreflang\n * alternates) the caller supplies.\n *\n * This is a deliberately separate, simpler surface from the React\n * `@takuhon/ui` (which is delivered as CSS-Modules components needing a\n * bundler). It reuses only `@takuhon/core` and has no DOM/browser dependency,\n * so it renders in plain Node and is unit-testable as a pure string function.\n *\n * Security: every piece of profile-derived text is escaped before it reaches\n * the markup ({@link escapeHtml}), and the JSON-LD payload is `<`/`>`/`&`\n * unicode-escaped so it cannot break out of its `<script>` element.\n */\n\nimport { generateJsonLd } from '@takuhon/core';\nimport type { LocalizedTakuhon } from '@takuhon/core';\n\ntype LocalizedProfile = LocalizedTakuhon['profile'];\n\n/** One entry in the human-facing locale switcher. */\nexport interface LocaleLink {\n locale: string;\n href: string;\n current: boolean;\n}\n\n/** One `<link rel=\"alternate\" hreflang>` entry. */\nexport interface Alternate {\n hreflang: string;\n href: string;\n}\n\nexport interface RenderInput {\n /** The locale-resolved document to render. */\n localized: LocalizedTakuhon;\n /** Absolute canonical URL for this page (only when `--base-url` was given). */\n canonicalUrl?: string;\n /** hreflang alternates (empty when no base URL is available). */\n alternates: readonly Alternate[];\n /** Human locale switcher links (rendered only when more than one locale). */\n localeNav: readonly LocaleLink[];\n /** Whether to emit Schema.org JSON-LD (mirrors `settings.enableJsonLd`). */\n jsonLd: boolean;\n}\n\n/** Escape text for use in HTML element content or double/single-quoted attributes. */\nexport function escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/** Unicode-escape `<`, `>`, `&` so a JSON-LD payload cannot break out of `<script>`. */\nfunction escapeJsonLd(json: string): string {\n return json.replace(/</g, '\\\\u003c').replace(/>/g, '\\\\u003e').replace(/&/g, '\\\\u0026');\n}\n\n/**\n * Return `url` only when its scheme is safe to place in an `href`/`src`, else\n * `undefined`. Relative, protocol-relative, fragment, and query URLs (no\n * scheme) are allowed; among absolute URLs only `http:`, `https:`, and\n * `mailto:` are. This blocks `javascript:`, `data:`, `vbscript:`, etc. — the\n * schema validates only a generic URI, so a hostile document could otherwise\n * smuggle an executable scheme into the generated page.\n */\nfunction safeUrl(url: string): string | undefined {\n const trimmed = url.trim();\n const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(trimmed)?.[1]?.toLowerCase();\n if (scheme === undefined) return trimmed; // relative / protocol-relative / fragment\n return scheme === 'http' || scheme === 'https' || scheme === 'mailto' ? trimmed : undefined;\n}\n\nconst CSS = `:root{--fg:#1a1a1a;--muted:#666;--accent:#0b5fff;--line:#e5e5e5}\n*{box-sizing:border-box}\nbody{margin:0;color:var(--fg);font:16px/1.6 system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;background:#fff}\nmain{max-width:42rem;margin:0 auto;padding:2rem 1.25rem}\na{color:var(--accent)}\nh1{font-size:1.9rem;margin:.2rem 0}\nh2{font-size:1.15rem;margin:2rem 0 .75rem;padding-bottom:.3rem;border-bottom:1px solid var(--line)}\nh3{font-size:1rem;margin:0}\nheader .avatar{width:96px;height:96px;border-radius:50%;object-fit:cover}\n.tagline{font-size:1.1rem;color:var(--muted);margin:.2rem 0}\n.location{color:var(--muted);margin:.2rem 0}\n.bio{margin:.75rem 0}\nul{padding:0;margin:0;list-style:none}\n.entries>li{margin:0 0 1.1rem}\n.sub{margin:.1rem 0;font-weight:600}\n.meta{margin:.1rem 0;color:var(--muted);font-size:.9rem}\n.links{display:flex;flex-wrap:wrap;gap:.5rem 1rem;margin:.75rem 0}\n.skills,.tags{display:flex;flex-wrap:wrap;gap:.4rem}\n.skills>li,.tags>li{background:#f2f2f2;border-radius:1rem;padding:.15rem .6rem;font-size:.85rem}\n.rec{margin:0 0 1.1rem}\n.rec blockquote{margin:0;padding-left:.9rem;border-left:3px solid var(--line)}\n.rec figcaption{color:var(--muted);font-size:.9rem;margin-top:.3rem}\nnav.locales{display:flex;gap:.75rem;margin-bottom:1rem;font-size:.9rem}\nfooter.powered{max-width:42rem;margin:0 auto;padding:1.5rem 1.25rem;color:var(--muted);font-size:.85rem}`;\n\ninterface EntryView {\n heading: string;\n sub?: string;\n dates?: string;\n body?: string;\n url?: string;\n tags?: readonly string[];\n}\n\n/** Format a YearMonth range; `null` end or `isCurrent` renders as \"Present\". */\nfunction dateRange(start?: string, end?: string | null, isCurrent?: boolean): string {\n const left = start ?? '';\n const right = isCurrent === true || end === null ? 'Present' : (end ?? '');\n if (left && right) return `${left} – ${right}`;\n return left || right;\n}\n\nfunction nonEmpty(values: readonly (string | undefined)[], separator: string): string | undefined {\n const joined = values\n .filter((v): v is string => typeof v === 'string' && v.length > 0)\n .join(separator);\n return joined.length > 0 ? joined : undefined;\n}\n\nfunction renderEntry(entry: EntryView): string {\n const href = entry.url ? safeUrl(entry.url) : undefined;\n const heading = href\n ? `<a href=\"${escapeHtml(href)}\">${escapeHtml(entry.heading)}</a>`\n : escapeHtml(entry.heading);\n const parts = [`<h3>${heading}</h3>`];\n if (entry.sub) parts.push(`<p class=\"sub\">${escapeHtml(entry.sub)}</p>`);\n if (entry.dates) parts.push(`<p class=\"meta\">${escapeHtml(entry.dates)}</p>`);\n if (entry.body) parts.push(`<p>${escapeHtml(entry.body)}</p>`);\n if (entry.tags && entry.tags.length > 0) {\n parts.push(\n `<ul class=\"tags\">${entry.tags.map((t) => `<li>${escapeHtml(t)}</li>`).join('')}</ul>`,\n );\n }\n return `<li>${parts.join('')}</li>`;\n}\n\n/** Render a `<section>` of entries, or `''` when there are none. */\nfunction entryList(title: string, entries: readonly EntryView[]): string {\n if (entries.length === 0) return '';\n return `<section><h2>${escapeHtml(title)}</h2><ul class=\"entries\">${entries\n .map(renderEntry)\n .join('')}</ul></section>`;\n}\n\nfunction renderHeader(p: LocalizedProfile): string {\n const parts: string[] = [];\n const avatarSrc = p.avatar?.url ? safeUrl(p.avatar.url) : undefined;\n if (avatarSrc) {\n parts.push(\n `<img class=\"avatar\" src=\"${escapeHtml(avatarSrc)}\" alt=\"${escapeHtml(p.avatar?.alt ?? '')}\">`,\n );\n }\n parts.push(`<h1>${escapeHtml(p.displayName)}</h1>`);\n if (p.tagline) parts.push(`<p class=\"tagline\">${escapeHtml(p.tagline)}</p>`);\n if (p.location?.display) parts.push(`<p class=\"location\">${escapeHtml(p.location.display)}</p>`);\n if (p.bio) parts.push(`<p class=\"bio\">${escapeHtml(p.bio)}</p>`);\n return `<header>${parts.join('')}</header>`;\n}\n\nfunction renderLinks(links: LocalizedTakuhon['links']): string {\n if (links.length === 0) return '';\n const items = links\n .map((l) => {\n const text = escapeHtml(l.label ?? l.url);\n const href = safeUrl(l.url);\n return href ? `<li><a href=\"${escapeHtml(href)}\">${text}</a></li>` : `<li>${text}</li>`;\n })\n .join('');\n return `<nav aria-label=\"Links\"><ul class=\"links\">${items}</ul></nav>`;\n}\n\nfunction renderSkills(skills: LocalizedTakuhon['skills']): string {\n if (skills.length === 0) return '';\n const items = skills.map((s) => `<li>${escapeHtml(s.label)}</li>`).join('');\n return `<section><h2>Skills</h2><ul class=\"skills\">${items}</ul></section>`;\n}\n\nfunction renderLanguages(languages: LocalizedTakuhon['languages']): string {\n if (languages.length === 0) return '';\n const items = languages\n .map((l) => `<li>${escapeHtml(`${l.displayName ?? l.language} — ${l.proficiency}`)}</li>`)\n .join('');\n return `<section><h2>Languages</h2><ul class=\"entries\">${items}</ul></section>`;\n}\n\nfunction renderRecommendations(recs: LocalizedTakuhon['recommendations']): string {\n if (recs.length === 0) return '';\n const items = recs\n .map((r) => {\n const authorHref = r.author.url ? safeUrl(r.author.url) : undefined;\n const name = authorHref\n ? `<a href=\"${escapeHtml(authorHref)}\">${escapeHtml(r.author.name)}</a>`\n : escapeHtml(r.author.name);\n const caption = [name, r.author.headline ? escapeHtml(r.author.headline) : '']\n .filter(Boolean)\n .join(', ');\n const rel = r.relationship ? ` (${escapeHtml(r.relationship)})` : '';\n return `<figure class=\"rec\"><blockquote>${escapeHtml(r.body)}</blockquote><figcaption>— ${caption}${rel}</figcaption></figure>`;\n })\n .join('');\n return `<section><h2>Recommendations</h2>${items}</section>`;\n}\n\nfunction renderContact(contact: LocalizedTakuhon['contact']): string {\n const items: string[] = [];\n if (contact.email) {\n items.push(\n `<li><a href=\"mailto:${escapeHtml(contact.email)}\">${escapeHtml(contact.email)}</a></li>`,\n );\n }\n const formHref = contact.formUrl ? safeUrl(contact.formUrl) : undefined;\n if (formHref) {\n items.push(`<li><a href=\"${escapeHtml(formHref)}\">Contact form</a></li>`);\n }\n if (items.length === 0) return '';\n return `<section><h2>Contact</h2><ul class=\"entries\">${items.join('')}</ul></section>`;\n}\n\nfunction renderJsonLdScript(data: LocalizedTakuhon): string {\n const payload = JSON.stringify(generateJsonLd(data));\n return `<script type=\"application/ld+json\">${escapeJsonLd(payload)}</script>`;\n}\n\nfunction renderLocaleNav(localeNav: readonly LocaleLink[]): string {\n const items = localeNav\n .map((l) =>\n l.current\n ? `<span aria-current=\"true\">${escapeHtml(l.locale)}</span>`\n : `<a href=\"${escapeHtml(l.href)}\">${escapeHtml(l.locale)}</a>`,\n )\n .join('');\n return `<nav class=\"locales\" aria-label=\"Language\">${items}</nav>`;\n}\n\n/** Render a complete static HTML document for one locale-resolved profile. */\nexport function renderProfileHtml(input: RenderInput): string {\n const d = input.localized;\n const p = d.profile;\n const description = p.tagline ?? p.bio ?? '';\n\n const head = [\n '<meta charset=\"utf-8\">',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">',\n `<title>${escapeHtml(p.displayName)}</title>`,\n description\n ? `<meta name=\"description\" content=\"${escapeHtml(description.slice(0, 300))}\">`\n : '',\n input.canonicalUrl ? `<link rel=\"canonical\" href=\"${escapeHtml(input.canonicalUrl)}\">` : '',\n ...input.alternates.map(\n (a) =>\n `<link rel=\"alternate\" hreflang=\"${escapeHtml(a.hreflang)}\" href=\"${escapeHtml(a.href)}\">`,\n ),\n input.jsonLd ? renderJsonLdScript(d) : '',\n `<style>${CSS}</style>`,\n ]\n .filter(Boolean)\n .join('\\n ');\n\n const body = [\n input.localeNav.length > 1 ? renderLocaleNav(input.localeNav) : '',\n renderHeader(p),\n renderLinks(d.links),\n entryList(\n 'Experience',\n d.careers.map((c) => ({\n heading: c.role,\n sub: c.organization,\n dates: dateRange(c.startDate, c.endDate, c.isCurrent),\n body: c.description,\n url: c.url,\n })),\n ),\n entryList(\n 'Projects',\n d.projects.map((x) => ({\n heading: x.title,\n dates: dateRange(x.startDate, x.endDate),\n body: x.description,\n url: x.url,\n tags: x.tags,\n })),\n ),\n renderSkills(d.skills),\n entryList(\n 'Education',\n d.education.map((e) => {\n const degree = nonEmpty([e.degree, e.fieldOfStudy], ', ');\n return {\n heading: degree ?? e.institution,\n sub: degree ? e.institution : undefined,\n dates: dateRange(e.startDate, e.endDate, e.isCurrent),\n body: e.description,\n url: e.url,\n };\n }),\n ),\n entryList(\n 'Certifications',\n d.certifications.map((c) => ({\n heading: c.title,\n sub: c.issuingOrganization,\n dates: dateRange(c.issueDate, c.expirationDate),\n url: c.url,\n })),\n ),\n entryList(\n 'Publications',\n d.publications.map((x) => ({\n heading: x.title,\n sub: nonEmpty([x.publisher, x.coAuthors?.join(', ')], ' · '),\n dates: dateRange(x.date),\n body: x.description,\n url: x.url ?? (x.doi ? `https://doi.org/${x.doi}` : undefined),\n })),\n ),\n entryList(\n 'Honors & awards',\n d.honors.map((x) => ({\n heading: x.title,\n sub: x.issuer,\n dates: dateRange(x.date),\n body: x.description,\n url: x.url,\n })),\n ),\n entryList(\n 'Memberships',\n d.memberships.map((x) => ({\n heading: x.role ?? x.organization,\n sub: x.role ? x.organization : undefined,\n dates: dateRange(x.startDate, x.endDate, x.isCurrent),\n body: x.description,\n url: x.url,\n })),\n ),\n entryList(\n 'Volunteering',\n d.volunteering.map((x) => ({\n heading: x.role,\n sub: nonEmpty([x.organization, x.cause], ' · '),\n dates: dateRange(x.startDate, x.endDate, x.isCurrent),\n body: x.description,\n url: x.url,\n })),\n ),\n entryList(\n 'Courses',\n d.courses.map((x) => ({\n heading: x.title,\n sub: x.provider,\n dates: dateRange(x.completionDate),\n body: x.description,\n url: x.certificateUrl,\n })),\n ),\n entryList(\n 'Patents',\n d.patents.map((x) => ({\n heading: x.title,\n sub: nonEmpty([x.patentNumber, x.office, x.status, x.coInventors?.join(', ')], ' · '),\n dates: dateRange(x.filingDate ?? x.grantDate),\n body: x.description,\n url: x.url,\n })),\n ),\n entryList(\n 'Test scores',\n d.testScores.map((x) => ({\n heading: `${x.title}: ${x.score}`,\n dates: dateRange(x.date),\n body: x.description,\n url: x.url,\n })),\n ),\n renderLanguages(d.languages),\n renderRecommendations(d.recommendations),\n renderContact(d.contact),\n ]\n .filter(Boolean)\n .join('\\n');\n\n const footer =\n d.settings.showPoweredBy === true ? '<footer class=\"powered\">Powered by takuhon</footer>' : '';\n\n return (\n `<!DOCTYPE html>\\n<html lang=\"${escapeHtml(d.resolvedLocale)}\">\\n<head>\\n ${head}\\n</head>\\n` +\n `<body>\\n<main>\\n${body}\\n</main>\\n${footer ? `${footer}\\n` : ''}</body>\\n</html>\\n`\n );\n}\n","/**\n * `takuhon dev [path] [--port <n>] [--base-url <url>]` — serve a `takuhon.json`\n * as a local static preview (Spec §14.1 Phase 1 \"edit → preview\").\n *\n * This is the in-memory companion of `takuhon build`: it renders the same\n * per-locale surface (via the shared {@link generateSite}) but serves it over\n * `node:http` instead of writing to disk — no bundler, no Hono/Vite/React, no\n * remote/secret coupling. The source is re-read and re-rendered on every\n * request, so editing `takuhon.json` and reloading the browser shows changes\n * with no watch machinery; an invalid file is served as a live error page so it\n * can be fixed in place.\n *\n * A long-running server does not fit the pure `runXxx → {code,stdout,stderr}`\n * shape of the other commands, so the testable logic is split from the I/O:\n * {@link loadSiteState} (source → route map), {@link resolveRoute},\n * {@link contentType}, and {@link handleRequest} are pure; {@link createDevServer}\n * and {@link runDev} are the thin `node:http` wrapper around them.\n *\n * Exit codes:\n * 0 — served, then stopped cleanly (Ctrl-C), or `--help`\n * 2 — the command could not run: bad arguments, a missing/unreadable file,\n * or the port was already in use\n */\n\nimport { readFileSync } from 'node:fs';\nimport { createServer, type Server } from 'node:http';\n\nimport { applyPublicPrivacyFilter, normalize, validate } from '@takuhon/core';\n\nimport { escapeHtml } from './build-html.js';\nimport { generateSite } from './site.js';\n\nconst DEFAULT_PATH = 'takuhon.json';\nconst DEFAULT_PORT = 4321;\n\nconst USAGE = `Usage: takuhon dev [path] [--port <n>] [--base-url <url>]\n\nServe a takuhon.json as a local static preview (one page per locale) — the same\nsurface \\`takuhon build\\` produces. With no path, serves ./takuhon.json. The file\nis re-read and re-rendered on every request, so edit it and reload the browser\nto see changes. Stop with Ctrl-C.\n\nOptions:\n --port <n> Port to listen on (default: ${DEFAULT_PORT}).\n --base-url <url> Site origin (e.g. https://me.example). Enables absolute\n canonical and hreflang links; without it those are omitted.\n\nThe public privacy filter is applied (meta.privacy is honoured). An invalid\ntakuhon.json is served as an error page so you can fix it and reload.\n\nExit codes: 0 = served then stopped, 2 = bad arguments / file missing /\nunreadable / port in use.\n`;\n\n/** Injectable output sinks so tests can capture streams without a real TTY. */\nexport interface DevDeps {\n stdout?: (text: string) => void;\n stderr?: (text: string) => void;\n}\n\ninterface ParsedArgs {\n path: string;\n port: number;\n baseUrl?: string;\n}\n\n/**\n * The current render state of the source file. Recomputed per request so edits\n * are reflected on reload; a read/parse/validate failure becomes a served error\n * page rather than crashing the server.\n */\nexport type SiteState =\n | { readonly ok: true; readonly pages: ReadonlyMap<string, string> }\n | { readonly ok: false; readonly status: number; readonly message: string };\n\n/** A fully-resolved HTTP response, independent of the `node:http` socket. */\nexport interface DevResponse {\n readonly status: number;\n readonly contentType: string;\n readonly body: string;\n}\n\n/**\n * Read, validate, and render `path` into a route→HTML map. Any failure (missing\n * file, bad JSON, invalid profile) yields a 500 state carrying a human-readable\n * message — validation errors are formatted with their JSON Pointers, mirroring\n * `takuhon build`. The public privacy filter is applied, exactly as `build` does.\n */\nexport function loadSiteState(path: string, baseUrl?: string): SiteState {\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return { ok: false, status: 500, message: `cannot read '${path}'.` };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { ok: false, status: 500, message: `'${path}' is not valid JSON: ${detail}` };\n }\n\n const result = validate(data);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n ok: false,\n status: 500,\n message: `'${path}' is not a valid takuhon profile:\\n${lines.join('\\n')}`,\n };\n }\n\n const filtered = applyPublicPrivacyFilter(normalize(result.data));\n const pages = new Map(generateSite(filtered, { baseUrl }).map((p) => [p.route, p.html]));\n return { ok: true, pages };\n}\n\n/**\n * Normalize a request path to a site route key. A trailing `index.html` is\n * stripped and a trailing slash is added, so `/ja`, `/ja/`, and\n * `/ja/index.html` all map to `/ja/` (and `/`, ``, `/index.html` to `/`).\n */\nexport function resolveRoute(urlPath: string): string {\n let p = urlPath;\n try {\n p = decodeURIComponent(urlPath);\n } catch {\n // Keep the raw path on malformed percent-encoding; it will simply 404.\n }\n p = p.replace(/\\/index\\.html$/, '/');\n if (p === '' || p === '/') return '/';\n if (!p.startsWith('/')) p = `/${p}`;\n if (!p.endsWith('/')) p = `${p}/`;\n return p;\n}\n\n/**\n * Content-type for a served route. The static surface is HTML-only (the build\n * emits one HTML page per locale and no assets/JSON), so this is constant; it is\n * a named function to keep the response shape ready should the surface grow.\n */\nexport function contentType(_route: string): string {\n return 'text/html; charset=utf-8';\n}\n\n/** Resolve a request to a response against the current {@link SiteState}. Pure. */\nexport function handleRequest(method: string, urlPath: string, state: SiteState): DevResponse {\n if (method !== 'GET' && method !== 'HEAD') {\n return { status: 405, contentType: 'text/plain; charset=utf-8', body: 'Method Not Allowed\\n' };\n }\n if (!state.ok) {\n return {\n status: state.status,\n contentType: contentType('/'),\n body: renderErrorPage(state.message),\n };\n }\n const route = resolveRoute(urlPath);\n const html = state.pages.get(route);\n if (html === undefined) {\n return {\n status: 404,\n contentType: contentType(route),\n body: renderNotFoundPage(route, [...state.pages.keys()]),\n };\n }\n return { status: 200, contentType: contentType(route), body: html };\n}\n\n/**\n * Create the preview server. Each request recomputes the site state (so edits\n * are live on reload) and delegates to the pure {@link handleRequest}. Not\n * started here — the caller binds a port. Importing this module has no side\n * effects.\n */\nexport function createDevServer(opts: { path: string; baseUrl?: string }): Server {\n return createServer((req, res) => {\n const method = req.method ?? 'GET';\n const state = loadSiteState(opts.path, opts.baseUrl);\n const response = handleRequest(method, pathnameOf(req.url ?? '/'), state);\n res.writeHead(response.status, { 'Content-Type': response.contentType });\n if (method === 'HEAD') res.end();\n else res.end(response.body);\n });\n}\n\n/**\n * Run `takuhon dev`. Resolves with the process exit code: it stays pending while\n * the server runs and resolves on graceful shutdown (Ctrl-C). Argument and\n * missing-file errors return before any port is bound.\n */\nexport async function runDev(args: readonly string[] = [], deps: DevDeps = {}): Promise<number> {\n const out = deps.stdout ?? ((text: string) => void process.stdout.write(text));\n const err = deps.stderr ?? ((text: string) => void process.stderr.write(text));\n\n if (args[0] === '--help' || args[0] === '-h') {\n out(USAGE);\n return 0;\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n err(`${parsed.error}\\nRun \\`takuhon dev --help\\` for usage.\\n`);\n return 2;\n }\n\n // Fast-fail only when the source is missing/unreadable — there is nothing to\n // preview. A present-but-invalid file is served as a live error page instead,\n // so it can be fixed without restarting the server.\n try {\n readFileSync(parsed.path, 'utf8');\n } catch {\n err(\n `takuhon: cannot read '${parsed.path}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n );\n return 2;\n }\n\n const server = createDevServer({ path: parsed.path, baseUrl: parsed.baseUrl });\n\n return await new Promise<number>((resolve) => {\n let closing = false;\n const shutdown = (): void => {\n if (closing) return;\n closing = true;\n process.removeListener('SIGINT', shutdown);\n process.removeListener('SIGTERM', shutdown);\n server.close(() => resolve(0));\n // Drop keep-alive sockets so close() does not hang (Node >= 18.2).\n server.closeAllConnections();\n };\n\n server.once('error', (error: NodeJS.ErrnoException) => {\n // The signal handlers are only registered once listening starts, so a\n // bind failure (e.g. EADDRINUSE) has none to detach.\n if (error.code === 'EADDRINUSE') {\n err(`takuhon: port ${parsed.port} is already in use; pass --port <n> to choose another.\\n`);\n } else {\n err(`takuhon: ${error.message}\\n`);\n }\n resolve(2);\n });\n\n // Bind to loopback only: a local preview must not expose draft profile\n // content (or the dev error pages) to the rest of the network.\n server.listen(parsed.port, '127.0.0.1', () => {\n out(\n `takuhon dev: serving ${parsed.path} at http://localhost:${parsed.port}/ (Ctrl-C to stop)\\n`,\n );\n // Surface a current validation problem up front; the browser shows it too.\n const state = loadSiteState(parsed.path, parsed.baseUrl);\n if (!state.ok) {\n err(\n `takuhon dev: ${parsed.path} is not a valid profile yet; the preview will show the error until it is fixed.\\n`,\n );\n }\n process.once('SIGINT', shutdown);\n process.once('SIGTERM', shutdown);\n });\n });\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let portRaw: string | undefined;\n let baseUrl: string | undefined;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--port' || arg === '--base-url') {\n const value = args[i + 1];\n if (value === undefined || value === '' || value.startsWith('-')) {\n return { error: `takuhon: \\`${arg}\\` requires a value.` };\n }\n if (arg === '--port') portRaw = value;\n else baseUrl = value;\n i++;\n continue;\n }\n if (arg.startsWith('--port=')) {\n const value = arg.slice('--port='.length);\n if (value === '') return { error: 'takuhon: `--port` requires a value.' };\n portRaw = value;\n continue;\n }\n if (arg.startsWith('--base-url=')) {\n const value = arg.slice('--base-url='.length);\n if (value === '') return { error: 'takuhon: `--base-url` requires a value.' };\n baseUrl = value;\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`dev\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `dev` takes at most one path argument.' };\n }\n path = arg;\n }\n\n let port = DEFAULT_PORT;\n if (portRaw !== undefined) {\n const parsedPort = parsePort(portRaw);\n if (parsedPort === undefined) {\n return {\n error: `takuhon: \\`--port\\` must be an integer between 1 and 65535 (got \\`${portRaw}\\`).`,\n };\n }\n port = parsedPort;\n }\n\n if (baseUrl !== undefined && !isHttpUrl(baseUrl)) {\n return { error: 'takuhon: `--base-url` must be an absolute http(s) URL.' };\n }\n\n return {\n path: path ?? DEFAULT_PATH,\n port,\n // Drop any trailing slash so URL joins are predictable.\n baseUrl: baseUrl?.replace(/\\/+$/, ''),\n };\n}\n\nfunction parsePort(value: string): number | undefined {\n if (!/^\\d+$/.test(value)) return undefined;\n const n = Number(value);\n return Number.isInteger(n) && n >= 1 && n <= 65535 ? n : undefined;\n}\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/** Extract the path portion of a request URL, dropping any query/fragment. */\nfunction pathnameOf(url: string): string {\n try {\n return new URL(url, 'http://localhost').pathname;\n } catch {\n return url;\n }\n}\n\n/** Minimal HTML document used by the dev-only error and 404 pages. */\nfunction devPage(title: string, body: string): string {\n return (\n `<!DOCTYPE html>\\n<html lang=\"en\">\\n<head>\\n` +\n `<meta charset=\"utf-8\">\\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\\n` +\n `<title>${escapeHtml(title)}</title>\\n` +\n `<style>body{margin:0;font:16px/1.6 system-ui,-apple-system,sans-serif;color:#1a1a1a}` +\n `main{max-width:42rem;margin:2rem auto;padding:0 1.25rem}` +\n `pre{background:#f6f6f6;padding:1rem;border-radius:.4rem;overflow:auto;white-space:pre-wrap}` +\n `code{background:#f2f2f2;padding:.1rem .3rem;border-radius:.2rem}</style>\\n` +\n `</head>\\n<body>\\n<main>\\n${body}\\n</main>\\n</body>\\n</html>\\n`\n );\n}\n\nfunction renderErrorPage(message: string): string {\n return devPage(\n 'takuhon dev — error',\n `<h1>takuhon dev</h1>\\n<p>The profile could not be rendered:</p>\\n` +\n `<pre>${escapeHtml(message)}</pre>\\n<p>Fix the file and reload.</p>`,\n );\n}\n\nfunction renderNotFoundPage(route: string, routes: readonly string[]): string {\n const links = routes\n .map((r) => `<li><a href=\"${escapeHtml(r)}\">${escapeHtml(r)}</a></li>`)\n .join('');\n return devPage(\n 'takuhon dev — 404',\n `<h1>404</h1>\\n<p>No page for <code>${escapeHtml(route)}</code>.</p>\\n` +\n `<p>Available pages:</p>\\n<ul>${links}</ul>`,\n );\n}\n","/**\n * `takuhon export [path] [--output <file>]` — serialise a `takuhon.json` into\n * its transport form for transfer or archival.\n *\n * Mirrors the other command runners: {@link runExport} is a pure function that\n * reads the source itself but returns its output as strings plus an exit code.\n * It validates the source first (an export should be a valid transport\n * artifact), then delegates to core's `exportTakuhon`, which deep-clones and\n * refreshes `meta.updatedAt` (the round-trip exception in\n * operational-lifecycle §5.1). The source file is only read, never modified.\n *\n * Output defaults to stdout so the command composes in a pipeline; `--output`\n * writes a file atomically instead. Asset embedding (`--embed-assets`) is a\n * remote-storage concern and is deferred — it is rejected with a clear message\n * rather than silently ignored.\n *\n * Exit codes:\n * 0 — exported (to stdout or `--output`)\n * 1 — the source was read but is not a valid takuhon profile\n * 2 — the command could not run: bad arguments, a missing/unreadable file,\n * a file that is not valid JSON, or a failed `--output` write\n */\n\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport { exportTakuhon, validate } from '@takuhon/core';\nimport type { Takuhon } from '@takuhon/core';\n\nimport { writeFileAtomic } from './backup.js';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon export [path] [--output <file>]\n\nSerialise a takuhon.json into its transport form and print it to stdout, or\nwrite it to a file with --output. With no path, exports ./takuhon.json in the\ncurrent working directory.\n\nOptions:\n --output <file> Write the export to <file> instead of stdout (atomic).\n\nExit codes: 0 = exported, 1 = source is not a valid profile,\n2 = bad arguments / file missing / unreadable / not JSON / write failed.\n`;\n\nexport interface ExportOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\ninterface ParsedArgs {\n path: string;\n output?: string;\n}\n\n/**\n * Run `takuhon export` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"export\"`).\n */\nexport function runExport(args: readonly string[] = []): ExportOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon export --help\\` for usage.\\n`,\n };\n }\n\n return exportFile(parsed);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let output: string | undefined;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--embed-assets') {\n return {\n error:\n 'takuhon: --embed-assets is not supported yet; assets are remote and asset embedding is deferred.',\n };\n }\n if (arg === '--output') {\n const value = args[i + 1];\n if (value === undefined || value === '' || value.startsWith('-')) {\n return { error: 'takuhon: `--output` requires a value.' };\n }\n output = value;\n i++;\n continue;\n }\n if (arg.startsWith('--output=')) {\n const value = arg.slice('--output='.length);\n if (value === '') {\n return { error: 'takuhon: `--output` requires a value.' };\n }\n output = value;\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`export\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `export` takes at most one path argument.' };\n }\n path = arg;\n }\n\n return { path: path ?? DEFAULT_PATH, output };\n}\n\nfunction exportFile(parsed: ParsedArgs): ExportOutcome {\n const { path, output } = parsed;\n\n // Export produces a separate transport artifact; refuse to write it over the\n // source (which would mutate the source via the refreshed meta.updatedAt).\n if (output !== undefined && resolve(output) === resolve(path)) {\n return {\n code: 2,\n stdout: '',\n stderr:\n `takuhon: --output '${output}' is the source file; export writes a separate artifact.\\n` +\n 'Omit --output to print to stdout, or choose a different file.\\n',\n };\n }\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: cannot read '${path}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${path}' is not valid JSON: ${detail}\\n` };\n }\n\n const result = validate(data);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${path}' is not a valid takuhon profile; refusing to export:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n // Export the validated source faithfully — only meta.updatedAt is refreshed\n // (operational-lifecycle §5.1). We pass the parsed document rather than\n // `result.data` so `validate`'s coercion of absent optional arrays into `[]`\n // does not silently rewrite the export.\n const content = `${JSON.stringify(exportTakuhon(data as Takuhon), null, 2)}\\n`;\n\n if (output === undefined) {\n // No --output: the serialised profile is the command's stdout.\n return { code: 0, stdout: content, stderr: '' };\n }\n\n try {\n writeFileAtomic(output, content);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: failed to write '${output}': ${detail}\\n` };\n }\n\n return { code: 0, stdout: `exported ${path} -> ${output}\\n`, stderr: '' };\n}\n","/**\n * `takuhon import <file> [path]` — load a previously exported profile into a\n * local `takuhon.json` (operational-lifecycle §5.3 / §17.2).\n *\n * Like the other command runners this returns its output as strings plus an\n * exit code. The flow follows §5.3: read the input, migrate it forward to the\n * current schema version if it is older (core's `importTakuhon` deliberately\n * does *not* auto-migrate, so the CLI composes `migrateTakuhon` +\n * `importTakuhon`), validate the result, back up the current profile, then\n * write the imported document. Unlike `restore` (a verbatim reproduction),\n * `import` writes the migrated-and-validated document re-serialised in\n * canonical form.\n *\n * Import overwrites the target, but a backup is taken first, so — matching the\n * spec, which mandates a confirmation prompt only for `restore` — there is no\n * interactive prompt. Asset expansion and edge-cache purge (§5.3 steps 5-6)\n * are remote concerns and do not apply to this local-file command.\n *\n * Exit codes:\n * 0 — imported\n * 1 — the input was read but cannot be imported (missing/unusable\n * schemaVersion, no migration path to the current version, or the\n * result failed validation)\n * 2 — the command could not run: bad arguments, a missing/unreadable input\n * or target, a non-JSON input, or a failed write\n */\n\nimport { readFileSync } from 'node:fs';\n\nimport {\n ImportError,\n MigrationError,\n SCHEMA_VERSION,\n importTakuhon,\n migrateTakuhon,\n} from '@takuhon/core';\nimport type { Takuhon } from '@takuhon/core';\n\nimport { BackupError, createBackup, preImportName, writeFileAtomic } from './backup.js';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon import <file> [path]\n\nLoad a previously exported profile from <file> into a local takuhon.json,\nmigrating it to the current schema version if needed. With no path, writes\n./takuhon.json in the current working directory.\n\nThe current profile (if any) is backed up to\n.takuhon-backups/pre-import-<timestamp>.json before being overwritten.\n\nExit codes: 0 = imported, 1 = input cannot be imported (invalid / unsupported\nversion), 2 = bad arguments / file missing / unreadable / not JSON / write failed.\n`;\n\nexport interface ImportOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/** Injectable dependencies, so tests can pin the backup timestamp. */\nexport interface ImportDeps {\n /** Clock used for the pre-import backup filename. Defaults to `() => new Date()`. */\n now?: () => Date;\n}\n\ninterface ParsedArgs {\n file: string;\n path: string;\n}\n\n/**\n * Run `takuhon import` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"import\"`).\n */\nexport function runImport(args: readonly string[] = [], deps: ImportDeps = {}): ImportOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon import --help\\` for usage.\\n`,\n };\n }\n\n const now = deps.now ?? (() => new Date());\n return importFile(parsed, now);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n const positionals: string[] = [];\n\n for (const arg of args) {\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`import\\`.` };\n }\n positionals.push(arg);\n }\n\n if (positionals.length === 0) {\n return { error: 'takuhon: `import` requires an input <file>.' };\n }\n if (positionals.length > 2) {\n return { error: 'takuhon: `import` takes at most an input <file> and a target path.' };\n }\n\n return { file: positionals[0]!, path: positionals[1] ?? DEFAULT_PATH };\n}\n\nfunction importFile(parsed: ParsedArgs, now: () => Date): ImportOutcome {\n const { file, path } = parsed;\n\n let raw: string;\n try {\n raw = readFileSync(file, 'utf8');\n } catch {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read '${file}'.\\n` };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${file}' is not valid JSON: ${detail}\\n` };\n }\n\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${file}' is not a takuhon profile (expected a JSON object).\\n`,\n };\n }\n\n const source = (data as { schemaVersion?: unknown }).schemaVersion;\n if (typeof source !== 'string' || source.length === 0) {\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${file}' has no usable schemaVersion; cannot import.\\n`,\n };\n }\n\n // Bring the input up to the current schema version (§5.3 step 2). core's\n // importTakuhon does not auto-migrate, so we migrate first when needed.\n let candidate: unknown = data;\n if (source !== SCHEMA_VERSION) {\n try {\n candidate = migrateTakuhon(data as Takuhon, SCHEMA_VERSION);\n } catch (error) {\n if (error instanceof MigrationError) {\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: cannot import '${file}': ${error.message}.\\n`,\n };\n }\n throw error;\n }\n }\n\n let imported: Takuhon;\n try {\n imported = importTakuhon(candidate as Takuhon);\n } catch (error) {\n if (error instanceof ImportError) {\n const lines = (error.errors ?? []).map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n const detail = lines.length > 0 ? `:\\n${lines.join('\\n')}` : '.';\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${file}' is not a valid takuhon profile; refusing to import${detail}\\n`,\n };\n }\n throw error;\n }\n\n // Back up the current profile before overwriting it (§5.3 step 3). A missing\n // target is fine — there is nothing to preserve on a fresh import.\n let currentRaw: string | undefined;\n try {\n currentRaw = readFileSync(path, 'utf8');\n } catch (error) {\n if (!isNotFound(error)) {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read current profile '${path}'.\\n` };\n }\n }\n\n let savedPath: string | undefined;\n if (currentRaw !== undefined) {\n // One timestamp for the backup name (createBackup may call the builder\n // twice on a same-second collision).\n const stamp = now();\n try {\n savedPath = createBackup({\n targetPath: path,\n content: currentRaw,\n name: (withMillis) => preImportName(stamp, withMillis),\n });\n } catch (error) {\n const detail = error instanceof BackupError ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: refusing to import into '${path}' — pre-import backup failed: ${detail}\\n`,\n };\n }\n }\n\n try {\n writeFileAtomic(path, `${JSON.stringify(imported, null, 2)}\\n`);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: failed to write '${path}': ${detail}\\n` };\n }\n\n const lines = [`imported ${file} -> ${path} (schemaVersion ${imported.schemaVersion})`];\n if (savedPath !== undefined) {\n lines.push(` previous profile saved to ${savedPath}`);\n }\n return { code: 0, stdout: `${lines.join('\\n')}\\n`, stderr: '' };\n}\n\nfunction isNotFound(error: unknown): boolean {\n return (\n typeof error === 'object' && error !== null && (error as { code?: unknown }).code === 'ENOENT'\n );\n}\n","/**\n * `takuhon migrate [path] [--to <version>] [--out <file>] [--dry-run]` —\n * forward-migrate a `takuhon.json` to a newer schema version.\n *\n * Mirrors `validate-command.ts`: {@link runMigrate} is a pure,\n * side-effect-light function that reads/writes files itself but returns its\n * output as strings plus an exit code, leaving stdout/stderr writes and\n * `process.exit` to the entry layer. The source version is read from the\n * file's own `schemaVersion` (the file is the source of truth), so the\n * command takes only `--to`; the default target is the latest schema this\n * build of `@takuhon/core` ships ({@link SCHEMA_VERSION}).\n *\n * The transform is intentionally minimal — `migrateTakuhon` then a re-`validate`\n * gate, with no `meta.updatedAt` touch and no `normalize` pass — so a\n * migration stays lossless (operational-lifecycle §2.6) and its diff is\n * limited to the schema-shape change. Before an in-place write the original\n * bytes are backed up beside the file (§3.1 / §3.3). Migrations are\n * forward-only (§2.4); downgrades surface as a clear error pointing at\n * `takuhon restore`.\n *\n * Exit codes:\n * 0 — migrated, already at the target (no-op), `--dry-run`, or `--help`\n * 1 — the document was read but cannot be migrated to the target (no\n * forward path / downgrade / unusable schemaVersion) or the migrated\n * result unexpectedly failed re-validation\n * 2 — the command could not run: bad arguments, an out-of-window `--to`, a\n * missing/unreadable file, or a file that is not valid JSON\n */\n\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport {\n MigrationError,\n SCHEMA_VERSION,\n SUPPORTED_SCHEMA_VERSIONS,\n migrateTakuhon,\n validate,\n} from '@takuhon/core';\nimport type { Takuhon } from '@takuhon/core';\n\nimport {\n BackupError,\n backupDirFor,\n createBackup,\n migrateBackupName,\n writeFileAtomic,\n} from './backup.js';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon migrate [path] [--to <version>] [--out <file>] [--dry-run]\n\nForward-migrate a takuhon.json to a newer schema version. The source version\nis read from the file's own schemaVersion. With no path, migrates\n./takuhon.json in the current working directory.\n\nOptions:\n --to <version> Target schema version (default: ${SCHEMA_VERSION}).\n One of: ${SUPPORTED_SCHEMA_VERSIONS.join(', ')}.\n --out <file> Write the result to <file> instead of in place. The source\n file is left unchanged and no backup is created.\n --dry-run Report the planned migration and backup path; write nothing.\n\nBefore an in-place write the current file is backed up to .takuhon-backups/\nbeside it. Migrations are forward-only; to move to an older schema, restore\nfrom a backup with \\`takuhon restore\\`.\n\nExit codes: 0 = migrated / already current / dry-run, 1 = cannot migrate,\n2 = bad arguments / file missing / unreadable / not JSON.\n`;\n\nexport interface MigrateOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/** Injectable dependencies, so tests can pin the backup timestamp. */\nexport interface MigrateDeps {\n /** Clock used for backup filenames. Defaults to `() => new Date()`. */\n now?: () => Date;\n}\n\ninterface ParsedArgs {\n path: string;\n to: string;\n out?: string;\n dryRun: boolean;\n}\n\n/**\n * Run `takuhon migrate` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"migrate\"`). Never throws\n * and never writes to the process streams.\n */\nexport function runMigrate(args: readonly string[] = [], deps: MigrateDeps = {}): MigrateOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon migrate --help\\` for usage.\\n`,\n };\n }\n\n const now = deps.now ?? (() => new Date());\n return migrateFile(parsed, now);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let to: string | undefined;\n let out: string | undefined;\n let dryRun = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--dry-run') {\n dryRun = true;\n continue;\n }\n if (arg === '--to' || arg === '--out') {\n const value = args[i + 1];\n if (value === undefined || value.startsWith('-')) {\n return { error: `takuhon: \\`${arg}\\` requires a value.` };\n }\n if (arg === '--to') to = value;\n else out = value;\n i++;\n continue;\n }\n if (arg.startsWith('--to=')) {\n to = arg.slice('--to='.length);\n continue;\n }\n if (arg.startsWith('--out=')) {\n out = arg.slice('--out='.length);\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`migrate\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `migrate` takes at most one path argument.' };\n }\n path = arg;\n }\n\n const target = to ?? SCHEMA_VERSION;\n if (!(SUPPORTED_SCHEMA_VERSIONS as readonly string[]).includes(target)) {\n return {\n error: `takuhon: unsupported --to version \"${target}\". Supported: ${SUPPORTED_SCHEMA_VERSIONS.join(', ')}.`,\n };\n }\n\n return { path: path ?? DEFAULT_PATH, to: target, out, dryRun };\n}\n\nfunction migrateFile(parsed: ParsedArgs, now: () => Date): MigrateOutcome {\n const { path, to: target, out, dryRun } = parsed;\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: cannot read '${path}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${path}' is not valid JSON: ${detail}\\n` };\n }\n\n const source = (data as { schemaVersion?: unknown }).schemaVersion;\n if (typeof source !== 'string' || source.length === 0) {\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${path}' has no usable schemaVersion; cannot determine what to migrate from.\\n`,\n };\n }\n\n if (source === target) {\n return {\n code: 0,\n stdout: `${path}: already at schemaVersion ${target}; nothing to do.\\n`,\n stderr: '',\n };\n }\n\n // Back up the original bytes only for a genuine in-place write. `--out` to a\n // different name leaves the source untouched, so a backup would be redundant.\n // The write is atomic (write-temp-then-rename), which replaces the target\n // *name* rather than following it, so even an `--out` symlink that points at\n // the source cannot clobber the source unbacked — it just replaces the link.\n const writeTarget = out ?? path;\n const inPlace = resolve(writeTarget) === resolve(path);\n\n let migrated: Takuhon;\n try {\n migrated = migrateTakuhon(data as Takuhon, target);\n } catch (error) {\n if (error instanceof MigrationError) {\n return {\n code: 1,\n stdout: '',\n stderr:\n `takuhon: cannot migrate '${path}': ${error.message}.\\n` +\n 'Migrations are forward-only; to move to an older schema, restore from a backup with `takuhon restore`.\\n',\n };\n }\n throw error;\n }\n\n // Re-validate as a structural safety gate. The bundled validator accepts the\n // entire supported window, so a non-latest `--to` still passes here;\n // `migrateTakuhon` is what guarantees the result carries the requested target\n // shape (it stops the chain at `target`). This catches only a migration that\n // produced something the schema rejects outright.\n const revalidated = validate(migrated);\n if (!revalidated.ok) {\n const lines = revalidated.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: migrated '${path}' to ${target} but the result failed validation:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n // One timestamp per run, shared by the dry-run preview and the real backup so\n // the reported and actual backup paths cannot drift.\n const stamp = now();\n\n // `--dry-run` previews only after the migration is proven feasible above, so\n // an impossible migration (e.g. a downgrade) still reports exit 1 rather than\n // a misleading \"would migrate\".\n if (dryRun) {\n const lines = [`${path}: would migrate ${source} -> ${target}`, ` write: ${writeTarget}`];\n if (inPlace) {\n lines.push(` backup: ${backupDirFor(path)}/${migrateBackupName(source, stamp)}`);\n } else {\n lines.push(' (source left unchanged; no backup created)');\n }\n return { code: 0, stdout: `${lines.join('\\n')}\\n`, stderr: '' };\n }\n\n let backupPath: string | undefined;\n if (inPlace) {\n try {\n backupPath = createBackup({\n targetPath: path,\n content: raw,\n name: (withMillis) => migrateBackupName(source, stamp, withMillis),\n });\n } catch (error) {\n const detail = error instanceof BackupError ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: refusing to migrate '${path}' — backup failed: ${detail}\\n`,\n };\n }\n }\n\n try {\n writeFileAtomic(writeTarget, `${JSON.stringify(migrated, null, 2)}\\n`);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: failed to write '${writeTarget}': ${detail}\\n`,\n };\n }\n\n const lines = [`migrated ${path}: ${source} -> ${target}`];\n if (inPlace) {\n lines.push(` backup: ${backupPath}`);\n } else {\n lines.push(` wrote: ${writeTarget} (source left unchanged; no backup created)`);\n }\n return { code: 0, stdout: `${lines.join('\\n')}\\n`, stderr: '' };\n}\n","/**\n * `takuhon restore --from <backup> [path] [--yes]` — overwrite a profile with\n * a previously saved backup (operational-lifecycle §4.1 / §4.3).\n *\n * Like the other command runners this returns its output as strings plus an\n * exit code rather than touching the process streams. It is `async` because\n * the confirmation prompt is interactive: the entry layer injects a `confirm`\n * callback that reads from the terminal, while tests inject a deterministic\n * predicate (or pass `--yes` to skip the prompt entirely).\n *\n * Restore is destructive, so the flow is deliberately careful:\n * 1. read and schema-`validate` the backup — never restore an invalid file;\n * 2. confirm (unless `--yes`); a non-interactive run with neither `--yes`\n * nor an injected `confirm` refuses rather than overwriting silently;\n * 3. back up the current profile to `.takuhon-backups/pre-restore-…json`;\n * 4. write the backup's bytes to the target verbatim (a faithful\n * reproduction; `validate` is only the gate, not a rewrite).\n *\n * Edge-cache purge (§4.1 step 4) is a remote-adapter concern and does not\n * apply to this local-file command.\n *\n * Exit codes:\n * 0 — restored, aborted at the prompt, or `--help`\n * 1 — the backup was read but failed schema validation\n * 2 — the command could not run: bad arguments, a missing `--from`, an\n * unreadable backup or current profile, a non-JSON backup, or a refusal\n * to overwrite without confirmation\n */\n\nimport { readFileSync } from 'node:fs';\n\nimport { validate } from '@takuhon/core';\nimport type { Takuhon } from '@takuhon/core';\n\nimport {\n BackupError,\n backupDirFor,\n createBackup,\n preRestoreName,\n writeFileAtomic,\n} from './backup.js';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon restore --from <backup> [path] [--yes]\n\nOverwrite a profile with a previously saved backup. With no path, restores\n./takuhon.json in the current working directory.\n\nOptions:\n --from <backup> Backup file to restore from (required).\n --yes, -y Skip the confirmation prompt.\n\nThe backup is schema-validated first, and the current profile is saved to\n.takuhon-backups/pre-restore-<timestamp>.json before being overwritten.\n\nExit codes: 0 = restored / aborted, 1 = backup failed validation,\n2 = bad arguments / file missing / unreadable / not JSON / unconfirmed.\n`;\n\nexport interface RestoreOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/** Injectable dependencies for deterministic tests and interactive prompting. */\nexport interface RestoreDeps {\n /** Clock used for the pre-restore backup filename. Defaults to `() => new Date()`. */\n now?: () => Date;\n /**\n * Confirmation prompt. Receives the rendered message and resolves to the\n * user's decision. Omitted in non-interactive contexts, where restore then\n * refuses unless `--yes` was passed.\n */\n confirm?: (message: string) => boolean | Promise<boolean>;\n}\n\ninterface ParsedArgs {\n from: string;\n path: string;\n yes: boolean;\n}\n\n/**\n * Run `takuhon restore` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"restore\"`).\n */\nexport async function runRestore(\n args: readonly string[] = [],\n deps: RestoreDeps = {},\n): Promise<RestoreOutcome> {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon restore --help\\` for usage.\\n`,\n };\n }\n\n const now = deps.now ?? (() => new Date());\n return restoreFile(parsed, now, deps.confirm);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let from: string | undefined;\n let path: string | undefined;\n let yes = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--yes' || arg === '-y') {\n yes = true;\n continue;\n }\n if (arg === '--from') {\n const value = args[i + 1];\n if (value === undefined || value.startsWith('-')) {\n return { error: 'takuhon: `--from` requires a value.' };\n }\n from = value;\n i++;\n continue;\n }\n if (arg.startsWith('--from=')) {\n from = arg.slice('--from='.length);\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`restore\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `restore` takes at most one path argument.' };\n }\n path = arg;\n }\n\n if (from === undefined || from.length === 0) {\n return { error: 'takuhon: `restore` requires `--from <backup>`.' };\n }\n\n return { from, path: path ?? DEFAULT_PATH, yes };\n}\n\nasync function restoreFile(\n parsed: ParsedArgs,\n now: () => Date,\n confirm: RestoreDeps['confirm'],\n): Promise<RestoreOutcome> {\n const { from, path, yes } = parsed;\n\n let backupRaw: string;\n try {\n backupRaw = readFileSync(from, 'utf8');\n } catch {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read backup '${from}'.\\n` };\n }\n\n let backupData: unknown;\n try {\n backupData = JSON.parse(backupRaw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: backup '${from}' is not valid JSON: ${detail}\\n`,\n };\n }\n\n const result = validate(backupData);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: backup '${from}' is not a valid takuhon profile; refusing to restore:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n // Read the current profile up front: its existence shapes the confirmation\n // message and decides whether a pre-restore backup is needed.\n let currentRaw: string | undefined;\n try {\n currentRaw = readFileSync(path, 'utf8');\n } catch (error) {\n if (!isNotFound(error)) {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read current profile '${path}'.\\n` };\n }\n }\n\n // One timestamp per run, shared by the prompt preview and the actual\n // pre-restore backup so the reported and written paths cannot drift.\n const stamp = now();\n const preRestorePath = `${backupDirFor(path)}/${preRestoreName(stamp)}`;\n\n if (!yes) {\n if (!confirm) {\n return {\n code: 2,\n stdout: '',\n stderr:\n `takuhon: refusing to overwrite '${path}' without confirmation.\\n` +\n 'Re-run interactively, or pass `--yes` to skip the prompt.\\n',\n };\n }\n const decided = await confirm(\n confirmationMessage(path, from, result.data, currentRaw, preRestorePath),\n );\n if (!decided) {\n return { code: 0, stdout: 'Aborted; no changes made.\\n', stderr: '' };\n }\n }\n\n let savedPath: string | undefined;\n if (currentRaw !== undefined) {\n try {\n savedPath = createBackup({\n targetPath: path,\n content: currentRaw,\n name: (withMillis) => preRestoreName(stamp, withMillis),\n });\n } catch (error) {\n const detail = error instanceof BackupError ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: refusing to restore '${path}' — pre-restore backup failed: ${detail}\\n`,\n };\n }\n }\n\n // Write the backup's bytes verbatim: restore is a faithful reproduction of\n // the saved state, and `validate` above was only the gate.\n try {\n writeFileAtomic(path, backupRaw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: failed to write '${path}': ${detail}\\n` };\n }\n\n const lines = [`restored ${path} from ${from}`];\n if (savedPath !== undefined) {\n lines.push(` previous profile saved to ${savedPath}`);\n }\n return { code: 0, stdout: `${lines.join('\\n')}\\n`, stderr: '' };\n}\n\nfunction confirmationMessage(\n path: string,\n from: string,\n data: Takuhon,\n currentRaw: string | undefined,\n preRestorePath: string,\n): string {\n const when = typeof data.meta.updatedAt === 'string' ? ` (from ${data.meta.updatedAt})` : '';\n const preNote =\n currentRaw !== undefined\n ? `Your current profile will be saved as ${preRestorePath}.`\n : `(no existing profile at ${path} to preserve)`;\n return (\n `This will overwrite the profile at ${path} with the backup ${from}${when}.\\n` +\n `${preNote}\\n` +\n 'Continue? [y/N]'\n );\n}\n\nfunction isNotFound(error: unknown): boolean {\n return (\n typeof error === 'object' && error !== null && (error as { code?: unknown }).code === 'ENOENT'\n );\n}\n","/**\n * `takuhon validate [path]` — validate a `takuhon.json` against `@takuhon/core`.\n *\n * All argument handling and the validation itself live here as pure,\n * side-effect-free functions so the whole command is unit-testable: `index.ts`\n * runs `process.exit(main(...))` at module top level and is therefore not\n * import-safe. `runValidate` reads the target file itself but returns its\n * output as strings plus an exit code, leaving the actual stdout/stderr writes\n * and `process.exit` to the caller.\n *\n * Exit codes:\n * 0 — the document is valid (or `--help` was requested)\n * 1 — the document was read and parsed but failed schema validation\n * 2 — the command could not run: bad arguments, a missing/unreadable file,\n * or a file that is not valid JSON (operational errors, distinct from an\n * invalid-but-readable document)\n */\n\nimport { readFileSync } from 'node:fs';\n\nimport { validate } from '@takuhon/core';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon validate [path]\n\nValidate a takuhon.json against the takuhon schema. With no path, validates\n./takuhon.json in the current working directory.\n\nExit codes: 0 = valid, 1 = invalid, 2 = file missing / unreadable / not JSON.\n`;\n\nexport interface ValidateOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/**\n * Run `takuhon validate` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"validate\"`).\n *\n * Handles `--help` / `-h` and rejects extra positionals, then validates the\n * `takuhon.json` at the single optional path argument (default\n * `./takuhon.json`). Never throws and never writes to the process streams —\n * the caller renders the returned `stdout` / `stderr` and exits with `code`.\n */\nexport function runValidate(args: readonly string[] = []): ValidateOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n if (args.length > 1) {\n return {\n code: 2,\n stdout: '',\n stderr:\n 'takuhon: `validate` takes at most one path argument.\\n' +\n 'Run `takuhon validate --help` for usage.\\n',\n };\n }\n\n return validateFile(args[0]);\n}\n\n/** Read, parse, and schema-validate the profile at `pathArg` (default `./takuhon.json`). */\nfunction validateFile(pathArg?: string): ValidateOutcome {\n const target = pathArg ?? DEFAULT_PATH;\n\n let raw: string;\n try {\n raw = readFileSync(target, 'utf8');\n } catch {\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: cannot read '${target}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: '${target}' is not valid JSON: ${detail}\\n`,\n };\n }\n\n const result = validate(data);\n if (result.ok) {\n return {\n code: 0,\n stdout: `${target}: valid (schemaVersion ${result.data.schemaVersion}).\\n`,\n stderr: '',\n };\n }\n\n const count = result.errors.length;\n const lines = result.errors.map((error) => ` ${error.pointer || '/'}: ${error.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `${target}: invalid (${count} error${count === 1 ? '' : 's'}):\\n${lines.join('\\n')}\\n`,\n };\n}\n"],"mappings":"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","names":["readFileSync","mkdirSync","dirname","join","join","mkdirSync","dirname","readFileSync","applyPublicPrivacyFilter","normalize","validate","DEFAULT_PATH","USAGE","readFileSync","validate","applyPublicPrivacyFilter","normalize","parseArgs","resolve","isHttpUrl","readFileSync","validate","DEFAULT_PATH","USAGE","parseArgs","readFileSync","validate","readFileSync","DEFAULT_PATH","USAGE","parseArgs","readFileSync","lines","readFileSync","resolve","MigrationError","SCHEMA_VERSION","migrateTakuhon","validate","DEFAULT_PATH","USAGE","SCHEMA_VERSION","parseArgs","readFileSync","resolve","migrateTakuhon","MigrationError","validate","lines","readFileSync","validate","DEFAULT_PATH","USAGE","parseArgs","readFileSync","validate","lines","isNotFound","readFileSync","validate","DEFAULT_PATH","USAGE","readFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/build-command.ts","../src/backup.ts","../src/site.ts","../src/build-html.ts","../src/dev-command.ts","../src/export-command.ts","../src/import-command.ts","../src/migrate-command.ts","../src/restore-command.ts","../src/sync-command.ts","../src/validate-command.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * `@takuhon/cli` entry point — the `takuhon` command.\n *\n * Exposes `--version` / `--help`, the local profile commands (`validate`,\n * `migrate`, `restore`, `export`, `import`, `build`, `dev`), `sync` (push a\n * local profile to a deployment), and a pointer to `create-takuhon` for\n * scaffolding.\n *\n * `main` is pure (returns an exit code, never calls `process.exit`); the only\n * place that exits the process is {@link run}, invoked either when this module\n * is the entry script or by the bare-name `takuhon` package's `bin.mjs`, which\n * imports and calls `run()`. Keeping `process.exit` at that single boundary\n * lets tests import this module without terminating the test runner.\n */\n\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { stdin, stdout } from 'node:process';\nimport { createInterface } from 'node:readline/promises';\nimport { fileURLToPath } from 'node:url';\n\nimport { runBuild } from './build-command.js';\nimport { runDev } from './dev-command.js';\nimport { runExport } from './export-command.js';\nimport { runImport } from './import-command.js';\nimport { runMigrate } from './migrate-command.js';\nimport { runRestore } from './restore-command.js';\nimport { runSync } from './sync-command.js';\nimport { runValidate } from './validate-command.js';\n\n// Source the reported version from package.json (read at runtime relative to\n// this module) so `takuhon --version` can never drift from the published\n// release — there is no hand-maintained version literal to fall out of sync.\nconst pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as {\n version: string;\n};\nconst VERSION = pkg.version;\n\nconst HELP = `takuhon ${VERSION}\n\nTakuhon — open-source portable profile API server.\n\nUsage:\n takuhon --version Show the installed CLI version\n takuhon --help Show this help\n\nCommands:\n takuhon validate [path] Validate a takuhon.json (default: ./takuhon.json)\n takuhon migrate [path] [--to <v>] Forward-migrate a takuhon.json to a newer schema\n version (default target: latest). Backs up first.\n Add --out <file> to write elsewhere, --dry-run to preview.\n takuhon restore --from <backup> Restore a profile from a backup (prompts before\n overwriting; pass --yes to skip).\n takuhon export [path] [--output <f>] Serialise a takuhon.json to stdout (or --output file).\n takuhon import <file> [path] Import an exported profile into a takuhon.json,\n migrating to the current schema version. Backs up first.\n takuhon build [path] [--output <d>] Render a takuhon.json into a static site (HTML +\n JSON-LD, one page per locale). --base-url <url> adds\n absolute canonical/hreflang links.\n takuhon dev [path] [--port <n>] Serve a takuhon.json as a local static preview,\n re-rendered on each request (default port: 4321).\n --base-url <url> adds canonical/hreflang links.\n takuhon sync [path] --url <url> Push a takuhon.json to a deployment's admin API\n (PUT <url>/api/admin/profile). Reads the admin token\n from TAKUHON_ADMIN_TOKEN. --if-match <etag> opts into\n optimistic locking; --dry-run previews without sending.\n\nScaffolding a new profile project:\n npx create-takuhon my-profile\n npx create-takuhon my-profile --license CC-BY-4.0\n`;\n\nasync function main(argv: readonly string[]): Promise<number> {\n const first = argv[0];\n\n if (first === '--version' || first === '-v') {\n process.stdout.write(`${VERSION}\\n`);\n return 0;\n }\n\n if (first === undefined || first === '--help' || first === '-h') {\n process.stdout.write(HELP);\n return 0;\n }\n\n if (first === 'validate') {\n return emit(runValidate(argv.slice(1)));\n }\n\n if (first === 'migrate') {\n return emit(runMigrate(argv.slice(1)));\n }\n\n if (first === 'export') {\n return emit(runExport(argv.slice(1)));\n }\n\n if (first === 'build') {\n return emit(runBuild(argv.slice(1)));\n }\n\n if (first === 'dev') {\n // `dev` runs a long-lived server and streams its own output, so it does not\n // go through `emit` (a one-shot result writer); it returns the exit code\n // directly and resolves only on graceful shutdown.\n return runDev(argv.slice(1));\n }\n\n if (first === 'import') {\n return emit(runImport(argv.slice(1)));\n }\n\n if (first === 'restore') {\n // Only offer an interactive prompt on a real TTY; otherwise `runRestore`\n // refuses to overwrite without `--yes`, which is the safe default for\n // pipelines.\n const confirm = stdin.isTTY ? promptConfirm : undefined;\n return emit(await runRestore(argv.slice(1), { confirm }));\n }\n\n if (first === 'sync') {\n return emit(await runSync(argv.slice(1)));\n }\n\n process.stderr.write(\n `takuhon: unknown command '${first}'\\n` +\n `Run \\`takuhon --help\\` for usage. For scaffolding a new project, use \\`create-takuhon\\`.\\n`,\n );\n return 2;\n}\n\n/** Write a command outcome's streams and return its exit code. */\nfunction emit(outcome: { code: number; stdout: string; stderr: string }): number {\n if (outcome.stdout) process.stdout.write(outcome.stdout);\n if (outcome.stderr) process.stderr.write(outcome.stderr);\n return outcome.code;\n}\n\n/** Interactive [y/N] confirmation used by `restore` on a TTY. */\nasync function promptConfirm(message: string): Promise<boolean> {\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n const answer = await rl.question(`${message} `);\n return /^y(es)?$/i.test(answer.trim());\n } finally {\n rl.close();\n }\n}\n\n/**\n * Process entry point: run {@link main} and exit with its code. This is the\n * only function that calls `process.exit`. Exported so the bare-name\n * `takuhon` package can invoke it after importing this module.\n */\nexport async function run(argv: readonly string[] = process.argv.slice(2)): Promise<void> {\n try {\n process.exit(await main(argv));\n } catch (error) {\n process.stderr.write(`takuhon: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n}\n\n/** True when this module was started directly (`node …/index.js`). */\nfunction isEntrypoint(): boolean {\n const entry = process.argv[1];\n if (entry === undefined) return false;\n try {\n return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url));\n } catch {\n return false;\n }\n}\n\nif (isEntrypoint()) {\n void run();\n}\n","/**\n * `takuhon build [path] [--output <dir>] [--base-url <url>]` — render a\n * `takuhon.json` into a deployable static site (Spec §13 Static Edition).\n *\n * Mirrors the other command runners: {@link runBuild} is a pure function that\n * reads the source itself and returns its output as strings plus an exit code.\n * The render pipeline reuses `@takuhon/core` only: validate → normalize →\n * `applyPublicPrivacyFilter` (so the static site honours `meta.privacy` exactly\n * like the live API) → for each available locale `resolveLocale` →\n * {@link renderProfileHtml}. The default locale is written to `<dir>/index.html`\n * and every other locale to `<dir>/<locale>/index.html`.\n *\n * Canonical / hreflang links require absolute URLs, so they are emitted only\n * when `--base-url` is supplied; the human locale switcher always uses\n * depth-correct relative links. Asset files are referenced by URL as-is and\n * never copied (out of scope; assets are remote per the schema). Writes are\n * atomic via {@link writeFileAtomic}.\n *\n * Exit codes:\n * 0 — site generated (or `--help`)\n * 1 — the source was read but is not a valid takuhon profile\n * 2 — the command could not run: bad arguments, a missing/unreadable file,\n * a non-JSON file, or a failed write\n */\n\nimport { mkdirSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nimport { applyPublicPrivacyFilter, normalize, validate } from '@takuhon/core';\n\nimport { writeFileAtomic } from './backup.js';\nimport { generateSite } from './site.js';\n\nconst DEFAULT_PATH = 'takuhon.json';\nconst DEFAULT_OUTPUT = 'dist';\n\nconst USAGE = `Usage: takuhon build [path] [--output <dir>] [--base-url <url>]\n\nRender a takuhon.json into a static site (one HTML page per locale, with\nbuild-time Schema.org JSON-LD). With no path, builds ./takuhon.json.\n\nOptions:\n --output <dir> Output directory (default: ${DEFAULT_OUTPUT}). The default\n locale is written to <dir>/index.html and each other locale\n to <dir>/<locale>/index.html.\n --base-url <url> Site origin (e.g. https://me.example). Enables absolute\n canonical and hreflang links; without it those are omitted.\n\nThe public privacy filter is applied (meta.privacy is honoured). Asset URLs are\nreferenced as-is and are not copied. The output directory is written into, not\ncleaned — use a dedicated/empty directory so stale pages do not linger.\n\nExit codes: 0 = built, 1 = source is not a valid profile,\n2 = bad arguments / file missing / unreadable / not JSON / write failed.\n`;\n\nexport interface BuildOutcome {\n readonly code: number;\n readonly stdout: string;\n readonly stderr: string;\n}\n\ninterface ParsedArgs {\n path: string;\n output: string;\n baseUrl?: string;\n}\n\n/**\n * Run `takuhon build` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"build\"`).\n */\nexport function runBuild(args: readonly string[] = []): BuildOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon build --help\\` for usage.\\n`,\n };\n }\n\n return buildSite(parsed);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let output: string | undefined;\n let baseUrl: string | undefined;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--output' || arg === '--base-url') {\n const value = args[i + 1];\n if (value === undefined || value === '' || value.startsWith('-')) {\n return { error: `takuhon: \\`${arg}\\` requires a value.` };\n }\n if (arg === '--output') output = value;\n else baseUrl = value;\n i++;\n continue;\n }\n if (arg.startsWith('--output=')) {\n const value = arg.slice('--output='.length);\n if (value === '') return { error: 'takuhon: `--output` requires a value.' };\n output = value;\n continue;\n }\n if (arg.startsWith('--base-url=')) {\n const value = arg.slice('--base-url='.length);\n if (value === '') return { error: 'takuhon: `--base-url` requires a value.' };\n baseUrl = value;\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`build\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `build` takes at most one path argument.' };\n }\n path = arg;\n }\n\n if (baseUrl !== undefined && !isHttpUrl(baseUrl)) {\n return { error: 'takuhon: `--base-url` must be an absolute http(s) URL.' };\n }\n\n return {\n path: path ?? DEFAULT_PATH,\n output: output ?? DEFAULT_OUTPUT,\n // Drop any trailing slash so URL joins are predictable.\n baseUrl: baseUrl?.replace(/\\/+$/, ''),\n };\n}\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nfunction buildSite(parsed: ParsedArgs): BuildOutcome {\n const { path, output, baseUrl } = parsed;\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: cannot read '${path}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${path}' is not valid JSON: ${detail}\\n` };\n }\n\n const result = validate(data);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${path}' is not a valid takuhon profile; refusing to build:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n const filtered = applyPublicPrivacyFilter(normalize(result.data));\n\n const written: string[] = [];\n try {\n for (const page of generateSite(filtered, { baseUrl })) {\n const outFile = join(output, page.file);\n mkdirSync(dirname(outFile), { recursive: true });\n writeFileAtomic(outFile, page.html);\n written.push(outFile);\n }\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: failed to write the site: ${detail}\\n` };\n }\n\n const summary = written.map((w) => ` ${w}`).join('\\n');\n return {\n code: 0,\n stdout: `built ${written.length} page${written.length === 1 ? '' : 's'} from ${path}:\\n${summary}\\n`,\n stderr: '',\n };\n}\n","/**\n * Local backup helpers shared by `takuhon migrate` and `takuhon restore`.\n *\n * Backups are written to a `.takuhon-backups/` directory co-located with the\n * profile file being mutated, rather than a `~/.takuhon/backups/{slug}/`\n * tree: a local `takuhon.json` operated on by path has no guaranteed slug,\n * and the restore flow documented in operational-lifecycle §4.1 / §4.3 reads\n * and writes `.takuhon-backups/...` relative to the working file. Keeping the\n * backups beside the source also mirrors the Vercel / Static adapter layout\n * (§3.1), which is the closest analogue for a local file workflow.\n *\n * Naming follows §3.1 (`takuhon-backup-v{version}-{timestamp}.json`) and the\n * pre-restore convention of §4.1 (`pre-restore-{timestamp}.json`). Timestamps\n * are ISO 8601 basic format in UTC at second precision; {@link createBackup}\n * implements the §3.3 overwrite guard by falling back to millisecond\n * precision when a same-second name already exists.\n */\n\nimport { mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';\nimport { basename, dirname, join } from 'node:path';\n\n/** Directory (relative to the target file) that holds local backups. */\nexport const BACKUP_DIR_NAME = '.takuhon-backups';\n\n/**\n * Thrown by {@link createBackup} when a backup cannot be written without\n * overwriting an existing file even after disambiguating with milliseconds.\n */\nexport class BackupError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'BackupError';\n }\n}\n\n/**\n * Format `date` as a compact ISO 8601 basic-format UTC timestamp.\n *\n * @example\n * compactTimestamp(new Date('2026-05-11T12:00:00.123Z')) // \"20260511T120000Z\"\n * compactTimestamp(new Date('2026-05-11T12:00:00.123Z'), true) // \"20260511T120000.123Z\"\n */\nexport function compactTimestamp(date: Date, withMillis = false): string {\n const iso = date.toISOString(); // e.g. \"2026-05-11T12:00:00.123Z\"\n const trimmed = withMillis ? iso : iso.replace(/\\.\\d{3}Z$/, 'Z');\n // Drop the extended-format separators; the millisecond `.` (if kept) stays.\n return trimmed.replace(/[-:]/g, '');\n}\n\n/** Build the migration pre-backup filename for a given source `version`. */\nexport function migrateBackupName(version: string, date: Date, withMillis = false): string {\n return `takuhon-backup-v${version}-${compactTimestamp(date, withMillis)}.json`;\n}\n\n/** Build the pre-restore backup filename (operational-lifecycle §4.1). */\nexport function preRestoreName(date: Date, withMillis = false): string {\n return `pre-restore-${compactTimestamp(date, withMillis)}.json`;\n}\n\n/** Build the pre-import backup filename (operational-lifecycle §5.3 step 3). */\nexport function preImportName(date: Date, withMillis = false): string {\n return `pre-import-${compactTimestamp(date, withMillis)}.json`;\n}\n\n/** Resolve the `.takuhon-backups/` directory beside `targetPath`. */\nexport function backupDirFor(targetPath: string): string {\n return join(dirname(targetPath), BACKUP_DIR_NAME);\n}\n\n/**\n * Write `content` into `.takuhon-backups/` beside `targetPath`, returning the\n * path actually written.\n *\n * `name(withMillis)` yields the second-precision filename when `false` and a\n * millisecond-precision variant when `true`. The directory is created if\n * absent and writes use the `wx` flag so an existing file is never\n * overwritten (operational-lifecycle §3.3): a same-second collision retries\n * once at millisecond precision, and a further collision throws\n * {@link BackupError}.\n */\nexport function createBackup(params: {\n targetPath: string;\n content: string;\n name: (withMillis: boolean) => string;\n}): string {\n const dir = backupDirFor(params.targetPath);\n mkdirSync(dir, { recursive: true });\n\n const primary = join(dir, params.name(false));\n try {\n writeFileSync(primary, params.content, { flag: 'wx' });\n return primary;\n } catch (error) {\n if (!isAlreadyExists(error)) throw error;\n }\n\n const fallback = join(dir, params.name(true));\n try {\n writeFileSync(fallback, params.content, { flag: 'wx' });\n return fallback;\n } catch (error) {\n if (isAlreadyExists(error)) {\n throw new BackupError(\n `backup target already exists and could not be disambiguated: ${fallback}`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return (\n typeof error === 'object' && error !== null && (error as { code?: unknown }).code === 'EEXIST'\n );\n}\n\n/**\n * Write `content` to `target` atomically: stage it in a sibling temp file and\n * `rename` it into place. A `rename` within a directory is atomic, so a reader\n * never observes a half-written profile and an interrupted write (crash,\n * ENOSPC) cannot truncate the existing file — it is replaced whole or not at\n * all. The temp file is removed on failure. Pairs with the backup-before-write\n * ordering in the migrate / restore commands.\n */\nexport function writeFileAtomic(target: string, content: string): void {\n const tmp = join(dirname(target), `.${basename(target)}.${process.pid}.tmp`);\n try {\n writeFileSync(tmp, content, 'utf8');\n renameSync(tmp, target);\n } catch (error) {\n rmSync(tmp, { force: true });\n throw error;\n }\n}\n","/**\n * Shared static-site generation for `takuhon build` and `takuhon dev`.\n *\n * {@link generateSite} turns one validated, normalized, privacy-filtered profile\n * into the full set of pages the static surface exposes: one per available\n * locale. `build` writes each page's {@link SitePage.file} to disk; `dev` serves\n * each page's {@link SitePage.route} from memory. Keeping the per-locale loop,\n * the locale switcher links, and the canonical/hreflang logic here means both\n * commands share a single source of truth for the site's structure — the only\n * difference between them is disk write vs. in-memory serve.\n *\n * This reuses `@takuhon/core` only (validate/normalize/resolve happen upstream;\n * this module just resolves each locale and renders), so it stays bundler-free\n * and unit-testable as a pure function.\n */\n\nimport type { NormalizedTakuhon } from '@takuhon/core';\nimport { resolveLocale } from '@takuhon/core';\n\nimport { renderProfileHtml, type Alternate, type LocaleLink } from './build-html.js';\n\n/** One generated page: a serve route, a relative output file, and its HTML. */\nexport interface SitePage {\n /** URL path used by `dev` (default locale at `/`, others at `/<locale>/`). */\n readonly route: string;\n /** Output path used by `build`, relative to the output dir. */\n readonly file: string;\n /** Rendered HTML document. */\n readonly html: string;\n}\n\nexport interface GenerateOptions {\n /**\n * Site origin (e.g. `https://me.example`). When set, pages carry absolute\n * canonical + hreflang links; when absent those are omitted (the human locale\n * switcher is always relative either way).\n */\n readonly baseUrl?: string;\n}\n\n/**\n * Generate every page for a profile: the default locale first, then the rest,\n * de-duplicated. Schema.org JSON-LD is emitted unless `settings.enableJsonLd`\n * is explicitly `false`.\n */\nexport function generateSite(\n profile: NormalizedTakuhon,\n options: GenerateOptions = {},\n): SitePage[] {\n const { baseUrl } = options;\n const defaultLocale = profile.settings.defaultLocale;\n // Default locale first, then the rest, de-duplicated.\n const locales = [...new Set([defaultLocale, ...profile.settings.availableLocales])];\n const jsonLd = profile.settings.enableJsonLd !== false;\n\n return locales.map((locale) => {\n const localized = resolveLocale(profile, locale);\n const isDefault = locale === defaultLocale;\n\n const localeNav: LocaleLink[] = locales.map((to) => ({\n locale: to,\n href: localeHref(locale, to, defaultLocale),\n current: to === locale,\n }));\n const canonicalUrl = baseUrl ? absoluteUrl(baseUrl, locale, defaultLocale) : undefined;\n const alternates: Alternate[] = baseUrl ? buildAlternates(baseUrl, locales, defaultLocale) : [];\n\n const html = renderProfileHtml({ localized, canonicalUrl, alternates, localeNav, jsonLd });\n return {\n route: isDefault ? '/' : `/${locale}/`,\n file: isDefault ? 'index.html' : `${locale}/index.html`,\n html,\n };\n });\n}\n\n/** Absolute URL for a locale's page (default locale lives at the site root). */\nfunction absoluteUrl(baseUrl: string, locale: string, defaultLocale: string): string {\n return locale === defaultLocale ? `${baseUrl}/` : `${baseUrl}/${locale}/`;\n}\n\n/** hreflang alternates for every locale plus an `x-default` pointing at the default. */\nfunction buildAlternates(\n baseUrl: string,\n locales: readonly string[],\n defaultLocale: string,\n): Alternate[] {\n const alternates: Alternate[] = locales.map((locale) => ({\n hreflang: locale,\n href: absoluteUrl(baseUrl, locale, defaultLocale),\n }));\n alternates.push({\n hreflang: 'x-default',\n href: absoluteUrl(baseUrl, defaultLocale, defaultLocale),\n });\n return alternates;\n}\n\n/**\n * Depth-correct relative link from the page for `from` to the page for `to`,\n * for the human locale switcher. Always relative (independent of `baseUrl`)\n * so the switcher works regardless of where the site is hosted: the default\n * locale lives at the root, every other locale one directory deep.\n */\nfunction localeHref(from: string, to: string, defaultLocale: string): string {\n const fromRoot = from === defaultLocale;\n const toRoot = to === defaultLocale;\n if (fromRoot) return toRoot ? './' : `${to}/`;\n return toRoot ? '../' : `../${to}/`;\n}\n","/**\n * Pure HTML rendering for `takuhon build`.\n *\n * {@link renderProfileHtml} turns one locale-resolved {@link LocalizedTakuhon}\n * into a complete, self-contained static HTML document: semantic markup for\n * every profile section, an inline stylesheet, optional Schema.org JSON-LD,\n * and the `<head>` metadata (`<title>`, description, canonical, hreflang\n * alternates) the caller supplies.\n *\n * This is a deliberately separate, simpler surface from the React\n * `@takuhon/ui` (which is delivered as CSS-Modules components needing a\n * bundler). It reuses only `@takuhon/core` and has no DOM/browser dependency,\n * so it renders in plain Node and is unit-testable as a pure string function.\n *\n * Security: every piece of profile-derived text is escaped before it reaches\n * the markup ({@link escapeHtml}), and the JSON-LD payload is `<`/`>`/`&`\n * unicode-escaped so it cannot break out of its `<script>` element.\n */\n\nimport { generateJsonLd } from '@takuhon/core';\nimport type { LocalizedTakuhon } from '@takuhon/core';\n\ntype LocalizedProfile = LocalizedTakuhon['profile'];\n\n/** One entry in the human-facing locale switcher. */\nexport interface LocaleLink {\n locale: string;\n href: string;\n current: boolean;\n}\n\n/** One `<link rel=\"alternate\" hreflang>` entry. */\nexport interface Alternate {\n hreflang: string;\n href: string;\n}\n\nexport interface RenderInput {\n /** The locale-resolved document to render. */\n localized: LocalizedTakuhon;\n /** Absolute canonical URL for this page (only when `--base-url` was given). */\n canonicalUrl?: string;\n /** hreflang alternates (empty when no base URL is available). */\n alternates: readonly Alternate[];\n /** Human locale switcher links (rendered only when more than one locale). */\n localeNav: readonly LocaleLink[];\n /** Whether to emit Schema.org JSON-LD (mirrors `settings.enableJsonLd`). */\n jsonLd: boolean;\n}\n\n/** Escape text for use in HTML element content or double/single-quoted attributes. */\nexport function escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/** Unicode-escape `<`, `>`, `&` so a JSON-LD payload cannot break out of `<script>`. */\nfunction escapeJsonLd(json: string): string {\n return json.replace(/</g, '\\\\u003c').replace(/>/g, '\\\\u003e').replace(/&/g, '\\\\u0026');\n}\n\n/**\n * Return `url` only when its scheme is safe to place in an `href`/`src`, else\n * `undefined`. Relative, protocol-relative, fragment, and query URLs (no\n * scheme) are allowed; among absolute URLs only `http:`, `https:`, and\n * `mailto:` are. This blocks `javascript:`, `data:`, `vbscript:`, etc. — the\n * schema validates only a generic URI, so a hostile document could otherwise\n * smuggle an executable scheme into the generated page.\n */\nfunction safeUrl(url: string): string | undefined {\n const trimmed = url.trim();\n const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(trimmed)?.[1]?.toLowerCase();\n if (scheme === undefined) return trimmed; // relative / protocol-relative / fragment\n return scheme === 'http' || scheme === 'https' || scheme === 'mailto' ? trimmed : undefined;\n}\n\nconst CSS = `:root{--fg:#1a1a1a;--muted:#666;--accent:#0b5fff;--line:#e5e5e5}\n*{box-sizing:border-box}\nbody{margin:0;color:var(--fg);font:16px/1.6 system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;background:#fff}\nmain{max-width:42rem;margin:0 auto;padding:2rem 1.25rem}\na{color:var(--accent)}\nh1{font-size:1.9rem;margin:.2rem 0}\nh2{font-size:1.15rem;margin:2rem 0 .75rem;padding-bottom:.3rem;border-bottom:1px solid var(--line)}\nh3{font-size:1rem;margin:0}\nheader .avatar{width:96px;height:96px;border-radius:50%;object-fit:cover}\n.tagline{font-size:1.1rem;color:var(--muted);margin:.2rem 0}\n.location{color:var(--muted);margin:.2rem 0}\n.bio{margin:.75rem 0}\nul{padding:0;margin:0;list-style:none}\n.entries>li{margin:0 0 1.1rem}\n.sub{margin:.1rem 0;font-weight:600}\n.meta{margin:.1rem 0;color:var(--muted);font-size:.9rem}\n.links{display:flex;flex-wrap:wrap;gap:.5rem 1rem;margin:.75rem 0}\n.skills,.tags{display:flex;flex-wrap:wrap;gap:.4rem}\n.skills>li,.tags>li{background:#f2f2f2;border-radius:1rem;padding:.15rem .6rem;font-size:.85rem}\n.rec{margin:0 0 1.1rem}\n.rec blockquote{margin:0;padding-left:.9rem;border-left:3px solid var(--line)}\n.rec figcaption{color:var(--muted);font-size:.9rem;margin-top:.3rem}\nnav.locales{display:flex;gap:.75rem;margin-bottom:1rem;font-size:.9rem}\nfooter.powered{max-width:42rem;margin:0 auto;padding:1.5rem 1.25rem;color:var(--muted);font-size:.85rem}`;\n\ninterface EntryView {\n heading: string;\n sub?: string;\n dates?: string;\n body?: string;\n url?: string;\n tags?: readonly string[];\n}\n\n/** Format a YearMonth range; `null` end or `isCurrent` renders as \"Present\". */\nfunction dateRange(start?: string, end?: string | null, isCurrent?: boolean): string {\n const left = start ?? '';\n const right = isCurrent === true || end === null ? 'Present' : (end ?? '');\n if (left && right) return `${left} – ${right}`;\n return left || right;\n}\n\nfunction nonEmpty(values: readonly (string | undefined)[], separator: string): string | undefined {\n const joined = values\n .filter((v): v is string => typeof v === 'string' && v.length > 0)\n .join(separator);\n return joined.length > 0 ? joined : undefined;\n}\n\nfunction renderEntry(entry: EntryView): string {\n const href = entry.url ? safeUrl(entry.url) : undefined;\n const heading = href\n ? `<a href=\"${escapeHtml(href)}\">${escapeHtml(entry.heading)}</a>`\n : escapeHtml(entry.heading);\n const parts = [`<h3>${heading}</h3>`];\n if (entry.sub) parts.push(`<p class=\"sub\">${escapeHtml(entry.sub)}</p>`);\n if (entry.dates) parts.push(`<p class=\"meta\">${escapeHtml(entry.dates)}</p>`);\n if (entry.body) parts.push(`<p>${escapeHtml(entry.body)}</p>`);\n if (entry.tags && entry.tags.length > 0) {\n parts.push(\n `<ul class=\"tags\">${entry.tags.map((t) => `<li>${escapeHtml(t)}</li>`).join('')}</ul>`,\n );\n }\n return `<li>${parts.join('')}</li>`;\n}\n\n/** Render a `<section>` of entries, or `''` when there are none. */\nfunction entryList(title: string, entries: readonly EntryView[]): string {\n if (entries.length === 0) return '';\n return `<section><h2>${escapeHtml(title)}</h2><ul class=\"entries\">${entries\n .map(renderEntry)\n .join('')}</ul></section>`;\n}\n\nfunction renderHeader(p: LocalizedProfile): string {\n const parts: string[] = [];\n const avatarSrc = p.avatar?.url ? safeUrl(p.avatar.url) : undefined;\n if (avatarSrc) {\n parts.push(\n `<img class=\"avatar\" src=\"${escapeHtml(avatarSrc)}\" alt=\"${escapeHtml(p.avatar?.alt ?? '')}\">`,\n );\n }\n parts.push(`<h1>${escapeHtml(p.displayName)}</h1>`);\n if (p.tagline) parts.push(`<p class=\"tagline\">${escapeHtml(p.tagline)}</p>`);\n if (p.location?.display) parts.push(`<p class=\"location\">${escapeHtml(p.location.display)}</p>`);\n if (p.bio) parts.push(`<p class=\"bio\">${escapeHtml(p.bio)}</p>`);\n return `<header>${parts.join('')}</header>`;\n}\n\nfunction renderLinks(links: LocalizedTakuhon['links']): string {\n if (links.length === 0) return '';\n const items = links\n .map((l) => {\n const text = escapeHtml(l.label ?? l.url);\n const href = safeUrl(l.url);\n return href ? `<li><a href=\"${escapeHtml(href)}\">${text}</a></li>` : `<li>${text}</li>`;\n })\n .join('');\n return `<nav aria-label=\"Links\"><ul class=\"links\">${items}</ul></nav>`;\n}\n\nfunction renderSkills(skills: LocalizedTakuhon['skills']): string {\n if (skills.length === 0) return '';\n const items = skills.map((s) => `<li>${escapeHtml(s.label)}</li>`).join('');\n return `<section><h2>Skills</h2><ul class=\"skills\">${items}</ul></section>`;\n}\n\nfunction renderLanguages(languages: LocalizedTakuhon['languages']): string {\n if (languages.length === 0) return '';\n const items = languages\n .map((l) => `<li>${escapeHtml(`${l.displayName ?? l.language} — ${l.proficiency}`)}</li>`)\n .join('');\n return `<section><h2>Languages</h2><ul class=\"entries\">${items}</ul></section>`;\n}\n\nfunction renderRecommendations(recs: LocalizedTakuhon['recommendations']): string {\n if (recs.length === 0) return '';\n const items = recs\n .map((r) => {\n const authorHref = r.author.url ? safeUrl(r.author.url) : undefined;\n const name = authorHref\n ? `<a href=\"${escapeHtml(authorHref)}\">${escapeHtml(r.author.name)}</a>`\n : escapeHtml(r.author.name);\n const caption = [name, r.author.headline ? escapeHtml(r.author.headline) : '']\n .filter(Boolean)\n .join(', ');\n const rel = r.relationship ? ` (${escapeHtml(r.relationship)})` : '';\n return `<figure class=\"rec\"><blockquote>${escapeHtml(r.body)}</blockquote><figcaption>— ${caption}${rel}</figcaption></figure>`;\n })\n .join('');\n return `<section><h2>Recommendations</h2>${items}</section>`;\n}\n\nfunction renderContact(contact: LocalizedTakuhon['contact']): string {\n const items: string[] = [];\n if (contact.email) {\n items.push(\n `<li><a href=\"mailto:${escapeHtml(contact.email)}\">${escapeHtml(contact.email)}</a></li>`,\n );\n }\n const formHref = contact.formUrl ? safeUrl(contact.formUrl) : undefined;\n if (formHref) {\n items.push(`<li><a href=\"${escapeHtml(formHref)}\">Contact form</a></li>`);\n }\n if (items.length === 0) return '';\n return `<section><h2>Contact</h2><ul class=\"entries\">${items.join('')}</ul></section>`;\n}\n\nfunction renderJsonLdScript(data: LocalizedTakuhon): string {\n const payload = JSON.stringify(generateJsonLd(data));\n return `<script type=\"application/ld+json\">${escapeJsonLd(payload)}</script>`;\n}\n\nfunction renderLocaleNav(localeNav: readonly LocaleLink[]): string {\n const items = localeNav\n .map((l) =>\n l.current\n ? `<span aria-current=\"true\">${escapeHtml(l.locale)}</span>`\n : `<a href=\"${escapeHtml(l.href)}\">${escapeHtml(l.locale)}</a>`,\n )\n .join('');\n return `<nav class=\"locales\" aria-label=\"Language\">${items}</nav>`;\n}\n\n/** Render a complete static HTML document for one locale-resolved profile. */\nexport function renderProfileHtml(input: RenderInput): string {\n const d = input.localized;\n const p = d.profile;\n const description = p.tagline ?? p.bio ?? '';\n\n const head = [\n '<meta charset=\"utf-8\">',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">',\n `<title>${escapeHtml(p.displayName)}</title>`,\n description\n ? `<meta name=\"description\" content=\"${escapeHtml(description.slice(0, 300))}\">`\n : '',\n input.canonicalUrl ? `<link rel=\"canonical\" href=\"${escapeHtml(input.canonicalUrl)}\">` : '',\n ...input.alternates.map(\n (a) =>\n `<link rel=\"alternate\" hreflang=\"${escapeHtml(a.hreflang)}\" href=\"${escapeHtml(a.href)}\">`,\n ),\n input.jsonLd ? renderJsonLdScript(d) : '',\n `<style>${CSS}</style>`,\n ]\n .filter(Boolean)\n .join('\\n ');\n\n const body = [\n input.localeNav.length > 1 ? renderLocaleNav(input.localeNav) : '',\n renderHeader(p),\n renderLinks(d.links),\n entryList(\n 'Experience',\n d.careers.map((c) => ({\n heading: c.role,\n sub: c.organization,\n dates: dateRange(c.startDate, c.endDate, c.isCurrent),\n body: c.description,\n url: c.url,\n })),\n ),\n entryList(\n 'Projects',\n d.projects.map((x) => ({\n heading: x.title,\n dates: dateRange(x.startDate, x.endDate),\n body: x.description,\n url: x.url,\n tags: x.tags,\n })),\n ),\n renderSkills(d.skills),\n entryList(\n 'Education',\n d.education.map((e) => {\n const degree = nonEmpty([e.degree, e.fieldOfStudy], ', ');\n return {\n heading: degree ?? e.institution,\n sub: degree ? e.institution : undefined,\n dates: dateRange(e.startDate, e.endDate, e.isCurrent),\n body: e.description,\n url: e.url,\n };\n }),\n ),\n entryList(\n 'Certifications',\n d.certifications.map((c) => ({\n heading: c.title,\n sub: c.issuingOrganization,\n dates: dateRange(c.issueDate, c.expirationDate),\n url: c.url,\n })),\n ),\n entryList(\n 'Publications',\n d.publications.map((x) => ({\n heading: x.title,\n sub: nonEmpty([x.publisher, x.coAuthors?.join(', ')], ' · '),\n dates: dateRange(x.date),\n body: x.description,\n url: x.url ?? (x.doi ? `https://doi.org/${x.doi}` : undefined),\n })),\n ),\n entryList(\n 'Honors & awards',\n d.honors.map((x) => ({\n heading: x.title,\n sub: x.issuer,\n dates: dateRange(x.date),\n body: x.description,\n url: x.url,\n })),\n ),\n entryList(\n 'Memberships',\n d.memberships.map((x) => ({\n heading: x.role ?? x.organization,\n sub: x.role ? x.organization : undefined,\n dates: dateRange(x.startDate, x.endDate, x.isCurrent),\n body: x.description,\n url: x.url,\n })),\n ),\n entryList(\n 'Volunteering',\n d.volunteering.map((x) => ({\n heading: x.role,\n sub: nonEmpty([x.organization, x.cause], ' · '),\n dates: dateRange(x.startDate, x.endDate, x.isCurrent),\n body: x.description,\n url: x.url,\n })),\n ),\n entryList(\n 'Courses',\n d.courses.map((x) => ({\n heading: x.title,\n sub: x.provider,\n dates: dateRange(x.completionDate),\n body: x.description,\n url: x.certificateUrl,\n })),\n ),\n entryList(\n 'Patents',\n d.patents.map((x) => ({\n heading: x.title,\n sub: nonEmpty([x.patentNumber, x.office, x.status, x.coInventors?.join(', ')], ' · '),\n dates: dateRange(x.filingDate ?? x.grantDate),\n body: x.description,\n url: x.url,\n })),\n ),\n entryList(\n 'Test scores',\n d.testScores.map((x) => ({\n heading: `${x.title}: ${x.score}`,\n dates: dateRange(x.date),\n body: x.description,\n url: x.url,\n })),\n ),\n renderLanguages(d.languages),\n renderRecommendations(d.recommendations),\n renderContact(d.contact),\n ]\n .filter(Boolean)\n .join('\\n');\n\n const footer =\n d.settings.showPoweredBy === true ? '<footer class=\"powered\">Powered by takuhon</footer>' : '';\n\n return (\n `<!DOCTYPE html>\\n<html lang=\"${escapeHtml(d.resolvedLocale)}\">\\n<head>\\n ${head}\\n</head>\\n` +\n `<body>\\n<main>\\n${body}\\n</main>\\n${footer ? `${footer}\\n` : ''}</body>\\n</html>\\n`\n );\n}\n","/**\n * `takuhon dev [path] [--port <n>] [--base-url <url>]` — serve a `takuhon.json`\n * as a local static preview (Spec §14.1 Phase 1 \"edit → preview\").\n *\n * This is the in-memory companion of `takuhon build`: it renders the same\n * per-locale surface (via the shared {@link generateSite}) but serves it over\n * `node:http` instead of writing to disk — no bundler, no Hono/Vite/React, no\n * remote/secret coupling. The source is re-read and re-rendered on every\n * request, so editing `takuhon.json` and reloading the browser shows changes\n * with no watch machinery; an invalid file is served as a live error page so it\n * can be fixed in place.\n *\n * A long-running server does not fit the pure `runXxx → {code,stdout,stderr}`\n * shape of the other commands, so the testable logic is split from the I/O:\n * {@link loadSiteState} (source → route map), {@link resolveRoute},\n * {@link contentType}, and {@link handleRequest} are pure; {@link createDevServer}\n * and {@link runDev} are the thin `node:http` wrapper around them.\n *\n * Exit codes:\n * 0 — served, then stopped cleanly (Ctrl-C), or `--help`\n * 2 — the command could not run: bad arguments, a missing/unreadable file,\n * or the port was already in use\n */\n\nimport { readFileSync } from 'node:fs';\nimport { createServer, type Server } from 'node:http';\n\nimport { applyPublicPrivacyFilter, normalize, validate } from '@takuhon/core';\n\nimport { escapeHtml } from './build-html.js';\nimport { generateSite } from './site.js';\n\nconst DEFAULT_PATH = 'takuhon.json';\nconst DEFAULT_PORT = 4321;\n\nconst USAGE = `Usage: takuhon dev [path] [--port <n>] [--base-url <url>]\n\nServe a takuhon.json as a local static preview (one page per locale) — the same\nsurface \\`takuhon build\\` produces. With no path, serves ./takuhon.json. The file\nis re-read and re-rendered on every request, so edit it and reload the browser\nto see changes. Stop with Ctrl-C.\n\nOptions:\n --port <n> Port to listen on (default: ${DEFAULT_PORT}).\n --base-url <url> Site origin (e.g. https://me.example). Enables absolute\n canonical and hreflang links; without it those are omitted.\n\nThe public privacy filter is applied (meta.privacy is honoured). An invalid\ntakuhon.json is served as an error page so you can fix it and reload.\n\nExit codes: 0 = served then stopped, 2 = bad arguments / file missing /\nunreadable / port in use.\n`;\n\n/** Injectable output sinks so tests can capture streams without a real TTY. */\nexport interface DevDeps {\n stdout?: (text: string) => void;\n stderr?: (text: string) => void;\n}\n\ninterface ParsedArgs {\n path: string;\n port: number;\n baseUrl?: string;\n}\n\n/**\n * The current render state of the source file. Recomputed per request so edits\n * are reflected on reload; a read/parse/validate failure becomes a served error\n * page rather than crashing the server.\n */\nexport type SiteState =\n | { readonly ok: true; readonly pages: ReadonlyMap<string, string> }\n | { readonly ok: false; readonly status: number; readonly message: string };\n\n/** A fully-resolved HTTP response, independent of the `node:http` socket. */\nexport interface DevResponse {\n readonly status: number;\n readonly contentType: string;\n readonly body: string;\n}\n\n/**\n * Read, validate, and render `path` into a route→HTML map. Any failure (missing\n * file, bad JSON, invalid profile) yields a 500 state carrying a human-readable\n * message — validation errors are formatted with their JSON Pointers, mirroring\n * `takuhon build`. The public privacy filter is applied, exactly as `build` does.\n */\nexport function loadSiteState(path: string, baseUrl?: string): SiteState {\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return { ok: false, status: 500, message: `cannot read '${path}'.` };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { ok: false, status: 500, message: `'${path}' is not valid JSON: ${detail}` };\n }\n\n const result = validate(data);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n ok: false,\n status: 500,\n message: `'${path}' is not a valid takuhon profile:\\n${lines.join('\\n')}`,\n };\n }\n\n const filtered = applyPublicPrivacyFilter(normalize(result.data));\n const pages = new Map(generateSite(filtered, { baseUrl }).map((p) => [p.route, p.html]));\n return { ok: true, pages };\n}\n\n/**\n * Normalize a request path to a site route key. A trailing `index.html` is\n * stripped and a trailing slash is added, so `/ja`, `/ja/`, and\n * `/ja/index.html` all map to `/ja/` (and `/`, ``, `/index.html` to `/`).\n */\nexport function resolveRoute(urlPath: string): string {\n let p = urlPath;\n try {\n p = decodeURIComponent(urlPath);\n } catch {\n // Keep the raw path on malformed percent-encoding; it will simply 404.\n }\n p = p.replace(/\\/index\\.html$/, '/');\n if (p === '' || p === '/') return '/';\n if (!p.startsWith('/')) p = `/${p}`;\n if (!p.endsWith('/')) p = `${p}/`;\n return p;\n}\n\n/**\n * Content-type for a served route. The static surface is HTML-only (the build\n * emits one HTML page per locale and no assets/JSON), so this is constant; it is\n * a named function to keep the response shape ready should the surface grow.\n */\nexport function contentType(_route: string): string {\n return 'text/html; charset=utf-8';\n}\n\n/** Resolve a request to a response against the current {@link SiteState}. Pure. */\nexport function handleRequest(method: string, urlPath: string, state: SiteState): DevResponse {\n if (method !== 'GET' && method !== 'HEAD') {\n return { status: 405, contentType: 'text/plain; charset=utf-8', body: 'Method Not Allowed\\n' };\n }\n if (!state.ok) {\n return {\n status: state.status,\n contentType: contentType('/'),\n body: renderErrorPage(state.message),\n };\n }\n const route = resolveRoute(urlPath);\n const html = state.pages.get(route);\n if (html === undefined) {\n return {\n status: 404,\n contentType: contentType(route),\n body: renderNotFoundPage(route, [...state.pages.keys()]),\n };\n }\n return { status: 200, contentType: contentType(route), body: html };\n}\n\n/**\n * Create the preview server. Each request recomputes the site state (so edits\n * are live on reload) and delegates to the pure {@link handleRequest}. Not\n * started here — the caller binds a port. Importing this module has no side\n * effects.\n */\nexport function createDevServer(opts: { path: string; baseUrl?: string }): Server {\n return createServer((req, res) => {\n const method = req.method ?? 'GET';\n const state = loadSiteState(opts.path, opts.baseUrl);\n const response = handleRequest(method, pathnameOf(req.url ?? '/'), state);\n res.writeHead(response.status, { 'Content-Type': response.contentType });\n if (method === 'HEAD') res.end();\n else res.end(response.body);\n });\n}\n\n/**\n * Run `takuhon dev`. Resolves with the process exit code: it stays pending while\n * the server runs and resolves on graceful shutdown (Ctrl-C). Argument and\n * missing-file errors return before any port is bound.\n */\nexport async function runDev(args: readonly string[] = [], deps: DevDeps = {}): Promise<number> {\n const out = deps.stdout ?? ((text: string) => void process.stdout.write(text));\n const err = deps.stderr ?? ((text: string) => void process.stderr.write(text));\n\n if (args[0] === '--help' || args[0] === '-h') {\n out(USAGE);\n return 0;\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n err(`${parsed.error}\\nRun \\`takuhon dev --help\\` for usage.\\n`);\n return 2;\n }\n\n // Fast-fail only when the source is missing/unreadable — there is nothing to\n // preview. A present-but-invalid file is served as a live error page instead,\n // so it can be fixed without restarting the server.\n try {\n readFileSync(parsed.path, 'utf8');\n } catch {\n err(\n `takuhon: cannot read '${parsed.path}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n );\n return 2;\n }\n\n const server = createDevServer({ path: parsed.path, baseUrl: parsed.baseUrl });\n\n return await new Promise<number>((resolve) => {\n let closing = false;\n const shutdown = (): void => {\n if (closing) return;\n closing = true;\n process.removeListener('SIGINT', shutdown);\n process.removeListener('SIGTERM', shutdown);\n server.close(() => resolve(0));\n // Drop keep-alive sockets so close() does not hang (Node >= 18.2).\n server.closeAllConnections();\n };\n\n server.once('error', (error: NodeJS.ErrnoException) => {\n // The signal handlers are only registered once listening starts, so a\n // bind failure (e.g. EADDRINUSE) has none to detach.\n if (error.code === 'EADDRINUSE') {\n err(`takuhon: port ${parsed.port} is already in use; pass --port <n> to choose another.\\n`);\n } else {\n err(`takuhon: ${error.message}\\n`);\n }\n resolve(2);\n });\n\n // Bind to loopback only: a local preview must not expose draft profile\n // content (or the dev error pages) to the rest of the network.\n server.listen(parsed.port, '127.0.0.1', () => {\n out(\n `takuhon dev: serving ${parsed.path} at http://localhost:${parsed.port}/ (Ctrl-C to stop)\\n`,\n );\n // Surface a current validation problem up front; the browser shows it too.\n const state = loadSiteState(parsed.path, parsed.baseUrl);\n if (!state.ok) {\n err(\n `takuhon dev: ${parsed.path} is not a valid profile yet; the preview will show the error until it is fixed.\\n`,\n );\n }\n process.once('SIGINT', shutdown);\n process.once('SIGTERM', shutdown);\n });\n });\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let portRaw: string | undefined;\n let baseUrl: string | undefined;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--port' || arg === '--base-url') {\n const value = args[i + 1];\n if (value === undefined || value === '' || value.startsWith('-')) {\n return { error: `takuhon: \\`${arg}\\` requires a value.` };\n }\n if (arg === '--port') portRaw = value;\n else baseUrl = value;\n i++;\n continue;\n }\n if (arg.startsWith('--port=')) {\n const value = arg.slice('--port='.length);\n if (value === '') return { error: 'takuhon: `--port` requires a value.' };\n portRaw = value;\n continue;\n }\n if (arg.startsWith('--base-url=')) {\n const value = arg.slice('--base-url='.length);\n if (value === '') return { error: 'takuhon: `--base-url` requires a value.' };\n baseUrl = value;\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`dev\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `dev` takes at most one path argument.' };\n }\n path = arg;\n }\n\n let port = DEFAULT_PORT;\n if (portRaw !== undefined) {\n const parsedPort = parsePort(portRaw);\n if (parsedPort === undefined) {\n return {\n error: `takuhon: \\`--port\\` must be an integer between 1 and 65535 (got \\`${portRaw}\\`).`,\n };\n }\n port = parsedPort;\n }\n\n if (baseUrl !== undefined && !isHttpUrl(baseUrl)) {\n return { error: 'takuhon: `--base-url` must be an absolute http(s) URL.' };\n }\n\n return {\n path: path ?? DEFAULT_PATH,\n port,\n // Drop any trailing slash so URL joins are predictable.\n baseUrl: baseUrl?.replace(/\\/+$/, ''),\n };\n}\n\nfunction parsePort(value: string): number | undefined {\n if (!/^\\d+$/.test(value)) return undefined;\n const n = Number(value);\n return Number.isInteger(n) && n >= 1 && n <= 65535 ? n : undefined;\n}\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/** Extract the path portion of a request URL, dropping any query/fragment. */\nfunction pathnameOf(url: string): string {\n try {\n return new URL(url, 'http://localhost').pathname;\n } catch {\n return url;\n }\n}\n\n/** Minimal HTML document used by the dev-only error and 404 pages. */\nfunction devPage(title: string, body: string): string {\n return (\n `<!DOCTYPE html>\\n<html lang=\"en\">\\n<head>\\n` +\n `<meta charset=\"utf-8\">\\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\\n` +\n `<title>${escapeHtml(title)}</title>\\n` +\n `<style>body{margin:0;font:16px/1.6 system-ui,-apple-system,sans-serif;color:#1a1a1a}` +\n `main{max-width:42rem;margin:2rem auto;padding:0 1.25rem}` +\n `pre{background:#f6f6f6;padding:1rem;border-radius:.4rem;overflow:auto;white-space:pre-wrap}` +\n `code{background:#f2f2f2;padding:.1rem .3rem;border-radius:.2rem}</style>\\n` +\n `</head>\\n<body>\\n<main>\\n${body}\\n</main>\\n</body>\\n</html>\\n`\n );\n}\n\nfunction renderErrorPage(message: string): string {\n return devPage(\n 'takuhon dev — error',\n `<h1>takuhon dev</h1>\\n<p>The profile could not be rendered:</p>\\n` +\n `<pre>${escapeHtml(message)}</pre>\\n<p>Fix the file and reload.</p>`,\n );\n}\n\nfunction renderNotFoundPage(route: string, routes: readonly string[]): string {\n const links = routes\n .map((r) => `<li><a href=\"${escapeHtml(r)}\">${escapeHtml(r)}</a></li>`)\n .join('');\n return devPage(\n 'takuhon dev — 404',\n `<h1>404</h1>\\n<p>No page for <code>${escapeHtml(route)}</code>.</p>\\n` +\n `<p>Available pages:</p>\\n<ul>${links}</ul>`,\n );\n}\n","/**\n * `takuhon export [path] [--output <file>]` — serialise a `takuhon.json` into\n * its transport form for transfer or archival.\n *\n * Mirrors the other command runners: {@link runExport} is a pure function that\n * reads the source itself but returns its output as strings plus an exit code.\n * It validates the source first (an export should be a valid transport\n * artifact), then delegates to core's `exportTakuhon`, which deep-clones and\n * refreshes `meta.updatedAt` (the round-trip exception in\n * operational-lifecycle §5.1). The source file is only read, never modified.\n *\n * Output defaults to stdout so the command composes in a pipeline; `--output`\n * writes a file atomically instead. Asset embedding (`--embed-assets`) is a\n * remote-storage concern and is deferred — it is rejected with a clear message\n * rather than silently ignored.\n *\n * Exit codes:\n * 0 — exported (to stdout or `--output`)\n * 1 — the source was read but is not a valid takuhon profile\n * 2 — the command could not run: bad arguments, a missing/unreadable file,\n * a file that is not valid JSON, or a failed `--output` write\n */\n\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport { exportTakuhon, validate } from '@takuhon/core';\nimport type { Takuhon } from '@takuhon/core';\n\nimport { writeFileAtomic } from './backup.js';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon export [path] [--output <file>]\n\nSerialise a takuhon.json into its transport form and print it to stdout, or\nwrite it to a file with --output. With no path, exports ./takuhon.json in the\ncurrent working directory.\n\nOptions:\n --output <file> Write the export to <file> instead of stdout (atomic).\n\nExit codes: 0 = exported, 1 = source is not a valid profile,\n2 = bad arguments / file missing / unreadable / not JSON / write failed.\n`;\n\nexport interface ExportOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\ninterface ParsedArgs {\n path: string;\n output?: string;\n}\n\n/**\n * Run `takuhon export` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"export\"`).\n */\nexport function runExport(args: readonly string[] = []): ExportOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon export --help\\` for usage.\\n`,\n };\n }\n\n return exportFile(parsed);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let output: string | undefined;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--embed-assets') {\n return {\n error:\n 'takuhon: --embed-assets is not supported yet; assets are remote and asset embedding is deferred.',\n };\n }\n if (arg === '--output') {\n const value = args[i + 1];\n if (value === undefined || value === '' || value.startsWith('-')) {\n return { error: 'takuhon: `--output` requires a value.' };\n }\n output = value;\n i++;\n continue;\n }\n if (arg.startsWith('--output=')) {\n const value = arg.slice('--output='.length);\n if (value === '') {\n return { error: 'takuhon: `--output` requires a value.' };\n }\n output = value;\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`export\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `export` takes at most one path argument.' };\n }\n path = arg;\n }\n\n return { path: path ?? DEFAULT_PATH, output };\n}\n\nfunction exportFile(parsed: ParsedArgs): ExportOutcome {\n const { path, output } = parsed;\n\n // Export produces a separate transport artifact; refuse to write it over the\n // source (which would mutate the source via the refreshed meta.updatedAt).\n if (output !== undefined && resolve(output) === resolve(path)) {\n return {\n code: 2,\n stdout: '',\n stderr:\n `takuhon: --output '${output}' is the source file; export writes a separate artifact.\\n` +\n 'Omit --output to print to stdout, or choose a different file.\\n',\n };\n }\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: cannot read '${path}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${path}' is not valid JSON: ${detail}\\n` };\n }\n\n const result = validate(data);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${path}' is not a valid takuhon profile; refusing to export:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n // Export the validated source faithfully — only meta.updatedAt is refreshed\n // (operational-lifecycle §5.1). We pass the parsed document rather than\n // `result.data` so `validate`'s coercion of absent optional arrays into `[]`\n // does not silently rewrite the export.\n const content = `${JSON.stringify(exportTakuhon(data as Takuhon), null, 2)}\\n`;\n\n if (output === undefined) {\n // No --output: the serialised profile is the command's stdout.\n return { code: 0, stdout: content, stderr: '' };\n }\n\n try {\n writeFileAtomic(output, content);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: failed to write '${output}': ${detail}\\n` };\n }\n\n return { code: 0, stdout: `exported ${path} -> ${output}\\n`, stderr: '' };\n}\n","/**\n * `takuhon import <file> [path]` — load a previously exported profile into a\n * local `takuhon.json` (operational-lifecycle §5.3 / §17.2).\n *\n * Like the other command runners this returns its output as strings plus an\n * exit code. The flow follows §5.3: read the input, migrate it forward to the\n * current schema version if it is older (core's `importTakuhon` deliberately\n * does *not* auto-migrate, so the CLI composes `migrateTakuhon` +\n * `importTakuhon`), validate the result, back up the current profile, then\n * write the imported document. Unlike `restore` (a verbatim reproduction),\n * `import` writes the migrated-and-validated document re-serialised in\n * canonical form.\n *\n * Import overwrites the target, but a backup is taken first, so — matching the\n * spec, which mandates a confirmation prompt only for `restore` — there is no\n * interactive prompt. Asset expansion and edge-cache purge (§5.3 steps 5-6)\n * are remote concerns and do not apply to this local-file command.\n *\n * Exit codes:\n * 0 — imported\n * 1 — the input was read but cannot be imported (missing/unusable\n * schemaVersion, no migration path to the current version, or the\n * result failed validation)\n * 2 — the command could not run: bad arguments, a missing/unreadable input\n * or target, a non-JSON input, or a failed write\n */\n\nimport { readFileSync } from 'node:fs';\n\nimport {\n ImportError,\n MigrationError,\n SCHEMA_VERSION,\n importTakuhon,\n migrateTakuhon,\n} from '@takuhon/core';\nimport type { Takuhon } from '@takuhon/core';\n\nimport { BackupError, createBackup, preImportName, writeFileAtomic } from './backup.js';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon import <file> [path]\n\nLoad a previously exported profile from <file> into a local takuhon.json,\nmigrating it to the current schema version if needed. With no path, writes\n./takuhon.json in the current working directory.\n\nThe current profile (if any) is backed up to\n.takuhon-backups/pre-import-<timestamp>.json before being overwritten.\n\nExit codes: 0 = imported, 1 = input cannot be imported (invalid / unsupported\nversion), 2 = bad arguments / file missing / unreadable / not JSON / write failed.\n`;\n\nexport interface ImportOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/** Injectable dependencies, so tests can pin the backup timestamp. */\nexport interface ImportDeps {\n /** Clock used for the pre-import backup filename. Defaults to `() => new Date()`. */\n now?: () => Date;\n}\n\ninterface ParsedArgs {\n file: string;\n path: string;\n}\n\n/**\n * Run `takuhon import` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"import\"`).\n */\nexport function runImport(args: readonly string[] = [], deps: ImportDeps = {}): ImportOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon import --help\\` for usage.\\n`,\n };\n }\n\n const now = deps.now ?? (() => new Date());\n return importFile(parsed, now);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n const positionals: string[] = [];\n\n for (const arg of args) {\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`import\\`.` };\n }\n positionals.push(arg);\n }\n\n if (positionals.length === 0) {\n return { error: 'takuhon: `import` requires an input <file>.' };\n }\n if (positionals.length > 2) {\n return { error: 'takuhon: `import` takes at most an input <file> and a target path.' };\n }\n\n return { file: positionals[0]!, path: positionals[1] ?? DEFAULT_PATH };\n}\n\nfunction importFile(parsed: ParsedArgs, now: () => Date): ImportOutcome {\n const { file, path } = parsed;\n\n let raw: string;\n try {\n raw = readFileSync(file, 'utf8');\n } catch {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read '${file}'.\\n` };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${file}' is not valid JSON: ${detail}\\n` };\n }\n\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${file}' is not a takuhon profile (expected a JSON object).\\n`,\n };\n }\n\n const source = (data as { schemaVersion?: unknown }).schemaVersion;\n if (typeof source !== 'string' || source.length === 0) {\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${file}' has no usable schemaVersion; cannot import.\\n`,\n };\n }\n\n // Bring the input up to the current schema version (§5.3 step 2). core's\n // importTakuhon does not auto-migrate, so we migrate first when needed.\n let candidate: unknown = data;\n if (source !== SCHEMA_VERSION) {\n try {\n candidate = migrateTakuhon(data as Takuhon, SCHEMA_VERSION);\n } catch (error) {\n if (error instanceof MigrationError) {\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: cannot import '${file}': ${error.message}.\\n`,\n };\n }\n throw error;\n }\n }\n\n let imported: Takuhon;\n try {\n imported = importTakuhon(candidate as Takuhon);\n } catch (error) {\n if (error instanceof ImportError) {\n const lines = (error.errors ?? []).map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n const detail = lines.length > 0 ? `:\\n${lines.join('\\n')}` : '.';\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${file}' is not a valid takuhon profile; refusing to import${detail}\\n`,\n };\n }\n throw error;\n }\n\n // Back up the current profile before overwriting it (§5.3 step 3). A missing\n // target is fine — there is nothing to preserve on a fresh import.\n let currentRaw: string | undefined;\n try {\n currentRaw = readFileSync(path, 'utf8');\n } catch (error) {\n if (!isNotFound(error)) {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read current profile '${path}'.\\n` };\n }\n }\n\n let savedPath: string | undefined;\n if (currentRaw !== undefined) {\n // One timestamp for the backup name (createBackup may call the builder\n // twice on a same-second collision).\n const stamp = now();\n try {\n savedPath = createBackup({\n targetPath: path,\n content: currentRaw,\n name: (withMillis) => preImportName(stamp, withMillis),\n });\n } catch (error) {\n const detail = error instanceof BackupError ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: refusing to import into '${path}' — pre-import backup failed: ${detail}\\n`,\n };\n }\n }\n\n try {\n writeFileAtomic(path, `${JSON.stringify(imported, null, 2)}\\n`);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: failed to write '${path}': ${detail}\\n` };\n }\n\n const lines = [`imported ${file} -> ${path} (schemaVersion ${imported.schemaVersion})`];\n if (savedPath !== undefined) {\n lines.push(` previous profile saved to ${savedPath}`);\n }\n return { code: 0, stdout: `${lines.join('\\n')}\\n`, stderr: '' };\n}\n\nfunction isNotFound(error: unknown): boolean {\n return (\n typeof error === 'object' && error !== null && (error as { code?: unknown }).code === 'ENOENT'\n );\n}\n","/**\n * `takuhon migrate [path] [--to <version>] [--out <file>] [--dry-run]` —\n * forward-migrate a `takuhon.json` to a newer schema version.\n *\n * Mirrors `validate-command.ts`: {@link runMigrate} is a pure,\n * side-effect-light function that reads/writes files itself but returns its\n * output as strings plus an exit code, leaving stdout/stderr writes and\n * `process.exit` to the entry layer. The source version is read from the\n * file's own `schemaVersion` (the file is the source of truth), so the\n * command takes only `--to`; the default target is the latest schema this\n * build of `@takuhon/core` ships ({@link SCHEMA_VERSION}).\n *\n * The transform is intentionally minimal — `migrateTakuhon` then a re-`validate`\n * gate, with no `meta.updatedAt` touch and no `normalize` pass — so a\n * migration stays lossless (operational-lifecycle §2.6) and its diff is\n * limited to the schema-shape change. Before an in-place write the original\n * bytes are backed up beside the file (§3.1 / §3.3). Migrations are\n * forward-only (§2.4); downgrades surface as a clear error pointing at\n * `takuhon restore`.\n *\n * Exit codes:\n * 0 — migrated, already at the target (no-op), `--dry-run`, or `--help`\n * 1 — the document was read but cannot be migrated to the target (no\n * forward path / downgrade / unusable schemaVersion) or the migrated\n * result unexpectedly failed re-validation\n * 2 — the command could not run: bad arguments, an out-of-window `--to`, a\n * missing/unreadable file, or a file that is not valid JSON\n */\n\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport {\n MigrationError,\n SCHEMA_VERSION,\n SUPPORTED_SCHEMA_VERSIONS,\n migrateTakuhon,\n validate,\n} from '@takuhon/core';\nimport type { Takuhon } from '@takuhon/core';\n\nimport {\n BackupError,\n backupDirFor,\n createBackup,\n migrateBackupName,\n writeFileAtomic,\n} from './backup.js';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon migrate [path] [--to <version>] [--out <file>] [--dry-run]\n\nForward-migrate a takuhon.json to a newer schema version. The source version\nis read from the file's own schemaVersion. With no path, migrates\n./takuhon.json in the current working directory.\n\nOptions:\n --to <version> Target schema version (default: ${SCHEMA_VERSION}).\n One of: ${SUPPORTED_SCHEMA_VERSIONS.join(', ')}.\n --out <file> Write the result to <file> instead of in place. The source\n file is left unchanged and no backup is created.\n --dry-run Report the planned migration and backup path; write nothing.\n\nBefore an in-place write the current file is backed up to .takuhon-backups/\nbeside it. Migrations are forward-only; to move to an older schema, restore\nfrom a backup with \\`takuhon restore\\`.\n\nExit codes: 0 = migrated / already current / dry-run, 1 = cannot migrate,\n2 = bad arguments / file missing / unreadable / not JSON.\n`;\n\nexport interface MigrateOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/** Injectable dependencies, so tests can pin the backup timestamp. */\nexport interface MigrateDeps {\n /** Clock used for backup filenames. Defaults to `() => new Date()`. */\n now?: () => Date;\n}\n\ninterface ParsedArgs {\n path: string;\n to: string;\n out?: string;\n dryRun: boolean;\n}\n\n/**\n * Run `takuhon migrate` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"migrate\"`). Never throws\n * and never writes to the process streams.\n */\nexport function runMigrate(args: readonly string[] = [], deps: MigrateDeps = {}): MigrateOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon migrate --help\\` for usage.\\n`,\n };\n }\n\n const now = deps.now ?? (() => new Date());\n return migrateFile(parsed, now);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let to: string | undefined;\n let out: string | undefined;\n let dryRun = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--dry-run') {\n dryRun = true;\n continue;\n }\n if (arg === '--to' || arg === '--out') {\n const value = args[i + 1];\n if (value === undefined || value.startsWith('-')) {\n return { error: `takuhon: \\`${arg}\\` requires a value.` };\n }\n if (arg === '--to') to = value;\n else out = value;\n i++;\n continue;\n }\n if (arg.startsWith('--to=')) {\n to = arg.slice('--to='.length);\n continue;\n }\n if (arg.startsWith('--out=')) {\n out = arg.slice('--out='.length);\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`migrate\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `migrate` takes at most one path argument.' };\n }\n path = arg;\n }\n\n const target = to ?? SCHEMA_VERSION;\n if (!(SUPPORTED_SCHEMA_VERSIONS as readonly string[]).includes(target)) {\n return {\n error: `takuhon: unsupported --to version \"${target}\". Supported: ${SUPPORTED_SCHEMA_VERSIONS.join(', ')}.`,\n };\n }\n\n return { path: path ?? DEFAULT_PATH, to: target, out, dryRun };\n}\n\nfunction migrateFile(parsed: ParsedArgs, now: () => Date): MigrateOutcome {\n const { path, to: target, out, dryRun } = parsed;\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: cannot read '${path}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${path}' is not valid JSON: ${detail}\\n` };\n }\n\n const source = (data as { schemaVersion?: unknown }).schemaVersion;\n if (typeof source !== 'string' || source.length === 0) {\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${path}' has no usable schemaVersion; cannot determine what to migrate from.\\n`,\n };\n }\n\n if (source === target) {\n return {\n code: 0,\n stdout: `${path}: already at schemaVersion ${target}; nothing to do.\\n`,\n stderr: '',\n };\n }\n\n // Back up the original bytes only for a genuine in-place write. `--out` to a\n // different name leaves the source untouched, so a backup would be redundant.\n // The write is atomic (write-temp-then-rename), which replaces the target\n // *name* rather than following it, so even an `--out` symlink that points at\n // the source cannot clobber the source unbacked — it just replaces the link.\n const writeTarget = out ?? path;\n const inPlace = resolve(writeTarget) === resolve(path);\n\n let migrated: Takuhon;\n try {\n migrated = migrateTakuhon(data as Takuhon, target);\n } catch (error) {\n if (error instanceof MigrationError) {\n return {\n code: 1,\n stdout: '',\n stderr:\n `takuhon: cannot migrate '${path}': ${error.message}.\\n` +\n 'Migrations are forward-only; to move to an older schema, restore from a backup with `takuhon restore`.\\n',\n };\n }\n throw error;\n }\n\n // Re-validate as a structural safety gate. The bundled validator accepts the\n // entire supported window, so a non-latest `--to` still passes here;\n // `migrateTakuhon` is what guarantees the result carries the requested target\n // shape (it stops the chain at `target`). This catches only a migration that\n // produced something the schema rejects outright.\n const revalidated = validate(migrated);\n if (!revalidated.ok) {\n const lines = revalidated.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: migrated '${path}' to ${target} but the result failed validation:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n // One timestamp per run, shared by the dry-run preview and the real backup so\n // the reported and actual backup paths cannot drift.\n const stamp = now();\n\n // `--dry-run` previews only after the migration is proven feasible above, so\n // an impossible migration (e.g. a downgrade) still reports exit 1 rather than\n // a misleading \"would migrate\".\n if (dryRun) {\n const lines = [`${path}: would migrate ${source} -> ${target}`, ` write: ${writeTarget}`];\n if (inPlace) {\n lines.push(` backup: ${backupDirFor(path)}/${migrateBackupName(source, stamp)}`);\n } else {\n lines.push(' (source left unchanged; no backup created)');\n }\n return { code: 0, stdout: `${lines.join('\\n')}\\n`, stderr: '' };\n }\n\n let backupPath: string | undefined;\n if (inPlace) {\n try {\n backupPath = createBackup({\n targetPath: path,\n content: raw,\n name: (withMillis) => migrateBackupName(source, stamp, withMillis),\n });\n } catch (error) {\n const detail = error instanceof BackupError ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: refusing to migrate '${path}' — backup failed: ${detail}\\n`,\n };\n }\n }\n\n try {\n writeFileAtomic(writeTarget, `${JSON.stringify(migrated, null, 2)}\\n`);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: failed to write '${writeTarget}': ${detail}\\n`,\n };\n }\n\n const lines = [`migrated ${path}: ${source} -> ${target}`];\n if (inPlace) {\n lines.push(` backup: ${backupPath}`);\n } else {\n lines.push(` wrote: ${writeTarget} (source left unchanged; no backup created)`);\n }\n return { code: 0, stdout: `${lines.join('\\n')}\\n`, stderr: '' };\n}\n","/**\n * `takuhon restore --from <backup> [path] [--yes]` — overwrite a profile with\n * a previously saved backup (operational-lifecycle §4.1 / §4.3).\n *\n * Like the other command runners this returns its output as strings plus an\n * exit code rather than touching the process streams. It is `async` because\n * the confirmation prompt is interactive: the entry layer injects a `confirm`\n * callback that reads from the terminal, while tests inject a deterministic\n * predicate (or pass `--yes` to skip the prompt entirely).\n *\n * Restore is destructive, so the flow is deliberately careful:\n * 1. read and schema-`validate` the backup — never restore an invalid file;\n * 2. confirm (unless `--yes`); a non-interactive run with neither `--yes`\n * nor an injected `confirm` refuses rather than overwriting silently;\n * 3. back up the current profile to `.takuhon-backups/pre-restore-…json`;\n * 4. write the backup's bytes to the target verbatim (a faithful\n * reproduction; `validate` is only the gate, not a rewrite).\n *\n * Edge-cache purge (§4.1 step 4) is a remote-adapter concern and does not\n * apply to this local-file command.\n *\n * Exit codes:\n * 0 — restored, aborted at the prompt, or `--help`\n * 1 — the backup was read but failed schema validation\n * 2 — the command could not run: bad arguments, a missing `--from`, an\n * unreadable backup or current profile, a non-JSON backup, or a refusal\n * to overwrite without confirmation\n */\n\nimport { readFileSync } from 'node:fs';\n\nimport { validate } from '@takuhon/core';\nimport type { Takuhon } from '@takuhon/core';\n\nimport {\n BackupError,\n backupDirFor,\n createBackup,\n preRestoreName,\n writeFileAtomic,\n} from './backup.js';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon restore --from <backup> [path] [--yes]\n\nOverwrite a profile with a previously saved backup. With no path, restores\n./takuhon.json in the current working directory.\n\nOptions:\n --from <backup> Backup file to restore from (required).\n --yes, -y Skip the confirmation prompt.\n\nThe backup is schema-validated first, and the current profile is saved to\n.takuhon-backups/pre-restore-<timestamp>.json before being overwritten.\n\nExit codes: 0 = restored / aborted, 1 = backup failed validation,\n2 = bad arguments / file missing / unreadable / not JSON / unconfirmed.\n`;\n\nexport interface RestoreOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/** Injectable dependencies for deterministic tests and interactive prompting. */\nexport interface RestoreDeps {\n /** Clock used for the pre-restore backup filename. Defaults to `() => new Date()`. */\n now?: () => Date;\n /**\n * Confirmation prompt. Receives the rendered message and resolves to the\n * user's decision. Omitted in non-interactive contexts, where restore then\n * refuses unless `--yes` was passed.\n */\n confirm?: (message: string) => boolean | Promise<boolean>;\n}\n\ninterface ParsedArgs {\n from: string;\n path: string;\n yes: boolean;\n}\n\n/**\n * Run `takuhon restore` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"restore\"`).\n */\nexport async function runRestore(\n args: readonly string[] = [],\n deps: RestoreDeps = {},\n): Promise<RestoreOutcome> {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon restore --help\\` for usage.\\n`,\n };\n }\n\n const now = deps.now ?? (() => new Date());\n return restoreFile(parsed, now, deps.confirm);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let from: string | undefined;\n let path: string | undefined;\n let yes = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--yes' || arg === '-y') {\n yes = true;\n continue;\n }\n if (arg === '--from') {\n const value = args[i + 1];\n if (value === undefined || value.startsWith('-')) {\n return { error: 'takuhon: `--from` requires a value.' };\n }\n from = value;\n i++;\n continue;\n }\n if (arg.startsWith('--from=')) {\n from = arg.slice('--from='.length);\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`restore\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `restore` takes at most one path argument.' };\n }\n path = arg;\n }\n\n if (from === undefined || from.length === 0) {\n return { error: 'takuhon: `restore` requires `--from <backup>`.' };\n }\n\n return { from, path: path ?? DEFAULT_PATH, yes };\n}\n\nasync function restoreFile(\n parsed: ParsedArgs,\n now: () => Date,\n confirm: RestoreDeps['confirm'],\n): Promise<RestoreOutcome> {\n const { from, path, yes } = parsed;\n\n let backupRaw: string;\n try {\n backupRaw = readFileSync(from, 'utf8');\n } catch {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read backup '${from}'.\\n` };\n }\n\n let backupData: unknown;\n try {\n backupData = JSON.parse(backupRaw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: backup '${from}' is not valid JSON: ${detail}\\n`,\n };\n }\n\n const result = validate(backupData);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: backup '${from}' is not a valid takuhon profile; refusing to restore:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n // Read the current profile up front: its existence shapes the confirmation\n // message and decides whether a pre-restore backup is needed.\n let currentRaw: string | undefined;\n try {\n currentRaw = readFileSync(path, 'utf8');\n } catch (error) {\n if (!isNotFound(error)) {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read current profile '${path}'.\\n` };\n }\n }\n\n // One timestamp per run, shared by the prompt preview and the actual\n // pre-restore backup so the reported and written paths cannot drift.\n const stamp = now();\n const preRestorePath = `${backupDirFor(path)}/${preRestoreName(stamp)}`;\n\n if (!yes) {\n if (!confirm) {\n return {\n code: 2,\n stdout: '',\n stderr:\n `takuhon: refusing to overwrite '${path}' without confirmation.\\n` +\n 'Re-run interactively, or pass `--yes` to skip the prompt.\\n',\n };\n }\n const decided = await confirm(\n confirmationMessage(path, from, result.data, currentRaw, preRestorePath),\n );\n if (!decided) {\n return { code: 0, stdout: 'Aborted; no changes made.\\n', stderr: '' };\n }\n }\n\n let savedPath: string | undefined;\n if (currentRaw !== undefined) {\n try {\n savedPath = createBackup({\n targetPath: path,\n content: currentRaw,\n name: (withMillis) => preRestoreName(stamp, withMillis),\n });\n } catch (error) {\n const detail = error instanceof BackupError ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: refusing to restore '${path}' — pre-restore backup failed: ${detail}\\n`,\n };\n }\n }\n\n // Write the backup's bytes verbatim: restore is a faithful reproduction of\n // the saved state, and `validate` above was only the gate.\n try {\n writeFileAtomic(path, backupRaw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: failed to write '${path}': ${detail}\\n` };\n }\n\n const lines = [`restored ${path} from ${from}`];\n if (savedPath !== undefined) {\n lines.push(` previous profile saved to ${savedPath}`);\n }\n return { code: 0, stdout: `${lines.join('\\n')}\\n`, stderr: '' };\n}\n\nfunction confirmationMessage(\n path: string,\n from: string,\n data: Takuhon,\n currentRaw: string | undefined,\n preRestorePath: string,\n): string {\n const when = typeof data.meta.updatedAt === 'string' ? ` (from ${data.meta.updatedAt})` : '';\n const preNote =\n currentRaw !== undefined\n ? `Your current profile will be saved as ${preRestorePath}.`\n : `(no existing profile at ${path} to preserve)`;\n return (\n `This will overwrite the profile at ${path} with the backup ${from}${when}.\\n` +\n `${preNote}\\n` +\n 'Continue? [y/N]'\n );\n}\n\nfunction isNotFound(error: unknown): boolean {\n return (\n typeof error === 'object' && error !== null && (error as { code?: unknown }).code === 'ENOENT'\n );\n}\n","/**\n * `takuhon sync [path] --url <base-url> [--if-match <etag>] [--dry-run]` —\n * push a local `takuhon.json` to a deployed takuhon instance.\n *\n * `sync` is the secondary update path in Spec §9.6: it mirrors the local\n * profile into the deployment's store by calling the same admin write\n * endpoint the Admin UI uses — `PUT <base-url>/api/admin/profile` — so it\n * reuses the server's schema validation, optimistic locking, audit logging,\n * and edge-cache purge. The local file is the source of truth: by default the\n * push is unconditional (a mirror). Pass `--if-match <etag>` to opt into\n * optimistic locking (the server rejects the write with 409 if the stored\n * version no longer matches).\n *\n * The admin bearer token is read from the `TAKUHON_ADMIN_TOKEN` environment\n * variable, never a flag, so it cannot leak into shell history; the name\n * matches the Worker secret. The document is sent as-is after a local schema\n * check — `sync` does not migrate (run `takuhon migrate` first if the file is\n * an older schema version).\n *\n * Exit codes:\n * 0 — synced (or, with --dry-run, the payload is valid and ready to send)\n * 1 — the local file failed validation, or the remote refused the write for\n * content reasons (422 validation, 409 If-Match conflict)\n * 2 — the command could not run: bad arguments, a missing/unreadable/non-JSON\n * file, an unset token, an auth failure (401/403), a network error, or\n * any other non-success response\n */\n\nimport { readFileSync } from 'node:fs';\n\nimport { validate } from '@takuhon/core';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\n/** Admin write endpoint, appended to the supplied `--url` origin. */\nconst ADMIN_PROFILE_PATH = '/api/admin/profile';\n\n/** Environment variable carrying the deployment's admin bearer token. */\nconst TOKEN_ENV = 'TAKUHON_ADMIN_TOKEN';\n\nconst USAGE = `Usage: takuhon sync [path] --url <base-url> [--if-match <etag>] [--dry-run]\n\nPush a local takuhon.json to a deployed takuhon instance by calling its admin\nwrite endpoint (PUT <base-url>/api/admin/profile). With no path, syncs\n./takuhon.json in the current working directory.\n\nThe local file is the source of truth: by default the push is unconditional\n(a mirror). Pass --if-match <etag> to opt into optimistic locking (the server\nreturns 409 if the stored version no longer matches). The document is sent\nas-is after a local schema check; run \\`takuhon migrate\\` first if it is an\nolder schema version.\n\nThe admin bearer token is read from the ${TOKEN_ENV} environment variable, e.g.:\n ${TOKEN_ENV}=... takuhon sync --url https://me.example\n\nOptions:\n --url <base-url> Required. Absolute http(s) origin of the deployment.\n --if-match <etag> Send If-Match for optimistic locking (opt-in).\n --dry-run Validate locally and report what would be sent; no request.\n\nExit codes: 0 = synced (or dry-run ok), 1 = local invalid / remote refused\n(422 / 409), 2 = bad arguments / file missing / unreadable / not JSON / token\nunset / auth failure / network error / other non-success response.\n`;\n\nexport interface SyncOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/** Injectable dependencies, so tests can stub the network and the token source. */\nexport interface SyncDeps {\n /** HTTP client. Defaults to the global `fetch` (Node 22+). */\n fetch?: typeof fetch;\n /** Admin token source. Defaults to reading `TAKUHON_ADMIN_TOKEN`. */\n getToken?: () => string | undefined;\n}\n\ninterface ParsedArgs {\n path: string;\n url: string;\n ifMatch?: string;\n dryRun: boolean;\n}\n\n/**\n * Run `takuhon sync` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"sync\"`).\n */\nexport async function runSync(\n args: readonly string[] = [],\n deps: SyncDeps = {},\n): Promise<SyncOutcome> {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n const parsed = parseArgs(args);\n if ('error' in parsed) {\n return {\n code: 2,\n stdout: '',\n stderr: `${parsed.error}\\nRun \\`takuhon sync --help\\` for usage.\\n`,\n };\n }\n\n return syncProfile(parsed, deps);\n}\n\nfunction parseArgs(args: readonly string[]): ParsedArgs | { error: string } {\n let path: string | undefined;\n let url: string | undefined;\n let ifMatch: string | undefined;\n let dryRun = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === '--dry-run') {\n dryRun = true;\n continue;\n }\n if (arg === '--url' || arg === '--if-match') {\n const value = args[i + 1];\n if (value === undefined || value === '' || value.startsWith('-')) {\n return { error: `takuhon: \\`${arg}\\` requires a value.` };\n }\n if (arg === '--url') url = value;\n else ifMatch = value;\n i++;\n continue;\n }\n if (arg.startsWith('--url=')) {\n const value = arg.slice('--url='.length);\n if (value === '') return { error: 'takuhon: `--url` requires a value.' };\n url = value;\n continue;\n }\n if (arg.startsWith('--if-match=')) {\n const value = arg.slice('--if-match='.length);\n if (value === '') return { error: 'takuhon: `--if-match` requires a value.' };\n ifMatch = value;\n continue;\n }\n if (arg.startsWith('-')) {\n return { error: `takuhon: unknown option \\`${arg}\\` for \\`sync\\`.` };\n }\n if (path !== undefined) {\n return { error: 'takuhon: `sync` takes at most one path argument.' };\n }\n path = arg;\n }\n\n if (url === undefined) {\n return { error: 'takuhon: `sync` requires `--url <base-url>`.' };\n }\n const base = parseOrigin(url);\n if ('error' in base) return base;\n\n return { path: path ?? DEFAULT_PATH, url: base.origin, ifMatch, dryRun };\n}\n\n/**\n * Validate `--url` and reduce it to a bare `http(s)` origin. We reject any URL\n * carrying a path, query, fragment, or credentials: the admin endpoint is\n * appended to the origin, and a non-origin URL would both misplace that suffix\n * and risk sending the bearer token to an unintended target.\n */\nfunction parseOrigin(value: string): { origin: string } | { error: string } {\n let parsed: URL;\n try {\n parsed = new URL(value);\n } catch {\n return { error: 'takuhon: `--url` must be an absolute http(s) URL.' };\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return { error: 'takuhon: `--url` must be an absolute http(s) URL.' };\n }\n if (\n parsed.username !== '' ||\n parsed.password !== '' ||\n parsed.search !== '' ||\n parsed.hash !== '' ||\n (parsed.pathname !== '/' && parsed.pathname !== '')\n ) {\n return {\n error:\n \"takuhon: `--url` must be the deployment's origin (e.g. https://me.example), \" +\n 'with no path, query, or credentials.',\n };\n }\n return { origin: parsed.origin };\n}\n\n/** Remove any literal occurrence of a secret from a string before it is shown. */\nfunction redact(text: string, secret: string): string {\n return secret === '' ? text : text.split(secret).join('***');\n}\n\n/** Strip RFC 7232 double-quote delimiters so the value can be re-wrapped cleanly. */\nfunction unquoteETag(raw: string): string {\n const trimmed = raw.trim();\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"') && trimmed.length >= 2) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nasync function syncProfile(parsed: ParsedArgs, deps: SyncDeps): Promise<SyncOutcome> {\n const { path, url, ifMatch, dryRun } = parsed;\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf8');\n } catch {\n return { code: 2, stdout: '', stderr: `takuhon: cannot read '${path}'.\\n` };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return { code: 2, stdout: '', stderr: `takuhon: '${path}' is not valid JSON: ${detail}\\n` };\n }\n\n const result = validate(data);\n if (!result.ok) {\n const lines = result.errors.map((e) => ` ${e.pointer || '/'}: ${e.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: '${path}' is not a valid takuhon profile; refusing to sync:\\n${lines.join('\\n')}\\n`,\n };\n }\n\n const endpoint = `${url}${ADMIN_PROFILE_PATH}`;\n const body = `${JSON.stringify(result.data)}\\n`;\n const bytes = Buffer.byteLength(body, 'utf8');\n\n if (dryRun) {\n const lock = ifMatch !== undefined ? `, If-Match \"${unquoteETag(ifMatch)}\"` : '';\n return {\n code: 0,\n stdout: `would sync ${path} -> ${endpoint} (${String(bytes)} bytes${lock})\\n--dry-run: nothing sent.\\n`,\n stderr: '',\n };\n }\n\n const getToken = deps.getToken ?? (() => process.env[TOKEN_ENV]);\n const token = getToken();\n if (token === undefined || token === '') {\n return {\n code: 2,\n stdout: '',\n stderr:\n `takuhon: ${TOKEN_ENV} is not set; sync needs the deployment's admin token.\\n` +\n `Set it for this command only, e.g.:\\n` +\n ` ${TOKEN_ENV}=... takuhon sync --url ${url}\\n`,\n };\n }\n\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n authorization: `Bearer ${token}`,\n };\n if (ifMatch !== undefined) {\n headers['if-match'] = `\"${unquoteETag(ifMatch)}\"`;\n }\n\n const fetchImpl = deps.fetch ?? fetch;\n let res: Response;\n try {\n res = await fetchImpl(endpoint, { method: 'PUT', headers, body });\n } catch (error) {\n const detail = redact(error instanceof Error ? error.message : String(error), token);\n return { code: 2, stdout: '', stderr: `takuhon: could not reach ${endpoint}: ${detail}\\n` };\n }\n\n return interpretResponse(res, { path, url, endpoint });\n}\n\ninterface Target {\n path: string;\n url: string;\n endpoint: string;\n}\n\nasync function interpretResponse(res: Response, target: Target): Promise<SyncOutcome> {\n const { path, url, endpoint } = target;\n\n if (res.ok) {\n const version = await readVersion(res);\n if (version === undefined) {\n // A 2xx without the admin API's `{ meta: { version } }` envelope means we\n // did not actually reach a takuhon admin endpoint (a proxy login page, a\n // static host, a wrong path). Do not claim success.\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: unexpected response from ${endpoint} (HTTP ${String(res.status)} but no meta.version); is --url a takuhon deployment?\\n`,\n };\n }\n return { code: 0, stdout: `synced ${path} -> ${url} (version ${version})\\n`, stderr: '' };\n }\n\n const problem = await readProblem(res);\n const status = res.status;\n\n if (status === 409) {\n const current = problem?.currentVersion;\n const hint =\n current !== undefined\n ? `remote is at version ${current}. Re-sync against it, or drop --if-match to overwrite.`\n : 'the stored version no longer matches --if-match. Re-sync, or drop --if-match to overwrite.';\n return { code: 1, stdout: '', stderr: `takuhon: sync conflict (409): ${hint}\\n` };\n }\n\n if (status === 422) {\n const errors = Array.isArray(problem?.errors) ? problem.errors : [];\n const lines = errors.map((e) => ` ${e.path}: ${e.message}`);\n const detail = lines.length > 0 ? `:\\n${lines.join('\\n')}` : '.';\n return {\n code: 1,\n stdout: '',\n stderr: `takuhon: the deployment rejected the profile (422)${detail}\\n`,\n };\n }\n\n if (status === 401 || status === 403) {\n const reason =\n status === 401\n ? `unauthorized (401); check ${TOKEN_ENV}`\n : 'forbidden (403); the request origin may not be allowed';\n return { code: 2, stdout: '', stderr: `takuhon: ${reason}.\\n` };\n }\n\n const detail = problem?.detail ?? res.statusText ?? '';\n const tail = detail ? `: ${detail}` : '.';\n return { code: 2, stdout: '', stderr: `takuhon: sync failed (${String(status)})${tail}\\n` };\n}\n\ninterface ProblemBody {\n detail?: string;\n currentVersion?: string;\n errors?: { path: string; message: string }[];\n}\n\n/** Best-effort parse of the success body's `meta.version`. */\nasync function readVersion(res: Response): Promise<string | undefined> {\n try {\n const parsed = (await res.json()) as { meta?: { version?: unknown } };\n const version = parsed.meta?.version;\n return typeof version === 'string' ? version : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Best-effort parse of an RFC 7807 problem body; undefined if it is not JSON. */\nasync function readProblem(res: Response): Promise<ProblemBody | undefined> {\n let text: string;\n try {\n text = await res.text();\n } catch {\n return undefined;\n }\n try {\n return JSON.parse(text) as ProblemBody;\n } catch {\n return undefined;\n }\n}\n","/**\n * `takuhon validate [path]` — validate a `takuhon.json` against `@takuhon/core`.\n *\n * All argument handling and the validation itself live here as pure,\n * side-effect-free functions so the whole command is unit-testable: `index.ts`\n * runs `process.exit(main(...))` at module top level and is therefore not\n * import-safe. `runValidate` reads the target file itself but returns its\n * output as strings plus an exit code, leaving the actual stdout/stderr writes\n * and `process.exit` to the caller.\n *\n * Exit codes:\n * 0 — the document is valid (or `--help` was requested)\n * 1 — the document was read and parsed but failed schema validation\n * 2 — the command could not run: bad arguments, a missing/unreadable file,\n * or a file that is not valid JSON (operational errors, distinct from an\n * invalid-but-readable document)\n */\n\nimport { readFileSync } from 'node:fs';\n\nimport { validate } from '@takuhon/core';\n\n/** Default profile filename, resolved relative to the current working directory. */\nconst DEFAULT_PATH = 'takuhon.json';\n\nconst USAGE = `Usage: takuhon validate [path]\n\nValidate a takuhon.json against the takuhon schema. With no path, validates\n./takuhon.json in the current working directory.\n\nExit codes: 0 = valid, 1 = invalid, 2 = file missing / unreadable / not JSON.\n`;\n\nexport interface ValidateOutcome {\n /** Process exit code (see module docstring). */\n readonly code: number;\n /** Text destined for stdout (empty when there is nothing to print). */\n readonly stdout: string;\n /** Text destined for stderr (empty when there is nothing to print). */\n readonly stderr: string;\n}\n\n/**\n * Run `takuhon validate` against the arguments that follow the subcommand\n * (i.e. `process.argv.slice(2)` minus the leading `\"validate\"`).\n *\n * Handles `--help` / `-h` and rejects extra positionals, then validates the\n * `takuhon.json` at the single optional path argument (default\n * `./takuhon.json`). Never throws and never writes to the process streams —\n * the caller renders the returned `stdout` / `stderr` and exits with `code`.\n */\nexport function runValidate(args: readonly string[] = []): ValidateOutcome {\n if (args[0] === '--help' || args[0] === '-h') {\n return { code: 0, stdout: USAGE, stderr: '' };\n }\n\n if (args.length > 1) {\n return {\n code: 2,\n stdout: '',\n stderr:\n 'takuhon: `validate` takes at most one path argument.\\n' +\n 'Run `takuhon validate --help` for usage.\\n',\n };\n }\n\n return validateFile(args[0]);\n}\n\n/** Read, parse, and schema-validate the profile at `pathArg` (default `./takuhon.json`). */\nfunction validateFile(pathArg?: string): ValidateOutcome {\n const target = pathArg ?? DEFAULT_PATH;\n\n let raw: string;\n try {\n raw = readFileSync(target, 'utf8');\n } catch {\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: cannot read '${target}'. Pass a path, or run from a directory containing a takuhon.json.\\n`,\n };\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return {\n code: 2,\n stdout: '',\n stderr: `takuhon: '${target}' is not valid JSON: ${detail}\\n`,\n };\n }\n\n const result = validate(data);\n if (result.ok) {\n return {\n code: 0,\n stdout: `${target}: valid (schemaVersion ${result.data.schemaVersion}).\\n`,\n stderr: '',\n };\n }\n\n const count = result.errors.length;\n const lines = result.errors.map((error) => ` ${error.pointer || '/'}: ${error.message}`);\n return {\n code: 1,\n stdout: '',\n stderr: `${target}: invalid (${count} error${count === 1 ? '' : 's'}):\\n${lines.join('\\n')}\\n`,\n };\n}\n"],"mappings":"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","names":["readFileSync","mkdirSync","dirname","join","join","mkdirSync","dirname","readFileSync","applyPublicPrivacyFilter","normalize","validate","DEFAULT_PATH","USAGE","readFileSync","validate","applyPublicPrivacyFilter","normalize","parseArgs","resolve","isHttpUrl","readFileSync","validate","DEFAULT_PATH","USAGE","parseArgs","readFileSync","validate","readFileSync","DEFAULT_PATH","USAGE","parseArgs","readFileSync","lines","readFileSync","resolve","MigrationError","SCHEMA_VERSION","migrateTakuhon","validate","DEFAULT_PATH","USAGE","SCHEMA_VERSION","parseArgs","readFileSync","resolve","migrateTakuhon","MigrationError","validate","lines","readFileSync","validate","DEFAULT_PATH","USAGE","parseArgs","readFileSync","validate","lines","isNotFound","readFileSync","validate","DEFAULT_PATH","USAGE","parseArgs","detail","readFileSync","validate","DEFAULT_PATH","USAGE","readFileSync"]}
|