@kurotako/cli 0.1.0 → 0.1.2
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/CHANGELOG.md +41 -0
- package/dist/bin/tako.js +2 -2
- package/dist/bin/tako.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @kurotako/cli
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c1437da: Same root cause as the `parser-openapi`/`gen-typescript` fix (`fix-stale-ir-dependency-range`, `fix-lockfile-workspace-resolution`): every package published before the `bun.lock` / release-workflow fix still carries a stale internal dependency range from the drifted lockfile.
|
|
8
|
+
|
|
9
|
+
- `@kurotako/core@0.1.2` and `@kurotako/config@0.1.2` declare `"@kurotako/ir": "^0.2.0"`. `@kurotako/core` is what actually runs IR validation during `tako generate` — with this stale range, its own nested `@kurotako/ir@0.2.0` copy gets resolved instead of `^0.3.0`, so `array`/`map` field types still fail validation even with `parser-openapi@0.2.2`/`gen-typescript@0.3.2` installed.
|
|
10
|
+
- `@kurotako/parser-prisma@0.2.1`, `@kurotako/gen-zod@0.3.0` and `@kurotako/gen-angular@0.2.0` declare the same stale `"@kurotako/ir": "^0.2.0"`.
|
|
11
|
+
- `@kurotako/cli@0.1.1` declares `"@kurotako/core": "^0.1.1"` / `"@kurotako/config": "^0.1.1"`, both below the packages' actual current versions.
|
|
12
|
+
|
|
13
|
+
No source change needed anywhere (`workspace:^` already resolves correctly with the fixed release workflow); this changeset only forces the patch releases needed to publish corrected tarballs.
|
|
14
|
+
- Updated dependencies [c1437da]
|
|
15
|
+
- @kurotako/core@0.1.3
|
|
16
|
+
- @kurotako/config@0.1.3
|
|
17
|
+
|
|
18
|
+
## 0.1.1
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 22e6559: Make the ambiguous root-barrel export warning understandable.
|
|
23
|
+
|
|
24
|
+
- `@kurotako/core`: when several generators export identically-named
|
|
25
|
+
declarations under one namespace, `synthesizeRootBarrels` now emits a single
|
|
26
|
+
plain-language warning per namespace instead of one terse line per identifier.
|
|
27
|
+
It says what caused the clash, that it is not an error, which import path
|
|
28
|
+
yields which declaration, and how to silence it, plus a bounded deterministic
|
|
29
|
+
sample of the affected names. The full per-identifier detail
|
|
30
|
+
(`collisionCount`, `identifiers`, `sample`, `resolutions`) stays on the
|
|
31
|
+
warning's structured meta object. The warning fires once from the aggregate
|
|
32
|
+
tree rather than once per configured output, and the generated barrel content
|
|
33
|
+
is unchanged.
|
|
34
|
+
- `@kurotako/core`: `OutputNotGeneratedError` now explains the `"//"` marker and
|
|
35
|
+
the two ways to unblock the path (delete the directory, or add the marker).
|
|
36
|
+
- `@kurotako/cli`: `ConsoleReporter` prints the human-readable message at
|
|
37
|
+
`info` / `warn` / `error` level and appends the structured `meta` object only
|
|
38
|
+
with `--debug`. A custom `Logger` still receives `meta` in full, so default
|
|
39
|
+
output stays prose instead of `key=value` noise.
|
|
40
|
+
- Updated dependencies [22e6559]
|
|
41
|
+
- @kurotako/core@0.1.2
|
|
42
|
+
- @kurotako/config@0.1.2
|
|
43
|
+
|
|
3
44
|
## 0.1.0
|
|
4
45
|
|
|
5
46
|
### Minor Changes
|
package/dist/bin/tako.js
CHANGED
|
@@ -171,7 +171,7 @@ var ConsoleReporter = class {
|
|
|
171
171
|
}
|
|
172
172
|
write(level, msg, meta) {
|
|
173
173
|
const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : "tako";
|
|
174
|
-
const detail = meta === void 0 ? "" : ` ${formatMeta(meta)}`;
|
|
174
|
+
const detail = meta === void 0 || !this.showDebug ? "" : ` ${formatMeta(meta)}`;
|
|
175
175
|
this.stream.write(`${prefix} ${msg}${detail}
|
|
176
176
|
`);
|
|
177
177
|
}
|
|
@@ -614,7 +614,7 @@ var validateCommand = defineCommand4({
|
|
|
614
614
|
});
|
|
615
615
|
|
|
616
616
|
// src/cli.ts
|
|
617
|
-
var VERSION = true ? "0.1.
|
|
617
|
+
var VERSION = true ? "0.1.2" : "0.0.0-dev";
|
|
618
618
|
var subCommands = {
|
|
619
619
|
init: initCommand,
|
|
620
620
|
generate: generateCommand,
|
package/dist/bin/tako.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli.ts","../../src/commands/check.ts","../../src/args.ts","../../src/diff.ts","../../src/reporter.ts","../../src/commands/generate.ts","../../src/watch.ts","../../src/errors.ts","../../src/commands/init.ts","../../src/commands/validate.ts","../../src/bin/tako.ts"],"sourcesContent":["/**\n * `runCli()` — build the citty command tree, dispatch, map every `TakoError` to\n * a formatted message + exit 1. `--version` / `--help` are handled here (citty's\n * own handling lives in `runMain`, which hard-exits — not what a testable\n * `runCli` wants).\n *\n * `backlog/features/cli/technical.md` §Command surface, §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\nimport { type CommandDef, defineCommand, renderUsage, runCommand } from 'citty';\nimport { checkCommand } from './commands/check.js';\nimport { generateCommand } from './commands/generate.js';\nimport { initCommand } from './commands/init.js';\nimport { validateCommand } from './commands/validate.js';\nimport { renderError } from './errors.js';\nimport { ConsoleReporter } from './reporter.js';\n\ndeclare const __TAKO_VERSION__: string;\nconst VERSION =\n typeof __TAKO_VERSION__ === 'string' ? __TAKO_VERSION__ : '0.0.0-dev';\n\nconst subCommands = {\n init: initCommand,\n generate: generateCommand,\n validate: validateCommand,\n check: checkCommand,\n};\n\nconst main = defineCommand({\n meta: {\n name: 'tako',\n version: VERSION,\n description: 'synchronise TypeScript schemas from data model to forms',\n },\n subCommands,\n});\n\nexport async function runCli(argv: string[]): Promise<void> {\n const reporter = new ConsoleReporter({\n debug: argv.includes('--debug') || Boolean(process.env.TAKO_DEBUG),\n });\n\n if (argv.includes('--version') || argv.includes('-v')) {\n process.stdout.write(`${VERSION}\\n`);\n process.exitCode ??= 0;\n return;\n }\n\n if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {\n const sub = argv.find((a) => !a.startsWith('-'));\n const isSub = sub !== undefined && sub in subCommands;\n const cmd = (\n isSub ? subCommands[sub as keyof typeof subCommands] : main\n ) as CommandDef;\n process.stdout.write(\n `${await renderUsage(cmd, isSub ? (main as CommandDef) : undefined)}\\n`,\n );\n process.exitCode ??= 0;\n return;\n }\n\n try {\n await runCommand(main, { rawArgs: argv });\n process.exitCode ??= 0;\n } catch (error) {\n if (error instanceof TakoError) {\n reporter.error(renderError(error));\n process.exitCode = 1;\n } else if (error instanceof Error && error.name === 'CLIError') {\n // citty usage error (unknown command, missing argument, …).\n reporter.error(error.message);\n process.exitCode = 1;\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n process.exitCode = 1;\n }\n }\n}\n","/**\n * `tako check` — drift guard. Runs the pipeline in plan mode (no disk writes,\n * no `afterEmit`), then compares the planned tree against what is on disk.\n * Exit 0 when they match, exit 1 on any drift or any `TakoError` (the latter\n * via the top-level handler in `cli.ts`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §Command surface.\n */\nimport { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { loadConfig } from '@kurotako/config';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport {\n comparePlanToDisk,\n type DriftEntry,\n ignoreBuildArtifacts,\n markedPackageDirs,\n} from '../diff.js';\nimport { ConsoleReporter } from '../reporter.js';\n\nexport const checkCommand = defineCommand({\n meta: {\n name: 'check',\n description:\n 'check the generated output on disk matches a fresh generate (drift guard)',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n\n const { config } = await loadConfig({\n cwd,\n configPath: args.config || undefined,\n });\n const { plan = [] } = await run(config, { logger: reporter, plan: true });\n\n const roots: string[] = [];\n const ignores: ((absPath: string) => boolean)[] = [];\n\n for (const output of config.outputs) {\n if (output.mode === 'package') {\n ignores.push(ignoreBuildArtifacts);\n if (output.packagesDir) {\n roots.push(...(await markedPackageDirs(output.packagesDir)));\n }\n } else {\n const dir = output.dir;\n if (!dir) {\n continue;\n }\n if (!existsSync(dir)) {\n reporter.info(\n `output directory ${relative(config.rootDir, dir)} does not exist — run tako generate`,\n );\n process.exitCode = 1;\n return;\n }\n roots.push(dir);\n }\n }\n\n const ignore = (absPath: string): boolean =>\n ignores.some((fn) => fn(absPath));\n\n const drift = await comparePlanToDisk({\n plan,\n roots,\n ignore,\n rootDir: config.rootDir,\n });\n\n if (drift.length === 0) {\n reporter.info('output is in sync');\n process.exitCode ??= 0;\n return;\n }\n\n reporter.error(formatDrift(drift));\n process.exitCode = 1;\n },\n});\n\nfunction formatDrift(drift: DriftEntry[]): string {\n const width = Math.max(...drift.map((entry) => entry.kind.length));\n const lines = drift.map(\n (entry) => ` ${entry.kind.padEnd(width)} ${entry.path}`,\n );\n return [\n 'drift detected',\n '',\n ...lines,\n '',\n `${drift.length} files differ from a fresh generate. Run \\`tako generate\\`.`,\n ].join('\\n');\n}\n","/**\n * `sharedArgs` — the options every sub-command carries. citty has no\n * first-class global-option slot, so this object is spread into each command's\n * `args` (`backlog/features/cli/technical.md` §Global option).\n */\nimport type { ArgsDef } from 'citty';\n\nexport const sharedArgs = {\n config: {\n type: 'string',\n description: 'path to the tako config file (default: ./tako.config.ts)',\n },\n /** Hidden: not advertised, kept minimal. Enables `debug` reporter output. */\n debug: {\n type: 'boolean',\n default: false,\n },\n} as const satisfies ArgsDef;\n","/**\n * `comparePlanToDisk` — the in-memory comparison behind `tako check`. Takes the\n * `PlannedFile[]` a fresh `generate` would write (from `run({ plan: true })`)\n * and reports every way the tree on disk diverges from it: a planned file that\n * is absent (`missing`) or whose bytes differ (`modified`), and any file under\n * the scanned roots that no planned file claims (`orphan`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §The comparison.\n */\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PlannedFile } from '@kurotako/core';\n\nexport type DriftKind = 'modified' | 'missing' | 'orphan';\n\nexport interface DriftEntry {\n kind: DriftKind;\n /** Relative to `rootDir`, POSIX separators; a collapsed dir ends with `/`. */\n path: string;\n}\n\nexport interface ComparePlanToDiskArgs {\n plan: PlannedFile[];\n /** Directories walked for orphans (absolute). */\n roots: string[];\n /** Return `true` to exclude an absolute path from the orphan scan. */\n ignore: (absPath: string) => boolean;\n /** Anchor for the reported relative paths (the config-file directory). */\n rootDir: string;\n}\n\nfunction toPosix(rootDir: string, absPath: string): string {\n return path.relative(rootDir, absPath).split(path.sep).join('/');\n}\n\nexport async function comparePlanToDisk(\n args: ComparePlanToDiskArgs,\n): Promise<DriftEntry[]> {\n const { plan, roots, ignore, rootDir } = args;\n const plannedByPath = new Map(plan.map((f) => [path.resolve(f.path), f]));\n const entries: DriftEntry[] = [];\n\n // 1. Expected vs disk.\n for (const [absPath, file] of plannedByPath) {\n if (!existsSync(absPath)) {\n entries.push({ kind: 'missing', path: toPosix(rootDir, absPath) });\n continue;\n }\n const onDisk = await readFile(absPath, 'utf8');\n if (onDisk !== file.content) {\n entries.push({ kind: 'modified', path: toPosix(rootDir, absPath) });\n }\n }\n\n // 2. Orphan scan — a planned file lives under `dir` iff any planned absolute\n // path is `dir` itself or sits below it.\n const plannedPaths = [...plannedByPath.keys()];\n const hasPlannedUnder = (dir: string): boolean => {\n const prefix = `${dir}${path.sep}`;\n return plannedPaths.some((p) => p === dir || p.startsWith(prefix));\n };\n\n const seenRoots = new Set<string>();\n for (const root of roots) {\n const absRoot = path.resolve(root);\n if (seenRoots.has(absRoot) || !existsSync(absRoot)) {\n continue;\n }\n seenRoots.add(absRoot);\n await scan(absRoot);\n }\n\n async function scan(dir: string): Promise<void> {\n // A directory with no planned file underneath collapses to a single entry —\n // unless it holds nothing but ignored files (e.g. only `dist/`).\n if (!hasPlannedUnder(dir)) {\n if (await hasNonIgnoredFile(dir)) {\n entries.push({ kind: 'orphan', path: `${toPosix(rootDir, dir)}/` });\n }\n return;\n }\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isDirectory()) {\n await scan(abs);\n } else if (dirent.isFile() && !plannedByPath.has(abs)) {\n entries.push({ kind: 'orphan', path: toPosix(rootDir, abs) });\n }\n }\n }\n\n async function hasNonIgnoredFile(dir: string): Promise<boolean> {\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isFile()) {\n return true;\n }\n if (dirent.isDirectory() && (await hasNonIgnoredFile(abs))) {\n return true;\n }\n }\n return false;\n }\n\n entries.sort((a, b) =>\n a.path < b.path\n ? -1\n : a.path > b.path\n ? 1\n : a.kind < b.kind\n ? -1\n : a.kind > b.kind\n ? 1\n : 0,\n );\n return entries;\n}\n\n/** Rejects `dist/` and `node_modules/` anywhere in the path (mode B). */\nexport function ignoreBuildArtifacts(absPath: string): boolean {\n return /(^|[/\\\\])(dist|node_modules)([/\\\\]|$)/.test(absPath);\n}\n\n/**\n * Whether `<packagesDir>/<name>` looks like a directory `tako` generated: a\n * `package.json` whose `\"//\"` marker starts with `Generated by tako`.\n */\nexport async function hasGeneratedMarker(pkgDir: string): Promise<boolean> {\n try {\n const pkg = JSON.parse(\n await readFile(path.join(pkgDir, 'package.json'), 'utf8'),\n ) as { '//'?: unknown };\n return (\n typeof pkg['//'] === 'string' && pkg['//'].startsWith('Generated by tako')\n );\n } catch {\n return false;\n }\n}\n\n/** Every immediate subdirectory of `packagesDir` carrying the tako marker. */\nexport async function markedPackageDirs(\n packagesDir: string,\n): Promise<string[]> {\n if (!existsSync(packagesDir)) {\n return [];\n }\n const out: string[] = [];\n for (const dirent of await readdir(packagesDir, { withFileTypes: true })) {\n if (!dirent.isDirectory()) {\n continue;\n }\n const abs = path.join(packagesDir, dirent.name);\n if (await hasGeneratedMarker(abs)) {\n out.push(abs);\n }\n }\n return out.sort();\n}\n","/**\n * `ConsoleReporter` — the `@kurotako/core` `Logger` the CLI injects into\n * `loadConfig()` / `run()`, plus the per-phase / summary output.\n *\n * Contract (`backlog/features/cli/technical.md` §Reporter):\n * - human output goes to **stderr**, `stdout` stays clean;\n * - `info` / `warn` / `error` shown by default; `debug` only with `--debug` /\n * `TAKO_DEBUG` (a hidden flag, not advertised);\n * - `tako ` prefix, level-coloured; colour auto-off when the stream is not a TTY\n * or `NO_COLOR` is set;\n * - `child(tag)` returns a `Logger` tagging every `meta` with `{ scope: tag }`.\n */\nimport { childLogger, type Logger } from '@kurotako/core';\n\ntype Level = 'debug' | 'info' | 'warn' | 'error';\n\n/** The slice of a writable stream the reporter needs (keeps tests trivial). */\nexport interface WriteStream {\n write(chunk: string): unknown;\n isTTY?: boolean;\n}\n\nexport interface ConsoleReporterOptions {\n /** Show `debug` output. Default: `false` unless `TAKO_DEBUG` is set. */\n debug?: boolean;\n /** Sink for human output. Default: `process.stderr`. */\n stream?: WriteStream;\n /** Force colour on/off. Default: auto (TTY and no `NO_COLOR`). */\n color?: boolean;\n}\n\nconst ESC = String.fromCharCode(27);\nconst ANSI: Record<Level, string> = {\n debug: `${ESC}[2m`, // dim\n info: `${ESC}[36m`, // cyan\n warn: `${ESC}[33m`, // yellow\n error: `${ESC}[31m`, // red\n};\nconst ANSI_RESET = `${ESC}[0m`;\n\nexport class ConsoleReporter implements Logger {\n private readonly stream: WriteStream;\n private readonly showDebug: boolean;\n private readonly color: boolean;\n\n constructor(options: ConsoleReporterOptions = {}) {\n this.stream = options.stream ?? process.stderr;\n this.showDebug = options.debug ?? Boolean(process.env.TAKO_DEBUG);\n this.color =\n options.color ??\n (Boolean(this.stream.isTTY) && process.env.NO_COLOR === undefined);\n }\n\n debug(msg: string, meta?: unknown): void {\n if (this.showDebug) {\n this.write('debug', msg, meta);\n }\n }\n\n info(msg: string, meta?: unknown): void {\n this.write('info', msg, meta);\n }\n\n warn(msg: string, meta?: unknown): void {\n this.write('warn', msg, meta);\n }\n\n error(msg: string, meta?: unknown): void {\n this.write('error', msg, meta);\n }\n\n /** A child `Logger` whose calls carry `{ scope: tag }` in `meta`. */\n child(tag: string): Logger {\n return childLogger(this, { scope: tag });\n }\n\n private write(level: Level, msg: string, meta?: unknown): void {\n const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : 'tako';\n const detail = meta === undefined ? '' : ` ${formatMeta(meta)}`;\n this.stream.write(`${prefix} ${msg}${detail}\\n`);\n }\n}\n\nfunction formatMeta(meta: unknown): string {\n if (meta !== null && typeof meta === 'object' && !Array.isArray(meta)) {\n return Object.entries(meta as Record<string, unknown>)\n .map(([k, v]) => `${k}=${stringify(v)}`)\n .join(' ');\n }\n return stringify(meta);\n}\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","/**\n * `tako generate` — `loadConfig()` then `run()`. `--dry-run` runs everything but\n * skips the Writer; `--watch` hands off to the chokidar loop\n * (`backlog/features/cli/technical.md` §`tako generate`).\n */\nimport { relative } from 'node:path';\nimport { type LoadResult, loadConfig } from '@kurotako/config';\nimport type { OutputConfig, ResolvedConfig, RunResult } from '@kurotako/core';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { watchAndRun } from '../watch.js';\n\nexport interface LoadAndRunOptions {\n cwd: string;\n configPath?: string;\n write: boolean;\n signal?: AbortSignal;\n reporter: ConsoleReporter;\n}\n\nexport interface LoadAndRunResult {\n result: RunResult;\n config: ResolvedConfig;\n configFile: string;\n rootDir: string;\n}\n\n/** The directory named in the `wrote N files -> …` summary line, for one output. */\nexport function outputSummaryDir(\n output: OutputConfig,\n config: ResolvedConfig,\n): string {\n return output.mode === 'package'\n ? (output.packagesDir ?? config.rootDir)\n : (output.dir ?? config.rootDir);\n}\n\n/**\n * The shared body of `generate`, `validate` and each watch cycle: resolve +\n * load the config, then run the pipeline. `write: false` also skips the\n * `afterEmit` hook (`@kurotako/core` `run()`).\n */\nexport async function loadAndRun(\n opts: LoadAndRunOptions,\n): Promise<LoadAndRunResult> {\n const loaded: LoadResult = await loadConfig({\n cwd: opts.cwd,\n configPath: opts.configPath,\n });\n const result = await run(loaded.config, {\n logger: opts.reporter,\n write: opts.write,\n signal: opts.signal,\n });\n return {\n result,\n config: loaded.config,\n configFile: loaded.configFile,\n rootDir: loaded.rootDir,\n };\n}\n\nexport const generateCommand = defineCommand({\n meta: {\n name: 'generate',\n description: 'run the pipeline and write the generated code',\n },\n args: {\n ...sharedArgs,\n watch: {\n type: 'boolean',\n description: 'rebuild on every schema / config change',\n default: false,\n },\n 'dry-run': {\n type: 'boolean',\n description: 'run everything but write nothing',\n default: false,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n const configPath = args.config || undefined;\n\n if (args.watch) {\n await watchAndRun({ cwd, configPath, reporter });\n return;\n }\n\n const dryRun = Boolean(args['dry-run']);\n const { result, config } = await loadAndRun({\n cwd,\n configPath,\n write: !dryRun,\n reporter,\n });\n\n if (dryRun) {\n reporter.info(`dry run: ${result.files.length} files would be written`);\n return;\n }\n\n const dirs = config.outputs\n .map((output) => relative(cwd, outputSummaryDir(output, config)))\n .join(', ');\n reporter.info(`wrote ${result.files.length} files -> ${dirs}`);\n },\n});\n","/**\n * `tako generate --watch` — a chokidar loop around `loadConfig()` + `run()`.\n * Full regeneration on every change (no incremental). A 100 ms trailing\n * debounce coalesces bursts; a change mid-cycle aborts the in-flight `run()`\n * (via `RunOptions.signal`) and re-runs once it settles. `loadConfig` failures\n * are reported, not fatal — the watcher stays up on `tako.config.ts`.\n *\n * `backlog/features/cli/technical.md` §Watch mode.\n */\nimport { basename, resolve } from 'node:path';\nimport {\n type LoadResult,\n loadConfig as realLoadConfig,\n} from '@kurotako/config';\nimport { run as realRun, TakoError } from '@kurotako/core';\nimport chokidar from 'chokidar';\nimport { renderError } from './errors.js';\nimport type { ConsoleReporter } from './reporter.js';\n\n/** Minimal watcher seam so the loop is unit-testable without touching the fs. */\nexport interface Watcher {\n add(paths: string | readonly string[]): void;\n unwatch(paths: string | readonly string[]): void;\n on(handler: (event: string, path: string) => void): void;\n close(): Promise<void>;\n}\n\nexport interface WatchAndRunOptions {\n cwd: string;\n configPath?: string;\n reporter: ConsoleReporter;\n}\n\nexport interface WatchDeps {\n createWatcher: () => Watcher;\n loadConfig: typeof realLoadConfig;\n run: typeof realRun;\n debounceMs: number;\n}\n\nconst DEBOUNCE_MS = 100;\n\nfunction chokidarWatcher(): Watcher {\n const fsw = chokidar.watch([], {\n ignoreInitial: true,\n awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 20 },\n });\n return {\n add: (paths) => fsw.add(paths as string | string[]),\n unwatch: (paths) => fsw.unwatch(paths as string | string[]),\n on: (handler) => {\n fsw.on('add', (p) => handler('add', p));\n fsw.on('change', (p) => handler('change', p));\n fsw.on('unlink', (p) => handler('unlink', p));\n },\n close: () => fsw.close(),\n };\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError';\n}\n\n/**\n * Runs until `SIGINT` / `SIGTERM`, then closes the watcher and resolves so the\n * caller can exit 0. (The design doc types this `Promise<never>`; it resolves\n * on shutdown here purely so it stays testable.)\n */\nexport async function watchAndRun(\n opts: WatchAndRunOptions,\n deps: Partial<WatchDeps> = {},\n): Promise<void> {\n const { cwd, configPath, reporter } = opts;\n const createWatcher = deps.createWatcher ?? chokidarWatcher;\n const loadConfig = deps.loadConfig ?? realLoadConfig;\n const run = deps.run ?? realRun;\n const debounceMs = deps.debounceMs ?? DEBOUNCE_MS;\n\n const watcher = createWatcher();\n let watched = new Set<string>();\n let inFlight: AbortController | null = null;\n let queued = false;\n let closed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let reason = 'initial build';\n\n const guessedConfigFile = configPath\n ? resolve(cwd, configPath)\n : resolve(cwd, 'tako.config.ts');\n\n function applyWatchSet(desired: Set<string>): void {\n for (const path of desired) {\n if (!watched.has(path)) {\n watcher.add(path);\n }\n }\n for (const path of watched) {\n if (!desired.has(path)) {\n watcher.unwatch(path);\n }\n }\n watched = desired;\n }\n\n async function reconcileWatchSet(loaded: LoadResult): Promise<void> {\n const desired = new Set<string>([loaded.configFile]);\n for (const [namespace, source] of Object.entries(loaded.config.sources)) {\n const paths =\n (await source.parser.watchPaths?.({\n namespace,\n cwd: loaded.rootDir,\n logger: reporter,\n })) ?? [];\n for (const path of paths) {\n desired.add(resolve(loaded.rootDir, path));\n }\n }\n applyWatchSet(desired);\n }\n\n async function cycle(): Promise<void> {\n const why = reason;\n reporter.info(`--- rebuild (${why}) ---`);\n const ac = new AbortController();\n inFlight = ac;\n try {\n const loaded = await loadConfig({ cwd, configPath });\n await reconcileWatchSet(loaded);\n const result = await run(loaded.config, {\n logger: reporter,\n signal: ac.signal,\n write: true,\n });\n if (!ac.signal.aborted) {\n reporter.info(`wrote ${result.files.length} files`);\n }\n } catch (error) {\n if (isAbortError(error) || ac.signal.aborted) {\n // Superseded by a newer cycle — swallow.\n } else if (error instanceof TakoError) {\n reporter.error(renderError(error));\n // Keep watching at least the config file so a fix is picked up.\n applyWatchSet(new Set([...watched, guessedConfigFile]));\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n }\n } finally {\n inFlight = null;\n if (queued && !closed) {\n queued = false;\n await cycle();\n }\n }\n }\n\n function trigger(): void {\n if (inFlight) {\n queued = true;\n inFlight.abort();\n return;\n }\n void cycle();\n }\n\n function schedule(event: string, path: string): void {\n if (closed) {\n return;\n }\n reason = `${basename(path)} ${event === 'unlink' ? 'removed' : 'changed'}`;\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => {\n timer = null;\n trigger();\n }, debounceMs);\n }\n\n watcher.on(schedule);\n\n // Initial cycle: a failure is reported inside `cycle()`, never fatal.\n applyWatchSet(new Set([guessedConfigFile]));\n await cycle();\n reporter.info(`watching ${watched.size} paths`);\n\n await new Promise<void>((resolvePromise) => {\n const shutdown = () => {\n closed = true;\n if (timer) {\n clearTimeout(timer);\n }\n inFlight?.abort();\n process.off('SIGINT', shutdown);\n process.off('SIGTERM', shutdown);\n void watcher.close().finally(() => resolvePromise());\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n}\n","/**\n * CLI-owned error(s) and `renderError()` — the single formatter the top-level\n * handler in `cli.ts` uses for any `TakoError` (from `@kurotako/core`,\n * `@kurotako/config`, or this package).\n *\n * `backlog/features/cli/technical.md` §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\n\n/** `tako init` refuses to overwrite an existing config unless `--force`. */\nexport class ConfigExistsError extends TakoError {\n readonly path: string;\n\n constructor(path: string) {\n super(\n 'config_exists',\n `a config file already exists at '${path}' (pass --force to overwrite)`,\n );\n this.path = path;\n }\n}\n\ninterface Issue {\n path?: string;\n message?: string;\n}\n\n/**\n * `error [<code>]: <message>` plus any carried context on its own indented\n * lines: located issues (`ConfigShapeError`, `IrValidationError`,\n * `DriverOptionsError`), the offending driver / namespace (`DriverError`,\n * `UnknownNamespaceError`), the dependency cycle path (`DependencyCycleError`),\n * and the `cause` message of a wrapped failure.\n */\nexport function renderError(error: TakoError): string {\n const lines = [`error [${error.code}]: ${error.message}`];\n\n const issues = (error as { issues?: unknown }).issues;\n if (Array.isArray(issues)) {\n for (const issue of issues as Issue[]) {\n const at =\n issue.path === undefined || issue.path === '' ? '<root>' : issue.path;\n lines.push(` - ${at}: ${issue.message}`);\n }\n }\n\n const cycle = (error as { cycle?: unknown }).cycle;\n if (Array.isArray(cycle) && cycle.length > 0) {\n lines.push(` cycle: ${(cycle as string[]).join(' -> ')}`);\n }\n\n const driverName = (error as { driverName?: unknown }).driverName;\n if (typeof driverName === 'string') {\n const role = (error as { role?: unknown }).role;\n const namespace = (error as { namespace?: unknown }).namespace;\n const roleLabel = typeof role === 'string' ? role : 'driver';\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` ${roleLabel}: ${driverName}${where}`);\n } else {\n const generator = (error as { generator?: unknown }).generator;\n if (typeof generator === 'string') {\n const namespace = (error as { namespace?: unknown }).namespace;\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` generator: ${generator}${where}`);\n }\n }\n\n // Wrapped failures (`DriverError`, `HookError`, `ConfigLoadError`, …) carry the\n // real error in `cause`; core masks its type, so surface at least its message.\n const cause = error.cause;\n if (cause !== undefined && cause !== null) {\n const message = cause instanceof Error ? cause.message : String(cause);\n const code = cause instanceof TakoError ? ` [${cause.code}]` : '';\n lines.push(` cause${code}: ${message}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * `tako init` — write the commented `tako.config.ts` skeleton into the current\n * directory. No prompts, no schema auto-detection; refuses to overwrite unless\n * `--force` (`backlog/features/cli/technical.md` §`tako init`).\n *\n * `--monorepo` / `--no-monorepo` picks between `CONFIG_TEMPLATE` and\n * `CONFIG_TEMPLATE_MONOREPO`; unset, it auto-detects a workspace by walking up\n * for the nearest `package.json` (`workspaces` key, or a sibling\n * `pnpm-workspace.yaml`).\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, relative, resolve } from 'node:path';\nimport { CONFIG_TEMPLATE, CONFIG_TEMPLATE_MONOREPO } from '@kurotako/config';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConfigExistsError } from '../errors.js';\nimport { ConsoleReporter } from '../reporter.js';\n\n/**\n * Walk up from `startDir` to the first directory holding a `package.json`. A\n * workspace when that `package.json` has a `workspaces` key (array, or\n * `{ packages: [...] }`), or when a `pnpm-workspace.yaml` sits next to it.\n * Returns `false` when no `package.json` is found.\n */\nfunction detectMonorepo(startDir: string): boolean {\n let dir = resolve(startDir);\n while (true) {\n const pkgPath = resolve(dir, 'package.json');\n if (existsSync(pkgPath)) {\n if (existsSync(resolve(dir, 'pnpm-workspace.yaml'))) {\n return true;\n }\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n workspaces?: unknown;\n };\n const ws = pkg.workspaces;\n if (\n Array.isArray(ws) ||\n (typeof ws === 'object' &&\n ws !== null &&\n Array.isArray((ws as { packages?: unknown }).packages))\n ) {\n return true;\n }\n } catch {\n // Unreadable / invalid package.json: treat as not a workspace.\n }\n return false;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return false;\n }\n dir = parent;\n }\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: 'init',\n description: 'create a tako.config.ts in the current directory',\n },\n args: {\n ...sharedArgs,\n force: {\n type: 'boolean',\n description: 'overwrite an existing config file',\n default: false,\n },\n monorepo: {\n type: 'boolean',\n description:\n 'write the monorepo config layout (auto-detected from workspaces when unset)',\n default: undefined,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n // Unlike `loadConfig`, `init` never walks up: it always targets `cwd`.\n const target = args.config\n ? resolve(cwd, args.config)\n : resolve(cwd, 'tako.config.ts');\n\n if (existsSync(target) && !args.force) {\n throw new ConfigExistsError(target);\n }\n\n // citty leaves an unset boolean flag `undefined` (no `default`), so\n // `--monorepo` / `--no-monorepo` win and absence falls back to detection.\n const monorepo: boolean =\n typeof args.monorepo === 'boolean' ? args.monorepo : detectMonorepo(cwd);\n\n await mkdir(dirname(target), { recursive: true });\n await writeFile(\n target,\n monorepo ? CONFIG_TEMPLATE_MONOREPO : CONFIG_TEMPLATE,\n 'utf8',\n );\n\n const name = relative(cwd, target) || 'tako.config.ts';\n reporter.info(\n monorepo ? `created ${name} (monorepo layout)` : `created ${name}`,\n );\n },\n});\n","/**\n * `tako validate` — the same checks as `generate` up to (not including)\n * emission. `loadConfig()` + `run({ write: false })`; any `TakoError` propagates\n * to the top-level handler and exits 1\n * (`backlog/features/cli/technical.md` §`tako validate`).\n */\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { loadAndRun } from './generate.js';\n\nexport const validateCommand = defineCommand({\n meta: {\n name: 'validate',\n description: 'check the config and schema without writing anything',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n await loadAndRun({\n cwd: process.cwd(),\n configPath: args.config || undefined,\n write: false,\n reporter,\n });\n reporter.info('config and schema are valid');\n },\n});\n","#!/usr/bin/env node\n/**\n * Executable entry. Thin: parse `process.argv` and delegate to `runCli()`,\n * which sets `process.exitCode`.\n */\nimport { runCli } from '../cli.js';\n\nawait runCli(process.argv.slice(2));\n"],"mappings":"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","names":["TakoError","defineCommand","existsSync","existsSync","relative","loadConfig","run","defineCommand","TakoError","path","loadConfig","run","path","TakoError","loadConfig","run","defineCommand","relative","existsSync","relative","resolve","defineCommand","resolve","existsSync","defineCommand","relative","defineCommand","defineCommand","defineCommand","TakoError"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli.ts","../../src/commands/check.ts","../../src/args.ts","../../src/diff.ts","../../src/reporter.ts","../../src/commands/generate.ts","../../src/watch.ts","../../src/errors.ts","../../src/commands/init.ts","../../src/commands/validate.ts","../../src/bin/tako.ts"],"sourcesContent":["/**\n * `runCli()` — build the citty command tree, dispatch, map every `TakoError` to\n * a formatted message + exit 1. `--version` / `--help` are handled here (citty's\n * own handling lives in `runMain`, which hard-exits — not what a testable\n * `runCli` wants).\n *\n * `backlog/features/cli/technical.md` §Command surface, §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\nimport { type CommandDef, defineCommand, renderUsage, runCommand } from 'citty';\nimport { checkCommand } from './commands/check.js';\nimport { generateCommand } from './commands/generate.js';\nimport { initCommand } from './commands/init.js';\nimport { validateCommand } from './commands/validate.js';\nimport { renderError } from './errors.js';\nimport { ConsoleReporter } from './reporter.js';\n\ndeclare const __TAKO_VERSION__: string;\nconst VERSION =\n typeof __TAKO_VERSION__ === 'string' ? __TAKO_VERSION__ : '0.0.0-dev';\n\nconst subCommands = {\n init: initCommand,\n generate: generateCommand,\n validate: validateCommand,\n check: checkCommand,\n};\n\nconst main = defineCommand({\n meta: {\n name: 'tako',\n version: VERSION,\n description: 'synchronise TypeScript schemas from data model to forms',\n },\n subCommands,\n});\n\nexport async function runCli(argv: string[]): Promise<void> {\n const reporter = new ConsoleReporter({\n debug: argv.includes('--debug') || Boolean(process.env.TAKO_DEBUG),\n });\n\n if (argv.includes('--version') || argv.includes('-v')) {\n process.stdout.write(`${VERSION}\\n`);\n process.exitCode ??= 0;\n return;\n }\n\n if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {\n const sub = argv.find((a) => !a.startsWith('-'));\n const isSub = sub !== undefined && sub in subCommands;\n const cmd = (\n isSub ? subCommands[sub as keyof typeof subCommands] : main\n ) as CommandDef;\n process.stdout.write(\n `${await renderUsage(cmd, isSub ? (main as CommandDef) : undefined)}\\n`,\n );\n process.exitCode ??= 0;\n return;\n }\n\n try {\n await runCommand(main, { rawArgs: argv });\n process.exitCode ??= 0;\n } catch (error) {\n if (error instanceof TakoError) {\n reporter.error(renderError(error));\n process.exitCode = 1;\n } else if (error instanceof Error && error.name === 'CLIError') {\n // citty usage error (unknown command, missing argument, …).\n reporter.error(error.message);\n process.exitCode = 1;\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n process.exitCode = 1;\n }\n }\n}\n","/**\n * `tako check` — drift guard. Runs the pipeline in plan mode (no disk writes,\n * no `afterEmit`), then compares the planned tree against what is on disk.\n * Exit 0 when they match, exit 1 on any drift or any `TakoError` (the latter\n * via the top-level handler in `cli.ts`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §Command surface.\n */\nimport { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { loadConfig } from '@kurotako/config';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport {\n comparePlanToDisk,\n type DriftEntry,\n ignoreBuildArtifacts,\n markedPackageDirs,\n} from '../diff.js';\nimport { ConsoleReporter } from '../reporter.js';\n\nexport const checkCommand = defineCommand({\n meta: {\n name: 'check',\n description:\n 'check the generated output on disk matches a fresh generate (drift guard)',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n\n const { config } = await loadConfig({\n cwd,\n configPath: args.config || undefined,\n });\n const { plan = [] } = await run(config, { logger: reporter, plan: true });\n\n const roots: string[] = [];\n const ignores: ((absPath: string) => boolean)[] = [];\n\n for (const output of config.outputs) {\n if (output.mode === 'package') {\n ignores.push(ignoreBuildArtifacts);\n if (output.packagesDir) {\n roots.push(...(await markedPackageDirs(output.packagesDir)));\n }\n } else {\n const dir = output.dir;\n if (!dir) {\n continue;\n }\n if (!existsSync(dir)) {\n reporter.info(\n `output directory ${relative(config.rootDir, dir)} does not exist — run tako generate`,\n );\n process.exitCode = 1;\n return;\n }\n roots.push(dir);\n }\n }\n\n const ignore = (absPath: string): boolean =>\n ignores.some((fn) => fn(absPath));\n\n const drift = await comparePlanToDisk({\n plan,\n roots,\n ignore,\n rootDir: config.rootDir,\n });\n\n if (drift.length === 0) {\n reporter.info('output is in sync');\n process.exitCode ??= 0;\n return;\n }\n\n reporter.error(formatDrift(drift));\n process.exitCode = 1;\n },\n});\n\nfunction formatDrift(drift: DriftEntry[]): string {\n const width = Math.max(...drift.map((entry) => entry.kind.length));\n const lines = drift.map(\n (entry) => ` ${entry.kind.padEnd(width)} ${entry.path}`,\n );\n return [\n 'drift detected',\n '',\n ...lines,\n '',\n `${drift.length} files differ from a fresh generate. Run \\`tako generate\\`.`,\n ].join('\\n');\n}\n","/**\n * `sharedArgs` — the options every sub-command carries. citty has no\n * first-class global-option slot, so this object is spread into each command's\n * `args` (`backlog/features/cli/technical.md` §Global option).\n */\nimport type { ArgsDef } from 'citty';\n\nexport const sharedArgs = {\n config: {\n type: 'string',\n description: 'path to the tako config file (default: ./tako.config.ts)',\n },\n /** Hidden: not advertised, kept minimal. Enables `debug` reporter output. */\n debug: {\n type: 'boolean',\n default: false,\n },\n} as const satisfies ArgsDef;\n","/**\n * `comparePlanToDisk` — the in-memory comparison behind `tako check`. Takes the\n * `PlannedFile[]` a fresh `generate` would write (from `run({ plan: true })`)\n * and reports every way the tree on disk diverges from it: a planned file that\n * is absent (`missing`) or whose bytes differ (`modified`), and any file under\n * the scanned roots that no planned file claims (`orphan`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §The comparison.\n */\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PlannedFile } from '@kurotako/core';\n\nexport type DriftKind = 'modified' | 'missing' | 'orphan';\n\nexport interface DriftEntry {\n kind: DriftKind;\n /** Relative to `rootDir`, POSIX separators; a collapsed dir ends with `/`. */\n path: string;\n}\n\nexport interface ComparePlanToDiskArgs {\n plan: PlannedFile[];\n /** Directories walked for orphans (absolute). */\n roots: string[];\n /** Return `true` to exclude an absolute path from the orphan scan. */\n ignore: (absPath: string) => boolean;\n /** Anchor for the reported relative paths (the config-file directory). */\n rootDir: string;\n}\n\nfunction toPosix(rootDir: string, absPath: string): string {\n return path.relative(rootDir, absPath).split(path.sep).join('/');\n}\n\nexport async function comparePlanToDisk(\n args: ComparePlanToDiskArgs,\n): Promise<DriftEntry[]> {\n const { plan, roots, ignore, rootDir } = args;\n const plannedByPath = new Map(plan.map((f) => [path.resolve(f.path), f]));\n const entries: DriftEntry[] = [];\n\n // 1. Expected vs disk.\n for (const [absPath, file] of plannedByPath) {\n if (!existsSync(absPath)) {\n entries.push({ kind: 'missing', path: toPosix(rootDir, absPath) });\n continue;\n }\n const onDisk = await readFile(absPath, 'utf8');\n if (onDisk !== file.content) {\n entries.push({ kind: 'modified', path: toPosix(rootDir, absPath) });\n }\n }\n\n // 2. Orphan scan — a planned file lives under `dir` iff any planned absolute\n // path is `dir` itself or sits below it.\n const plannedPaths = [...plannedByPath.keys()];\n const hasPlannedUnder = (dir: string): boolean => {\n const prefix = `${dir}${path.sep}`;\n return plannedPaths.some((p) => p === dir || p.startsWith(prefix));\n };\n\n const seenRoots = new Set<string>();\n for (const root of roots) {\n const absRoot = path.resolve(root);\n if (seenRoots.has(absRoot) || !existsSync(absRoot)) {\n continue;\n }\n seenRoots.add(absRoot);\n await scan(absRoot);\n }\n\n async function scan(dir: string): Promise<void> {\n // A directory with no planned file underneath collapses to a single entry —\n // unless it holds nothing but ignored files (e.g. only `dist/`).\n if (!hasPlannedUnder(dir)) {\n if (await hasNonIgnoredFile(dir)) {\n entries.push({ kind: 'orphan', path: `${toPosix(rootDir, dir)}/` });\n }\n return;\n }\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isDirectory()) {\n await scan(abs);\n } else if (dirent.isFile() && !plannedByPath.has(abs)) {\n entries.push({ kind: 'orphan', path: toPosix(rootDir, abs) });\n }\n }\n }\n\n async function hasNonIgnoredFile(dir: string): Promise<boolean> {\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isFile()) {\n return true;\n }\n if (dirent.isDirectory() && (await hasNonIgnoredFile(abs))) {\n return true;\n }\n }\n return false;\n }\n\n entries.sort((a, b) =>\n a.path < b.path\n ? -1\n : a.path > b.path\n ? 1\n : a.kind < b.kind\n ? -1\n : a.kind > b.kind\n ? 1\n : 0,\n );\n return entries;\n}\n\n/** Rejects `dist/` and `node_modules/` anywhere in the path (mode B). */\nexport function ignoreBuildArtifacts(absPath: string): boolean {\n return /(^|[/\\\\])(dist|node_modules)([/\\\\]|$)/.test(absPath);\n}\n\n/**\n * Whether `<packagesDir>/<name>` looks like a directory `tako` generated: a\n * `package.json` whose `\"//\"` marker starts with `Generated by tako`.\n */\nexport async function hasGeneratedMarker(pkgDir: string): Promise<boolean> {\n try {\n const pkg = JSON.parse(\n await readFile(path.join(pkgDir, 'package.json'), 'utf8'),\n ) as { '//'?: unknown };\n return (\n typeof pkg['//'] === 'string' && pkg['//'].startsWith('Generated by tako')\n );\n } catch {\n return false;\n }\n}\n\n/** Every immediate subdirectory of `packagesDir` carrying the tako marker. */\nexport async function markedPackageDirs(\n packagesDir: string,\n): Promise<string[]> {\n if (!existsSync(packagesDir)) {\n return [];\n }\n const out: string[] = [];\n for (const dirent of await readdir(packagesDir, { withFileTypes: true })) {\n if (!dirent.isDirectory()) {\n continue;\n }\n const abs = path.join(packagesDir, dirent.name);\n if (await hasGeneratedMarker(abs)) {\n out.push(abs);\n }\n }\n return out.sort();\n}\n","/**\n * `ConsoleReporter` — the `@kurotako/core` `Logger` the CLI injects into\n * `loadConfig()` / `run()`, plus the per-phase / summary output.\n *\n * Contract (`backlog/features/cli/technical.md` §Reporter):\n * - human output goes to **stderr**, `stdout` stays clean;\n * - `info` / `warn` / `error` shown by default; `debug` only with `--debug` /\n * `TAKO_DEBUG` (a hidden flag, not advertised);\n * - the human-readable message is always shown; the structured `meta` object is\n * printed only with `--debug` (a custom `Logger` still receives it in full),\n * so default output stays prose, not `key=value` noise;\n * - `tako ` prefix, level-coloured; colour auto-off when the stream is not a TTY\n * or `NO_COLOR` is set;\n * - `child(tag)` returns a `Logger` tagging every `meta` with `{ scope: tag }`.\n */\nimport { childLogger, type Logger } from '@kurotako/core';\n\ntype Level = 'debug' | 'info' | 'warn' | 'error';\n\n/** The slice of a writable stream the reporter needs (keeps tests trivial). */\nexport interface WriteStream {\n write(chunk: string): unknown;\n isTTY?: boolean;\n}\n\nexport interface ConsoleReporterOptions {\n /** Show `debug` output. Default: `false` unless `TAKO_DEBUG` is set. */\n debug?: boolean;\n /** Sink for human output. Default: `process.stderr`. */\n stream?: WriteStream;\n /** Force colour on/off. Default: auto (TTY and no `NO_COLOR`). */\n color?: boolean;\n}\n\nconst ESC = String.fromCharCode(27);\nconst ANSI: Record<Level, string> = {\n debug: `${ESC}[2m`, // dim\n info: `${ESC}[36m`, // cyan\n warn: `${ESC}[33m`, // yellow\n error: `${ESC}[31m`, // red\n};\nconst ANSI_RESET = `${ESC}[0m`;\n\nexport class ConsoleReporter implements Logger {\n private readonly stream: WriteStream;\n private readonly showDebug: boolean;\n private readonly color: boolean;\n\n constructor(options: ConsoleReporterOptions = {}) {\n this.stream = options.stream ?? process.stderr;\n this.showDebug = options.debug ?? Boolean(process.env.TAKO_DEBUG);\n this.color =\n options.color ??\n (Boolean(this.stream.isTTY) && process.env.NO_COLOR === undefined);\n }\n\n debug(msg: string, meta?: unknown): void {\n if (this.showDebug) {\n this.write('debug', msg, meta);\n }\n }\n\n info(msg: string, meta?: unknown): void {\n this.write('info', msg, meta);\n }\n\n warn(msg: string, meta?: unknown): void {\n this.write('warn', msg, meta);\n }\n\n error(msg: string, meta?: unknown): void {\n this.write('error', msg, meta);\n }\n\n /** A child `Logger` whose calls carry `{ scope: tag }` in `meta`. */\n child(tag: string): Logger {\n return childLogger(this, { scope: tag });\n }\n\n private write(level: Level, msg: string, meta?: unknown): void {\n const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : 'tako';\n const detail =\n meta === undefined || !this.showDebug ? '' : ` ${formatMeta(meta)}`;\n this.stream.write(`${prefix} ${msg}${detail}\\n`);\n }\n}\n\nfunction formatMeta(meta: unknown): string {\n if (meta !== null && typeof meta === 'object' && !Array.isArray(meta)) {\n return Object.entries(meta as Record<string, unknown>)\n .map(([k, v]) => `${k}=${stringify(v)}`)\n .join(' ');\n }\n return stringify(meta);\n}\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","/**\n * `tako generate` — `loadConfig()` then `run()`. `--dry-run` runs everything but\n * skips the Writer; `--watch` hands off to the chokidar loop\n * (`backlog/features/cli/technical.md` §`tako generate`).\n */\nimport { relative } from 'node:path';\nimport { type LoadResult, loadConfig } from '@kurotako/config';\nimport type { OutputConfig, ResolvedConfig, RunResult } from '@kurotako/core';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { watchAndRun } from '../watch.js';\n\nexport interface LoadAndRunOptions {\n cwd: string;\n configPath?: string;\n write: boolean;\n signal?: AbortSignal;\n reporter: ConsoleReporter;\n}\n\nexport interface LoadAndRunResult {\n result: RunResult;\n config: ResolvedConfig;\n configFile: string;\n rootDir: string;\n}\n\n/** The directory named in the `wrote N files -> …` summary line, for one output. */\nexport function outputSummaryDir(\n output: OutputConfig,\n config: ResolvedConfig,\n): string {\n return output.mode === 'package'\n ? (output.packagesDir ?? config.rootDir)\n : (output.dir ?? config.rootDir);\n}\n\n/**\n * The shared body of `generate`, `validate` and each watch cycle: resolve +\n * load the config, then run the pipeline. `write: false` also skips the\n * `afterEmit` hook (`@kurotako/core` `run()`).\n */\nexport async function loadAndRun(\n opts: LoadAndRunOptions,\n): Promise<LoadAndRunResult> {\n const loaded: LoadResult = await loadConfig({\n cwd: opts.cwd,\n configPath: opts.configPath,\n });\n const result = await run(loaded.config, {\n logger: opts.reporter,\n write: opts.write,\n signal: opts.signal,\n });\n return {\n result,\n config: loaded.config,\n configFile: loaded.configFile,\n rootDir: loaded.rootDir,\n };\n}\n\nexport const generateCommand = defineCommand({\n meta: {\n name: 'generate',\n description: 'run the pipeline and write the generated code',\n },\n args: {\n ...sharedArgs,\n watch: {\n type: 'boolean',\n description: 'rebuild on every schema / config change',\n default: false,\n },\n 'dry-run': {\n type: 'boolean',\n description: 'run everything but write nothing',\n default: false,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n const configPath = args.config || undefined;\n\n if (args.watch) {\n await watchAndRun({ cwd, configPath, reporter });\n return;\n }\n\n const dryRun = Boolean(args['dry-run']);\n const { result, config } = await loadAndRun({\n cwd,\n configPath,\n write: !dryRun,\n reporter,\n });\n\n if (dryRun) {\n reporter.info(`dry run: ${result.files.length} files would be written`);\n return;\n }\n\n const dirs = config.outputs\n .map((output) => relative(cwd, outputSummaryDir(output, config)))\n .join(', ');\n reporter.info(`wrote ${result.files.length} files -> ${dirs}`);\n },\n});\n","/**\n * `tako generate --watch` — a chokidar loop around `loadConfig()` + `run()`.\n * Full regeneration on every change (no incremental). A 100 ms trailing\n * debounce coalesces bursts; a change mid-cycle aborts the in-flight `run()`\n * (via `RunOptions.signal`) and re-runs once it settles. `loadConfig` failures\n * are reported, not fatal — the watcher stays up on `tako.config.ts`.\n *\n * `backlog/features/cli/technical.md` §Watch mode.\n */\nimport { basename, resolve } from 'node:path';\nimport {\n type LoadResult,\n loadConfig as realLoadConfig,\n} from '@kurotako/config';\nimport { run as realRun, TakoError } from '@kurotako/core';\nimport chokidar from 'chokidar';\nimport { renderError } from './errors.js';\nimport type { ConsoleReporter } from './reporter.js';\n\n/** Minimal watcher seam so the loop is unit-testable without touching the fs. */\nexport interface Watcher {\n add(paths: string | readonly string[]): void;\n unwatch(paths: string | readonly string[]): void;\n on(handler: (event: string, path: string) => void): void;\n close(): Promise<void>;\n}\n\nexport interface WatchAndRunOptions {\n cwd: string;\n configPath?: string;\n reporter: ConsoleReporter;\n}\n\nexport interface WatchDeps {\n createWatcher: () => Watcher;\n loadConfig: typeof realLoadConfig;\n run: typeof realRun;\n debounceMs: number;\n}\n\nconst DEBOUNCE_MS = 100;\n\nfunction chokidarWatcher(): Watcher {\n const fsw = chokidar.watch([], {\n ignoreInitial: true,\n awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 20 },\n });\n return {\n add: (paths) => fsw.add(paths as string | string[]),\n unwatch: (paths) => fsw.unwatch(paths as string | string[]),\n on: (handler) => {\n fsw.on('add', (p) => handler('add', p));\n fsw.on('change', (p) => handler('change', p));\n fsw.on('unlink', (p) => handler('unlink', p));\n },\n close: () => fsw.close(),\n };\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError';\n}\n\n/**\n * Runs until `SIGINT` / `SIGTERM`, then closes the watcher and resolves so the\n * caller can exit 0. (The design doc types this `Promise<never>`; it resolves\n * on shutdown here purely so it stays testable.)\n */\nexport async function watchAndRun(\n opts: WatchAndRunOptions,\n deps: Partial<WatchDeps> = {},\n): Promise<void> {\n const { cwd, configPath, reporter } = opts;\n const createWatcher = deps.createWatcher ?? chokidarWatcher;\n const loadConfig = deps.loadConfig ?? realLoadConfig;\n const run = deps.run ?? realRun;\n const debounceMs = deps.debounceMs ?? DEBOUNCE_MS;\n\n const watcher = createWatcher();\n let watched = new Set<string>();\n let inFlight: AbortController | null = null;\n let queued = false;\n let closed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let reason = 'initial build';\n\n const guessedConfigFile = configPath\n ? resolve(cwd, configPath)\n : resolve(cwd, 'tako.config.ts');\n\n function applyWatchSet(desired: Set<string>): void {\n for (const path of desired) {\n if (!watched.has(path)) {\n watcher.add(path);\n }\n }\n for (const path of watched) {\n if (!desired.has(path)) {\n watcher.unwatch(path);\n }\n }\n watched = desired;\n }\n\n async function reconcileWatchSet(loaded: LoadResult): Promise<void> {\n const desired = new Set<string>([loaded.configFile]);\n for (const [namespace, source] of Object.entries(loaded.config.sources)) {\n const paths =\n (await source.parser.watchPaths?.({\n namespace,\n cwd: loaded.rootDir,\n logger: reporter,\n })) ?? [];\n for (const path of paths) {\n desired.add(resolve(loaded.rootDir, path));\n }\n }\n applyWatchSet(desired);\n }\n\n async function cycle(): Promise<void> {\n const why = reason;\n reporter.info(`--- rebuild (${why}) ---`);\n const ac = new AbortController();\n inFlight = ac;\n try {\n const loaded = await loadConfig({ cwd, configPath });\n await reconcileWatchSet(loaded);\n const result = await run(loaded.config, {\n logger: reporter,\n signal: ac.signal,\n write: true,\n });\n if (!ac.signal.aborted) {\n reporter.info(`wrote ${result.files.length} files`);\n }\n } catch (error) {\n if (isAbortError(error) || ac.signal.aborted) {\n // Superseded by a newer cycle — swallow.\n } else if (error instanceof TakoError) {\n reporter.error(renderError(error));\n // Keep watching at least the config file so a fix is picked up.\n applyWatchSet(new Set([...watched, guessedConfigFile]));\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n }\n } finally {\n inFlight = null;\n if (queued && !closed) {\n queued = false;\n await cycle();\n }\n }\n }\n\n function trigger(): void {\n if (inFlight) {\n queued = true;\n inFlight.abort();\n return;\n }\n void cycle();\n }\n\n function schedule(event: string, path: string): void {\n if (closed) {\n return;\n }\n reason = `${basename(path)} ${event === 'unlink' ? 'removed' : 'changed'}`;\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => {\n timer = null;\n trigger();\n }, debounceMs);\n }\n\n watcher.on(schedule);\n\n // Initial cycle: a failure is reported inside `cycle()`, never fatal.\n applyWatchSet(new Set([guessedConfigFile]));\n await cycle();\n reporter.info(`watching ${watched.size} paths`);\n\n await new Promise<void>((resolvePromise) => {\n const shutdown = () => {\n closed = true;\n if (timer) {\n clearTimeout(timer);\n }\n inFlight?.abort();\n process.off('SIGINT', shutdown);\n process.off('SIGTERM', shutdown);\n void watcher.close().finally(() => resolvePromise());\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n}\n","/**\n * CLI-owned error(s) and `renderError()` — the single formatter the top-level\n * handler in `cli.ts` uses for any `TakoError` (from `@kurotako/core`,\n * `@kurotako/config`, or this package).\n *\n * `backlog/features/cli/technical.md` §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\n\n/** `tako init` refuses to overwrite an existing config unless `--force`. */\nexport class ConfigExistsError extends TakoError {\n readonly path: string;\n\n constructor(path: string) {\n super(\n 'config_exists',\n `a config file already exists at '${path}' (pass --force to overwrite)`,\n );\n this.path = path;\n }\n}\n\ninterface Issue {\n path?: string;\n message?: string;\n}\n\n/**\n * `error [<code>]: <message>` plus any carried context on its own indented\n * lines: located issues (`ConfigShapeError`, `IrValidationError`,\n * `DriverOptionsError`), the offending driver / namespace (`DriverError`,\n * `UnknownNamespaceError`), the dependency cycle path (`DependencyCycleError`),\n * and the `cause` message of a wrapped failure.\n */\nexport function renderError(error: TakoError): string {\n const lines = [`error [${error.code}]: ${error.message}`];\n\n const issues = (error as { issues?: unknown }).issues;\n if (Array.isArray(issues)) {\n for (const issue of issues as Issue[]) {\n const at =\n issue.path === undefined || issue.path === '' ? '<root>' : issue.path;\n lines.push(` - ${at}: ${issue.message}`);\n }\n }\n\n const cycle = (error as { cycle?: unknown }).cycle;\n if (Array.isArray(cycle) && cycle.length > 0) {\n lines.push(` cycle: ${(cycle as string[]).join(' -> ')}`);\n }\n\n const driverName = (error as { driverName?: unknown }).driverName;\n if (typeof driverName === 'string') {\n const role = (error as { role?: unknown }).role;\n const namespace = (error as { namespace?: unknown }).namespace;\n const roleLabel = typeof role === 'string' ? role : 'driver';\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` ${roleLabel}: ${driverName}${where}`);\n } else {\n const generator = (error as { generator?: unknown }).generator;\n if (typeof generator === 'string') {\n const namespace = (error as { namespace?: unknown }).namespace;\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` generator: ${generator}${where}`);\n }\n }\n\n // Wrapped failures (`DriverError`, `HookError`, `ConfigLoadError`, …) carry the\n // real error in `cause`; core masks its type, so surface at least its message.\n const cause = error.cause;\n if (cause !== undefined && cause !== null) {\n const message = cause instanceof Error ? cause.message : String(cause);\n const code = cause instanceof TakoError ? ` [${cause.code}]` : '';\n lines.push(` cause${code}: ${message}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * `tako init` — write the commented `tako.config.ts` skeleton into the current\n * directory. No prompts, no schema auto-detection; refuses to overwrite unless\n * `--force` (`backlog/features/cli/technical.md` §`tako init`).\n *\n * `--monorepo` / `--no-monorepo` picks between `CONFIG_TEMPLATE` and\n * `CONFIG_TEMPLATE_MONOREPO`; unset, it auto-detects a workspace by walking up\n * for the nearest `package.json` (`workspaces` key, or a sibling\n * `pnpm-workspace.yaml`).\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, relative, resolve } from 'node:path';\nimport { CONFIG_TEMPLATE, CONFIG_TEMPLATE_MONOREPO } from '@kurotako/config';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConfigExistsError } from '../errors.js';\nimport { ConsoleReporter } from '../reporter.js';\n\n/**\n * Walk up from `startDir` to the first directory holding a `package.json`. A\n * workspace when that `package.json` has a `workspaces` key (array, or\n * `{ packages: [...] }`), or when a `pnpm-workspace.yaml` sits next to it.\n * Returns `false` when no `package.json` is found.\n */\nfunction detectMonorepo(startDir: string): boolean {\n let dir = resolve(startDir);\n while (true) {\n const pkgPath = resolve(dir, 'package.json');\n if (existsSync(pkgPath)) {\n if (existsSync(resolve(dir, 'pnpm-workspace.yaml'))) {\n return true;\n }\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n workspaces?: unknown;\n };\n const ws = pkg.workspaces;\n if (\n Array.isArray(ws) ||\n (typeof ws === 'object' &&\n ws !== null &&\n Array.isArray((ws as { packages?: unknown }).packages))\n ) {\n return true;\n }\n } catch {\n // Unreadable / invalid package.json: treat as not a workspace.\n }\n return false;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return false;\n }\n dir = parent;\n }\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: 'init',\n description: 'create a tako.config.ts in the current directory',\n },\n args: {\n ...sharedArgs,\n force: {\n type: 'boolean',\n description: 'overwrite an existing config file',\n default: false,\n },\n monorepo: {\n type: 'boolean',\n description:\n 'write the monorepo config layout (auto-detected from workspaces when unset)',\n default: undefined,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n // Unlike `loadConfig`, `init` never walks up: it always targets `cwd`.\n const target = args.config\n ? resolve(cwd, args.config)\n : resolve(cwd, 'tako.config.ts');\n\n if (existsSync(target) && !args.force) {\n throw new ConfigExistsError(target);\n }\n\n // citty leaves an unset boolean flag `undefined` (no `default`), so\n // `--monorepo` / `--no-monorepo` win and absence falls back to detection.\n const monorepo: boolean =\n typeof args.monorepo === 'boolean' ? args.monorepo : detectMonorepo(cwd);\n\n await mkdir(dirname(target), { recursive: true });\n await writeFile(\n target,\n monorepo ? CONFIG_TEMPLATE_MONOREPO : CONFIG_TEMPLATE,\n 'utf8',\n );\n\n const name = relative(cwd, target) || 'tako.config.ts';\n reporter.info(\n monorepo ? `created ${name} (monorepo layout)` : `created ${name}`,\n );\n },\n});\n","/**\n * `tako validate` — the same checks as `generate` up to (not including)\n * emission. `loadConfig()` + `run({ write: false })`; any `TakoError` propagates\n * to the top-level handler and exits 1\n * (`backlog/features/cli/technical.md` §`tako validate`).\n */\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { loadAndRun } from './generate.js';\n\nexport const validateCommand = defineCommand({\n meta: {\n name: 'validate',\n description: 'check the config and schema without writing anything',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n await loadAndRun({\n cwd: process.cwd(),\n configPath: args.config || undefined,\n write: false,\n reporter,\n });\n reporter.info('config and schema are valid');\n },\n});\n","#!/usr/bin/env node\n/**\n * Executable entry. Thin: parse `process.argv` and delegate to `runCli()`,\n * which sets `process.exitCode`.\n */\nimport { runCli } from '../cli.js';\n\nawait runCli(process.argv.slice(2));\n"],"mappings":";;;AAQA,SAAS,aAAAA,kBAAiB;AAC1B,SAA0B,iBAAAC,gBAAe,aAAa,kBAAkB;;;ACDxE,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,WAAW;AACpB,SAAS,qBAAqB;;;ACLvB,IAAM,aAAa;AAAA,EACxB,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA;AAAA,EAEA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AACF;;;ACRA,SAAS,kBAAkB;AAC3B,SAAS,SAAS,gBAAgB;AAClC,OAAO,UAAU;AAqBjB,SAAS,QAAQ,SAAiB,SAAyB;AACzD,SAAO,KAAK,SAAS,SAAS,OAAO,EAAE,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AACjE;AAEA,eAAsB,kBACpB,MACuB;AACvB,QAAM,EAAE,MAAM,OAAO,QAAQ,QAAQ,IAAI;AACzC,QAAM,gBAAgB,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,QAAQ,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;AACxE,QAAM,UAAwB,CAAC;AAG/B,aAAW,CAAC,SAAS,IAAI,KAAK,eAAe;AAC3C,QAAI,CAAC,WAAW,OAAO,GAAG;AACxB,cAAQ,KAAK,EAAE,MAAM,WAAW,MAAM,QAAQ,SAAS,OAAO,EAAE,CAAC;AACjE;AAAA,IACF;AACA,UAAM,SAAS,MAAM,SAAS,SAAS,MAAM;AAC7C,QAAI,WAAW,KAAK,SAAS;AAC3B,cAAQ,KAAK,EAAE,MAAM,YAAY,MAAM,QAAQ,SAAS,OAAO,EAAE,CAAC;AAAA,IACpE;AAAA,EACF;AAIA,QAAM,eAAe,CAAC,GAAG,cAAc,KAAK,CAAC;AAC7C,QAAM,kBAAkB,CAAC,QAAyB;AAChD,UAAM,SAAS,GAAG,GAAG,GAAG,KAAK,GAAG;AAChC,WAAO,aAAa,KAAK,CAAC,MAAM,MAAM,OAAO,EAAE,WAAW,MAAM,CAAC;AAAA,EACnE;AAEA,QAAM,YAAY,oBAAI,IAAY;AAClC,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,QAAQ,IAAI;AACjC,QAAI,UAAU,IAAI,OAAO,KAAK,CAAC,WAAW,OAAO,GAAG;AAClD;AAAA,IACF;AACA,cAAU,IAAI,OAAO;AACrB,UAAM,KAAK,OAAO;AAAA,EACpB;AAEA,iBAAe,KAAK,KAA4B;AAG9C,QAAI,CAAC,gBAAgB,GAAG,GAAG;AACzB,UAAI,MAAM,kBAAkB,GAAG,GAAG;AAChC,gBAAQ,KAAK,EAAE,MAAM,UAAU,MAAM,GAAG,QAAQ,SAAS,GAAG,CAAC,IAAI,CAAC;AAAA,MACpE;AACA;AAAA,IACF;AACA,eAAW,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAChE,YAAM,MAAM,KAAK,KAAK,KAAK,OAAO,IAAI;AACtC,UAAI,OAAO,GAAG,GAAG;AACf;AAAA,MACF;AACA,UAAI,OAAO,YAAY,GAAG;AACxB,cAAM,KAAK,GAAG;AAAA,MAChB,WAAW,OAAO,OAAO,KAAK,CAAC,cAAc,IAAI,GAAG,GAAG;AACrD,gBAAQ,KAAK,EAAE,MAAM,UAAU,MAAM,QAAQ,SAAS,GAAG,EAAE,CAAC;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEA,iBAAe,kBAAkB,KAA+B;AAC9D,eAAW,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAChE,YAAM,MAAM,KAAK,KAAK,KAAK,OAAO,IAAI;AACtC,UAAI,OAAO,GAAG,GAAG;AACf;AAAA,MACF;AACA,UAAI,OAAO,OAAO,GAAG;AACnB,eAAO;AAAA,MACT;AACA,UAAI,OAAO,YAAY,KAAM,MAAM,kBAAkB,GAAG,GAAI;AAC1D,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,UAAQ;AAAA,IAAK,CAAC,GAAG,MACf,EAAE,OAAO,EAAE,OACP,KACA,EAAE,OAAO,EAAE,OACT,IACA,EAAE,OAAO,EAAE,OACT,KACA,EAAE,OAAO,EAAE,OACT,IACA;AAAA,EACZ;AACA,SAAO;AACT;AAGO,SAAS,qBAAqB,SAA0B;AAC7D,SAAO,wCAAwC,KAAK,OAAO;AAC7D;AAMA,eAAsB,mBAAmB,QAAkC;AACzE,MAAI;AACF,UAAM,MAAM,KAAK;AAAA,MACf,MAAM,SAAS,KAAK,KAAK,QAAQ,cAAc,GAAG,MAAM;AAAA,IAC1D;AACA,WACE,OAAO,IAAI,IAAI,MAAM,YAAY,IAAI,IAAI,EAAE,WAAW,mBAAmB;AAAA,EAE7E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAsB,kBACpB,aACmB;AACnB,MAAI,CAAC,WAAW,WAAW,GAAG;AAC5B,WAAO,CAAC;AAAA,EACV;AACA,QAAM,MAAgB,CAAC;AACvB,aAAW,UAAU,MAAM,QAAQ,aAAa,EAAE,eAAe,KAAK,CAAC,GAAG;AACxE,QAAI,CAAC,OAAO,YAAY,GAAG;AACzB;AAAA,IACF;AACA,UAAM,MAAM,KAAK,KAAK,aAAa,OAAO,IAAI;AAC9C,QAAI,MAAM,mBAAmB,GAAG,GAAG;AACjC,UAAI,KAAK,GAAG;AAAA,IACd;AAAA,EACF;AACA,SAAO,IAAI,KAAK;AAClB;;;ACtJA,SAAS,mBAAgC;AAmBzC,IAAM,MAAM,OAAO,aAAa,EAAE;AAClC,IAAM,OAA8B;AAAA,EAClC,OAAO,GAAG,GAAG;AAAA;AAAA,EACb,MAAM,GAAG,GAAG;AAAA;AAAA,EACZ,MAAM,GAAG,GAAG;AAAA;AAAA,EACZ,OAAO,GAAG,GAAG;AAAA;AACf;AACA,IAAM,aAAa,GAAG,GAAG;AAElB,IAAM,kBAAN,MAAwC;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,UAAkC,CAAC,GAAG;AAChD,SAAK,SAAS,QAAQ,UAAU,QAAQ;AACxC,SAAK,YAAY,QAAQ,SAAS,QAAQ,QAAQ,IAAI,UAAU;AAChE,SAAK,QACH,QAAQ,UACP,QAAQ,KAAK,OAAO,KAAK,KAAK,QAAQ,IAAI,aAAa;AAAA,EAC5D;AAAA,EAEA,MAAM,KAAa,MAAsB;AACvC,QAAI,KAAK,WAAW;AAClB,WAAK,MAAM,SAAS,KAAK,IAAI;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,KAAK,KAAa,MAAsB;AACtC,SAAK,MAAM,QAAQ,KAAK,IAAI;AAAA,EAC9B;AAAA,EAEA,KAAK,KAAa,MAAsB;AACtC,SAAK,MAAM,QAAQ,KAAK,IAAI;AAAA,EAC9B;AAAA,EAEA,MAAM,KAAa,MAAsB;AACvC,SAAK,MAAM,SAAS,KAAK,IAAI;AAAA,EAC/B;AAAA;AAAA,EAGA,MAAM,KAAqB;AACzB,WAAO,YAAY,MAAM,EAAE,OAAO,IAAI,CAAC;AAAA,EACzC;AAAA,EAEQ,MAAM,OAAc,KAAa,MAAsB;AAC7D,UAAM,SAAS,KAAK,QAAQ,GAAG,KAAK,KAAK,CAAC,OAAO,UAAU,KAAK;AAChE,UAAM,SACJ,SAAS,UAAa,CAAC,KAAK,YAAY,KAAK,IAAI,WAAW,IAAI,CAAC;AACnE,SAAK,OAAO,MAAM,GAAG,MAAM,IAAI,GAAG,GAAG,MAAM;AAAA,CAAI;AAAA,EACjD;AACF;AAEA,SAAS,WAAW,MAAuB;AACzC,MAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AACrE,WAAO,OAAO,QAAQ,IAA+B,EAClD,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,CAAC,EAAE,EACtC,KAAK,GAAG;AAAA,EACb;AACA,SAAO,UAAU,IAAI;AACvB;AAEA,SAAS,UAAU,OAAwB;AACzC,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,UAAU,KAAK,KAAK,OAAO,KAAK;AAAA,EAC9C,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;;;AHnFO,IAAM,eAAe,cAAc;AAAA,EACxC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM,EAAE,GAAG,WAAW;AAAA,EACtB,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,WAAW,IAAI,gBAAgB,EAAE,OAAO,QAAQ,KAAK,KAAK,EAAE,CAAC;AACnE,UAAM,MAAM,QAAQ,IAAI;AAExB,UAAM,EAAE,OAAO,IAAI,MAAM,WAAW;AAAA,MAClC;AAAA,MACA,YAAY,KAAK,UAAU;AAAA,IAC7B,CAAC;AACD,UAAM,EAAE,OAAO,CAAC,EAAE,IAAI,MAAM,IAAI,QAAQ,EAAE,QAAQ,UAAU,MAAM,KAAK,CAAC;AAExE,UAAM,QAAkB,CAAC;AACzB,UAAM,UAA4C,CAAC;AAEnD,eAAW,UAAU,OAAO,SAAS;AACnC,UAAI,OAAO,SAAS,WAAW;AAC7B,gBAAQ,KAAK,oBAAoB;AACjC,YAAI,OAAO,aAAa;AACtB,gBAAM,KAAK,GAAI,MAAM,kBAAkB,OAAO,WAAW,CAAE;AAAA,QAC7D;AAAA,MACF,OAAO;AACL,cAAM,MAAM,OAAO;AACnB,YAAI,CAAC,KAAK;AACR;AAAA,QACF;AACA,YAAI,CAACC,YAAW,GAAG,GAAG;AACpB,mBAAS;AAAA,YACP,oBAAoB,SAAS,OAAO,SAAS,GAAG,CAAC;AAAA,UACnD;AACA,kBAAQ,WAAW;AACnB;AAAA,QACF;AACA,cAAM,KAAK,GAAG;AAAA,MAChB;AAAA,IACF;AAEA,UAAM,SAAS,CAAC,YACd,QAAQ,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;AAElC,UAAM,QAAQ,MAAM,kBAAkB;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,QAAI,MAAM,WAAW,GAAG;AACtB,eAAS,KAAK,mBAAmB;AACjC,cAAQ,aAAa;AACrB;AAAA,IACF;AAEA,aAAS,MAAM,YAAY,KAAK,CAAC;AACjC,YAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAED,SAAS,YAAY,OAA6B;AAChD,QAAM,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,MAAM,KAAK,MAAM,CAAC;AACjE,QAAM,QAAQ,MAAM;AAAA,IAClB,CAAC,UAAU,KAAK,MAAM,KAAK,OAAO,KAAK,CAAC,KAAK,MAAM,IAAI;AAAA,EACzD;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA,GAAG,MAAM,MAAM;AAAA,EACjB,EAAE,KAAK,IAAI;AACb;;;AI5FA,SAAS,YAAAC,iBAAgB;AACzB,SAA0B,cAAAC,mBAAkB;AAE5C,SAAS,OAAAC,YAAW;AACpB,SAAS,iBAAAC,sBAAqB;;;ACA9B,SAAS,UAAU,eAAe;AAClC;AAAA,EAEE,cAAc;AAAA,OACT;AACP,SAAS,OAAO,SAAS,aAAAC,kBAAiB;AAC1C,OAAO,cAAc;;;ACRrB,SAAS,iBAAiB;AAGnB,IAAM,oBAAN,cAAgC,UAAU;AAAA,EACtC;AAAA,EAET,YAAYC,OAAc;AACxB;AAAA,MACE;AAAA,MACA,oCAAoCA,KAAI;AAAA,IAC1C;AACA,SAAK,OAAOA;AAAA,EACd;AACF;AAcO,SAAS,YAAY,OAA0B;AACpD,QAAM,QAAQ,CAAC,UAAU,MAAM,IAAI,MAAM,MAAM,OAAO,EAAE;AAExD,QAAM,SAAU,MAA+B;AAC/C,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,eAAW,SAAS,QAAmB;AACrC,YAAM,KACJ,MAAM,SAAS,UAAa,MAAM,SAAS,KAAK,WAAW,MAAM;AACnE,YAAM,KAAK,OAAO,EAAE,KAAK,MAAM,OAAO,EAAE;AAAA,IAC1C;AAAA,EACF;AAEA,QAAM,QAAS,MAA8B;AAC7C,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GAAG;AAC5C,UAAM,KAAK,YAAa,MAAmB,KAAK,MAAM,CAAC,EAAE;AAAA,EAC3D;AAEA,QAAM,aAAc,MAAmC;AACvD,MAAI,OAAO,eAAe,UAAU;AAClC,UAAM,OAAQ,MAA6B;AAC3C,UAAM,YAAa,MAAkC;AACrD,UAAM,YAAY,OAAO,SAAS,WAAW,OAAO;AACpD,UAAM,QACJ,OAAO,cAAc,WAAW,gBAAgB,SAAS,OAAO;AAClE,UAAM,KAAK,KAAK,SAAS,KAAK,UAAU,GAAG,KAAK,EAAE;AAAA,EACpD,OAAO;AACL,UAAM,YAAa,MAAkC;AACrD,QAAI,OAAO,cAAc,UAAU;AACjC,YAAM,YAAa,MAAkC;AACrD,YAAM,QACJ,OAAO,cAAc,WAAW,gBAAgB,SAAS,OAAO;AAClE,YAAM,KAAK,gBAAgB,SAAS,GAAG,KAAK,EAAE;AAAA,IAChD;AAAA,EACF;AAIA,QAAM,QAAQ,MAAM;AACpB,MAAI,UAAU,UAAa,UAAU,MAAM;AACzC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,OAAO,iBAAiB,YAAY,KAAK,MAAM,IAAI,MAAM;AAC/D,UAAM,KAAK,UAAU,IAAI,KAAK,OAAO,EAAE;AAAA,EACzC;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ADvCA,IAAM,cAAc;AAEpB,SAAS,kBAA2B;AAClC,QAAM,MAAM,SAAS,MAAM,CAAC,GAAG;AAAA,IAC7B,eAAe;AAAA,IACf,kBAAkB,EAAE,oBAAoB,KAAK,cAAc,GAAG;AAAA,EAChE,CAAC;AACD,SAAO;AAAA,IACL,KAAK,CAAC,UAAU,IAAI,IAAI,KAA0B;AAAA,IAClD,SAAS,CAAC,UAAU,IAAI,QAAQ,KAA0B;AAAA,IAC1D,IAAI,CAAC,YAAY;AACf,UAAI,GAAG,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,CAAC;AACtC,UAAI,GAAG,UAAU,CAAC,MAAM,QAAQ,UAAU,CAAC,CAAC;AAC5C,UAAI,GAAG,UAAU,CAAC,MAAM,QAAQ,UAAU,CAAC,CAAC;AAAA,IAC9C;AAAA,IACA,OAAO,MAAM,IAAI,MAAM;AAAA,EACzB;AACF;AAEA,SAAS,aAAa,OAAyB;AAC7C,SAAO,iBAAiB,SAAS,MAAM,SAAS;AAClD;AAOA,eAAsB,YACpB,MACA,OAA2B,CAAC,GACb;AACf,QAAM,EAAE,KAAK,YAAY,SAAS,IAAI;AACtC,QAAM,gBAAgB,KAAK,iBAAiB;AAC5C,QAAMC,cAAa,KAAK,cAAc;AACtC,QAAMC,OAAM,KAAK,OAAO;AACxB,QAAM,aAAa,KAAK,cAAc;AAEtC,QAAM,UAAU,cAAc;AAC9B,MAAI,UAAU,oBAAI,IAAY;AAC9B,MAAI,WAAmC;AACvC,MAAI,SAAS;AACb,MAAI,SAAS;AACb,MAAI,QAA8C;AAClD,MAAI,SAAS;AAEb,QAAM,oBAAoB,aACtB,QAAQ,KAAK,UAAU,IACvB,QAAQ,KAAK,gBAAgB;AAEjC,WAAS,cAAc,SAA4B;AACjD,eAAWC,SAAQ,SAAS;AAC1B,UAAI,CAAC,QAAQ,IAAIA,KAAI,GAAG;AACtB,gBAAQ,IAAIA,KAAI;AAAA,MAClB;AAAA,IACF;AACA,eAAWA,SAAQ,SAAS;AAC1B,UAAI,CAAC,QAAQ,IAAIA,KAAI,GAAG;AACtB,gBAAQ,QAAQA,KAAI;AAAA,MACtB;AAAA,IACF;AACA,cAAU;AAAA,EACZ;AAEA,iBAAe,kBAAkB,QAAmC;AAClE,UAAM,UAAU,oBAAI,IAAY,CAAC,OAAO,UAAU,CAAC;AACnD,eAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,OAAO,OAAO,OAAO,GAAG;AACvE,YAAM,QACH,MAAM,OAAO,OAAO,aAAa;AAAA,QAChC;AAAA,QACA,KAAK,OAAO;AAAA,QACZ,QAAQ;AAAA,MACV,CAAC,KAAM,CAAC;AACV,iBAAWA,SAAQ,OAAO;AACxB,gBAAQ,IAAI,QAAQ,OAAO,SAASA,KAAI,CAAC;AAAA,MAC3C;AAAA,IACF;AACA,kBAAc,OAAO;AAAA,EACvB;AAEA,iBAAe,QAAuB;AACpC,UAAM,MAAM;AACZ,aAAS,KAAK,gBAAgB,GAAG,OAAO;AACxC,UAAM,KAAK,IAAI,gBAAgB;AAC/B,eAAW;AACX,QAAI;AACF,YAAM,SAAS,MAAMF,YAAW,EAAE,KAAK,WAAW,CAAC;AACnD,YAAM,kBAAkB,MAAM;AAC9B,YAAM,SAAS,MAAMC,KAAI,OAAO,QAAQ;AAAA,QACtC,QAAQ;AAAA,QACR,QAAQ,GAAG;AAAA,QACX,OAAO;AAAA,MACT,CAAC;AACD,UAAI,CAAC,GAAG,OAAO,SAAS;AACtB,iBAAS,KAAK,SAAS,OAAO,MAAM,MAAM,QAAQ;AAAA,MACpD;AAAA,IACF,SAAS,OAAO;AACd,UAAI,aAAa,KAAK,KAAK,GAAG,OAAO,SAAS;AAAA,MAE9C,WAAW,iBAAiBE,YAAW;AACrC,iBAAS,MAAM,YAAY,KAAK,CAAC;AAEjC,sBAAc,oBAAI,IAAI,CAAC,GAAG,SAAS,iBAAiB,CAAC,CAAC;AAAA,MACxD,OAAO;AACL,iBAAS,MAAM,iCAAiC;AAChD,gBAAQ,MAAM,KAAK;AAAA,MACrB;AAAA,IACF,UAAE;AACA,iBAAW;AACX,UAAI,UAAU,CAAC,QAAQ;AACrB,iBAAS;AACT,cAAM,MAAM;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAEA,WAAS,UAAgB;AACvB,QAAI,UAAU;AACZ,eAAS;AACT,eAAS,MAAM;AACf;AAAA,IACF;AACA,SAAK,MAAM;AAAA,EACb;AAEA,WAAS,SAAS,OAAeD,OAAoB;AACnD,QAAI,QAAQ;AACV;AAAA,IACF;AACA,aAAS,GAAG,SAASA,KAAI,CAAC,IAAI,UAAU,WAAW,YAAY,SAAS;AACxE,QAAI,OAAO;AACT,mBAAa,KAAK;AAAA,IACpB;AACA,YAAQ,WAAW,MAAM;AACvB,cAAQ;AACR,cAAQ;AAAA,IACV,GAAG,UAAU;AAAA,EACf;AAEA,UAAQ,GAAG,QAAQ;AAGnB,gBAAc,oBAAI,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAC1C,QAAM,MAAM;AACZ,WAAS,KAAK,YAAY,QAAQ,IAAI,QAAQ;AAE9C,QAAM,IAAI,QAAc,CAAC,mBAAmB;AAC1C,UAAM,WAAW,MAAM;AACrB,eAAS;AACT,UAAI,OAAO;AACT,qBAAa,KAAK;AAAA,MACpB;AACA,gBAAU,MAAM;AAChB,cAAQ,IAAI,UAAU,QAAQ;AAC9B,cAAQ,IAAI,WAAW,QAAQ;AAC/B,WAAK,QAAQ,MAAM,EAAE,QAAQ,MAAM,eAAe,CAAC;AAAA,IACrD;AACA,YAAQ,GAAG,UAAU,QAAQ;AAC7B,YAAQ,GAAG,WAAW,QAAQ;AAAA,EAChC,CAAC;AACH;;;AD1KO,SAAS,iBACd,QACA,QACQ;AACR,SAAO,OAAO,SAAS,YAClB,OAAO,eAAe,OAAO,UAC7B,OAAO,OAAO,OAAO;AAC5B;AAOA,eAAsB,WACpB,MAC2B;AAC3B,QAAM,SAAqB,MAAME,YAAW;AAAA,IAC1C,KAAK,KAAK;AAAA,IACV,YAAY,KAAK;AAAA,EACnB,CAAC;AACD,QAAM,SAAS,MAAMC,KAAI,OAAO,QAAQ;AAAA,IACtC,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,EACf,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,OAAO;AAAA,IACf,YAAY,OAAO;AAAA,IACnB,SAAS,OAAO;AAAA,EAClB;AACF;AAEO,IAAM,kBAAkBC,eAAc;AAAA,EAC3C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,GAAG;AAAA,IACH,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,WAAW,IAAI,gBAAgB,EAAE,OAAO,QAAQ,KAAK,KAAK,EAAE,CAAC;AACnE,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,aAAa,KAAK,UAAU;AAElC,QAAI,KAAK,OAAO;AACd,YAAM,YAAY,EAAE,KAAK,YAAY,SAAS,CAAC;AAC/C;AAAA,IACF;AAEA,UAAM,SAAS,QAAQ,KAAK,SAAS,CAAC;AACtC,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,WAAW;AAAA,MAC1C;AAAA,MACA;AAAA,MACA,OAAO,CAAC;AAAA,MACR;AAAA,IACF,CAAC;AAED,QAAI,QAAQ;AACV,eAAS,KAAK,YAAY,OAAO,MAAM,MAAM,yBAAyB;AACtE;AAAA,IACF;AAEA,UAAM,OAAO,OAAO,QACjB,IAAI,CAAC,WAAWC,UAAS,KAAK,iBAAiB,QAAQ,MAAM,CAAC,CAAC,EAC/D,KAAK,IAAI;AACZ,aAAS,KAAK,SAAS,OAAO,MAAM,MAAM,aAAa,IAAI,EAAE;AAAA,EAC/D;AACF,CAAC;;;AGpGD,SAAS,cAAAC,aAAY,oBAAoB;AACzC,SAAS,OAAO,iBAAiB;AACjC,SAAS,SAAS,YAAAC,WAAU,WAAAC,gBAAe;AAC3C,SAAS,iBAAiB,gCAAgC;AAC1D,SAAS,iBAAAC,sBAAqB;AAW9B,SAAS,eAAe,UAA2B;AACjD,MAAI,MAAMC,SAAQ,QAAQ;AAC1B,SAAO,MAAM;AACX,UAAM,UAAUA,SAAQ,KAAK,cAAc;AAC3C,QAAIC,YAAW,OAAO,GAAG;AACvB,UAAIA,YAAWD,SAAQ,KAAK,qBAAqB,CAAC,GAAG;AACnD,eAAO;AAAA,MACT;AACA,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,aAAa,SAAS,MAAM,CAAC;AAGpD,cAAM,KAAK,IAAI;AACf,YACE,MAAM,QAAQ,EAAE,KACf,OAAO,OAAO,YACb,OAAO,QACP,MAAM,QAAS,GAA8B,QAAQ,GACvD;AACA,iBAAO;AAAA,QACT;AAAA,MACF,QAAQ;AAAA,MAER;AACA,aAAO;AAAA,IACT;AACA,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,KAAK;AAClB,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEO,IAAM,cAAcE,eAAc;AAAA,EACvC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,GAAG;AAAA,IACH,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,aACE;AAAA,MACF,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,WAAW,IAAI,gBAAgB,EAAE,OAAO,QAAQ,KAAK,KAAK,EAAE,CAAC;AACnE,UAAM,MAAM,QAAQ,IAAI;AAExB,UAAM,SAAS,KAAK,SAChBF,SAAQ,KAAK,KAAK,MAAM,IACxBA,SAAQ,KAAK,gBAAgB;AAEjC,QAAIC,YAAW,MAAM,KAAK,CAAC,KAAK,OAAO;AACrC,YAAM,IAAI,kBAAkB,MAAM;AAAA,IACpC;AAIA,UAAM,WACJ,OAAO,KAAK,aAAa,YAAY,KAAK,WAAW,eAAe,GAAG;AAEzE,UAAM,MAAM,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,UAAM;AAAA,MACJ;AAAA,MACA,WAAW,2BAA2B;AAAA,MACtC;AAAA,IACF;AAEA,UAAM,OAAOE,UAAS,KAAK,MAAM,KAAK;AACtC,aAAS;AAAA,MACP,WAAW,WAAW,IAAI,uBAAuB,WAAW,IAAI;AAAA,IAClE;AAAA,EACF;AACF,CAAC;;;ACrGD,SAAS,iBAAAC,sBAAqB;AAKvB,IAAM,kBAAkBC,eAAc;AAAA,EAC3C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM,EAAE,GAAG,WAAW;AAAA,EACtB,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,WAAW,IAAI,gBAAgB,EAAE,OAAO,QAAQ,KAAK,KAAK,EAAE,CAAC;AACnE,UAAM,WAAW;AAAA,MACf,KAAK,QAAQ,IAAI;AAAA,MACjB,YAAY,KAAK,UAAU;AAAA,MAC3B,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AACD,aAAS,KAAK,6BAA6B;AAAA,EAC7C;AACF,CAAC;;;ATTD,IAAM,UACJ,OAAuC,UAAmB;AAE5D,IAAM,cAAc;AAAA,EAClB,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,OAAO;AACT;AAEA,IAAM,OAAOC,eAAc;AAAA,EACzB,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA;AACF,CAAC;AAED,eAAsB,OAAO,MAA+B;AAC1D,QAAM,WAAW,IAAI,gBAAgB;AAAA,IACnC,OAAO,KAAK,SAAS,SAAS,KAAK,QAAQ,QAAQ,IAAI,UAAU;AAAA,EACnE,CAAC;AAED,MAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,IAAI,GAAG;AACrD,YAAQ,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AACnC,YAAQ,aAAa;AACrB;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,KAAK,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;AACvE,UAAM,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC;AAC/C,UAAM,QAAQ,QAAQ,UAAa,OAAO;AAC1C,UAAM,MACJ,QAAQ,YAAY,GAA+B,IAAI;AAEzD,YAAQ,OAAO;AAAA,MACb,GAAG,MAAM,YAAY,KAAK,QAAS,OAAsB,MAAS,CAAC;AAAA;AAAA,IACrE;AACA,YAAQ,aAAa;AACrB;AAAA,EACF;AAEA,MAAI;AACF,UAAM,WAAW,MAAM,EAAE,SAAS,KAAK,CAAC;AACxC,YAAQ,aAAa;AAAA,EACvB,SAAS,OAAO;AACd,QAAI,iBAAiBC,YAAW;AAC9B,eAAS,MAAM,YAAY,KAAK,CAAC;AACjC,cAAQ,WAAW;AAAA,IACrB,WAAW,iBAAiB,SAAS,MAAM,SAAS,YAAY;AAE9D,eAAS,MAAM,MAAM,OAAO;AAC5B,cAAQ,WAAW;AAAA,IACrB,OAAO;AACL,eAAS,MAAM,iCAAiC;AAChD,cAAQ,MAAM,KAAK;AACnB,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF;AACF;;;AUvEA,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC,CAAC;","names":["TakoError","defineCommand","existsSync","existsSync","relative","loadConfig","run","defineCommand","TakoError","path","loadConfig","run","path","TakoError","loadConfig","run","defineCommand","relative","existsSync","relative","resolve","defineCommand","resolve","existsSync","defineCommand","relative","defineCommand","defineCommand","defineCommand","TakoError"]}
|
package/dist/index.cjs
CHANGED
|
@@ -209,7 +209,7 @@ var ConsoleReporter = class {
|
|
|
209
209
|
}
|
|
210
210
|
write(level, msg, meta) {
|
|
211
211
|
const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : "tako";
|
|
212
|
-
const detail = meta === void 0 ? "" : ` ${formatMeta(meta)}`;
|
|
212
|
+
const detail = meta === void 0 || !this.showDebug ? "" : ` ${formatMeta(meta)}`;
|
|
213
213
|
this.stream.write(`${prefix} ${msg}${detail}
|
|
214
214
|
`);
|
|
215
215
|
}
|
|
@@ -650,7 +650,7 @@ var validateCommand = (0, import_citty4.defineCommand)({
|
|
|
650
650
|
});
|
|
651
651
|
|
|
652
652
|
// src/cli.ts
|
|
653
|
-
var VERSION = true ? "0.1.
|
|
653
|
+
var VERSION = true ? "0.1.2" : "0.0.0-dev";
|
|
654
654
|
var subCommands = {
|
|
655
655
|
init: initCommand,
|
|
656
656
|
generate: generateCommand,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/commands/check.ts","../src/args.ts","../src/diff.ts","../src/reporter.ts","../src/commands/generate.ts","../src/watch.ts","../src/errors.ts","../src/commands/init.ts","../src/commands/validate.ts"],"sourcesContent":["/**\n * `@kurotako/cli` — the `tako` binary. This barrel is the programmatic surface:\n * `runCli()` plus the reporter / error helpers, for embedders and tests.\n */\nexport { runCli } from './cli.js';\nexport {\n type ComparePlanToDiskArgs,\n comparePlanToDisk,\n type DriftEntry,\n type DriftKind,\n} from './diff.js';\nexport { ConfigExistsError, renderError } from './errors.js';\nexport { ConsoleReporter, type ConsoleReporterOptions } from './reporter.js';\n","/**\n * `runCli()` — build the citty command tree, dispatch, map every `TakoError` to\n * a formatted message + exit 1. `--version` / `--help` are handled here (citty's\n * own handling lives in `runMain`, which hard-exits — not what a testable\n * `runCli` wants).\n *\n * `backlog/features/cli/technical.md` §Command surface, §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\nimport { type CommandDef, defineCommand, renderUsage, runCommand } from 'citty';\nimport { checkCommand } from './commands/check.js';\nimport { generateCommand } from './commands/generate.js';\nimport { initCommand } from './commands/init.js';\nimport { validateCommand } from './commands/validate.js';\nimport { renderError } from './errors.js';\nimport { ConsoleReporter } from './reporter.js';\n\ndeclare const __TAKO_VERSION__: string;\nconst VERSION =\n typeof __TAKO_VERSION__ === 'string' ? __TAKO_VERSION__ : '0.0.0-dev';\n\nconst subCommands = {\n init: initCommand,\n generate: generateCommand,\n validate: validateCommand,\n check: checkCommand,\n};\n\nconst main = defineCommand({\n meta: {\n name: 'tako',\n version: VERSION,\n description: 'synchronise TypeScript schemas from data model to forms',\n },\n subCommands,\n});\n\nexport async function runCli(argv: string[]): Promise<void> {\n const reporter = new ConsoleReporter({\n debug: argv.includes('--debug') || Boolean(process.env.TAKO_DEBUG),\n });\n\n if (argv.includes('--version') || argv.includes('-v')) {\n process.stdout.write(`${VERSION}\\n`);\n process.exitCode ??= 0;\n return;\n }\n\n if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {\n const sub = argv.find((a) => !a.startsWith('-'));\n const isSub = sub !== undefined && sub in subCommands;\n const cmd = (\n isSub ? subCommands[sub as keyof typeof subCommands] : main\n ) as CommandDef;\n process.stdout.write(\n `${await renderUsage(cmd, isSub ? (main as CommandDef) : undefined)}\\n`,\n );\n process.exitCode ??= 0;\n return;\n }\n\n try {\n await runCommand(main, { rawArgs: argv });\n process.exitCode ??= 0;\n } catch (error) {\n if (error instanceof TakoError) {\n reporter.error(renderError(error));\n process.exitCode = 1;\n } else if (error instanceof Error && error.name === 'CLIError') {\n // citty usage error (unknown command, missing argument, …).\n reporter.error(error.message);\n process.exitCode = 1;\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n process.exitCode = 1;\n }\n }\n}\n","/**\n * `tako check` — drift guard. Runs the pipeline in plan mode (no disk writes,\n * no `afterEmit`), then compares the planned tree against what is on disk.\n * Exit 0 when they match, exit 1 on any drift or any `TakoError` (the latter\n * via the top-level handler in `cli.ts`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §Command surface.\n */\nimport { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { loadConfig } from '@kurotako/config';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport {\n comparePlanToDisk,\n type DriftEntry,\n ignoreBuildArtifacts,\n markedPackageDirs,\n} from '../diff.js';\nimport { ConsoleReporter } from '../reporter.js';\n\nexport const checkCommand = defineCommand({\n meta: {\n name: 'check',\n description:\n 'check the generated output on disk matches a fresh generate (drift guard)',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n\n const { config } = await loadConfig({\n cwd,\n configPath: args.config || undefined,\n });\n const { plan = [] } = await run(config, { logger: reporter, plan: true });\n\n const roots: string[] = [];\n const ignores: ((absPath: string) => boolean)[] = [];\n\n for (const output of config.outputs) {\n if (output.mode === 'package') {\n ignores.push(ignoreBuildArtifacts);\n if (output.packagesDir) {\n roots.push(...(await markedPackageDirs(output.packagesDir)));\n }\n } else {\n const dir = output.dir;\n if (!dir) {\n continue;\n }\n if (!existsSync(dir)) {\n reporter.info(\n `output directory ${relative(config.rootDir, dir)} does not exist — run tako generate`,\n );\n process.exitCode = 1;\n return;\n }\n roots.push(dir);\n }\n }\n\n const ignore = (absPath: string): boolean =>\n ignores.some((fn) => fn(absPath));\n\n const drift = await comparePlanToDisk({\n plan,\n roots,\n ignore,\n rootDir: config.rootDir,\n });\n\n if (drift.length === 0) {\n reporter.info('output is in sync');\n process.exitCode ??= 0;\n return;\n }\n\n reporter.error(formatDrift(drift));\n process.exitCode = 1;\n },\n});\n\nfunction formatDrift(drift: DriftEntry[]): string {\n const width = Math.max(...drift.map((entry) => entry.kind.length));\n const lines = drift.map(\n (entry) => ` ${entry.kind.padEnd(width)} ${entry.path}`,\n );\n return [\n 'drift detected',\n '',\n ...lines,\n '',\n `${drift.length} files differ from a fresh generate. Run \\`tako generate\\`.`,\n ].join('\\n');\n}\n","/**\n * `sharedArgs` — the options every sub-command carries. citty has no\n * first-class global-option slot, so this object is spread into each command's\n * `args` (`backlog/features/cli/technical.md` §Global option).\n */\nimport type { ArgsDef } from 'citty';\n\nexport const sharedArgs = {\n config: {\n type: 'string',\n description: 'path to the tako config file (default: ./tako.config.ts)',\n },\n /** Hidden: not advertised, kept minimal. Enables `debug` reporter output. */\n debug: {\n type: 'boolean',\n default: false,\n },\n} as const satisfies ArgsDef;\n","/**\n * `comparePlanToDisk` — the in-memory comparison behind `tako check`. Takes the\n * `PlannedFile[]` a fresh `generate` would write (from `run({ plan: true })`)\n * and reports every way the tree on disk diverges from it: a planned file that\n * is absent (`missing`) or whose bytes differ (`modified`), and any file under\n * the scanned roots that no planned file claims (`orphan`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §The comparison.\n */\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PlannedFile } from '@kurotako/core';\n\nexport type DriftKind = 'modified' | 'missing' | 'orphan';\n\nexport interface DriftEntry {\n kind: DriftKind;\n /** Relative to `rootDir`, POSIX separators; a collapsed dir ends with `/`. */\n path: string;\n}\n\nexport interface ComparePlanToDiskArgs {\n plan: PlannedFile[];\n /** Directories walked for orphans (absolute). */\n roots: string[];\n /** Return `true` to exclude an absolute path from the orphan scan. */\n ignore: (absPath: string) => boolean;\n /** Anchor for the reported relative paths (the config-file directory). */\n rootDir: string;\n}\n\nfunction toPosix(rootDir: string, absPath: string): string {\n return path.relative(rootDir, absPath).split(path.sep).join('/');\n}\n\nexport async function comparePlanToDisk(\n args: ComparePlanToDiskArgs,\n): Promise<DriftEntry[]> {\n const { plan, roots, ignore, rootDir } = args;\n const plannedByPath = new Map(plan.map((f) => [path.resolve(f.path), f]));\n const entries: DriftEntry[] = [];\n\n // 1. Expected vs disk.\n for (const [absPath, file] of plannedByPath) {\n if (!existsSync(absPath)) {\n entries.push({ kind: 'missing', path: toPosix(rootDir, absPath) });\n continue;\n }\n const onDisk = await readFile(absPath, 'utf8');\n if (onDisk !== file.content) {\n entries.push({ kind: 'modified', path: toPosix(rootDir, absPath) });\n }\n }\n\n // 2. Orphan scan — a planned file lives under `dir` iff any planned absolute\n // path is `dir` itself or sits below it.\n const plannedPaths = [...plannedByPath.keys()];\n const hasPlannedUnder = (dir: string): boolean => {\n const prefix = `${dir}${path.sep}`;\n return plannedPaths.some((p) => p === dir || p.startsWith(prefix));\n };\n\n const seenRoots = new Set<string>();\n for (const root of roots) {\n const absRoot = path.resolve(root);\n if (seenRoots.has(absRoot) || !existsSync(absRoot)) {\n continue;\n }\n seenRoots.add(absRoot);\n await scan(absRoot);\n }\n\n async function scan(dir: string): Promise<void> {\n // A directory with no planned file underneath collapses to a single entry —\n // unless it holds nothing but ignored files (e.g. only `dist/`).\n if (!hasPlannedUnder(dir)) {\n if (await hasNonIgnoredFile(dir)) {\n entries.push({ kind: 'orphan', path: `${toPosix(rootDir, dir)}/` });\n }\n return;\n }\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isDirectory()) {\n await scan(abs);\n } else if (dirent.isFile() && !plannedByPath.has(abs)) {\n entries.push({ kind: 'orphan', path: toPosix(rootDir, abs) });\n }\n }\n }\n\n async function hasNonIgnoredFile(dir: string): Promise<boolean> {\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isFile()) {\n return true;\n }\n if (dirent.isDirectory() && (await hasNonIgnoredFile(abs))) {\n return true;\n }\n }\n return false;\n }\n\n entries.sort((a, b) =>\n a.path < b.path\n ? -1\n : a.path > b.path\n ? 1\n : a.kind < b.kind\n ? -1\n : a.kind > b.kind\n ? 1\n : 0,\n );\n return entries;\n}\n\n/** Rejects `dist/` and `node_modules/` anywhere in the path (mode B). */\nexport function ignoreBuildArtifacts(absPath: string): boolean {\n return /(^|[/\\\\])(dist|node_modules)([/\\\\]|$)/.test(absPath);\n}\n\n/**\n * Whether `<packagesDir>/<name>` looks like a directory `tako` generated: a\n * `package.json` whose `\"//\"` marker starts with `Generated by tako`.\n */\nexport async function hasGeneratedMarker(pkgDir: string): Promise<boolean> {\n try {\n const pkg = JSON.parse(\n await readFile(path.join(pkgDir, 'package.json'), 'utf8'),\n ) as { '//'?: unknown };\n return (\n typeof pkg['//'] === 'string' && pkg['//'].startsWith('Generated by tako')\n );\n } catch {\n return false;\n }\n}\n\n/** Every immediate subdirectory of `packagesDir` carrying the tako marker. */\nexport async function markedPackageDirs(\n packagesDir: string,\n): Promise<string[]> {\n if (!existsSync(packagesDir)) {\n return [];\n }\n const out: string[] = [];\n for (const dirent of await readdir(packagesDir, { withFileTypes: true })) {\n if (!dirent.isDirectory()) {\n continue;\n }\n const abs = path.join(packagesDir, dirent.name);\n if (await hasGeneratedMarker(abs)) {\n out.push(abs);\n }\n }\n return out.sort();\n}\n","/**\n * `ConsoleReporter` — the `@kurotako/core` `Logger` the CLI injects into\n * `loadConfig()` / `run()`, plus the per-phase / summary output.\n *\n * Contract (`backlog/features/cli/technical.md` §Reporter):\n * - human output goes to **stderr**, `stdout` stays clean;\n * - `info` / `warn` / `error` shown by default; `debug` only with `--debug` /\n * `TAKO_DEBUG` (a hidden flag, not advertised);\n * - `tako ` prefix, level-coloured; colour auto-off when the stream is not a TTY\n * or `NO_COLOR` is set;\n * - `child(tag)` returns a `Logger` tagging every `meta` with `{ scope: tag }`.\n */\nimport { childLogger, type Logger } from '@kurotako/core';\n\ntype Level = 'debug' | 'info' | 'warn' | 'error';\n\n/** The slice of a writable stream the reporter needs (keeps tests trivial). */\nexport interface WriteStream {\n write(chunk: string): unknown;\n isTTY?: boolean;\n}\n\nexport interface ConsoleReporterOptions {\n /** Show `debug` output. Default: `false` unless `TAKO_DEBUG` is set. */\n debug?: boolean;\n /** Sink for human output. Default: `process.stderr`. */\n stream?: WriteStream;\n /** Force colour on/off. Default: auto (TTY and no `NO_COLOR`). */\n color?: boolean;\n}\n\nconst ESC = String.fromCharCode(27);\nconst ANSI: Record<Level, string> = {\n debug: `${ESC}[2m`, // dim\n info: `${ESC}[36m`, // cyan\n warn: `${ESC}[33m`, // yellow\n error: `${ESC}[31m`, // red\n};\nconst ANSI_RESET = `${ESC}[0m`;\n\nexport class ConsoleReporter implements Logger {\n private readonly stream: WriteStream;\n private readonly showDebug: boolean;\n private readonly color: boolean;\n\n constructor(options: ConsoleReporterOptions = {}) {\n this.stream = options.stream ?? process.stderr;\n this.showDebug = options.debug ?? Boolean(process.env.TAKO_DEBUG);\n this.color =\n options.color ??\n (Boolean(this.stream.isTTY) && process.env.NO_COLOR === undefined);\n }\n\n debug(msg: string, meta?: unknown): void {\n if (this.showDebug) {\n this.write('debug', msg, meta);\n }\n }\n\n info(msg: string, meta?: unknown): void {\n this.write('info', msg, meta);\n }\n\n warn(msg: string, meta?: unknown): void {\n this.write('warn', msg, meta);\n }\n\n error(msg: string, meta?: unknown): void {\n this.write('error', msg, meta);\n }\n\n /** A child `Logger` whose calls carry `{ scope: tag }` in `meta`. */\n child(tag: string): Logger {\n return childLogger(this, { scope: tag });\n }\n\n private write(level: Level, msg: string, meta?: unknown): void {\n const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : 'tako';\n const detail = meta === undefined ? '' : ` ${formatMeta(meta)}`;\n this.stream.write(`${prefix} ${msg}${detail}\\n`);\n }\n}\n\nfunction formatMeta(meta: unknown): string {\n if (meta !== null && typeof meta === 'object' && !Array.isArray(meta)) {\n return Object.entries(meta as Record<string, unknown>)\n .map(([k, v]) => `${k}=${stringify(v)}`)\n .join(' ');\n }\n return stringify(meta);\n}\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","/**\n * `tako generate` — `loadConfig()` then `run()`. `--dry-run` runs everything but\n * skips the Writer; `--watch` hands off to the chokidar loop\n * (`backlog/features/cli/technical.md` §`tako generate`).\n */\nimport { relative } from 'node:path';\nimport { type LoadResult, loadConfig } from '@kurotako/config';\nimport type { OutputConfig, ResolvedConfig, RunResult } from '@kurotako/core';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { watchAndRun } from '../watch.js';\n\nexport interface LoadAndRunOptions {\n cwd: string;\n configPath?: string;\n write: boolean;\n signal?: AbortSignal;\n reporter: ConsoleReporter;\n}\n\nexport interface LoadAndRunResult {\n result: RunResult;\n config: ResolvedConfig;\n configFile: string;\n rootDir: string;\n}\n\n/** The directory named in the `wrote N files -> …` summary line, for one output. */\nexport function outputSummaryDir(\n output: OutputConfig,\n config: ResolvedConfig,\n): string {\n return output.mode === 'package'\n ? (output.packagesDir ?? config.rootDir)\n : (output.dir ?? config.rootDir);\n}\n\n/**\n * The shared body of `generate`, `validate` and each watch cycle: resolve +\n * load the config, then run the pipeline. `write: false` also skips the\n * `afterEmit` hook (`@kurotako/core` `run()`).\n */\nexport async function loadAndRun(\n opts: LoadAndRunOptions,\n): Promise<LoadAndRunResult> {\n const loaded: LoadResult = await loadConfig({\n cwd: opts.cwd,\n configPath: opts.configPath,\n });\n const result = await run(loaded.config, {\n logger: opts.reporter,\n write: opts.write,\n signal: opts.signal,\n });\n return {\n result,\n config: loaded.config,\n configFile: loaded.configFile,\n rootDir: loaded.rootDir,\n };\n}\n\nexport const generateCommand = defineCommand({\n meta: {\n name: 'generate',\n description: 'run the pipeline and write the generated code',\n },\n args: {\n ...sharedArgs,\n watch: {\n type: 'boolean',\n description: 'rebuild on every schema / config change',\n default: false,\n },\n 'dry-run': {\n type: 'boolean',\n description: 'run everything but write nothing',\n default: false,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n const configPath = args.config || undefined;\n\n if (args.watch) {\n await watchAndRun({ cwd, configPath, reporter });\n return;\n }\n\n const dryRun = Boolean(args['dry-run']);\n const { result, config } = await loadAndRun({\n cwd,\n configPath,\n write: !dryRun,\n reporter,\n });\n\n if (dryRun) {\n reporter.info(`dry run: ${result.files.length} files would be written`);\n return;\n }\n\n const dirs = config.outputs\n .map((output) => relative(cwd, outputSummaryDir(output, config)))\n .join(', ');\n reporter.info(`wrote ${result.files.length} files -> ${dirs}`);\n },\n});\n","/**\n * `tako generate --watch` — a chokidar loop around `loadConfig()` + `run()`.\n * Full regeneration on every change (no incremental). A 100 ms trailing\n * debounce coalesces bursts; a change mid-cycle aborts the in-flight `run()`\n * (via `RunOptions.signal`) and re-runs once it settles. `loadConfig` failures\n * are reported, not fatal — the watcher stays up on `tako.config.ts`.\n *\n * `backlog/features/cli/technical.md` §Watch mode.\n */\nimport { basename, resolve } from 'node:path';\nimport {\n type LoadResult,\n loadConfig as realLoadConfig,\n} from '@kurotako/config';\nimport { run as realRun, TakoError } from '@kurotako/core';\nimport chokidar from 'chokidar';\nimport { renderError } from './errors.js';\nimport type { ConsoleReporter } from './reporter.js';\n\n/** Minimal watcher seam so the loop is unit-testable without touching the fs. */\nexport interface Watcher {\n add(paths: string | readonly string[]): void;\n unwatch(paths: string | readonly string[]): void;\n on(handler: (event: string, path: string) => void): void;\n close(): Promise<void>;\n}\n\nexport interface WatchAndRunOptions {\n cwd: string;\n configPath?: string;\n reporter: ConsoleReporter;\n}\n\nexport interface WatchDeps {\n createWatcher: () => Watcher;\n loadConfig: typeof realLoadConfig;\n run: typeof realRun;\n debounceMs: number;\n}\n\nconst DEBOUNCE_MS = 100;\n\nfunction chokidarWatcher(): Watcher {\n const fsw = chokidar.watch([], {\n ignoreInitial: true,\n awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 20 },\n });\n return {\n add: (paths) => fsw.add(paths as string | string[]),\n unwatch: (paths) => fsw.unwatch(paths as string | string[]),\n on: (handler) => {\n fsw.on('add', (p) => handler('add', p));\n fsw.on('change', (p) => handler('change', p));\n fsw.on('unlink', (p) => handler('unlink', p));\n },\n close: () => fsw.close(),\n };\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError';\n}\n\n/**\n * Runs until `SIGINT` / `SIGTERM`, then closes the watcher and resolves so the\n * caller can exit 0. (The design doc types this `Promise<never>`; it resolves\n * on shutdown here purely so it stays testable.)\n */\nexport async function watchAndRun(\n opts: WatchAndRunOptions,\n deps: Partial<WatchDeps> = {},\n): Promise<void> {\n const { cwd, configPath, reporter } = opts;\n const createWatcher = deps.createWatcher ?? chokidarWatcher;\n const loadConfig = deps.loadConfig ?? realLoadConfig;\n const run = deps.run ?? realRun;\n const debounceMs = deps.debounceMs ?? DEBOUNCE_MS;\n\n const watcher = createWatcher();\n let watched = new Set<string>();\n let inFlight: AbortController | null = null;\n let queued = false;\n let closed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let reason = 'initial build';\n\n const guessedConfigFile = configPath\n ? resolve(cwd, configPath)\n : resolve(cwd, 'tako.config.ts');\n\n function applyWatchSet(desired: Set<string>): void {\n for (const path of desired) {\n if (!watched.has(path)) {\n watcher.add(path);\n }\n }\n for (const path of watched) {\n if (!desired.has(path)) {\n watcher.unwatch(path);\n }\n }\n watched = desired;\n }\n\n async function reconcileWatchSet(loaded: LoadResult): Promise<void> {\n const desired = new Set<string>([loaded.configFile]);\n for (const [namespace, source] of Object.entries(loaded.config.sources)) {\n const paths =\n (await source.parser.watchPaths?.({\n namespace,\n cwd: loaded.rootDir,\n logger: reporter,\n })) ?? [];\n for (const path of paths) {\n desired.add(resolve(loaded.rootDir, path));\n }\n }\n applyWatchSet(desired);\n }\n\n async function cycle(): Promise<void> {\n const why = reason;\n reporter.info(`--- rebuild (${why}) ---`);\n const ac = new AbortController();\n inFlight = ac;\n try {\n const loaded = await loadConfig({ cwd, configPath });\n await reconcileWatchSet(loaded);\n const result = await run(loaded.config, {\n logger: reporter,\n signal: ac.signal,\n write: true,\n });\n if (!ac.signal.aborted) {\n reporter.info(`wrote ${result.files.length} files`);\n }\n } catch (error) {\n if (isAbortError(error) || ac.signal.aborted) {\n // Superseded by a newer cycle — swallow.\n } else if (error instanceof TakoError) {\n reporter.error(renderError(error));\n // Keep watching at least the config file so a fix is picked up.\n applyWatchSet(new Set([...watched, guessedConfigFile]));\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n }\n } finally {\n inFlight = null;\n if (queued && !closed) {\n queued = false;\n await cycle();\n }\n }\n }\n\n function trigger(): void {\n if (inFlight) {\n queued = true;\n inFlight.abort();\n return;\n }\n void cycle();\n }\n\n function schedule(event: string, path: string): void {\n if (closed) {\n return;\n }\n reason = `${basename(path)} ${event === 'unlink' ? 'removed' : 'changed'}`;\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => {\n timer = null;\n trigger();\n }, debounceMs);\n }\n\n watcher.on(schedule);\n\n // Initial cycle: a failure is reported inside `cycle()`, never fatal.\n applyWatchSet(new Set([guessedConfigFile]));\n await cycle();\n reporter.info(`watching ${watched.size} paths`);\n\n await new Promise<void>((resolvePromise) => {\n const shutdown = () => {\n closed = true;\n if (timer) {\n clearTimeout(timer);\n }\n inFlight?.abort();\n process.off('SIGINT', shutdown);\n process.off('SIGTERM', shutdown);\n void watcher.close().finally(() => resolvePromise());\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n}\n","/**\n * CLI-owned error(s) and `renderError()` — the single formatter the top-level\n * handler in `cli.ts` uses for any `TakoError` (from `@kurotako/core`,\n * `@kurotako/config`, or this package).\n *\n * `backlog/features/cli/technical.md` §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\n\n/** `tako init` refuses to overwrite an existing config unless `--force`. */\nexport class ConfigExistsError extends TakoError {\n readonly path: string;\n\n constructor(path: string) {\n super(\n 'config_exists',\n `a config file already exists at '${path}' (pass --force to overwrite)`,\n );\n this.path = path;\n }\n}\n\ninterface Issue {\n path?: string;\n message?: string;\n}\n\n/**\n * `error [<code>]: <message>` plus any carried context on its own indented\n * lines: located issues (`ConfigShapeError`, `IrValidationError`,\n * `DriverOptionsError`), the offending driver / namespace (`DriverError`,\n * `UnknownNamespaceError`), the dependency cycle path (`DependencyCycleError`),\n * and the `cause` message of a wrapped failure.\n */\nexport function renderError(error: TakoError): string {\n const lines = [`error [${error.code}]: ${error.message}`];\n\n const issues = (error as { issues?: unknown }).issues;\n if (Array.isArray(issues)) {\n for (const issue of issues as Issue[]) {\n const at =\n issue.path === undefined || issue.path === '' ? '<root>' : issue.path;\n lines.push(` - ${at}: ${issue.message}`);\n }\n }\n\n const cycle = (error as { cycle?: unknown }).cycle;\n if (Array.isArray(cycle) && cycle.length > 0) {\n lines.push(` cycle: ${(cycle as string[]).join(' -> ')}`);\n }\n\n const driverName = (error as { driverName?: unknown }).driverName;\n if (typeof driverName === 'string') {\n const role = (error as { role?: unknown }).role;\n const namespace = (error as { namespace?: unknown }).namespace;\n const roleLabel = typeof role === 'string' ? role : 'driver';\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` ${roleLabel}: ${driverName}${where}`);\n } else {\n const generator = (error as { generator?: unknown }).generator;\n if (typeof generator === 'string') {\n const namespace = (error as { namespace?: unknown }).namespace;\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` generator: ${generator}${where}`);\n }\n }\n\n // Wrapped failures (`DriverError`, `HookError`, `ConfigLoadError`, …) carry the\n // real error in `cause`; core masks its type, so surface at least its message.\n const cause = error.cause;\n if (cause !== undefined && cause !== null) {\n const message = cause instanceof Error ? cause.message : String(cause);\n const code = cause instanceof TakoError ? ` [${cause.code}]` : '';\n lines.push(` cause${code}: ${message}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * `tako init` — write the commented `tako.config.ts` skeleton into the current\n * directory. No prompts, no schema auto-detection; refuses to overwrite unless\n * `--force` (`backlog/features/cli/technical.md` §`tako init`).\n *\n * `--monorepo` / `--no-monorepo` picks between `CONFIG_TEMPLATE` and\n * `CONFIG_TEMPLATE_MONOREPO`; unset, it auto-detects a workspace by walking up\n * for the nearest `package.json` (`workspaces` key, or a sibling\n * `pnpm-workspace.yaml`).\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, relative, resolve } from 'node:path';\nimport { CONFIG_TEMPLATE, CONFIG_TEMPLATE_MONOREPO } from '@kurotako/config';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConfigExistsError } from '../errors.js';\nimport { ConsoleReporter } from '../reporter.js';\n\n/**\n * Walk up from `startDir` to the first directory holding a `package.json`. A\n * workspace when that `package.json` has a `workspaces` key (array, or\n * `{ packages: [...] }`), or when a `pnpm-workspace.yaml` sits next to it.\n * Returns `false` when no `package.json` is found.\n */\nfunction detectMonorepo(startDir: string): boolean {\n let dir = resolve(startDir);\n while (true) {\n const pkgPath = resolve(dir, 'package.json');\n if (existsSync(pkgPath)) {\n if (existsSync(resolve(dir, 'pnpm-workspace.yaml'))) {\n return true;\n }\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n workspaces?: unknown;\n };\n const ws = pkg.workspaces;\n if (\n Array.isArray(ws) ||\n (typeof ws === 'object' &&\n ws !== null &&\n Array.isArray((ws as { packages?: unknown }).packages))\n ) {\n return true;\n }\n } catch {\n // Unreadable / invalid package.json: treat as not a workspace.\n }\n return false;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return false;\n }\n dir = parent;\n }\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: 'init',\n description: 'create a tako.config.ts in the current directory',\n },\n args: {\n ...sharedArgs,\n force: {\n type: 'boolean',\n description: 'overwrite an existing config file',\n default: false,\n },\n monorepo: {\n type: 'boolean',\n description:\n 'write the monorepo config layout (auto-detected from workspaces when unset)',\n default: undefined,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n // Unlike `loadConfig`, `init` never walks up: it always targets `cwd`.\n const target = args.config\n ? resolve(cwd, args.config)\n : resolve(cwd, 'tako.config.ts');\n\n if (existsSync(target) && !args.force) {\n throw new ConfigExistsError(target);\n }\n\n // citty leaves an unset boolean flag `undefined` (no `default`), so\n // `--monorepo` / `--no-monorepo` win and absence falls back to detection.\n const monorepo: boolean =\n typeof args.monorepo === 'boolean' ? args.monorepo : detectMonorepo(cwd);\n\n await mkdir(dirname(target), { recursive: true });\n await writeFile(\n target,\n monorepo ? CONFIG_TEMPLATE_MONOREPO : CONFIG_TEMPLATE,\n 'utf8',\n );\n\n const name = relative(cwd, target) || 'tako.config.ts';\n reporter.info(\n monorepo ? `created ${name} (monorepo layout)` : `created ${name}`,\n );\n },\n});\n","/**\n * `tako validate` — the same checks as `generate` up to (not including)\n * emission. `loadConfig()` + `run({ write: false })`; any `TakoError` propagates\n * to the top-level handler and exits 1\n * (`backlog/features/cli/technical.md` §`tako validate`).\n */\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { loadAndRun } from './generate.js';\n\nexport const validateCommand = defineCommand({\n meta: {\n name: 'validate',\n description: 'check the config and schema without writing anything',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n await loadAndRun({\n cwd: process.cwd(),\n configPath: args.config || undefined,\n write: false,\n reporter,\n });\n reporter.info('config and schema are valid');\n },\n});\n"],"mappings":"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","names":["import_core","import_citty","import_node_fs","import_node_path","import_core","path","import_node_path","import_config","import_core","import_citty","import_node_path","import_config","import_core","import_core","path","chokidar","loadConfig","realLoadConfig","run","realRun","path","import_node_fs","import_promises","import_node_path","import_config","import_citty","import_citty"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/commands/check.ts","../src/args.ts","../src/diff.ts","../src/reporter.ts","../src/commands/generate.ts","../src/watch.ts","../src/errors.ts","../src/commands/init.ts","../src/commands/validate.ts"],"sourcesContent":["/**\n * `@kurotako/cli` — the `tako` binary. This barrel is the programmatic surface:\n * `runCli()` plus the reporter / error helpers, for embedders and tests.\n */\nexport { runCli } from './cli.js';\nexport {\n type ComparePlanToDiskArgs,\n comparePlanToDisk,\n type DriftEntry,\n type DriftKind,\n} from './diff.js';\nexport { ConfigExistsError, renderError } from './errors.js';\nexport { ConsoleReporter, type ConsoleReporterOptions } from './reporter.js';\n","/**\n * `runCli()` — build the citty command tree, dispatch, map every `TakoError` to\n * a formatted message + exit 1. `--version` / `--help` are handled here (citty's\n * own handling lives in `runMain`, which hard-exits — not what a testable\n * `runCli` wants).\n *\n * `backlog/features/cli/technical.md` §Command surface, §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\nimport { type CommandDef, defineCommand, renderUsage, runCommand } from 'citty';\nimport { checkCommand } from './commands/check.js';\nimport { generateCommand } from './commands/generate.js';\nimport { initCommand } from './commands/init.js';\nimport { validateCommand } from './commands/validate.js';\nimport { renderError } from './errors.js';\nimport { ConsoleReporter } from './reporter.js';\n\ndeclare const __TAKO_VERSION__: string;\nconst VERSION =\n typeof __TAKO_VERSION__ === 'string' ? __TAKO_VERSION__ : '0.0.0-dev';\n\nconst subCommands = {\n init: initCommand,\n generate: generateCommand,\n validate: validateCommand,\n check: checkCommand,\n};\n\nconst main = defineCommand({\n meta: {\n name: 'tako',\n version: VERSION,\n description: 'synchronise TypeScript schemas from data model to forms',\n },\n subCommands,\n});\n\nexport async function runCli(argv: string[]): Promise<void> {\n const reporter = new ConsoleReporter({\n debug: argv.includes('--debug') || Boolean(process.env.TAKO_DEBUG),\n });\n\n if (argv.includes('--version') || argv.includes('-v')) {\n process.stdout.write(`${VERSION}\\n`);\n process.exitCode ??= 0;\n return;\n }\n\n if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {\n const sub = argv.find((a) => !a.startsWith('-'));\n const isSub = sub !== undefined && sub in subCommands;\n const cmd = (\n isSub ? subCommands[sub as keyof typeof subCommands] : main\n ) as CommandDef;\n process.stdout.write(\n `${await renderUsage(cmd, isSub ? (main as CommandDef) : undefined)}\\n`,\n );\n process.exitCode ??= 0;\n return;\n }\n\n try {\n await runCommand(main, { rawArgs: argv });\n process.exitCode ??= 0;\n } catch (error) {\n if (error instanceof TakoError) {\n reporter.error(renderError(error));\n process.exitCode = 1;\n } else if (error instanceof Error && error.name === 'CLIError') {\n // citty usage error (unknown command, missing argument, …).\n reporter.error(error.message);\n process.exitCode = 1;\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n process.exitCode = 1;\n }\n }\n}\n","/**\n * `tako check` — drift guard. Runs the pipeline in plan mode (no disk writes,\n * no `afterEmit`), then compares the planned tree against what is on disk.\n * Exit 0 when they match, exit 1 on any drift or any `TakoError` (the latter\n * via the top-level handler in `cli.ts`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §Command surface.\n */\nimport { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { loadConfig } from '@kurotako/config';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport {\n comparePlanToDisk,\n type DriftEntry,\n ignoreBuildArtifacts,\n markedPackageDirs,\n} from '../diff.js';\nimport { ConsoleReporter } from '../reporter.js';\n\nexport const checkCommand = defineCommand({\n meta: {\n name: 'check',\n description:\n 'check the generated output on disk matches a fresh generate (drift guard)',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n\n const { config } = await loadConfig({\n cwd,\n configPath: args.config || undefined,\n });\n const { plan = [] } = await run(config, { logger: reporter, plan: true });\n\n const roots: string[] = [];\n const ignores: ((absPath: string) => boolean)[] = [];\n\n for (const output of config.outputs) {\n if (output.mode === 'package') {\n ignores.push(ignoreBuildArtifacts);\n if (output.packagesDir) {\n roots.push(...(await markedPackageDirs(output.packagesDir)));\n }\n } else {\n const dir = output.dir;\n if (!dir) {\n continue;\n }\n if (!existsSync(dir)) {\n reporter.info(\n `output directory ${relative(config.rootDir, dir)} does not exist — run tako generate`,\n );\n process.exitCode = 1;\n return;\n }\n roots.push(dir);\n }\n }\n\n const ignore = (absPath: string): boolean =>\n ignores.some((fn) => fn(absPath));\n\n const drift = await comparePlanToDisk({\n plan,\n roots,\n ignore,\n rootDir: config.rootDir,\n });\n\n if (drift.length === 0) {\n reporter.info('output is in sync');\n process.exitCode ??= 0;\n return;\n }\n\n reporter.error(formatDrift(drift));\n process.exitCode = 1;\n },\n});\n\nfunction formatDrift(drift: DriftEntry[]): string {\n const width = Math.max(...drift.map((entry) => entry.kind.length));\n const lines = drift.map(\n (entry) => ` ${entry.kind.padEnd(width)} ${entry.path}`,\n );\n return [\n 'drift detected',\n '',\n ...lines,\n '',\n `${drift.length} files differ from a fresh generate. Run \\`tako generate\\`.`,\n ].join('\\n');\n}\n","/**\n * `sharedArgs` — the options every sub-command carries. citty has no\n * first-class global-option slot, so this object is spread into each command's\n * `args` (`backlog/features/cli/technical.md` §Global option).\n */\nimport type { ArgsDef } from 'citty';\n\nexport const sharedArgs = {\n config: {\n type: 'string',\n description: 'path to the tako config file (default: ./tako.config.ts)',\n },\n /** Hidden: not advertised, kept minimal. Enables `debug` reporter output. */\n debug: {\n type: 'boolean',\n default: false,\n },\n} as const satisfies ArgsDef;\n","/**\n * `comparePlanToDisk` — the in-memory comparison behind `tako check`. Takes the\n * `PlannedFile[]` a fresh `generate` would write (from `run({ plan: true })`)\n * and reports every way the tree on disk diverges from it: a planned file that\n * is absent (`missing`) or whose bytes differ (`modified`), and any file under\n * the scanned roots that no planned file claims (`orphan`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §The comparison.\n */\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PlannedFile } from '@kurotako/core';\n\nexport type DriftKind = 'modified' | 'missing' | 'orphan';\n\nexport interface DriftEntry {\n kind: DriftKind;\n /** Relative to `rootDir`, POSIX separators; a collapsed dir ends with `/`. */\n path: string;\n}\n\nexport interface ComparePlanToDiskArgs {\n plan: PlannedFile[];\n /** Directories walked for orphans (absolute). */\n roots: string[];\n /** Return `true` to exclude an absolute path from the orphan scan. */\n ignore: (absPath: string) => boolean;\n /** Anchor for the reported relative paths (the config-file directory). */\n rootDir: string;\n}\n\nfunction toPosix(rootDir: string, absPath: string): string {\n return path.relative(rootDir, absPath).split(path.sep).join('/');\n}\n\nexport async function comparePlanToDisk(\n args: ComparePlanToDiskArgs,\n): Promise<DriftEntry[]> {\n const { plan, roots, ignore, rootDir } = args;\n const plannedByPath = new Map(plan.map((f) => [path.resolve(f.path), f]));\n const entries: DriftEntry[] = [];\n\n // 1. Expected vs disk.\n for (const [absPath, file] of plannedByPath) {\n if (!existsSync(absPath)) {\n entries.push({ kind: 'missing', path: toPosix(rootDir, absPath) });\n continue;\n }\n const onDisk = await readFile(absPath, 'utf8');\n if (onDisk !== file.content) {\n entries.push({ kind: 'modified', path: toPosix(rootDir, absPath) });\n }\n }\n\n // 2. Orphan scan — a planned file lives under `dir` iff any planned absolute\n // path is `dir` itself or sits below it.\n const plannedPaths = [...plannedByPath.keys()];\n const hasPlannedUnder = (dir: string): boolean => {\n const prefix = `${dir}${path.sep}`;\n return plannedPaths.some((p) => p === dir || p.startsWith(prefix));\n };\n\n const seenRoots = new Set<string>();\n for (const root of roots) {\n const absRoot = path.resolve(root);\n if (seenRoots.has(absRoot) || !existsSync(absRoot)) {\n continue;\n }\n seenRoots.add(absRoot);\n await scan(absRoot);\n }\n\n async function scan(dir: string): Promise<void> {\n // A directory with no planned file underneath collapses to a single entry —\n // unless it holds nothing but ignored files (e.g. only `dist/`).\n if (!hasPlannedUnder(dir)) {\n if (await hasNonIgnoredFile(dir)) {\n entries.push({ kind: 'orphan', path: `${toPosix(rootDir, dir)}/` });\n }\n return;\n }\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isDirectory()) {\n await scan(abs);\n } else if (dirent.isFile() && !plannedByPath.has(abs)) {\n entries.push({ kind: 'orphan', path: toPosix(rootDir, abs) });\n }\n }\n }\n\n async function hasNonIgnoredFile(dir: string): Promise<boolean> {\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isFile()) {\n return true;\n }\n if (dirent.isDirectory() && (await hasNonIgnoredFile(abs))) {\n return true;\n }\n }\n return false;\n }\n\n entries.sort((a, b) =>\n a.path < b.path\n ? -1\n : a.path > b.path\n ? 1\n : a.kind < b.kind\n ? -1\n : a.kind > b.kind\n ? 1\n : 0,\n );\n return entries;\n}\n\n/** Rejects `dist/` and `node_modules/` anywhere in the path (mode B). */\nexport function ignoreBuildArtifacts(absPath: string): boolean {\n return /(^|[/\\\\])(dist|node_modules)([/\\\\]|$)/.test(absPath);\n}\n\n/**\n * Whether `<packagesDir>/<name>` looks like a directory `tako` generated: a\n * `package.json` whose `\"//\"` marker starts with `Generated by tako`.\n */\nexport async function hasGeneratedMarker(pkgDir: string): Promise<boolean> {\n try {\n const pkg = JSON.parse(\n await readFile(path.join(pkgDir, 'package.json'), 'utf8'),\n ) as { '//'?: unknown };\n return (\n typeof pkg['//'] === 'string' && pkg['//'].startsWith('Generated by tako')\n );\n } catch {\n return false;\n }\n}\n\n/** Every immediate subdirectory of `packagesDir` carrying the tako marker. */\nexport async function markedPackageDirs(\n packagesDir: string,\n): Promise<string[]> {\n if (!existsSync(packagesDir)) {\n return [];\n }\n const out: string[] = [];\n for (const dirent of await readdir(packagesDir, { withFileTypes: true })) {\n if (!dirent.isDirectory()) {\n continue;\n }\n const abs = path.join(packagesDir, dirent.name);\n if (await hasGeneratedMarker(abs)) {\n out.push(abs);\n }\n }\n return out.sort();\n}\n","/**\n * `ConsoleReporter` — the `@kurotako/core` `Logger` the CLI injects into\n * `loadConfig()` / `run()`, plus the per-phase / summary output.\n *\n * Contract (`backlog/features/cli/technical.md` §Reporter):\n * - human output goes to **stderr**, `stdout` stays clean;\n * - `info` / `warn` / `error` shown by default; `debug` only with `--debug` /\n * `TAKO_DEBUG` (a hidden flag, not advertised);\n * - the human-readable message is always shown; the structured `meta` object is\n * printed only with `--debug` (a custom `Logger` still receives it in full),\n * so default output stays prose, not `key=value` noise;\n * - `tako ` prefix, level-coloured; colour auto-off when the stream is not a TTY\n * or `NO_COLOR` is set;\n * - `child(tag)` returns a `Logger` tagging every `meta` with `{ scope: tag }`.\n */\nimport { childLogger, type Logger } from '@kurotako/core';\n\ntype Level = 'debug' | 'info' | 'warn' | 'error';\n\n/** The slice of a writable stream the reporter needs (keeps tests trivial). */\nexport interface WriteStream {\n write(chunk: string): unknown;\n isTTY?: boolean;\n}\n\nexport interface ConsoleReporterOptions {\n /** Show `debug` output. Default: `false` unless `TAKO_DEBUG` is set. */\n debug?: boolean;\n /** Sink for human output. Default: `process.stderr`. */\n stream?: WriteStream;\n /** Force colour on/off. Default: auto (TTY and no `NO_COLOR`). */\n color?: boolean;\n}\n\nconst ESC = String.fromCharCode(27);\nconst ANSI: Record<Level, string> = {\n debug: `${ESC}[2m`, // dim\n info: `${ESC}[36m`, // cyan\n warn: `${ESC}[33m`, // yellow\n error: `${ESC}[31m`, // red\n};\nconst ANSI_RESET = `${ESC}[0m`;\n\nexport class ConsoleReporter implements Logger {\n private readonly stream: WriteStream;\n private readonly showDebug: boolean;\n private readonly color: boolean;\n\n constructor(options: ConsoleReporterOptions = {}) {\n this.stream = options.stream ?? process.stderr;\n this.showDebug = options.debug ?? Boolean(process.env.TAKO_DEBUG);\n this.color =\n options.color ??\n (Boolean(this.stream.isTTY) && process.env.NO_COLOR === undefined);\n }\n\n debug(msg: string, meta?: unknown): void {\n if (this.showDebug) {\n this.write('debug', msg, meta);\n }\n }\n\n info(msg: string, meta?: unknown): void {\n this.write('info', msg, meta);\n }\n\n warn(msg: string, meta?: unknown): void {\n this.write('warn', msg, meta);\n }\n\n error(msg: string, meta?: unknown): void {\n this.write('error', msg, meta);\n }\n\n /** A child `Logger` whose calls carry `{ scope: tag }` in `meta`. */\n child(tag: string): Logger {\n return childLogger(this, { scope: tag });\n }\n\n private write(level: Level, msg: string, meta?: unknown): void {\n const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : 'tako';\n const detail =\n meta === undefined || !this.showDebug ? '' : ` ${formatMeta(meta)}`;\n this.stream.write(`${prefix} ${msg}${detail}\\n`);\n }\n}\n\nfunction formatMeta(meta: unknown): string {\n if (meta !== null && typeof meta === 'object' && !Array.isArray(meta)) {\n return Object.entries(meta as Record<string, unknown>)\n .map(([k, v]) => `${k}=${stringify(v)}`)\n .join(' ');\n }\n return stringify(meta);\n}\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","/**\n * `tako generate` — `loadConfig()` then `run()`. `--dry-run` runs everything but\n * skips the Writer; `--watch` hands off to the chokidar loop\n * (`backlog/features/cli/technical.md` §`tako generate`).\n */\nimport { relative } from 'node:path';\nimport { type LoadResult, loadConfig } from '@kurotako/config';\nimport type { OutputConfig, ResolvedConfig, RunResult } from '@kurotako/core';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { watchAndRun } from '../watch.js';\n\nexport interface LoadAndRunOptions {\n cwd: string;\n configPath?: string;\n write: boolean;\n signal?: AbortSignal;\n reporter: ConsoleReporter;\n}\n\nexport interface LoadAndRunResult {\n result: RunResult;\n config: ResolvedConfig;\n configFile: string;\n rootDir: string;\n}\n\n/** The directory named in the `wrote N files -> …` summary line, for one output. */\nexport function outputSummaryDir(\n output: OutputConfig,\n config: ResolvedConfig,\n): string {\n return output.mode === 'package'\n ? (output.packagesDir ?? config.rootDir)\n : (output.dir ?? config.rootDir);\n}\n\n/**\n * The shared body of `generate`, `validate` and each watch cycle: resolve +\n * load the config, then run the pipeline. `write: false` also skips the\n * `afterEmit` hook (`@kurotako/core` `run()`).\n */\nexport async function loadAndRun(\n opts: LoadAndRunOptions,\n): Promise<LoadAndRunResult> {\n const loaded: LoadResult = await loadConfig({\n cwd: opts.cwd,\n configPath: opts.configPath,\n });\n const result = await run(loaded.config, {\n logger: opts.reporter,\n write: opts.write,\n signal: opts.signal,\n });\n return {\n result,\n config: loaded.config,\n configFile: loaded.configFile,\n rootDir: loaded.rootDir,\n };\n}\n\nexport const generateCommand = defineCommand({\n meta: {\n name: 'generate',\n description: 'run the pipeline and write the generated code',\n },\n args: {\n ...sharedArgs,\n watch: {\n type: 'boolean',\n description: 'rebuild on every schema / config change',\n default: false,\n },\n 'dry-run': {\n type: 'boolean',\n description: 'run everything but write nothing',\n default: false,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n const configPath = args.config || undefined;\n\n if (args.watch) {\n await watchAndRun({ cwd, configPath, reporter });\n return;\n }\n\n const dryRun = Boolean(args['dry-run']);\n const { result, config } = await loadAndRun({\n cwd,\n configPath,\n write: !dryRun,\n reporter,\n });\n\n if (dryRun) {\n reporter.info(`dry run: ${result.files.length} files would be written`);\n return;\n }\n\n const dirs = config.outputs\n .map((output) => relative(cwd, outputSummaryDir(output, config)))\n .join(', ');\n reporter.info(`wrote ${result.files.length} files -> ${dirs}`);\n },\n});\n","/**\n * `tako generate --watch` — a chokidar loop around `loadConfig()` + `run()`.\n * Full regeneration on every change (no incremental). A 100 ms trailing\n * debounce coalesces bursts; a change mid-cycle aborts the in-flight `run()`\n * (via `RunOptions.signal`) and re-runs once it settles. `loadConfig` failures\n * are reported, not fatal — the watcher stays up on `tako.config.ts`.\n *\n * `backlog/features/cli/technical.md` §Watch mode.\n */\nimport { basename, resolve } from 'node:path';\nimport {\n type LoadResult,\n loadConfig as realLoadConfig,\n} from '@kurotako/config';\nimport { run as realRun, TakoError } from '@kurotako/core';\nimport chokidar from 'chokidar';\nimport { renderError } from './errors.js';\nimport type { ConsoleReporter } from './reporter.js';\n\n/** Minimal watcher seam so the loop is unit-testable without touching the fs. */\nexport interface Watcher {\n add(paths: string | readonly string[]): void;\n unwatch(paths: string | readonly string[]): void;\n on(handler: (event: string, path: string) => void): void;\n close(): Promise<void>;\n}\n\nexport interface WatchAndRunOptions {\n cwd: string;\n configPath?: string;\n reporter: ConsoleReporter;\n}\n\nexport interface WatchDeps {\n createWatcher: () => Watcher;\n loadConfig: typeof realLoadConfig;\n run: typeof realRun;\n debounceMs: number;\n}\n\nconst DEBOUNCE_MS = 100;\n\nfunction chokidarWatcher(): Watcher {\n const fsw = chokidar.watch([], {\n ignoreInitial: true,\n awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 20 },\n });\n return {\n add: (paths) => fsw.add(paths as string | string[]),\n unwatch: (paths) => fsw.unwatch(paths as string | string[]),\n on: (handler) => {\n fsw.on('add', (p) => handler('add', p));\n fsw.on('change', (p) => handler('change', p));\n fsw.on('unlink', (p) => handler('unlink', p));\n },\n close: () => fsw.close(),\n };\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError';\n}\n\n/**\n * Runs until `SIGINT` / `SIGTERM`, then closes the watcher and resolves so the\n * caller can exit 0. (The design doc types this `Promise<never>`; it resolves\n * on shutdown here purely so it stays testable.)\n */\nexport async function watchAndRun(\n opts: WatchAndRunOptions,\n deps: Partial<WatchDeps> = {},\n): Promise<void> {\n const { cwd, configPath, reporter } = opts;\n const createWatcher = deps.createWatcher ?? chokidarWatcher;\n const loadConfig = deps.loadConfig ?? realLoadConfig;\n const run = deps.run ?? realRun;\n const debounceMs = deps.debounceMs ?? DEBOUNCE_MS;\n\n const watcher = createWatcher();\n let watched = new Set<string>();\n let inFlight: AbortController | null = null;\n let queued = false;\n let closed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let reason = 'initial build';\n\n const guessedConfigFile = configPath\n ? resolve(cwd, configPath)\n : resolve(cwd, 'tako.config.ts');\n\n function applyWatchSet(desired: Set<string>): void {\n for (const path of desired) {\n if (!watched.has(path)) {\n watcher.add(path);\n }\n }\n for (const path of watched) {\n if (!desired.has(path)) {\n watcher.unwatch(path);\n }\n }\n watched = desired;\n }\n\n async function reconcileWatchSet(loaded: LoadResult): Promise<void> {\n const desired = new Set<string>([loaded.configFile]);\n for (const [namespace, source] of Object.entries(loaded.config.sources)) {\n const paths =\n (await source.parser.watchPaths?.({\n namespace,\n cwd: loaded.rootDir,\n logger: reporter,\n })) ?? [];\n for (const path of paths) {\n desired.add(resolve(loaded.rootDir, path));\n }\n }\n applyWatchSet(desired);\n }\n\n async function cycle(): Promise<void> {\n const why = reason;\n reporter.info(`--- rebuild (${why}) ---`);\n const ac = new AbortController();\n inFlight = ac;\n try {\n const loaded = await loadConfig({ cwd, configPath });\n await reconcileWatchSet(loaded);\n const result = await run(loaded.config, {\n logger: reporter,\n signal: ac.signal,\n write: true,\n });\n if (!ac.signal.aborted) {\n reporter.info(`wrote ${result.files.length} files`);\n }\n } catch (error) {\n if (isAbortError(error) || ac.signal.aborted) {\n // Superseded by a newer cycle — swallow.\n } else if (error instanceof TakoError) {\n reporter.error(renderError(error));\n // Keep watching at least the config file so a fix is picked up.\n applyWatchSet(new Set([...watched, guessedConfigFile]));\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n }\n } finally {\n inFlight = null;\n if (queued && !closed) {\n queued = false;\n await cycle();\n }\n }\n }\n\n function trigger(): void {\n if (inFlight) {\n queued = true;\n inFlight.abort();\n return;\n }\n void cycle();\n }\n\n function schedule(event: string, path: string): void {\n if (closed) {\n return;\n }\n reason = `${basename(path)} ${event === 'unlink' ? 'removed' : 'changed'}`;\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => {\n timer = null;\n trigger();\n }, debounceMs);\n }\n\n watcher.on(schedule);\n\n // Initial cycle: a failure is reported inside `cycle()`, never fatal.\n applyWatchSet(new Set([guessedConfigFile]));\n await cycle();\n reporter.info(`watching ${watched.size} paths`);\n\n await new Promise<void>((resolvePromise) => {\n const shutdown = () => {\n closed = true;\n if (timer) {\n clearTimeout(timer);\n }\n inFlight?.abort();\n process.off('SIGINT', shutdown);\n process.off('SIGTERM', shutdown);\n void watcher.close().finally(() => resolvePromise());\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n}\n","/**\n * CLI-owned error(s) and `renderError()` — the single formatter the top-level\n * handler in `cli.ts` uses for any `TakoError` (from `@kurotako/core`,\n * `@kurotako/config`, or this package).\n *\n * `backlog/features/cli/technical.md` §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\n\n/** `tako init` refuses to overwrite an existing config unless `--force`. */\nexport class ConfigExistsError extends TakoError {\n readonly path: string;\n\n constructor(path: string) {\n super(\n 'config_exists',\n `a config file already exists at '${path}' (pass --force to overwrite)`,\n );\n this.path = path;\n }\n}\n\ninterface Issue {\n path?: string;\n message?: string;\n}\n\n/**\n * `error [<code>]: <message>` plus any carried context on its own indented\n * lines: located issues (`ConfigShapeError`, `IrValidationError`,\n * `DriverOptionsError`), the offending driver / namespace (`DriverError`,\n * `UnknownNamespaceError`), the dependency cycle path (`DependencyCycleError`),\n * and the `cause` message of a wrapped failure.\n */\nexport function renderError(error: TakoError): string {\n const lines = [`error [${error.code}]: ${error.message}`];\n\n const issues = (error as { issues?: unknown }).issues;\n if (Array.isArray(issues)) {\n for (const issue of issues as Issue[]) {\n const at =\n issue.path === undefined || issue.path === '' ? '<root>' : issue.path;\n lines.push(` - ${at}: ${issue.message}`);\n }\n }\n\n const cycle = (error as { cycle?: unknown }).cycle;\n if (Array.isArray(cycle) && cycle.length > 0) {\n lines.push(` cycle: ${(cycle as string[]).join(' -> ')}`);\n }\n\n const driverName = (error as { driverName?: unknown }).driverName;\n if (typeof driverName === 'string') {\n const role = (error as { role?: unknown }).role;\n const namespace = (error as { namespace?: unknown }).namespace;\n const roleLabel = typeof role === 'string' ? role : 'driver';\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` ${roleLabel}: ${driverName}${where}`);\n } else {\n const generator = (error as { generator?: unknown }).generator;\n if (typeof generator === 'string') {\n const namespace = (error as { namespace?: unknown }).namespace;\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` generator: ${generator}${where}`);\n }\n }\n\n // Wrapped failures (`DriverError`, `HookError`, `ConfigLoadError`, …) carry the\n // real error in `cause`; core masks its type, so surface at least its message.\n const cause = error.cause;\n if (cause !== undefined && cause !== null) {\n const message = cause instanceof Error ? cause.message : String(cause);\n const code = cause instanceof TakoError ? ` [${cause.code}]` : '';\n lines.push(` cause${code}: ${message}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * `tako init` — write the commented `tako.config.ts` skeleton into the current\n * directory. No prompts, no schema auto-detection; refuses to overwrite unless\n * `--force` (`backlog/features/cli/technical.md` §`tako init`).\n *\n * `--monorepo` / `--no-monorepo` picks between `CONFIG_TEMPLATE` and\n * `CONFIG_TEMPLATE_MONOREPO`; unset, it auto-detects a workspace by walking up\n * for the nearest `package.json` (`workspaces` key, or a sibling\n * `pnpm-workspace.yaml`).\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, relative, resolve } from 'node:path';\nimport { CONFIG_TEMPLATE, CONFIG_TEMPLATE_MONOREPO } from '@kurotako/config';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConfigExistsError } from '../errors.js';\nimport { ConsoleReporter } from '../reporter.js';\n\n/**\n * Walk up from `startDir` to the first directory holding a `package.json`. A\n * workspace when that `package.json` has a `workspaces` key (array, or\n * `{ packages: [...] }`), or when a `pnpm-workspace.yaml` sits next to it.\n * Returns `false` when no `package.json` is found.\n */\nfunction detectMonorepo(startDir: string): boolean {\n let dir = resolve(startDir);\n while (true) {\n const pkgPath = resolve(dir, 'package.json');\n if (existsSync(pkgPath)) {\n if (existsSync(resolve(dir, 'pnpm-workspace.yaml'))) {\n return true;\n }\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n workspaces?: unknown;\n };\n const ws = pkg.workspaces;\n if (\n Array.isArray(ws) ||\n (typeof ws === 'object' &&\n ws !== null &&\n Array.isArray((ws as { packages?: unknown }).packages))\n ) {\n return true;\n }\n } catch {\n // Unreadable / invalid package.json: treat as not a workspace.\n }\n return false;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return false;\n }\n dir = parent;\n }\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: 'init',\n description: 'create a tako.config.ts in the current directory',\n },\n args: {\n ...sharedArgs,\n force: {\n type: 'boolean',\n description: 'overwrite an existing config file',\n default: false,\n },\n monorepo: {\n type: 'boolean',\n description:\n 'write the monorepo config layout (auto-detected from workspaces when unset)',\n default: undefined,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n // Unlike `loadConfig`, `init` never walks up: it always targets `cwd`.\n const target = args.config\n ? resolve(cwd, args.config)\n : resolve(cwd, 'tako.config.ts');\n\n if (existsSync(target) && !args.force) {\n throw new ConfigExistsError(target);\n }\n\n // citty leaves an unset boolean flag `undefined` (no `default`), so\n // `--monorepo` / `--no-monorepo` win and absence falls back to detection.\n const monorepo: boolean =\n typeof args.monorepo === 'boolean' ? args.monorepo : detectMonorepo(cwd);\n\n await mkdir(dirname(target), { recursive: true });\n await writeFile(\n target,\n monorepo ? CONFIG_TEMPLATE_MONOREPO : CONFIG_TEMPLATE,\n 'utf8',\n );\n\n const name = relative(cwd, target) || 'tako.config.ts';\n reporter.info(\n monorepo ? `created ${name} (monorepo layout)` : `created ${name}`,\n );\n },\n});\n","/**\n * `tako validate` — the same checks as `generate` up to (not including)\n * emission. `loadConfig()` + `run({ write: false })`; any `TakoError` propagates\n * to the top-level handler and exits 1\n * (`backlog/features/cli/technical.md` §`tako validate`).\n */\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { loadAndRun } from './generate.js';\n\nexport const validateCommand = defineCommand({\n meta: {\n name: 'validate',\n description: 'check the config and schema without writing anything',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n await loadAndRun({\n cwd: process.cwd(),\n configPath: args.config || undefined,\n write: false,\n reporter,\n });\n reporter.info('config and schema are valid');\n },\n});\n"],"mappings":"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","names":["import_core","import_citty","import_node_fs","import_node_path","import_core","path","import_node_path","import_config","import_core","import_citty","import_node_path","import_config","import_core","import_core","path","chokidar","loadConfig","realLoadConfig","run","realRun","path","import_node_fs","import_promises","import_node_path","import_config","import_citty","import_citty"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -49,6 +49,9 @@ declare function renderError(error: TakoError): string;
|
|
|
49
49
|
* - human output goes to **stderr**, `stdout` stays clean;
|
|
50
50
|
* - `info` / `warn` / `error` shown by default; `debug` only with `--debug` /
|
|
51
51
|
* `TAKO_DEBUG` (a hidden flag, not advertised);
|
|
52
|
+
* - the human-readable message is always shown; the structured `meta` object is
|
|
53
|
+
* printed only with `--debug` (a custom `Logger` still receives it in full),
|
|
54
|
+
* so default output stays prose, not `key=value` noise;
|
|
52
55
|
* - `tako ` prefix, level-coloured; colour auto-off when the stream is not a TTY
|
|
53
56
|
* or `NO_COLOR` is set;
|
|
54
57
|
* - `child(tag)` returns a `Logger` tagging every `meta` with `{ scope: tag }`.
|
package/dist/index.d.ts
CHANGED
|
@@ -49,6 +49,9 @@ declare function renderError(error: TakoError): string;
|
|
|
49
49
|
* - human output goes to **stderr**, `stdout` stays clean;
|
|
50
50
|
* - `info` / `warn` / `error` shown by default; `debug` only with `--debug` /
|
|
51
51
|
* `TAKO_DEBUG` (a hidden flag, not advertised);
|
|
52
|
+
* - the human-readable message is always shown; the structured `meta` object is
|
|
53
|
+
* printed only with `--debug` (a custom `Logger` still receives it in full),
|
|
54
|
+
* so default output stays prose, not `key=value` noise;
|
|
52
55
|
* - `tako ` prefix, level-coloured; colour auto-off when the stream is not a TTY
|
|
53
56
|
* or `NO_COLOR` is set;
|
|
54
57
|
* - `child(tag)` returns a `Logger` tagging every `meta` with `{ scope: tag }`.
|
package/dist/index.js
CHANGED
|
@@ -169,7 +169,7 @@ var ConsoleReporter = class {
|
|
|
169
169
|
}
|
|
170
170
|
write(level, msg, meta) {
|
|
171
171
|
const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : "tako";
|
|
172
|
-
const detail = meta === void 0 ? "" : ` ${formatMeta(meta)}`;
|
|
172
|
+
const detail = meta === void 0 || !this.showDebug ? "" : ` ${formatMeta(meta)}`;
|
|
173
173
|
this.stream.write(`${prefix} ${msg}${detail}
|
|
174
174
|
`);
|
|
175
175
|
}
|
|
@@ -612,7 +612,7 @@ var validateCommand = defineCommand4({
|
|
|
612
612
|
});
|
|
613
613
|
|
|
614
614
|
// src/cli.ts
|
|
615
|
-
var VERSION = true ? "0.1.
|
|
615
|
+
var VERSION = true ? "0.1.2" : "0.0.0-dev";
|
|
616
616
|
var subCommands = {
|
|
617
617
|
init: initCommand,
|
|
618
618
|
generate: generateCommand,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/check.ts","../src/args.ts","../src/diff.ts","../src/reporter.ts","../src/commands/generate.ts","../src/watch.ts","../src/errors.ts","../src/commands/init.ts","../src/commands/validate.ts"],"sourcesContent":["/**\n * `runCli()` — build the citty command tree, dispatch, map every `TakoError` to\n * a formatted message + exit 1. `--version` / `--help` are handled here (citty's\n * own handling lives in `runMain`, which hard-exits — not what a testable\n * `runCli` wants).\n *\n * `backlog/features/cli/technical.md` §Command surface, §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\nimport { type CommandDef, defineCommand, renderUsage, runCommand } from 'citty';\nimport { checkCommand } from './commands/check.js';\nimport { generateCommand } from './commands/generate.js';\nimport { initCommand } from './commands/init.js';\nimport { validateCommand } from './commands/validate.js';\nimport { renderError } from './errors.js';\nimport { ConsoleReporter } from './reporter.js';\n\ndeclare const __TAKO_VERSION__: string;\nconst VERSION =\n typeof __TAKO_VERSION__ === 'string' ? __TAKO_VERSION__ : '0.0.0-dev';\n\nconst subCommands = {\n init: initCommand,\n generate: generateCommand,\n validate: validateCommand,\n check: checkCommand,\n};\n\nconst main = defineCommand({\n meta: {\n name: 'tako',\n version: VERSION,\n description: 'synchronise TypeScript schemas from data model to forms',\n },\n subCommands,\n});\n\nexport async function runCli(argv: string[]): Promise<void> {\n const reporter = new ConsoleReporter({\n debug: argv.includes('--debug') || Boolean(process.env.TAKO_DEBUG),\n });\n\n if (argv.includes('--version') || argv.includes('-v')) {\n process.stdout.write(`${VERSION}\\n`);\n process.exitCode ??= 0;\n return;\n }\n\n if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {\n const sub = argv.find((a) => !a.startsWith('-'));\n const isSub = sub !== undefined && sub in subCommands;\n const cmd = (\n isSub ? subCommands[sub as keyof typeof subCommands] : main\n ) as CommandDef;\n process.stdout.write(\n `${await renderUsage(cmd, isSub ? (main as CommandDef) : undefined)}\\n`,\n );\n process.exitCode ??= 0;\n return;\n }\n\n try {\n await runCommand(main, { rawArgs: argv });\n process.exitCode ??= 0;\n } catch (error) {\n if (error instanceof TakoError) {\n reporter.error(renderError(error));\n process.exitCode = 1;\n } else if (error instanceof Error && error.name === 'CLIError') {\n // citty usage error (unknown command, missing argument, …).\n reporter.error(error.message);\n process.exitCode = 1;\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n process.exitCode = 1;\n }\n }\n}\n","/**\n * `tako check` — drift guard. Runs the pipeline in plan mode (no disk writes,\n * no `afterEmit`), then compares the planned tree against what is on disk.\n * Exit 0 when they match, exit 1 on any drift or any `TakoError` (the latter\n * via the top-level handler in `cli.ts`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §Command surface.\n */\nimport { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { loadConfig } from '@kurotako/config';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport {\n comparePlanToDisk,\n type DriftEntry,\n ignoreBuildArtifacts,\n markedPackageDirs,\n} from '../diff.js';\nimport { ConsoleReporter } from '../reporter.js';\n\nexport const checkCommand = defineCommand({\n meta: {\n name: 'check',\n description:\n 'check the generated output on disk matches a fresh generate (drift guard)',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n\n const { config } = await loadConfig({\n cwd,\n configPath: args.config || undefined,\n });\n const { plan = [] } = await run(config, { logger: reporter, plan: true });\n\n const roots: string[] = [];\n const ignores: ((absPath: string) => boolean)[] = [];\n\n for (const output of config.outputs) {\n if (output.mode === 'package') {\n ignores.push(ignoreBuildArtifacts);\n if (output.packagesDir) {\n roots.push(...(await markedPackageDirs(output.packagesDir)));\n }\n } else {\n const dir = output.dir;\n if (!dir) {\n continue;\n }\n if (!existsSync(dir)) {\n reporter.info(\n `output directory ${relative(config.rootDir, dir)} does not exist — run tako generate`,\n );\n process.exitCode = 1;\n return;\n }\n roots.push(dir);\n }\n }\n\n const ignore = (absPath: string): boolean =>\n ignores.some((fn) => fn(absPath));\n\n const drift = await comparePlanToDisk({\n plan,\n roots,\n ignore,\n rootDir: config.rootDir,\n });\n\n if (drift.length === 0) {\n reporter.info('output is in sync');\n process.exitCode ??= 0;\n return;\n }\n\n reporter.error(formatDrift(drift));\n process.exitCode = 1;\n },\n});\n\nfunction formatDrift(drift: DriftEntry[]): string {\n const width = Math.max(...drift.map((entry) => entry.kind.length));\n const lines = drift.map(\n (entry) => ` ${entry.kind.padEnd(width)} ${entry.path}`,\n );\n return [\n 'drift detected',\n '',\n ...lines,\n '',\n `${drift.length} files differ from a fresh generate. Run \\`tako generate\\`.`,\n ].join('\\n');\n}\n","/**\n * `sharedArgs` — the options every sub-command carries. citty has no\n * first-class global-option slot, so this object is spread into each command's\n * `args` (`backlog/features/cli/technical.md` §Global option).\n */\nimport type { ArgsDef } from 'citty';\n\nexport const sharedArgs = {\n config: {\n type: 'string',\n description: 'path to the tako config file (default: ./tako.config.ts)',\n },\n /** Hidden: not advertised, kept minimal. Enables `debug` reporter output. */\n debug: {\n type: 'boolean',\n default: false,\n },\n} as const satisfies ArgsDef;\n","/**\n * `comparePlanToDisk` — the in-memory comparison behind `tako check`. Takes the\n * `PlannedFile[]` a fresh `generate` would write (from `run({ plan: true })`)\n * and reports every way the tree on disk diverges from it: a planned file that\n * is absent (`missing`) or whose bytes differ (`modified`), and any file under\n * the scanned roots that no planned file claims (`orphan`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §The comparison.\n */\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PlannedFile } from '@kurotako/core';\n\nexport type DriftKind = 'modified' | 'missing' | 'orphan';\n\nexport interface DriftEntry {\n kind: DriftKind;\n /** Relative to `rootDir`, POSIX separators; a collapsed dir ends with `/`. */\n path: string;\n}\n\nexport interface ComparePlanToDiskArgs {\n plan: PlannedFile[];\n /** Directories walked for orphans (absolute). */\n roots: string[];\n /** Return `true` to exclude an absolute path from the orphan scan. */\n ignore: (absPath: string) => boolean;\n /** Anchor for the reported relative paths (the config-file directory). */\n rootDir: string;\n}\n\nfunction toPosix(rootDir: string, absPath: string): string {\n return path.relative(rootDir, absPath).split(path.sep).join('/');\n}\n\nexport async function comparePlanToDisk(\n args: ComparePlanToDiskArgs,\n): Promise<DriftEntry[]> {\n const { plan, roots, ignore, rootDir } = args;\n const plannedByPath = new Map(plan.map((f) => [path.resolve(f.path), f]));\n const entries: DriftEntry[] = [];\n\n // 1. Expected vs disk.\n for (const [absPath, file] of plannedByPath) {\n if (!existsSync(absPath)) {\n entries.push({ kind: 'missing', path: toPosix(rootDir, absPath) });\n continue;\n }\n const onDisk = await readFile(absPath, 'utf8');\n if (onDisk !== file.content) {\n entries.push({ kind: 'modified', path: toPosix(rootDir, absPath) });\n }\n }\n\n // 2. Orphan scan — a planned file lives under `dir` iff any planned absolute\n // path is `dir` itself or sits below it.\n const plannedPaths = [...plannedByPath.keys()];\n const hasPlannedUnder = (dir: string): boolean => {\n const prefix = `${dir}${path.sep}`;\n return plannedPaths.some((p) => p === dir || p.startsWith(prefix));\n };\n\n const seenRoots = new Set<string>();\n for (const root of roots) {\n const absRoot = path.resolve(root);\n if (seenRoots.has(absRoot) || !existsSync(absRoot)) {\n continue;\n }\n seenRoots.add(absRoot);\n await scan(absRoot);\n }\n\n async function scan(dir: string): Promise<void> {\n // A directory with no planned file underneath collapses to a single entry —\n // unless it holds nothing but ignored files (e.g. only `dist/`).\n if (!hasPlannedUnder(dir)) {\n if (await hasNonIgnoredFile(dir)) {\n entries.push({ kind: 'orphan', path: `${toPosix(rootDir, dir)}/` });\n }\n return;\n }\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isDirectory()) {\n await scan(abs);\n } else if (dirent.isFile() && !plannedByPath.has(abs)) {\n entries.push({ kind: 'orphan', path: toPosix(rootDir, abs) });\n }\n }\n }\n\n async function hasNonIgnoredFile(dir: string): Promise<boolean> {\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isFile()) {\n return true;\n }\n if (dirent.isDirectory() && (await hasNonIgnoredFile(abs))) {\n return true;\n }\n }\n return false;\n }\n\n entries.sort((a, b) =>\n a.path < b.path\n ? -1\n : a.path > b.path\n ? 1\n : a.kind < b.kind\n ? -1\n : a.kind > b.kind\n ? 1\n : 0,\n );\n return entries;\n}\n\n/** Rejects `dist/` and `node_modules/` anywhere in the path (mode B). */\nexport function ignoreBuildArtifacts(absPath: string): boolean {\n return /(^|[/\\\\])(dist|node_modules)([/\\\\]|$)/.test(absPath);\n}\n\n/**\n * Whether `<packagesDir>/<name>` looks like a directory `tako` generated: a\n * `package.json` whose `\"//\"` marker starts with `Generated by tako`.\n */\nexport async function hasGeneratedMarker(pkgDir: string): Promise<boolean> {\n try {\n const pkg = JSON.parse(\n await readFile(path.join(pkgDir, 'package.json'), 'utf8'),\n ) as { '//'?: unknown };\n return (\n typeof pkg['//'] === 'string' && pkg['//'].startsWith('Generated by tako')\n );\n } catch {\n return false;\n }\n}\n\n/** Every immediate subdirectory of `packagesDir` carrying the tako marker. */\nexport async function markedPackageDirs(\n packagesDir: string,\n): Promise<string[]> {\n if (!existsSync(packagesDir)) {\n return [];\n }\n const out: string[] = [];\n for (const dirent of await readdir(packagesDir, { withFileTypes: true })) {\n if (!dirent.isDirectory()) {\n continue;\n }\n const abs = path.join(packagesDir, dirent.name);\n if (await hasGeneratedMarker(abs)) {\n out.push(abs);\n }\n }\n return out.sort();\n}\n","/**\n * `ConsoleReporter` — the `@kurotako/core` `Logger` the CLI injects into\n * `loadConfig()` / `run()`, plus the per-phase / summary output.\n *\n * Contract (`backlog/features/cli/technical.md` §Reporter):\n * - human output goes to **stderr**, `stdout` stays clean;\n * - `info` / `warn` / `error` shown by default; `debug` only with `--debug` /\n * `TAKO_DEBUG` (a hidden flag, not advertised);\n * - `tako ` prefix, level-coloured; colour auto-off when the stream is not a TTY\n * or `NO_COLOR` is set;\n * - `child(tag)` returns a `Logger` tagging every `meta` with `{ scope: tag }`.\n */\nimport { childLogger, type Logger } from '@kurotako/core';\n\ntype Level = 'debug' | 'info' | 'warn' | 'error';\n\n/** The slice of a writable stream the reporter needs (keeps tests trivial). */\nexport interface WriteStream {\n write(chunk: string): unknown;\n isTTY?: boolean;\n}\n\nexport interface ConsoleReporterOptions {\n /** Show `debug` output. Default: `false` unless `TAKO_DEBUG` is set. */\n debug?: boolean;\n /** Sink for human output. Default: `process.stderr`. */\n stream?: WriteStream;\n /** Force colour on/off. Default: auto (TTY and no `NO_COLOR`). */\n color?: boolean;\n}\n\nconst ESC = String.fromCharCode(27);\nconst ANSI: Record<Level, string> = {\n debug: `${ESC}[2m`, // dim\n info: `${ESC}[36m`, // cyan\n warn: `${ESC}[33m`, // yellow\n error: `${ESC}[31m`, // red\n};\nconst ANSI_RESET = `${ESC}[0m`;\n\nexport class ConsoleReporter implements Logger {\n private readonly stream: WriteStream;\n private readonly showDebug: boolean;\n private readonly color: boolean;\n\n constructor(options: ConsoleReporterOptions = {}) {\n this.stream = options.stream ?? process.stderr;\n this.showDebug = options.debug ?? Boolean(process.env.TAKO_DEBUG);\n this.color =\n options.color ??\n (Boolean(this.stream.isTTY) && process.env.NO_COLOR === undefined);\n }\n\n debug(msg: string, meta?: unknown): void {\n if (this.showDebug) {\n this.write('debug', msg, meta);\n }\n }\n\n info(msg: string, meta?: unknown): void {\n this.write('info', msg, meta);\n }\n\n warn(msg: string, meta?: unknown): void {\n this.write('warn', msg, meta);\n }\n\n error(msg: string, meta?: unknown): void {\n this.write('error', msg, meta);\n }\n\n /** A child `Logger` whose calls carry `{ scope: tag }` in `meta`. */\n child(tag: string): Logger {\n return childLogger(this, { scope: tag });\n }\n\n private write(level: Level, msg: string, meta?: unknown): void {\n const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : 'tako';\n const detail = meta === undefined ? '' : ` ${formatMeta(meta)}`;\n this.stream.write(`${prefix} ${msg}${detail}\\n`);\n }\n}\n\nfunction formatMeta(meta: unknown): string {\n if (meta !== null && typeof meta === 'object' && !Array.isArray(meta)) {\n return Object.entries(meta as Record<string, unknown>)\n .map(([k, v]) => `${k}=${stringify(v)}`)\n .join(' ');\n }\n return stringify(meta);\n}\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","/**\n * `tako generate` — `loadConfig()` then `run()`. `--dry-run` runs everything but\n * skips the Writer; `--watch` hands off to the chokidar loop\n * (`backlog/features/cli/technical.md` §`tako generate`).\n */\nimport { relative } from 'node:path';\nimport { type LoadResult, loadConfig } from '@kurotako/config';\nimport type { OutputConfig, ResolvedConfig, RunResult } from '@kurotako/core';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { watchAndRun } from '../watch.js';\n\nexport interface LoadAndRunOptions {\n cwd: string;\n configPath?: string;\n write: boolean;\n signal?: AbortSignal;\n reporter: ConsoleReporter;\n}\n\nexport interface LoadAndRunResult {\n result: RunResult;\n config: ResolvedConfig;\n configFile: string;\n rootDir: string;\n}\n\n/** The directory named in the `wrote N files -> …` summary line, for one output. */\nexport function outputSummaryDir(\n output: OutputConfig,\n config: ResolvedConfig,\n): string {\n return output.mode === 'package'\n ? (output.packagesDir ?? config.rootDir)\n : (output.dir ?? config.rootDir);\n}\n\n/**\n * The shared body of `generate`, `validate` and each watch cycle: resolve +\n * load the config, then run the pipeline. `write: false` also skips the\n * `afterEmit` hook (`@kurotako/core` `run()`).\n */\nexport async function loadAndRun(\n opts: LoadAndRunOptions,\n): Promise<LoadAndRunResult> {\n const loaded: LoadResult = await loadConfig({\n cwd: opts.cwd,\n configPath: opts.configPath,\n });\n const result = await run(loaded.config, {\n logger: opts.reporter,\n write: opts.write,\n signal: opts.signal,\n });\n return {\n result,\n config: loaded.config,\n configFile: loaded.configFile,\n rootDir: loaded.rootDir,\n };\n}\n\nexport const generateCommand = defineCommand({\n meta: {\n name: 'generate',\n description: 'run the pipeline and write the generated code',\n },\n args: {\n ...sharedArgs,\n watch: {\n type: 'boolean',\n description: 'rebuild on every schema / config change',\n default: false,\n },\n 'dry-run': {\n type: 'boolean',\n description: 'run everything but write nothing',\n default: false,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n const configPath = args.config || undefined;\n\n if (args.watch) {\n await watchAndRun({ cwd, configPath, reporter });\n return;\n }\n\n const dryRun = Boolean(args['dry-run']);\n const { result, config } = await loadAndRun({\n cwd,\n configPath,\n write: !dryRun,\n reporter,\n });\n\n if (dryRun) {\n reporter.info(`dry run: ${result.files.length} files would be written`);\n return;\n }\n\n const dirs = config.outputs\n .map((output) => relative(cwd, outputSummaryDir(output, config)))\n .join(', ');\n reporter.info(`wrote ${result.files.length} files -> ${dirs}`);\n },\n});\n","/**\n * `tako generate --watch` — a chokidar loop around `loadConfig()` + `run()`.\n * Full regeneration on every change (no incremental). A 100 ms trailing\n * debounce coalesces bursts; a change mid-cycle aborts the in-flight `run()`\n * (via `RunOptions.signal`) and re-runs once it settles. `loadConfig` failures\n * are reported, not fatal — the watcher stays up on `tako.config.ts`.\n *\n * `backlog/features/cli/technical.md` §Watch mode.\n */\nimport { basename, resolve } from 'node:path';\nimport {\n type LoadResult,\n loadConfig as realLoadConfig,\n} from '@kurotako/config';\nimport { run as realRun, TakoError } from '@kurotako/core';\nimport chokidar from 'chokidar';\nimport { renderError } from './errors.js';\nimport type { ConsoleReporter } from './reporter.js';\n\n/** Minimal watcher seam so the loop is unit-testable without touching the fs. */\nexport interface Watcher {\n add(paths: string | readonly string[]): void;\n unwatch(paths: string | readonly string[]): void;\n on(handler: (event: string, path: string) => void): void;\n close(): Promise<void>;\n}\n\nexport interface WatchAndRunOptions {\n cwd: string;\n configPath?: string;\n reporter: ConsoleReporter;\n}\n\nexport interface WatchDeps {\n createWatcher: () => Watcher;\n loadConfig: typeof realLoadConfig;\n run: typeof realRun;\n debounceMs: number;\n}\n\nconst DEBOUNCE_MS = 100;\n\nfunction chokidarWatcher(): Watcher {\n const fsw = chokidar.watch([], {\n ignoreInitial: true,\n awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 20 },\n });\n return {\n add: (paths) => fsw.add(paths as string | string[]),\n unwatch: (paths) => fsw.unwatch(paths as string | string[]),\n on: (handler) => {\n fsw.on('add', (p) => handler('add', p));\n fsw.on('change', (p) => handler('change', p));\n fsw.on('unlink', (p) => handler('unlink', p));\n },\n close: () => fsw.close(),\n };\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError';\n}\n\n/**\n * Runs until `SIGINT` / `SIGTERM`, then closes the watcher and resolves so the\n * caller can exit 0. (The design doc types this `Promise<never>`; it resolves\n * on shutdown here purely so it stays testable.)\n */\nexport async function watchAndRun(\n opts: WatchAndRunOptions,\n deps: Partial<WatchDeps> = {},\n): Promise<void> {\n const { cwd, configPath, reporter } = opts;\n const createWatcher = deps.createWatcher ?? chokidarWatcher;\n const loadConfig = deps.loadConfig ?? realLoadConfig;\n const run = deps.run ?? realRun;\n const debounceMs = deps.debounceMs ?? DEBOUNCE_MS;\n\n const watcher = createWatcher();\n let watched = new Set<string>();\n let inFlight: AbortController | null = null;\n let queued = false;\n let closed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let reason = 'initial build';\n\n const guessedConfigFile = configPath\n ? resolve(cwd, configPath)\n : resolve(cwd, 'tako.config.ts');\n\n function applyWatchSet(desired: Set<string>): void {\n for (const path of desired) {\n if (!watched.has(path)) {\n watcher.add(path);\n }\n }\n for (const path of watched) {\n if (!desired.has(path)) {\n watcher.unwatch(path);\n }\n }\n watched = desired;\n }\n\n async function reconcileWatchSet(loaded: LoadResult): Promise<void> {\n const desired = new Set<string>([loaded.configFile]);\n for (const [namespace, source] of Object.entries(loaded.config.sources)) {\n const paths =\n (await source.parser.watchPaths?.({\n namespace,\n cwd: loaded.rootDir,\n logger: reporter,\n })) ?? [];\n for (const path of paths) {\n desired.add(resolve(loaded.rootDir, path));\n }\n }\n applyWatchSet(desired);\n }\n\n async function cycle(): Promise<void> {\n const why = reason;\n reporter.info(`--- rebuild (${why}) ---`);\n const ac = new AbortController();\n inFlight = ac;\n try {\n const loaded = await loadConfig({ cwd, configPath });\n await reconcileWatchSet(loaded);\n const result = await run(loaded.config, {\n logger: reporter,\n signal: ac.signal,\n write: true,\n });\n if (!ac.signal.aborted) {\n reporter.info(`wrote ${result.files.length} files`);\n }\n } catch (error) {\n if (isAbortError(error) || ac.signal.aborted) {\n // Superseded by a newer cycle — swallow.\n } else if (error instanceof TakoError) {\n reporter.error(renderError(error));\n // Keep watching at least the config file so a fix is picked up.\n applyWatchSet(new Set([...watched, guessedConfigFile]));\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n }\n } finally {\n inFlight = null;\n if (queued && !closed) {\n queued = false;\n await cycle();\n }\n }\n }\n\n function trigger(): void {\n if (inFlight) {\n queued = true;\n inFlight.abort();\n return;\n }\n void cycle();\n }\n\n function schedule(event: string, path: string): void {\n if (closed) {\n return;\n }\n reason = `${basename(path)} ${event === 'unlink' ? 'removed' : 'changed'}`;\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => {\n timer = null;\n trigger();\n }, debounceMs);\n }\n\n watcher.on(schedule);\n\n // Initial cycle: a failure is reported inside `cycle()`, never fatal.\n applyWatchSet(new Set([guessedConfigFile]));\n await cycle();\n reporter.info(`watching ${watched.size} paths`);\n\n await new Promise<void>((resolvePromise) => {\n const shutdown = () => {\n closed = true;\n if (timer) {\n clearTimeout(timer);\n }\n inFlight?.abort();\n process.off('SIGINT', shutdown);\n process.off('SIGTERM', shutdown);\n void watcher.close().finally(() => resolvePromise());\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n}\n","/**\n * CLI-owned error(s) and `renderError()` — the single formatter the top-level\n * handler in `cli.ts` uses for any `TakoError` (from `@kurotako/core`,\n * `@kurotako/config`, or this package).\n *\n * `backlog/features/cli/technical.md` §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\n\n/** `tako init` refuses to overwrite an existing config unless `--force`. */\nexport class ConfigExistsError extends TakoError {\n readonly path: string;\n\n constructor(path: string) {\n super(\n 'config_exists',\n `a config file already exists at '${path}' (pass --force to overwrite)`,\n );\n this.path = path;\n }\n}\n\ninterface Issue {\n path?: string;\n message?: string;\n}\n\n/**\n * `error [<code>]: <message>` plus any carried context on its own indented\n * lines: located issues (`ConfigShapeError`, `IrValidationError`,\n * `DriverOptionsError`), the offending driver / namespace (`DriverError`,\n * `UnknownNamespaceError`), the dependency cycle path (`DependencyCycleError`),\n * and the `cause` message of a wrapped failure.\n */\nexport function renderError(error: TakoError): string {\n const lines = [`error [${error.code}]: ${error.message}`];\n\n const issues = (error as { issues?: unknown }).issues;\n if (Array.isArray(issues)) {\n for (const issue of issues as Issue[]) {\n const at =\n issue.path === undefined || issue.path === '' ? '<root>' : issue.path;\n lines.push(` - ${at}: ${issue.message}`);\n }\n }\n\n const cycle = (error as { cycle?: unknown }).cycle;\n if (Array.isArray(cycle) && cycle.length > 0) {\n lines.push(` cycle: ${(cycle as string[]).join(' -> ')}`);\n }\n\n const driverName = (error as { driverName?: unknown }).driverName;\n if (typeof driverName === 'string') {\n const role = (error as { role?: unknown }).role;\n const namespace = (error as { namespace?: unknown }).namespace;\n const roleLabel = typeof role === 'string' ? role : 'driver';\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` ${roleLabel}: ${driverName}${where}`);\n } else {\n const generator = (error as { generator?: unknown }).generator;\n if (typeof generator === 'string') {\n const namespace = (error as { namespace?: unknown }).namespace;\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` generator: ${generator}${where}`);\n }\n }\n\n // Wrapped failures (`DriverError`, `HookError`, `ConfigLoadError`, …) carry the\n // real error in `cause`; core masks its type, so surface at least its message.\n const cause = error.cause;\n if (cause !== undefined && cause !== null) {\n const message = cause instanceof Error ? cause.message : String(cause);\n const code = cause instanceof TakoError ? ` [${cause.code}]` : '';\n lines.push(` cause${code}: ${message}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * `tako init` — write the commented `tako.config.ts` skeleton into the current\n * directory. No prompts, no schema auto-detection; refuses to overwrite unless\n * `--force` (`backlog/features/cli/technical.md` §`tako init`).\n *\n * `--monorepo` / `--no-monorepo` picks between `CONFIG_TEMPLATE` and\n * `CONFIG_TEMPLATE_MONOREPO`; unset, it auto-detects a workspace by walking up\n * for the nearest `package.json` (`workspaces` key, or a sibling\n * `pnpm-workspace.yaml`).\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, relative, resolve } from 'node:path';\nimport { CONFIG_TEMPLATE, CONFIG_TEMPLATE_MONOREPO } from '@kurotako/config';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConfigExistsError } from '../errors.js';\nimport { ConsoleReporter } from '../reporter.js';\n\n/**\n * Walk up from `startDir` to the first directory holding a `package.json`. A\n * workspace when that `package.json` has a `workspaces` key (array, or\n * `{ packages: [...] }`), or when a `pnpm-workspace.yaml` sits next to it.\n * Returns `false` when no `package.json` is found.\n */\nfunction detectMonorepo(startDir: string): boolean {\n let dir = resolve(startDir);\n while (true) {\n const pkgPath = resolve(dir, 'package.json');\n if (existsSync(pkgPath)) {\n if (existsSync(resolve(dir, 'pnpm-workspace.yaml'))) {\n return true;\n }\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n workspaces?: unknown;\n };\n const ws = pkg.workspaces;\n if (\n Array.isArray(ws) ||\n (typeof ws === 'object' &&\n ws !== null &&\n Array.isArray((ws as { packages?: unknown }).packages))\n ) {\n return true;\n }\n } catch {\n // Unreadable / invalid package.json: treat as not a workspace.\n }\n return false;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return false;\n }\n dir = parent;\n }\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: 'init',\n description: 'create a tako.config.ts in the current directory',\n },\n args: {\n ...sharedArgs,\n force: {\n type: 'boolean',\n description: 'overwrite an existing config file',\n default: false,\n },\n monorepo: {\n type: 'boolean',\n description:\n 'write the monorepo config layout (auto-detected from workspaces when unset)',\n default: undefined,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n // Unlike `loadConfig`, `init` never walks up: it always targets `cwd`.\n const target = args.config\n ? resolve(cwd, args.config)\n : resolve(cwd, 'tako.config.ts');\n\n if (existsSync(target) && !args.force) {\n throw new ConfigExistsError(target);\n }\n\n // citty leaves an unset boolean flag `undefined` (no `default`), so\n // `--monorepo` / `--no-monorepo` win and absence falls back to detection.\n const monorepo: boolean =\n typeof args.monorepo === 'boolean' ? args.monorepo : detectMonorepo(cwd);\n\n await mkdir(dirname(target), { recursive: true });\n await writeFile(\n target,\n monorepo ? CONFIG_TEMPLATE_MONOREPO : CONFIG_TEMPLATE,\n 'utf8',\n );\n\n const name = relative(cwd, target) || 'tako.config.ts';\n reporter.info(\n monorepo ? `created ${name} (monorepo layout)` : `created ${name}`,\n );\n },\n});\n","/**\n * `tako validate` — the same checks as `generate` up to (not including)\n * emission. `loadConfig()` + `run({ write: false })`; any `TakoError` propagates\n * to the top-level handler and exits 1\n * (`backlog/features/cli/technical.md` §`tako validate`).\n */\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { loadAndRun } from './generate.js';\n\nexport const validateCommand = defineCommand({\n meta: {\n name: 'validate',\n description: 'check the config and schema without writing anything',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n await loadAndRun({\n cwd: process.cwd(),\n configPath: args.config || undefined,\n write: false,\n reporter,\n });\n reporter.info('config and schema are valid');\n },\n});\n"],"mappings":"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","names":["TakoError","defineCommand","existsSync","existsSync","relative","loadConfig","run","defineCommand","TakoError","path","loadConfig","run","path","TakoError","loadConfig","run","defineCommand","relative","existsSync","relative","resolve","defineCommand","resolve","existsSync","defineCommand","relative","defineCommand","defineCommand","defineCommand","TakoError"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/check.ts","../src/args.ts","../src/diff.ts","../src/reporter.ts","../src/commands/generate.ts","../src/watch.ts","../src/errors.ts","../src/commands/init.ts","../src/commands/validate.ts"],"sourcesContent":["/**\n * `runCli()` — build the citty command tree, dispatch, map every `TakoError` to\n * a formatted message + exit 1. `--version` / `--help` are handled here (citty's\n * own handling lives in `runMain`, which hard-exits — not what a testable\n * `runCli` wants).\n *\n * `backlog/features/cli/technical.md` §Command surface, §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\nimport { type CommandDef, defineCommand, renderUsage, runCommand } from 'citty';\nimport { checkCommand } from './commands/check.js';\nimport { generateCommand } from './commands/generate.js';\nimport { initCommand } from './commands/init.js';\nimport { validateCommand } from './commands/validate.js';\nimport { renderError } from './errors.js';\nimport { ConsoleReporter } from './reporter.js';\n\ndeclare const __TAKO_VERSION__: string;\nconst VERSION =\n typeof __TAKO_VERSION__ === 'string' ? __TAKO_VERSION__ : '0.0.0-dev';\n\nconst subCommands = {\n init: initCommand,\n generate: generateCommand,\n validate: validateCommand,\n check: checkCommand,\n};\n\nconst main = defineCommand({\n meta: {\n name: 'tako',\n version: VERSION,\n description: 'synchronise TypeScript schemas from data model to forms',\n },\n subCommands,\n});\n\nexport async function runCli(argv: string[]): Promise<void> {\n const reporter = new ConsoleReporter({\n debug: argv.includes('--debug') || Boolean(process.env.TAKO_DEBUG),\n });\n\n if (argv.includes('--version') || argv.includes('-v')) {\n process.stdout.write(`${VERSION}\\n`);\n process.exitCode ??= 0;\n return;\n }\n\n if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {\n const sub = argv.find((a) => !a.startsWith('-'));\n const isSub = sub !== undefined && sub in subCommands;\n const cmd = (\n isSub ? subCommands[sub as keyof typeof subCommands] : main\n ) as CommandDef;\n process.stdout.write(\n `${await renderUsage(cmd, isSub ? (main as CommandDef) : undefined)}\\n`,\n );\n process.exitCode ??= 0;\n return;\n }\n\n try {\n await runCommand(main, { rawArgs: argv });\n process.exitCode ??= 0;\n } catch (error) {\n if (error instanceof TakoError) {\n reporter.error(renderError(error));\n process.exitCode = 1;\n } else if (error instanceof Error && error.name === 'CLIError') {\n // citty usage error (unknown command, missing argument, …).\n reporter.error(error.message);\n process.exitCode = 1;\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n process.exitCode = 1;\n }\n }\n}\n","/**\n * `tako check` — drift guard. Runs the pipeline in plan mode (no disk writes,\n * no `afterEmit`), then compares the planned tree against what is on disk.\n * Exit 0 when they match, exit 1 on any drift or any `TakoError` (the latter\n * via the top-level handler in `cli.ts`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §Command surface.\n */\nimport { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { loadConfig } from '@kurotako/config';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport {\n comparePlanToDisk,\n type DriftEntry,\n ignoreBuildArtifacts,\n markedPackageDirs,\n} from '../diff.js';\nimport { ConsoleReporter } from '../reporter.js';\n\nexport const checkCommand = defineCommand({\n meta: {\n name: 'check',\n description:\n 'check the generated output on disk matches a fresh generate (drift guard)',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n\n const { config } = await loadConfig({\n cwd,\n configPath: args.config || undefined,\n });\n const { plan = [] } = await run(config, { logger: reporter, plan: true });\n\n const roots: string[] = [];\n const ignores: ((absPath: string) => boolean)[] = [];\n\n for (const output of config.outputs) {\n if (output.mode === 'package') {\n ignores.push(ignoreBuildArtifacts);\n if (output.packagesDir) {\n roots.push(...(await markedPackageDirs(output.packagesDir)));\n }\n } else {\n const dir = output.dir;\n if (!dir) {\n continue;\n }\n if (!existsSync(dir)) {\n reporter.info(\n `output directory ${relative(config.rootDir, dir)} does not exist — run tako generate`,\n );\n process.exitCode = 1;\n return;\n }\n roots.push(dir);\n }\n }\n\n const ignore = (absPath: string): boolean =>\n ignores.some((fn) => fn(absPath));\n\n const drift = await comparePlanToDisk({\n plan,\n roots,\n ignore,\n rootDir: config.rootDir,\n });\n\n if (drift.length === 0) {\n reporter.info('output is in sync');\n process.exitCode ??= 0;\n return;\n }\n\n reporter.error(formatDrift(drift));\n process.exitCode = 1;\n },\n});\n\nfunction formatDrift(drift: DriftEntry[]): string {\n const width = Math.max(...drift.map((entry) => entry.kind.length));\n const lines = drift.map(\n (entry) => ` ${entry.kind.padEnd(width)} ${entry.path}`,\n );\n return [\n 'drift detected',\n '',\n ...lines,\n '',\n `${drift.length} files differ from a fresh generate. Run \\`tako generate\\`.`,\n ].join('\\n');\n}\n","/**\n * `sharedArgs` — the options every sub-command carries. citty has no\n * first-class global-option slot, so this object is spread into each command's\n * `args` (`backlog/features/cli/technical.md` §Global option).\n */\nimport type { ArgsDef } from 'citty';\n\nexport const sharedArgs = {\n config: {\n type: 'string',\n description: 'path to the tako config file (default: ./tako.config.ts)',\n },\n /** Hidden: not advertised, kept minimal. Enables `debug` reporter output. */\n debug: {\n type: 'boolean',\n default: false,\n },\n} as const satisfies ArgsDef;\n","/**\n * `comparePlanToDisk` — the in-memory comparison behind `tako check`. Takes the\n * `PlannedFile[]` a fresh `generate` would write (from `run({ plan: true })`)\n * and reports every way the tree on disk diverges from it: a planned file that\n * is absent (`missing`) or whose bytes differ (`modified`), and any file under\n * the scanned roots that no planned file claims (`orphan`).\n *\n * Design: `backlog/features/drift-guard/technical.md` §The comparison.\n */\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PlannedFile } from '@kurotako/core';\n\nexport type DriftKind = 'modified' | 'missing' | 'orphan';\n\nexport interface DriftEntry {\n kind: DriftKind;\n /** Relative to `rootDir`, POSIX separators; a collapsed dir ends with `/`. */\n path: string;\n}\n\nexport interface ComparePlanToDiskArgs {\n plan: PlannedFile[];\n /** Directories walked for orphans (absolute). */\n roots: string[];\n /** Return `true` to exclude an absolute path from the orphan scan. */\n ignore: (absPath: string) => boolean;\n /** Anchor for the reported relative paths (the config-file directory). */\n rootDir: string;\n}\n\nfunction toPosix(rootDir: string, absPath: string): string {\n return path.relative(rootDir, absPath).split(path.sep).join('/');\n}\n\nexport async function comparePlanToDisk(\n args: ComparePlanToDiskArgs,\n): Promise<DriftEntry[]> {\n const { plan, roots, ignore, rootDir } = args;\n const plannedByPath = new Map(plan.map((f) => [path.resolve(f.path), f]));\n const entries: DriftEntry[] = [];\n\n // 1. Expected vs disk.\n for (const [absPath, file] of plannedByPath) {\n if (!existsSync(absPath)) {\n entries.push({ kind: 'missing', path: toPosix(rootDir, absPath) });\n continue;\n }\n const onDisk = await readFile(absPath, 'utf8');\n if (onDisk !== file.content) {\n entries.push({ kind: 'modified', path: toPosix(rootDir, absPath) });\n }\n }\n\n // 2. Orphan scan — a planned file lives under `dir` iff any planned absolute\n // path is `dir` itself or sits below it.\n const plannedPaths = [...plannedByPath.keys()];\n const hasPlannedUnder = (dir: string): boolean => {\n const prefix = `${dir}${path.sep}`;\n return plannedPaths.some((p) => p === dir || p.startsWith(prefix));\n };\n\n const seenRoots = new Set<string>();\n for (const root of roots) {\n const absRoot = path.resolve(root);\n if (seenRoots.has(absRoot) || !existsSync(absRoot)) {\n continue;\n }\n seenRoots.add(absRoot);\n await scan(absRoot);\n }\n\n async function scan(dir: string): Promise<void> {\n // A directory with no planned file underneath collapses to a single entry —\n // unless it holds nothing but ignored files (e.g. only `dist/`).\n if (!hasPlannedUnder(dir)) {\n if (await hasNonIgnoredFile(dir)) {\n entries.push({ kind: 'orphan', path: `${toPosix(rootDir, dir)}/` });\n }\n return;\n }\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isDirectory()) {\n await scan(abs);\n } else if (dirent.isFile() && !plannedByPath.has(abs)) {\n entries.push({ kind: 'orphan', path: toPosix(rootDir, abs) });\n }\n }\n }\n\n async function hasNonIgnoredFile(dir: string): Promise<boolean> {\n for (const dirent of await readdir(dir, { withFileTypes: true })) {\n const abs = path.join(dir, dirent.name);\n if (ignore(abs)) {\n continue;\n }\n if (dirent.isFile()) {\n return true;\n }\n if (dirent.isDirectory() && (await hasNonIgnoredFile(abs))) {\n return true;\n }\n }\n return false;\n }\n\n entries.sort((a, b) =>\n a.path < b.path\n ? -1\n : a.path > b.path\n ? 1\n : a.kind < b.kind\n ? -1\n : a.kind > b.kind\n ? 1\n : 0,\n );\n return entries;\n}\n\n/** Rejects `dist/` and `node_modules/` anywhere in the path (mode B). */\nexport function ignoreBuildArtifacts(absPath: string): boolean {\n return /(^|[/\\\\])(dist|node_modules)([/\\\\]|$)/.test(absPath);\n}\n\n/**\n * Whether `<packagesDir>/<name>` looks like a directory `tako` generated: a\n * `package.json` whose `\"//\"` marker starts with `Generated by tako`.\n */\nexport async function hasGeneratedMarker(pkgDir: string): Promise<boolean> {\n try {\n const pkg = JSON.parse(\n await readFile(path.join(pkgDir, 'package.json'), 'utf8'),\n ) as { '//'?: unknown };\n return (\n typeof pkg['//'] === 'string' && pkg['//'].startsWith('Generated by tako')\n );\n } catch {\n return false;\n }\n}\n\n/** Every immediate subdirectory of `packagesDir` carrying the tako marker. */\nexport async function markedPackageDirs(\n packagesDir: string,\n): Promise<string[]> {\n if (!existsSync(packagesDir)) {\n return [];\n }\n const out: string[] = [];\n for (const dirent of await readdir(packagesDir, { withFileTypes: true })) {\n if (!dirent.isDirectory()) {\n continue;\n }\n const abs = path.join(packagesDir, dirent.name);\n if (await hasGeneratedMarker(abs)) {\n out.push(abs);\n }\n }\n return out.sort();\n}\n","/**\n * `ConsoleReporter` — the `@kurotako/core` `Logger` the CLI injects into\n * `loadConfig()` / `run()`, plus the per-phase / summary output.\n *\n * Contract (`backlog/features/cli/technical.md` §Reporter):\n * - human output goes to **stderr**, `stdout` stays clean;\n * - `info` / `warn` / `error` shown by default; `debug` only with `--debug` /\n * `TAKO_DEBUG` (a hidden flag, not advertised);\n * - the human-readable message is always shown; the structured `meta` object is\n * printed only with `--debug` (a custom `Logger` still receives it in full),\n * so default output stays prose, not `key=value` noise;\n * - `tako ` prefix, level-coloured; colour auto-off when the stream is not a TTY\n * or `NO_COLOR` is set;\n * - `child(tag)` returns a `Logger` tagging every `meta` with `{ scope: tag }`.\n */\nimport { childLogger, type Logger } from '@kurotako/core';\n\ntype Level = 'debug' | 'info' | 'warn' | 'error';\n\n/** The slice of a writable stream the reporter needs (keeps tests trivial). */\nexport interface WriteStream {\n write(chunk: string): unknown;\n isTTY?: boolean;\n}\n\nexport interface ConsoleReporterOptions {\n /** Show `debug` output. Default: `false` unless `TAKO_DEBUG` is set. */\n debug?: boolean;\n /** Sink for human output. Default: `process.stderr`. */\n stream?: WriteStream;\n /** Force colour on/off. Default: auto (TTY and no `NO_COLOR`). */\n color?: boolean;\n}\n\nconst ESC = String.fromCharCode(27);\nconst ANSI: Record<Level, string> = {\n debug: `${ESC}[2m`, // dim\n info: `${ESC}[36m`, // cyan\n warn: `${ESC}[33m`, // yellow\n error: `${ESC}[31m`, // red\n};\nconst ANSI_RESET = `${ESC}[0m`;\n\nexport class ConsoleReporter implements Logger {\n private readonly stream: WriteStream;\n private readonly showDebug: boolean;\n private readonly color: boolean;\n\n constructor(options: ConsoleReporterOptions = {}) {\n this.stream = options.stream ?? process.stderr;\n this.showDebug = options.debug ?? Boolean(process.env.TAKO_DEBUG);\n this.color =\n options.color ??\n (Boolean(this.stream.isTTY) && process.env.NO_COLOR === undefined);\n }\n\n debug(msg: string, meta?: unknown): void {\n if (this.showDebug) {\n this.write('debug', msg, meta);\n }\n }\n\n info(msg: string, meta?: unknown): void {\n this.write('info', msg, meta);\n }\n\n warn(msg: string, meta?: unknown): void {\n this.write('warn', msg, meta);\n }\n\n error(msg: string, meta?: unknown): void {\n this.write('error', msg, meta);\n }\n\n /** A child `Logger` whose calls carry `{ scope: tag }` in `meta`. */\n child(tag: string): Logger {\n return childLogger(this, { scope: tag });\n }\n\n private write(level: Level, msg: string, meta?: unknown): void {\n const prefix = this.color ? `${ANSI[level]}tako${ANSI_RESET}` : 'tako';\n const detail =\n meta === undefined || !this.showDebug ? '' : ` ${formatMeta(meta)}`;\n this.stream.write(`${prefix} ${msg}${detail}\\n`);\n }\n}\n\nfunction formatMeta(meta: unknown): string {\n if (meta !== null && typeof meta === 'object' && !Array.isArray(meta)) {\n return Object.entries(meta as Record<string, unknown>)\n .map(([k, v]) => `${k}=${stringify(v)}`)\n .join(' ');\n }\n return stringify(meta);\n}\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","/**\n * `tako generate` — `loadConfig()` then `run()`. `--dry-run` runs everything but\n * skips the Writer; `--watch` hands off to the chokidar loop\n * (`backlog/features/cli/technical.md` §`tako generate`).\n */\nimport { relative } from 'node:path';\nimport { type LoadResult, loadConfig } from '@kurotako/config';\nimport type { OutputConfig, ResolvedConfig, RunResult } from '@kurotako/core';\nimport { run } from '@kurotako/core';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { watchAndRun } from '../watch.js';\n\nexport interface LoadAndRunOptions {\n cwd: string;\n configPath?: string;\n write: boolean;\n signal?: AbortSignal;\n reporter: ConsoleReporter;\n}\n\nexport interface LoadAndRunResult {\n result: RunResult;\n config: ResolvedConfig;\n configFile: string;\n rootDir: string;\n}\n\n/** The directory named in the `wrote N files -> …` summary line, for one output. */\nexport function outputSummaryDir(\n output: OutputConfig,\n config: ResolvedConfig,\n): string {\n return output.mode === 'package'\n ? (output.packagesDir ?? config.rootDir)\n : (output.dir ?? config.rootDir);\n}\n\n/**\n * The shared body of `generate`, `validate` and each watch cycle: resolve +\n * load the config, then run the pipeline. `write: false` also skips the\n * `afterEmit` hook (`@kurotako/core` `run()`).\n */\nexport async function loadAndRun(\n opts: LoadAndRunOptions,\n): Promise<LoadAndRunResult> {\n const loaded: LoadResult = await loadConfig({\n cwd: opts.cwd,\n configPath: opts.configPath,\n });\n const result = await run(loaded.config, {\n logger: opts.reporter,\n write: opts.write,\n signal: opts.signal,\n });\n return {\n result,\n config: loaded.config,\n configFile: loaded.configFile,\n rootDir: loaded.rootDir,\n };\n}\n\nexport const generateCommand = defineCommand({\n meta: {\n name: 'generate',\n description: 'run the pipeline and write the generated code',\n },\n args: {\n ...sharedArgs,\n watch: {\n type: 'boolean',\n description: 'rebuild on every schema / config change',\n default: false,\n },\n 'dry-run': {\n type: 'boolean',\n description: 'run everything but write nothing',\n default: false,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n const configPath = args.config || undefined;\n\n if (args.watch) {\n await watchAndRun({ cwd, configPath, reporter });\n return;\n }\n\n const dryRun = Boolean(args['dry-run']);\n const { result, config } = await loadAndRun({\n cwd,\n configPath,\n write: !dryRun,\n reporter,\n });\n\n if (dryRun) {\n reporter.info(`dry run: ${result.files.length} files would be written`);\n return;\n }\n\n const dirs = config.outputs\n .map((output) => relative(cwd, outputSummaryDir(output, config)))\n .join(', ');\n reporter.info(`wrote ${result.files.length} files -> ${dirs}`);\n },\n});\n","/**\n * `tako generate --watch` — a chokidar loop around `loadConfig()` + `run()`.\n * Full regeneration on every change (no incremental). A 100 ms trailing\n * debounce coalesces bursts; a change mid-cycle aborts the in-flight `run()`\n * (via `RunOptions.signal`) and re-runs once it settles. `loadConfig` failures\n * are reported, not fatal — the watcher stays up on `tako.config.ts`.\n *\n * `backlog/features/cli/technical.md` §Watch mode.\n */\nimport { basename, resolve } from 'node:path';\nimport {\n type LoadResult,\n loadConfig as realLoadConfig,\n} from '@kurotako/config';\nimport { run as realRun, TakoError } from '@kurotako/core';\nimport chokidar from 'chokidar';\nimport { renderError } from './errors.js';\nimport type { ConsoleReporter } from './reporter.js';\n\n/** Minimal watcher seam so the loop is unit-testable without touching the fs. */\nexport interface Watcher {\n add(paths: string | readonly string[]): void;\n unwatch(paths: string | readonly string[]): void;\n on(handler: (event: string, path: string) => void): void;\n close(): Promise<void>;\n}\n\nexport interface WatchAndRunOptions {\n cwd: string;\n configPath?: string;\n reporter: ConsoleReporter;\n}\n\nexport interface WatchDeps {\n createWatcher: () => Watcher;\n loadConfig: typeof realLoadConfig;\n run: typeof realRun;\n debounceMs: number;\n}\n\nconst DEBOUNCE_MS = 100;\n\nfunction chokidarWatcher(): Watcher {\n const fsw = chokidar.watch([], {\n ignoreInitial: true,\n awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 20 },\n });\n return {\n add: (paths) => fsw.add(paths as string | string[]),\n unwatch: (paths) => fsw.unwatch(paths as string | string[]),\n on: (handler) => {\n fsw.on('add', (p) => handler('add', p));\n fsw.on('change', (p) => handler('change', p));\n fsw.on('unlink', (p) => handler('unlink', p));\n },\n close: () => fsw.close(),\n };\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError';\n}\n\n/**\n * Runs until `SIGINT` / `SIGTERM`, then closes the watcher and resolves so the\n * caller can exit 0. (The design doc types this `Promise<never>`; it resolves\n * on shutdown here purely so it stays testable.)\n */\nexport async function watchAndRun(\n opts: WatchAndRunOptions,\n deps: Partial<WatchDeps> = {},\n): Promise<void> {\n const { cwd, configPath, reporter } = opts;\n const createWatcher = deps.createWatcher ?? chokidarWatcher;\n const loadConfig = deps.loadConfig ?? realLoadConfig;\n const run = deps.run ?? realRun;\n const debounceMs = deps.debounceMs ?? DEBOUNCE_MS;\n\n const watcher = createWatcher();\n let watched = new Set<string>();\n let inFlight: AbortController | null = null;\n let queued = false;\n let closed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let reason = 'initial build';\n\n const guessedConfigFile = configPath\n ? resolve(cwd, configPath)\n : resolve(cwd, 'tako.config.ts');\n\n function applyWatchSet(desired: Set<string>): void {\n for (const path of desired) {\n if (!watched.has(path)) {\n watcher.add(path);\n }\n }\n for (const path of watched) {\n if (!desired.has(path)) {\n watcher.unwatch(path);\n }\n }\n watched = desired;\n }\n\n async function reconcileWatchSet(loaded: LoadResult): Promise<void> {\n const desired = new Set<string>([loaded.configFile]);\n for (const [namespace, source] of Object.entries(loaded.config.sources)) {\n const paths =\n (await source.parser.watchPaths?.({\n namespace,\n cwd: loaded.rootDir,\n logger: reporter,\n })) ?? [];\n for (const path of paths) {\n desired.add(resolve(loaded.rootDir, path));\n }\n }\n applyWatchSet(desired);\n }\n\n async function cycle(): Promise<void> {\n const why = reason;\n reporter.info(`--- rebuild (${why}) ---`);\n const ac = new AbortController();\n inFlight = ac;\n try {\n const loaded = await loadConfig({ cwd, configPath });\n await reconcileWatchSet(loaded);\n const result = await run(loaded.config, {\n logger: reporter,\n signal: ac.signal,\n write: true,\n });\n if (!ac.signal.aborted) {\n reporter.info(`wrote ${result.files.length} files`);\n }\n } catch (error) {\n if (isAbortError(error) || ac.signal.aborted) {\n // Superseded by a newer cycle — swallow.\n } else if (error instanceof TakoError) {\n reporter.error(renderError(error));\n // Keep watching at least the config file so a fix is picked up.\n applyWatchSet(new Set([...watched, guessedConfigFile]));\n } else {\n reporter.error('internal error (this is a bug):');\n console.error(error);\n }\n } finally {\n inFlight = null;\n if (queued && !closed) {\n queued = false;\n await cycle();\n }\n }\n }\n\n function trigger(): void {\n if (inFlight) {\n queued = true;\n inFlight.abort();\n return;\n }\n void cycle();\n }\n\n function schedule(event: string, path: string): void {\n if (closed) {\n return;\n }\n reason = `${basename(path)} ${event === 'unlink' ? 'removed' : 'changed'}`;\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => {\n timer = null;\n trigger();\n }, debounceMs);\n }\n\n watcher.on(schedule);\n\n // Initial cycle: a failure is reported inside `cycle()`, never fatal.\n applyWatchSet(new Set([guessedConfigFile]));\n await cycle();\n reporter.info(`watching ${watched.size} paths`);\n\n await new Promise<void>((resolvePromise) => {\n const shutdown = () => {\n closed = true;\n if (timer) {\n clearTimeout(timer);\n }\n inFlight?.abort();\n process.off('SIGINT', shutdown);\n process.off('SIGTERM', shutdown);\n void watcher.close().finally(() => resolvePromise());\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n}\n","/**\n * CLI-owned error(s) and `renderError()` — the single formatter the top-level\n * handler in `cli.ts` uses for any `TakoError` (from `@kurotako/core`,\n * `@kurotako/config`, or this package).\n *\n * `backlog/features/cli/technical.md` §Errors and exit codes.\n */\nimport { TakoError } from '@kurotako/core';\n\n/** `tako init` refuses to overwrite an existing config unless `--force`. */\nexport class ConfigExistsError extends TakoError {\n readonly path: string;\n\n constructor(path: string) {\n super(\n 'config_exists',\n `a config file already exists at '${path}' (pass --force to overwrite)`,\n );\n this.path = path;\n }\n}\n\ninterface Issue {\n path?: string;\n message?: string;\n}\n\n/**\n * `error [<code>]: <message>` plus any carried context on its own indented\n * lines: located issues (`ConfigShapeError`, `IrValidationError`,\n * `DriverOptionsError`), the offending driver / namespace (`DriverError`,\n * `UnknownNamespaceError`), the dependency cycle path (`DependencyCycleError`),\n * and the `cause` message of a wrapped failure.\n */\nexport function renderError(error: TakoError): string {\n const lines = [`error [${error.code}]: ${error.message}`];\n\n const issues = (error as { issues?: unknown }).issues;\n if (Array.isArray(issues)) {\n for (const issue of issues as Issue[]) {\n const at =\n issue.path === undefined || issue.path === '' ? '<root>' : issue.path;\n lines.push(` - ${at}: ${issue.message}`);\n }\n }\n\n const cycle = (error as { cycle?: unknown }).cycle;\n if (Array.isArray(cycle) && cycle.length > 0) {\n lines.push(` cycle: ${(cycle as string[]).join(' -> ')}`);\n }\n\n const driverName = (error as { driverName?: unknown }).driverName;\n if (typeof driverName === 'string') {\n const role = (error as { role?: unknown }).role;\n const namespace = (error as { namespace?: unknown }).namespace;\n const roleLabel = typeof role === 'string' ? role : 'driver';\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` ${roleLabel}: ${driverName}${where}`);\n } else {\n const generator = (error as { generator?: unknown }).generator;\n if (typeof generator === 'string') {\n const namespace = (error as { namespace?: unknown }).namespace;\n const where =\n typeof namespace === 'string' ? ` (namespace '${namespace}')` : '';\n lines.push(` generator: ${generator}${where}`);\n }\n }\n\n // Wrapped failures (`DriverError`, `HookError`, `ConfigLoadError`, …) carry the\n // real error in `cause`; core masks its type, so surface at least its message.\n const cause = error.cause;\n if (cause !== undefined && cause !== null) {\n const message = cause instanceof Error ? cause.message : String(cause);\n const code = cause instanceof TakoError ? ` [${cause.code}]` : '';\n lines.push(` cause${code}: ${message}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * `tako init` — write the commented `tako.config.ts` skeleton into the current\n * directory. No prompts, no schema auto-detection; refuses to overwrite unless\n * `--force` (`backlog/features/cli/technical.md` §`tako init`).\n *\n * `--monorepo` / `--no-monorepo` picks between `CONFIG_TEMPLATE` and\n * `CONFIG_TEMPLATE_MONOREPO`; unset, it auto-detects a workspace by walking up\n * for the nearest `package.json` (`workspaces` key, or a sibling\n * `pnpm-workspace.yaml`).\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, relative, resolve } from 'node:path';\nimport { CONFIG_TEMPLATE, CONFIG_TEMPLATE_MONOREPO } from '@kurotako/config';\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConfigExistsError } from '../errors.js';\nimport { ConsoleReporter } from '../reporter.js';\n\n/**\n * Walk up from `startDir` to the first directory holding a `package.json`. A\n * workspace when that `package.json` has a `workspaces` key (array, or\n * `{ packages: [...] }`), or when a `pnpm-workspace.yaml` sits next to it.\n * Returns `false` when no `package.json` is found.\n */\nfunction detectMonorepo(startDir: string): boolean {\n let dir = resolve(startDir);\n while (true) {\n const pkgPath = resolve(dir, 'package.json');\n if (existsSync(pkgPath)) {\n if (existsSync(resolve(dir, 'pnpm-workspace.yaml'))) {\n return true;\n }\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n workspaces?: unknown;\n };\n const ws = pkg.workspaces;\n if (\n Array.isArray(ws) ||\n (typeof ws === 'object' &&\n ws !== null &&\n Array.isArray((ws as { packages?: unknown }).packages))\n ) {\n return true;\n }\n } catch {\n // Unreadable / invalid package.json: treat as not a workspace.\n }\n return false;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return false;\n }\n dir = parent;\n }\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: 'init',\n description: 'create a tako.config.ts in the current directory',\n },\n args: {\n ...sharedArgs,\n force: {\n type: 'boolean',\n description: 'overwrite an existing config file',\n default: false,\n },\n monorepo: {\n type: 'boolean',\n description:\n 'write the monorepo config layout (auto-detected from workspaces when unset)',\n default: undefined,\n },\n },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n const cwd = process.cwd();\n // Unlike `loadConfig`, `init` never walks up: it always targets `cwd`.\n const target = args.config\n ? resolve(cwd, args.config)\n : resolve(cwd, 'tako.config.ts');\n\n if (existsSync(target) && !args.force) {\n throw new ConfigExistsError(target);\n }\n\n // citty leaves an unset boolean flag `undefined` (no `default`), so\n // `--monorepo` / `--no-monorepo` win and absence falls back to detection.\n const monorepo: boolean =\n typeof args.monorepo === 'boolean' ? args.monorepo : detectMonorepo(cwd);\n\n await mkdir(dirname(target), { recursive: true });\n await writeFile(\n target,\n monorepo ? CONFIG_TEMPLATE_MONOREPO : CONFIG_TEMPLATE,\n 'utf8',\n );\n\n const name = relative(cwd, target) || 'tako.config.ts';\n reporter.info(\n monorepo ? `created ${name} (monorepo layout)` : `created ${name}`,\n );\n },\n});\n","/**\n * `tako validate` — the same checks as `generate` up to (not including)\n * emission. `loadConfig()` + `run({ write: false })`; any `TakoError` propagates\n * to the top-level handler and exits 1\n * (`backlog/features/cli/technical.md` §`tako validate`).\n */\nimport { defineCommand } from 'citty';\nimport { sharedArgs } from '../args.js';\nimport { ConsoleReporter } from '../reporter.js';\nimport { loadAndRun } from './generate.js';\n\nexport const validateCommand = defineCommand({\n meta: {\n name: 'validate',\n description: 'check the config and schema without writing anything',\n },\n args: { ...sharedArgs },\n run: async ({ args }) => {\n const reporter = new ConsoleReporter({ debug: Boolean(args.debug) });\n await loadAndRun({\n cwd: process.cwd(),\n configPath: args.config || undefined,\n write: false,\n reporter,\n });\n reporter.info('config and schema are valid');\n },\n});\n"],"mappings":"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","names":["TakoError","defineCommand","existsSync","existsSync","relative","loadConfig","run","defineCommand","TakoError","path","loadConfig","run","path","TakoError","loadConfig","run","defineCommand","relative","existsSync","relative","resolve","defineCommand","resolve","existsSync","defineCommand","relative","defineCommand","defineCommand","defineCommand","TakoError"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kurotako/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The tako command-line interface for kurotako.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kurotako",
|
|
@@ -50,13 +50,14 @@
|
|
|
50
50
|
"tako": "./dist/bin/tako.js"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@kurotako/config": "^0.1.
|
|
54
|
-
"@kurotako/core": "^0.1.
|
|
53
|
+
"@kurotako/config": "^0.1.3",
|
|
54
|
+
"@kurotako/core": "^0.1.3",
|
|
55
55
|
"chokidar": "^5",
|
|
56
56
|
"citty": "0.2.2"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@kurotako/gen-
|
|
60
|
-
"@kurotako/
|
|
59
|
+
"@kurotako/gen-typescript": "^0.3.2",
|
|
60
|
+
"@kurotako/gen-zod": "^0.3.1",
|
|
61
|
+
"@kurotako/parser-prisma": "^0.2.2"
|
|
61
62
|
}
|
|
62
63
|
}
|