@dudousxd/nestjs-inertia-codegen 1.0.7 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/main.ts","../../src/config/load-config.ts","../../src/exceptions.ts","../../src/discovery/pages.ts","../../src/emit/emit-api.ts","../../src/emit/emit-cache.ts","../../src/emit/emit-index.ts","../../src/emit/emit-pages.ts","../../src/emit/emit-routes.ts","../../src/generate.ts","../../src/watch/watcher.ts","../../src/discovery/contracts-fast.ts","../../src/watch/lock-file.ts","../../src/index.ts","../../src/cli/codegen.ts","../../src/cli/init.ts"],"sourcesContent":["import { cac } from 'cac';\nimport { VERSION } from '../index.js';\nimport { runCodegen } from './codegen.js';\nimport { runInit } from './init.js';\n\n/**\n * Parse `argv` (everything after `node <bin>`) and execute the matched command.\n *\n * Returns an exit code: 0 = success, 1 = error.\n *\n * Exported so tests can call `run(argv)` directly without spawning a subprocess.\n */\nexport async function run(argv: string[]): Promise<number> {\n const cli = cac('nestjs-inertia');\n\n cli\n .command('codegen', 'Generate typed artifacts from your NestJS + Inertia app')\n .option('--watch', 'Watch for file changes and re-generate automatically')\n .action(async (opts: { watch?: boolean }) => {\n await runCodegen({ watch: Boolean(opts.watch), cwd: process.cwd() });\n });\n\n cli\n .command('init', 'Initialise nestjs-inertia-codegen in the current project')\n .action(async () => {\n await runInit({ cwd: process.cwd() });\n });\n\n cli.help();\n cli.version(VERSION);\n\n try {\n // cac needs the first two argv entries to be 'node' and the binary name\n cli.parse(['node', 'nestjs-inertia', ...argv], { run: false });\n await cli.runMatchedCommand();\n return 0;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`[nestjs-inertia] Error: ${message}`);\n return 1;\n }\n}\n","import { access } from 'node:fs/promises';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { ConfigError } from '../exceptions.js';\nimport type { ResolvedConfig, UserConfig } from './types.js';\n\nconst CONFIG_FILE = 'nestjs-inertia.config.ts';\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function importTs(filePath: string): Promise<unknown> {\n // Use tsx ESM API to load TypeScript config files at runtime\n let tsImport:\n | ((specifier: string, options: string | { parentURL: string }) => Promise<unknown>)\n | undefined;\n try {\n const tsxEsm = await import('tsx/esm/api');\n tsImport = tsxEsm.tsImport;\n } catch {\n throw new ConfigError(\n 'Failed to load config: `tsx` is required for loading TypeScript config files. ' +\n 'Install it as a dev dependency: pnpm add -D tsx',\n );\n }\n\n const parentURL = pathToFileURL(`${filePath}__parent__`).href;\n const fileUrl = pathToFileURL(filePath).href;\n return tsImport(fileUrl, { parentURL });\n}\n\nfunction resolveAbsolute(cwd: string, p: string): string {\n if (isAbsolute(p)) return p;\n return resolve(cwd, p);\n}\n\n/**\n * Validates that `resolvedPath` is contained inside `cwd`.\n * Throws `ConfigError` if the path escapes the project root (e.g. via `..`\n * traversal or an absolute path outside cwd).\n */\nfunction assertInsideCwd(cwd: string, resolvedPath: string, fieldName: string): void {\n const rel = relative(cwd, resolvedPath);\n // relative() returns a path starting with '..' when the target is outside cwd,\n // and isAbsolute() catches platform edge-cases (e.g. Windows drive letters).\n if (rel.startsWith(`..${sep}`) || rel === '..' || isAbsolute(rel)) {\n throw new ConfigError(\n `\\`${fieldName}\\` must be inside the project cwd.\\n Resolved to: ${resolvedPath}\\n Project cwd: ${cwd}\\nIf this is intentional, move the file inside your project directory.`,\n );\n }\n}\n\nfunction applyDefaults(userConfig: UserConfig, cwd: string): ResolvedConfig {\n const outDir = userConfig.codegen?.outDir\n ? resolveAbsolute(cwd, userConfig.codegen.outDir)\n : join(cwd, '.nestjs-inertia');\n\n const resolvedCwd = userConfig.codegen?.cwd ? resolveAbsolute(cwd, userConfig.codegen.cwd) : cwd;\n\n let app: ResolvedConfig['app'] = null;\n if (userConfig.app) {\n const resolvedEntry = resolveAbsolute(cwd, userConfig.app.moduleEntry);\n assertInsideCwd(cwd, resolvedEntry, 'app.moduleEntry');\n\n let resolvedTsconfig: string | null = null;\n if (userConfig.app.tsconfig) {\n resolvedTsconfig = resolveAbsolute(cwd, userConfig.app.tsconfig);\n assertInsideCwd(cwd, resolvedTsconfig, 'app.tsconfig');\n }\n\n app = {\n moduleEntry: resolvedEntry,\n tsconfig: resolvedTsconfig,\n };\n }\n\n return {\n pages: {\n glob: userConfig.pages.glob,\n propsExport: userConfig.pages.propsExport ?? 'ComponentProps',\n componentNameStrategy: userConfig.pages.componentNameStrategy ?? 'relative-no-ext',\n },\n contracts: {\n glob: userConfig.contracts?.glob ?? 'src/**/*.controller.ts',\n debounceMs: userConfig.contracts?.debounceMs ?? 500,\n },\n scopes: userConfig.scopes ?? {},\n codegen: {\n outDir,\n cwd: resolvedCwd,\n },\n app,\n };\n}\n\nexport async function loadConfig(cwd?: string): Promise<ResolvedConfig> {\n const resolvedCwd = cwd ?? process.cwd();\n const configPath = join(resolvedCwd, CONFIG_FILE);\n\n if (!(await fileExists(configPath))) {\n throw new ConfigError(\n `Config file not found: ${configPath}\\nRun \\`nestjs-inertia init\\` to create a starter config.`,\n );\n }\n\n let mod: unknown;\n try {\n mod = await importTs(configPath);\n } catch (err) {\n if (err instanceof ConfigError) throw err;\n throw new ConfigError(`Failed to load config from ${configPath}`, { cause: err });\n }\n\n // tsImport returns a namespace module where `mod.default` is the module namespace object.\n // The actual `export default` value lives at `mod.default.default` (or `mod.default` for CJS interop).\n const modNs = (mod as Record<string, unknown>).default;\n const userConfig =\n modNs != null && typeof modNs === 'object' && 'default' in (modNs as object)\n ? ((modNs as Record<string, unknown>).default as UserConfig)\n : (modNs as UserConfig | undefined);\n\n if (!userConfig || typeof userConfig !== 'object') {\n throw new ConfigError(\n `Config file must have a default export. Did you forget \\`export default defineConfig({...})\\`? (${configPath})`,\n );\n }\n\n if (!userConfig.pages || typeof userConfig.pages.glob !== 'string') {\n throw new ConfigError(`Config validation failed: \\`pages.glob\\` is required (${configPath})`);\n }\n\n return applyDefaults(userConfig, resolvedCwd);\n}\n","export class ConfigError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'ConfigError';\n }\n}\n\nexport class CodegenError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'CodegenError';\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { relative } from 'node:path';\nimport fg from 'fast-glob';\n\nexport interface DiscoveredPage {\n name: string;\n absolutePath: string;\n relativePath: string;\n propsSource: string | null;\n}\n\nexport interface DiscoverPagesOptions {\n glob: string;\n cwd: string;\n propsExport: string;\n componentNameStrategy: 'relative-no-ext' | 'kebab' | ((path: string) => string);\n}\n\nexport async function discoverPages(opts: DiscoverPagesOptions): Promise<DiscoveredPage[]> {\n const files = await fg(opts.glob, { cwd: opts.cwd, absolute: true });\n files.sort();\n const out: DiscoveredPage[] = [];\n for (const file of files) {\n const rel = relative(opts.cwd, file);\n const name = computeName(rel, opts.componentNameStrategy);\n const source = await readFile(file, 'utf8');\n const propsSource = extractPropsSource(source, opts.propsExport);\n out.push({ name, absolutePath: file, relativePath: rel, propsSource });\n }\n return out;\n}\n\nfunction computeName(rel: string, strat: DiscoverPagesOptions['componentNameStrategy']): string {\n if (typeof strat === 'function') return strat(rel);\n const noExt = rel.replace(/\\.(tsx?|vue|svelte)$/, '');\n if (strat === 'kebab') return noExt.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n return noExt;\n}\n\nfunction extractPropsSource(source: string, exportName: string): string | null {\n const re = new RegExp(`export\\\\s+type\\\\s+${exportName}\\\\s*=\\\\s*`, 'm');\n const m = source.match(re);\n if (!m) return null;\n const start = m.index! + m[0].length;\n // Brace counting to capture type body\n let i = start;\n let depth = 0;\n let started = false;\n while (i < source.length) {\n const c = source[i];\n if (c === '{') {\n depth++;\n started = true;\n } else if (c === '}') {\n depth--;\n if (started && depth === 0) {\n return source.slice(start, i + 1);\n }\n } else if (c === ';' && !started) return source.slice(start, i);\n i++;\n }\n return source.slice(start);\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * Emits `api.ts` into `outDir` for all routes that carry a `.contract`.\n * - GET routes get `queryOptions`\n * - POST/PUT/PATCH/DELETE routes get `mutationOptions`\n */\nexport async function emitApi(routes: RouteDescriptor[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const content = buildApiFile(routes);\n await writeFile(join(outDir, 'api.ts'), content, 'utf8');\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Split a dot-notation name into its path segments. */\nfunction splitName(name: string): string[] {\n return name.split('.');\n}\n\n/**\n * Check whether a segment is a valid JS identifier.\n * If not, we wrap it in quotes so it produces a valid object key.\n */\nfunction toObjectKey(segment: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(segment)) {\n return segment;\n }\n return JSON.stringify(segment);\n}\n\n/**\n * Convert an arbitrary string segment to camelCase by splitting on non-alphanumeric chars.\n */\nfunction toCamelCase(s: string): string {\n return s\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((word, i) =>\n i === 0\n ? word.charAt(0).toLowerCase() + word.slice(1)\n : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n )\n .join('');\n}\n\n/**\n * Validate that a single name segment matches camelCase: starts with a lowercase letter,\n * followed only by alphanumeric chars. Throws a descriptive error on invalid segments.\n */\nfunction validateNameSegment(seg: string, fullName: string): void {\n if (!/^[a-z][a-zA-Z0-9]*$/.test(seg)) {\n const suggested = toCamelCase(seg);\n throw new Error(\n `Contract name \"${fullName}\" has invalid segment \"${seg}\". Use camelCase identifiers only (lowercase letter then alphanumeric). Suggested: \"${suggested}\"`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nested tree helpers\n// ---------------------------------------------------------------------------\n\ntype LeafEntry = {\n kind: 'leaf';\n method: string;\n name: string;\n path: string;\n contractSource: {\n query: string | null | undefined;\n body: string | null | undefined;\n response: string;\n };\n};\n\ntype BranchEntry = {\n kind: 'branch';\n children: Map<string, TreeNode>;\n};\n\ntype TreeNode = LeafEntry | BranchEntry;\n\nfunction detectCollisions(tree: Map<string, TreeNode>, name: string): void {\n // Walk to ensure no node that is a leaf also has children (or vice versa).\n // Called after insertion; we scan top-level keys for conflicts.\n for (const [key, node] of tree) {\n if (node.kind === 'leaf') {\n // A leaf at this position is fine\n } else {\n void key; // branch is fine too\n }\n }\n void name;\n}\n\n/**\n * Insert a contracted route into the mutable tree.\n * Throws if a name conflict is detected.\n */\nfunction insertIntoTree(\n tree: Map<string, TreeNode>,\n segments: string[],\n leaf: LeafEntry,\n fullName: string,\n): void {\n const head = segments[0] as string;\n const rest = segments.slice(1);\n\n if (rest.length === 0) {\n // This is the final segment — insert as a leaf\n const existing = tree.get(head);\n if (existing !== undefined && existing.kind === 'branch') {\n throw new Error(\n `Contract name conflict: \"${fullName}\" cannot have both a direct entry and child entries`,\n );\n }\n tree.set(head, leaf);\n } else {\n // Need to recurse into a branch\n const existing = tree.get(head);\n if (existing !== undefined && existing.kind === 'leaf') {\n // The leaf's name is the prefix of fullName\n const prefixName = fullName\n .split('.')\n .slice(0, segments.length - rest.length)\n .join('.');\n throw new Error(\n `Contract name conflict: \"${prefixName}\" cannot have both a direct entry and child entries`,\n );\n }\n let branch: BranchEntry;\n if (existing === undefined) {\n branch = { kind: 'branch', children: new Map() };\n tree.set(head, branch);\n } else {\n branch = existing as BranchEntry;\n }\n insertIntoTree(branch.children, rest, leaf, fullName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Code generation helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Emit the nested ApiRouter type block.\n */\nfunction emitRouterTypeBlock(tree: Map<string, TreeNode>, indent: number): string[] {\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n for (const [key, node] of tree) {\n const objKey = toObjectKey(key);\n if (node.kind === 'leaf') {\n const c = node;\n const method = c.method.toUpperCase();\n const query = c.contractSource.query ?? 'never';\n const body = method === 'GET' ? 'never' : (c.contractSource.body ?? 'never');\n const response = c.contractSource.response;\n const safeMethod = JSON.stringify(method);\n const safeUrl = JSON.stringify(c.path);\n lines.push(\n `${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`,\n );\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitRouterTypeBlock(node.children, indent + 2));\n lines.push(`${pad}};`);\n }\n }\n\n return lines;\n}\n\n/**\n * Emit the nested `api` object body.\n */\nfunction emitApiObjectBlock(tree: Map<string, TreeNode>, indent: number): string[] {\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n for (const [key, node] of tree) {\n const objKey = toObjectKey(key);\n if (node.kind === 'leaf') {\n const c = node;\n const method = c.method.toUpperCase();\n const flatName = JSON.stringify(c.name); // e.g. \"users.list\"\n const safePath = JSON.stringify(c.path);\n const fetcherMethod = method.toLowerCase();\n\n if (method === 'GET') {\n // Build the type path for ApiRouter traversal: ApiRouter['users']['list']\n const typeAccess = buildRouterTypeAccess(c.name);\n lines.push(`${pad}${objKey}: {`);\n lines.push(`${pad} queryOptions: (query?: ${typeAccess}['query']) =>`);\n lines.push(`${pad} queryOptions({`);\n lines.push(`${pad} queryKey: [${flatName}, query],`);\n lines.push(\n `${pad} queryFn: () => fetcher.get<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { query }),`,\n );\n lines.push(`${pad} }),`);\n lines.push(`${pad}},`);\n } else {\n const typeAccess = buildRouterTypeAccess(c.name);\n lines.push(`${pad}${objKey}: {`);\n lines.push(`${pad} mutationOptions: () => ({`);\n lines.push(\n `${pad} mutationFn: (body: ${typeAccess}['body']) => fetcher.${fetcherMethod}<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { body }),`,\n );\n lines.push(`${pad} }),`);\n lines.push(`${pad}},`);\n }\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitApiObjectBlock(node.children, indent + 2));\n lines.push(`${pad}},`);\n }\n }\n\n return lines;\n}\n\n/**\n * Build the ApiRouter type-access chain for a dot-separated name.\n * e.g. 'users.list' -> \"ApiRouter['users']['list']\"\n */\nfunction buildRouterTypeAccess(name: string): string {\n const segments = splitName(name);\n return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join('')}`;\n}\n\n// ---------------------------------------------------------------------------\n// Main builder\n// ---------------------------------------------------------------------------\n\nfunction buildApiFile(routes: RouteDescriptor[]): string {\n const contracted = routes.filter((r) => r.contract);\n\n const hasGetRoutes = contracted.some((r) => r.method === 'GET');\n\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.',\n '',\n ];\n\n if (hasGetRoutes) {\n lines.push(\"import { queryOptions } from '@tanstack/query-core';\");\n }\n lines.push(\"import { route } from './routes.js';\");\n lines.push(\"import { createFetcher } from '@dudousxd/nestjs-inertia-client';\");\n lines.push('');\n lines.push('export const fetcher = createFetcher();');\n lines.push('');\n\n if (contracted.length === 0) {\n lines.push('export type ApiRouter = Record<string, never>;');\n lines.push('');\n lines.push('export const api: Record<string, never> = {} as Record<string, never>;');\n lines.push('');\n lines.push('export namespace Route {');\n lines.push(' export type Response<K extends string> = never;');\n lines.push(' export type Body<K extends string> = never;');\n lines.push(' export type Query<K extends string> = never;');\n lines.push(' export type Params<K extends string> = never;');\n lines.push(' export type Error<K extends string> = never;');\n lines.push(\n ' export type Request<K extends string> = { body: never; query: never; params: never };',\n );\n lines.push('}');\n lines.push('');\n lines.push('export namespace Path {');\n lines.push(' export type Response<M extends string, U extends string> = never;');\n lines.push(' export type Body<M extends string, U extends string> = never;');\n lines.push(' export type Query<M extends string, U extends string> = never;');\n lines.push(' export type Params<M extends string, U extends string> = never;');\n lines.push(' export type Error<M extends string, U extends string> = never;');\n lines.push('}');\n lines.push('');\n return lines.join('\\n');\n }\n\n // Build a nested tree from all contracted routes\n const tree = new Map<string, TreeNode>();\n\n for (const r of contracted) {\n const c = r.contract!;\n const name: string = r.name;\n const segments = splitName(name);\n // Validate each segment is a valid camelCase identifier\n for (const seg of segments) {\n validateNameSegment(seg, name);\n }\n const leaf: LeafEntry = {\n kind: 'leaf',\n method: r.method,\n name: name,\n path: r.path,\n contractSource: c.contractSource,\n };\n insertIntoTree(tree, segments, leaf, name);\n }\n\n void detectCollisions; // used inline above\n\n // --- ApiRouter type ---\n lines.push('export type ApiRouter = {');\n lines.push(...emitRouterTypeBlock(tree, 2));\n lines.push('};');\n lines.push('');\n\n // --- api object ---\n lines.push('export const api = {');\n lines.push(...emitApiObjectBlock(tree, 2));\n lines.push('};');\n lines.push('');\n\n // --- Recursive helper type _RouterAt: walks nested ApiRouter by dot-path ---\n lines.push('type _RouterAt<R, P extends string> = P extends `${infer Head}.${infer Tail}`');\n lines.push(' ? Head extends keyof R ? _RouterAt<R[Head], Tail> : never');\n lines.push(' : P extends keyof R ? R[P] : never;');\n lines.push('');\n\n // --- ResolveByName: resolve a field from a dot-path name ---\n lines.push(\n 'type ResolveByName<K extends string, Field extends string> = _RouterAt<ApiRouter, K> extends infer R ? Field extends keyof R ? R[Field] : never : never;',\n );\n lines.push('');\n\n // --- ResolveByPath: scan all leaves for matching method + url ---\n // Flattens ApiRouter recursively and finds the entry whose method === M and url === U.\n lines.push('type _LeafValues<T> = T extends { method: string; url: string }');\n lines.push(' ? T');\n lines.push(' : T extends object ? _LeafValues<T[keyof T]> : never;');\n lines.push('');\n lines.push(\n 'type ResolveByPath<M extends string, U extends string, Field extends string> = _LeafValues<ApiRouter> extends infer L',\n );\n lines.push(' ? L extends { method: M; url: U }');\n lines.push(' ? Field extends keyof L ? L[Field] : never');\n lines.push(' : never');\n lines.push(' : never;');\n lines.push('');\n\n // --- Route namespace ---\n lines.push('export namespace Route {');\n lines.push(' export type Response<K extends string> = ResolveByName<K, \"response\">;');\n lines.push(' export type Body<K extends string> = ResolveByName<K, \"body\">;');\n lines.push(' export type Query<K extends string> = ResolveByName<K, \"query\">;');\n lines.push(' export type Params<K extends string> = ResolveByName<K, \"params\">;');\n lines.push(' export type Error<K extends string> = ResolveByName<K, \"error\">;');\n lines.push(' export type Request<K extends string> = {');\n lines.push(' body: Body<K>;');\n lines.push(' query: Query<K>;');\n lines.push(' params: Params<K>;');\n lines.push(' };');\n lines.push('}');\n lines.push('');\n\n // --- Path namespace ---\n lines.push('export namespace Path {');\n lines.push(\n ' export type Response<M extends string, U extends string> = ResolveByPath<M, U, \"response\">;',\n );\n lines.push(\n ' export type Body<M extends string, U extends string> = ResolveByPath<M, U, \"body\">;',\n );\n lines.push(\n ' export type Query<M extends string, U extends string> = ResolveByPath<M, U, \"query\">;',\n );\n lines.push(\n ' export type Params<M extends string, U extends string> = ResolveByPath<M, U, \"params\">;',\n );\n lines.push(\n ' export type Error<M extends string, U extends string> = ResolveByPath<M, U, \"error\">;',\n );\n lines.push('}');\n lines.push('');\n\n return lines.join('\\n');\n}\n","import { mkdir, stat, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\n\nexport interface CacheEntry {\n name: string;\n relativePath: string;\n mtime: string;\n}\n\nexport interface ComponentsCache {\n pages: CacheEntry[];\n}\n\nexport async function emitCache(pages: DiscoveredPage[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const entries: CacheEntry[] = await Promise.all(\n pages.map(async (p) => {\n const s = await stat(p.absolutePath);\n return {\n name: p.name,\n relativePath: p.relativePath,\n mtime: s.mtime.toISOString(),\n };\n }),\n );\n const cache: ComponentsCache = { pages: entries };\n await writeFile(join(outDir, 'components.json'), `${JSON.stringify(cache, null, 2)}\\n`, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function emitIndex(outDir: string, hasContracts = false): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const exports = [\"export * from './pages.js';\", \"export * from './routes.js';\"];\n if (hasContracts) {\n exports.push(\"export * from './api.js';\");\n }\n const content = [\n '// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.',\n ...exports,\n '',\n ].join('\\n');\n await writeFile(join(outDir, 'index.d.ts'), content, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\n\nexport async function emitPages(pages: DiscoveredPage[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const body = pages\n .map((p) => {\n const propType = p.propsSource ?? 'unknown';\n // Use JSON.stringify for the key so unsafe chars (quotes, backslashes, etc.)\n // are properly escaped. Strip the surrounding double-quotes for TypeScript\n // interface key syntax (TS accepts both 'key' and \"key\" — we use double).\n const key = needsQuotes(p.name) ? JSON.stringify(p.name) : p.name;\n return ` ${key}: ${propType};`;\n })\n .join('\\n');\n const content = `// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.\\nexport interface InertiaPages {\\n${body}\\n}\\n`;\n await writeFile(join(outDir, 'pages.d.ts'), content, 'utf8');\n}\n\nfunction needsQuotes(name: string): boolean {\n return !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * Emits `routes.ts` into `outDir` with:\n * - A `ROUTES` constant mapping name → path\n * - A `RouteName` union type of all route names\n * - A `RouteParams<K>` mapped type using template-literal `infer` to extract `:param` segments\n * - A runtime `route(name, params?)` helper that interpolates path params\n */\nexport async function emitRoutes(routes: RouteDescriptor[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const content = buildRoutesFile(routes);\n await writeFile(join(outDir, 'routes.ts'), content, 'utf8');\n}\n\nfunction buildRoutesFile(routes: RouteDescriptor[]): string {\n if (routes.length === 0) {\n return buildEmpty();\n }\n\n const entries = routes\n .map((r) => ` ${JSON.stringify(r.name)}: ${JSON.stringify(r.path)},`)\n .join('\\n');\n\n const routeNameUnion = routes.map((r) => ` | ${JSON.stringify(r.name)}`).join('\\n');\n\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.',\n '',\n '/** Map of route name → path pattern. */',\n 'export const ROUTES = {',\n entries,\n '} as const;',\n '',\n '/** Union of all known route names. */',\n 'export type RouteName =',\n `${routeNameUnion};`,\n '',\n '/**',\n ' * Extracts path-parameter names from a route path string.',\n ' * `ExtractParams<\"/users/:id\">` → `\"id\"`',\n ' */',\n 'export type ExtractParams<Path extends string> =',\n ' Path extends `${string}:${infer Param}/${infer Rest}`',\n ' ? Param | ExtractParams<`/${Rest}`>',\n ' : Path extends `${string}:${infer Param}`',\n ' ? Param',\n ' : never;',\n '',\n '/**',\n ' * Mapped type: given a `RouteName`, returns an object with each path param as `string`.',\n ' * `RouteParams<\"UsersController.show\">` → `{ id: string }`',\n ' * `RouteParams<\"UsersController.list\">` → `Record<string, never>`',\n ' */',\n 'export type RouteParams<K extends RouteName> =',\n ' ExtractParams<(typeof ROUTES)[K]> extends never',\n ' ? Record<string, never>',\n ' : { [P in ExtractParams<(typeof ROUTES)[K]>]: string };',\n '',\n '/**',\n ' * Map of every route name to its resolved params object.',\n ' * Use this for `InertiaRegistry` module augmentation.',\n ' */',\n 'export type RouteParamsMap = { [K in RouteName]: RouteParams<K> };',\n '',\n '/**',\n ' * Build a URL from a named route, interpolating path params and appending query string.',\n ' *',\n ' * @example',\n \" * route('UsersController.show', { id: '42' }) // → '/users/42'\",\n \" * route('UsersController.list') // → '/users'\",\n \" * route('users.list', undefined, { active: true }) // → '/api/users?active=true'\",\n ' */',\n 'export function route<K extends RouteName>(',\n ' name: K,',\n ' ...args: ExtractParams<(typeof ROUTES)[K]> extends never',\n ' ? [params?: undefined, query?: Record<string, unknown>]',\n ' : [params: RouteParams<K>, query?: Record<string, unknown>]',\n '): string {',\n ' const [params, query] = args as [Record<string, string> | undefined, Record<string, unknown> | undefined];',\n ' const path: string | undefined = ROUTES[name as RouteName];',\n ' if (path === undefined) {',\n \" const available = Object.keys(ROUTES).join(', ');\",\n ' throw new Error(',\n ' `[nestjs-inertia] Route \"${String(name)}\" does not exist.\\\\n\\\\n` +',\n ' `Available routes: ${available}\\\\n\\\\n` +',\n ' `This usually means:\\\\n` +',\n ' ` - The route name has a typo\\\\n` +',\n \" ` - The controller hasn't been scanned by codegen yet (run: nestjs-inertia codegen)\\\\n` +\",\n ' ` - The @As() decorator changed the route name\\\\n`',\n ' );',\n ' }',\n ' let resolvedPath: string = path;',\n ' if (params) {',\n ' resolvedPath = resolvedPath.replace(/:([^/]+)/g, (_, key) => {',\n ' const val = params[key];',\n ' if (val === undefined) throw new Error(`Missing route param: ${key}`);',\n ' return encodeURIComponent(val);',\n ' });',\n ' }',\n ' if (query && Object.keys(query).length > 0) {',\n ' const qs = new URLSearchParams();',\n ' for (const [k, v] of Object.entries(query)) {',\n ' if (v !== undefined && v !== null) qs.append(k, String(v));',\n ' }',\n ' const qStr = qs.toString();',\n ' if (qStr) {',\n \" const sep = resolvedPath.includes('?') ? '&' : '?';\",\n ' resolvedPath = `${resolvedPath}${sep}${qStr}`;',\n ' }',\n ' }',\n ' return resolvedPath;',\n '}',\n '',\n ];\n\n return lines.join('\\n');\n}\n\nfunction buildEmpty(): string {\n return [\n '// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.',\n '',\n 'export const ROUTES = {} as const;',\n 'export type RouteName = never;',\n 'export type ExtractParams<_Path extends string> = never;',\n 'export type RouteParams<_K extends RouteName> = Record<string, never>;',\n 'export function route(_name: never, _params?: undefined, _query?: Record<string, unknown>): string { return \"\"; }',\n '',\n ].join('\\n');\n}\n","import type { ResolvedConfig } from './config/types.js';\nimport { discoverPages } from './discovery/pages.js';\nimport type { RouteDescriptor } from './discovery/types.js';\nimport { emitApi } from './emit/emit-api.js';\nimport { emitCache } from './emit/emit-cache.js';\nimport { emitIndex } from './emit/emit-index.js';\nimport { emitPages } from './emit/emit-pages.js';\nimport { emitRoutes } from './emit/emit-routes.js';\n\n/**\n * Run one full codegen pass: discover pages, emit pages.d.ts, components.json, index.d.ts.\n * Route discovery is deliberately skipped — it requires spawning a Nest app and is\n * not appropriate for the hot path of a file watcher.\n *\n * Optionally accepts pre-discovered routes (e.g. from a full generate + route-discovery pass).\n * When routes are present, emits routes.ts.\n * When routes with contracts are present, also emits api.ts.\n */\nexport async function generate(\n config: ResolvedConfig,\n routes: RouteDescriptor[] = [],\n): Promise<void> {\n const pages = await discoverPages({\n glob: config.pages.glob,\n cwd: config.codegen.cwd,\n propsExport: config.pages.propsExport,\n componentNameStrategy: config.pages.componentNameStrategy,\n });\n\n await emitPages(pages, config.codegen.outDir);\n await emitCache(pages, config.codegen.outDir);\n\n const hasRoutes = routes.length > 0;\n const hasContracts = routes.some((r) => r.contract);\n\n if (hasRoutes) {\n await emitRoutes(routes, config.codegen.outDir);\n }\n\n await emitIndex(config.codegen.outDir, hasContracts);\n\n if (hasContracts) {\n await emitApi(routes, config.codegen.outDir);\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport chokidar from 'chokidar';\nimport type { ResolvedConfig } from '../config/types.js';\nimport { discoverContractsFast } from '../discovery/contracts-fast.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport { emitApi } from '../emit/emit-api.js';\nimport { emitIndex } from '../emit/emit-index.js';\nimport { emitRoutes } from '../emit/emit-routes.js';\nimport { generate } from '../generate.js';\nimport { acquireLock } from './lock-file.js';\n\nconst PAGES_DEBOUNCE_MS = 150;\n\nexport interface Watcher {\n close(): Promise<void>;\n}\n\n/** No-op watcher returned when the lock is already held. */\nconst NO_OP_WATCHER: Watcher = { close: async () => {} };\n\n/**\n * Start two chokidar watchers:\n *\n * 1. **Pages watcher** (`config.pages.glob`, 150 ms debounce) — runs `generate(config)` on\n * any page file change, regenerating `pages.d.ts` and the cache manifest.\n *\n * 2. **Contracts watcher** (`config.contracts.glob`, configurable debounce — default 500 ms) —\n * re-runs static AST route discovery via ts-morph, then re-emits `routes.ts` and (when\n * contracts are present) `api.ts` + `index.d.ts`.\n *\n * Both watchers share a single lock file in `config.codegen.outDir`. If another live process\n * already holds the lock, logs a warning and returns a no-op watcher.\n */\nexport async function watch(config: ResolvedConfig, onChange?: () => void): Promise<Watcher> {\n const lock = await acquireLock(config.codegen.outDir);\n\n if (lock === null) {\n // Read the lock file to include the PID in the warning message\n let holderPid = 'unknown';\n try {\n const raw = await readFile(join(config.codegen.outDir, '.watcher.lock'), 'utf8');\n const data = JSON.parse(raw) as { pid?: number };\n if (data.pid !== undefined) holderPid = String(data.pid);\n } catch {\n // Lock file unreadable — fall back to generic warning\n }\n console.warn(\n `[nestjs-inertia-codegen] auto-watch skipped — another process (PID ${holderPid}) is already running the watcher in ${config.codegen.outDir}. Files will continue to regenerate from that process. To take over, stop the other watcher.`,\n );\n return NO_OP_WATCHER;\n }\n\n // Run an initial full pass: pages + routes + contracts (same as a one-shot `codegen` run)\n try {\n const initialRoutes = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n await generate(config, initialRoutes);\n } catch (err) {\n // Best-effort; don't crash the watcher on initial generation failure\n console.warn(`[nestjs-inertia-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`);\n try { await generate(config); } catch { /* fallback: pages only */ }\n }\n\n // ── Pages watcher (fast path — no route discovery) ──────────────────────────\n let pagesDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n const pagesWatcher = chokidar.watch(join(config.codegen.cwd, config.pages.glob), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n function schedulePagesRegenerate(): void {\n if (pagesDebounceTimer !== undefined) {\n clearTimeout(pagesDebounceTimer);\n }\n pagesDebounceTimer = setTimeout(async () => {\n pagesDebounceTimer = undefined;\n try {\n await generate(config);\n } catch {\n // Swallow errors in watch mode\n }\n onChange?.();\n }, PAGES_DEBOUNCE_MS);\n }\n\n pagesWatcher.on('add', schedulePagesRegenerate);\n pagesWatcher.on('change', schedulePagesRegenerate);\n pagesWatcher.on('unlink', schedulePagesRegenerate);\n\n // ── Contracts watcher (static AST discovery via ts-morph) ────────────────────\n let contractsDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n const contractsWatcher = chokidar.watch(join(config.codegen.cwd, config.contracts.glob), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n function scheduleContractsRegenerate(): void {\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n }\n contractsDebounceTimer = setTimeout(async () => {\n contractsDebounceTimer = undefined;\n try {\n const routes: RouteDescriptor[] = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n\n await emitRoutes(routes, config.codegen.outDir);\n\n const hasContracts = routes.some((r) => r.contract);\n await emitIndex(config.codegen.outDir, hasContracts);\n\n if (hasContracts) {\n await emitApi(routes, config.codegen.outDir);\n }\n } catch {\n // Swallow errors in watch mode\n }\n onChange?.();\n }, config.contracts.debounceMs);\n }\n\n contractsWatcher.on('add', scheduleContractsRegenerate);\n contractsWatcher.on('change', scheduleContractsRegenerate);\n contractsWatcher.on('unlink', scheduleContractsRegenerate);\n\n return {\n close: async () => {\n if (pagesDebounceTimer !== undefined) {\n clearTimeout(pagesDebounceTimer);\n pagesDebounceTimer = undefined;\n }\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n contractsDebounceTimer = undefined;\n }\n await pagesWatcher.close();\n await contractsWatcher.close();\n await lock.release();\n },\n };\n}\n","import { dirname, join, resolve } from 'node:path';\nimport fg from 'fast-glob';\n/**\n * Static AST-based contract discovery using ts-morph.\n * Cold start ~100-500 ms.\n */\nimport {\n type ClassDeclaration,\n type InterfaceDeclaration,\n type MethodDeclaration,\n Node,\n Project,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport type { RouteDescriptor } from './types.js';\n\nexport interface FastDiscoveryOptions {\n /** Absolute path to the project root. */\n cwd: string;\n /** Controllers glob, e.g. 'src/**\\/*.controller.ts' */\n glob: string;\n /** Optional tsconfig.json path; default 'tsconfig.json' in cwd */\n tsconfig?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport async function discoverContractsFast(\n opts: FastDiscoveryOptions,\n): Promise<RouteDescriptor[]> {\n const { cwd, glob, tsconfig } = opts;\n\n const tsconfigPath = tsconfig ? resolve(tsconfig) : join(cwd, 'tsconfig.json');\n\n // Try to use tsconfig if it exists; fall back to bare compiler options\n let project: Project;\n try {\n project = new Project({\n tsConfigFilePath: tsconfigPath,\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n });\n } catch {\n // tsconfig not found — create a minimal project without it\n project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: {\n allowJs: true,\n resolveJsonModule: false,\n strict: false,\n },\n });\n }\n\n // Resolve controller file paths\n const files = await fg(glob, { cwd, absolute: true, onlyFiles: true });\n\n for (const f of files) {\n project.addSourceFileAtPath(f);\n }\n\n const routes: RouteDescriptor[] = [];\n\n for (const sourceFile of project.getSourceFiles()) {\n routes.push(...extractFromSourceFile(sourceFile, project));\n }\n\n return routes;\n}\n\n// ---------------------------------------------------------------------------\n// AST walker — exported so unit tests can import it directly\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a ts-morph Node (expression) representing a Zod schema call to a\n * TypeScript type-source string. Falls back to `'unknown'` for anything\n * unrecognised.\n */\nexport function zodAstToTs(node: Node): string {\n // We only handle call expressions (e.g. z.string(), z.object({…}).optional())\n if (!Node.isCallExpression(node)) return 'unknown';\n\n const expr = node.getExpression();\n\n // ── Chained calls: z.xxx().optional() / .nullable() ──────────────────────\n if (Node.isPropertyAccessExpression(expr)) {\n const methodName = expr.getName();\n const receiver = expr.getExpression();\n\n if (methodName === 'optional') {\n return `${zodAstToTs(receiver)} | undefined`;\n }\n if (methodName === 'nullable') {\n return `${zodAstToTs(receiver)} | null`;\n }\n\n // ── z.<method>(…) top-level calls ────────────────────────────────────────\n const args = node.getArguments();\n\n switch (methodName) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'unknown':\n return 'unknown';\n case 'any':\n return 'unknown';\n\n case 'literal': {\n const lit = args[0];\n if (!lit) return 'unknown';\n if (Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());\n if (Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();\n if (lit.getKind() === SyntaxKind.TrueKeyword) return 'true';\n if (lit.getKind() === SyntaxKind.FalseKeyword) return 'false';\n return 'unknown';\n }\n\n case 'enum': {\n // z.enum([\"a\",\"b\",\"c\"])\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n const members = arrArg\n .getElements()\n .map((el) =>\n Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : 'unknown',\n );\n return members.join(' | ');\n }\n\n case 'array': {\n const inner = args[0];\n if (!inner) return 'unknown';\n return `Array<${zodAstToTs(inner)}>`;\n }\n\n case 'object': {\n const objArg = args[0];\n if (!objArg || !Node.isObjectLiteralExpression(objArg)) return 'unknown';\n const lines: string[] = [];\n for (const prop of objArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const key = prop.getName();\n const valNode = prop.getInitializer();\n if (!valNode) continue;\n const tsType = zodAstToTs(valNode);\n // Mark optional if the value is .optional()\n const isOpt = isOptionalChain(valNode);\n lines.push(`${key}${isOpt ? '?' : ''}: ${tsType}`);\n }\n return `{ ${lines.join('; ')} }`;\n }\n\n case 'union': {\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n return arrArg.getElements().map(zodAstToTs).join(' | ');\n }\n\n case 'record': {\n // z.record(V) or z.record(K, V) — always emit Record<string, V>\n const valArg = args.length === 1 ? args[0] : args[1];\n if (!valArg) return 'unknown';\n return `Record<string, ${zodAstToTs(valArg)}>`;\n }\n\n case 'tuple': {\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n return `[${arrArg.getElements().map(zodAstToTs).join(', ')}]`;\n }\n\n default:\n return 'unknown';\n }\n }\n\n return 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Return true when `node` is a CallExpression ending in `.optional()`. */\nfunction isOptionalChain(node: Node): boolean {\n if (!Node.isCallExpression(node)) return false;\n const expr = node.getExpression();\n return Node.isPropertyAccessExpression(expr) && expr.getName() === 'optional';\n}\n\n/** Extract the string value from a decorator argument that is a string literal. */\nfunction decoratorStringArg(decoratorExpr: Node | undefined): string | undefined {\n if (!decoratorExpr) return undefined;\n if (Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();\n if (Node.isArrayLiteralExpression(decoratorExpr)) {\n const first = decoratorExpr.getElements()[0];\n if (first && Node.isStringLiteral(first)) return first.getLiteralValue();\n }\n return undefined;\n}\n\n/**\n * Parse a defineContract({...}) call expression.\n * Returns { query, body, response } or null if unrecognised.\n */\nfunction parseDefineContractCall(callExpr: Node): {\n query: string | null;\n body: string | null;\n response: string;\n} | null {\n if (!Node.isCallExpression(callExpr)) return null;\n\n const callee = callExpr.getExpression();\n // Accept both `defineContract(...)` and any identifier named defineContract\n const calleeName = Node.isIdentifier(callee)\n ? callee.getText()\n : Node.isPropertyAccessExpression(callee)\n ? callee.getName()\n : '';\n\n if (calleeName !== 'defineContract') return null;\n\n const args = callExpr.getArguments();\n const optsArg = args[0];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\n\n let query: string | null = null;\n let body: string | null = null;\n let response = 'unknown';\n\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const propName = prop.getName();\n const val = prop.getInitializer();\n if (!val) continue;\n\n if (propName === 'query') {\n query = zodAstToTs(val);\n } else if (propName === 'body') {\n body = zodAstToTs(val);\n } else if (propName === 'response') {\n response = zodAstToTs(val);\n }\n }\n\n return { query, body, response };\n}\n\n/**\n * Derive the route name from a controller class name and method name.\n * Strips the `Controller` suffix from the class name and lowercases the first letter.\n * e.g. `UsersController.list` → `users.list`\n */\nexport function deriveRouteName(className: string, methodName: string): string {\n const noSuffix = className.replace(/Controller$/, '');\n if (!noSuffix) {\n throw new Error(\n `Controller class name \"${className}\" derives empty route segment after stripping \"Controller\". Add an @As(...) override.`,\n );\n }\n const segment = noSuffix.charAt(0).toLowerCase() + noSuffix.slice(1);\n return `${segment}.${methodName}`;\n}\n\n/**\n * Derive just the class segment (no method) from a controller class name.\n * Strips the `Controller` suffix and lowercases the first letter.\n */\nexport function deriveClassSegment(className: string): string {\n const noSuffix = className.replace(/Controller$/, '');\n if (!noSuffix) {\n throw new Error(\n `Controller class name \"${className}\" derives empty route segment after stripping \"Controller\". Add an @As(...) override at the class level.`,\n );\n }\n return noSuffix.charAt(0).toLowerCase() + noSuffix.slice(1);\n}\n\n/**\n * Compose the final route name from class-level and method-level @As decorators.\n * Rule:\n * classPortion = class @As value ?? deriveClassSegment(className)\n * methodPortion = method @As value ?? methodName\n * result = `${classPortion}.${methodPortion}`\n */\nexport function resolveRouteName(\n className: string,\n methodName: string,\n classAs: string | undefined,\n methodAs: string | undefined,\n): string {\n const classPortion = classAs ?? deriveClassSegment(className);\n const methodPortion = methodAs ?? methodName;\n return `${classPortion}.${methodPortion}`;\n}\n\n/** Join two URL path segments, normalising duplicate slashes. */\nexport function joinPaths(prefix: string, suffix: string): string {\n if (!prefix && !suffix) return '/';\n if (!prefix) return suffix.startsWith('/') ? suffix : `/${suffix}`;\n if (!suffix) return prefix.startsWith('/') ? prefix : `/${prefix}`;\n\n const p = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const s = suffix.startsWith('/') ? suffix : `/${suffix}`;\n const combined = p + s;\n return combined === '' ? '/' : combined;\n}\n\n/** Extract path params from a URL pattern string, e.g. `/users/:id` → [{name:'id',source:'path'}] */\nfunction extractParams(\n path: string,\n): Array<{ name: string; source: 'path' | 'query' | 'body' | 'header' }> {\n const matches = path.matchAll(/:(\\w+)/g);\n return Array.from(matches).map((m) => ({ name: m[1] as string, source: 'path' as const }));\n}\n\n// ---------------------------------------------------------------------------\n// DTO-based contract extraction (standard NestJS patterns — no defineContract)\n// ---------------------------------------------------------------------------\n\ntype TypeDeclResult =\n | { kind: 'class'; decl: ClassDeclaration; file: SourceFile }\n | { kind: 'interface'; decl: InterfaceDeclaration; file: SourceFile }\n | { kind: 'typeAlias'; text: string }\n | { kind: 'enum'; members: string[] };\n\n/**\n * Try to find a type declaration (class, interface, type alias, enum) in a source file.\n */\nfunction findTypeInFile(name: string, file: SourceFile): TypeDeclResult | null {\n const cls = file.getClass(name);\n if (cls) return { kind: 'class', decl: cls, file };\n\n const iface = file.getInterface(name);\n if (iface) return { kind: 'interface', decl: iface, file };\n\n const alias = file.getTypeAlias(name);\n if (alias) {\n const typeNode = alias.getTypeNode();\n return { kind: 'typeAlias', text: typeNode ? typeNode.getText() : 'unknown' };\n }\n\n const enumDecl = file.getEnum(name);\n if (enumDecl) {\n const members = enumDecl.getMembers().map((m) => {\n const val = m.getValue();\n return typeof val === 'string' ? JSON.stringify(val) : JSON.stringify(m.getName());\n });\n return { kind: 'enum', members };\n }\n\n return null;\n}\n\n/**\n * Follow import declarations to find a type in another file.\n */\nfunction resolveImportedType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);\n if (!namedImport) continue;\n\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n if (!moduleSpecifier.startsWith('.')) return null;\n\n const dir = dirname(sourceFile.getFilePath());\n const candidates = [\n resolve(dir, `${moduleSpecifier}.ts`),\n resolve(dir, moduleSpecifier, 'index.ts'),\n ];\n\n for (const candidate of candidates) {\n let importedFile = project.getSourceFile(candidate);\n if (!importedFile) {\n try {\n importedFile = project.addSourceFileAtPath(candidate);\n } catch {\n continue;\n }\n }\n const result = findTypeInFile(name, importedFile);\n if (result) return result;\n }\n }\n return null;\n}\n\n/**\n * Find a type declaration by name: first in the current file, then by following imports.\n */\nfunction findType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n const local = findTypeInFile(name, sourceFile);\n if (local) return local;\n return resolveImportedType(name, sourceFile, project);\n}\n\n/**\n * Resolve a TypeNode to a TypeScript type-source string.\n * Follows imports across files via the ts-morph Project.\n * `depth` limits recursive expansion (guards against circular references).\n */\nfunction resolveTypeNodeToString(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (depth <= 0) return 'unknown';\n\n // Array<T> or T[] — unwrap and wrap\n if (Node.isArrayTypeNode(typeNode)) {\n const elementType = typeNode.getElementTypeNode();\n return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth)}>`;\n }\n\n // TypeReference: Foo, Foo[], Array<Foo>, Promise<Foo>, etc.\n if (Node.isTypeReference(typeNode)) {\n const typeName = typeNode.getTypeName();\n const name = Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();\n\n // Well-known pass-through primitives and types\n if (name === 'string' || name === 'number' || name === 'boolean') return name;\n if (name === 'Date') return 'string';\n if (name === 'unknown' || name === 'any') return 'unknown';\n\n // Array<T> generic form\n if (name === 'Array') {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return `Array<${resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth)}>`;\n }\n return 'Array<unknown>';\n }\n\n // Promise<T> — unwrap\n if (name === 'Promise') {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);\n }\n return 'unknown';\n }\n\n // Try same file first, then follow imports (class, interface, type alias, enum)\n const resolved = findType(name, sourceFile, project);\n if (resolved) {\n return expandTypeDecl(resolved, project, depth - 1);\n }\n\n // Fall back: use the name as-is\n return name;\n }\n\n // Primitive keyword types\n const kind = typeNode.getKind();\n if (kind === SyntaxKind.StringKeyword) return 'string';\n if (kind === SyntaxKind.NumberKeyword) return 'number';\n if (kind === SyntaxKind.BooleanKeyword) return 'boolean';\n if (kind === SyntaxKind.UnknownKeyword) return 'unknown';\n if (kind === SyntaxKind.AnyKeyword) return 'unknown';\n\n // Fallback: raw text\n return typeNode.getText();\n}\n\n/**\n * Expand a TypeDeclResult into an inline TS type string.\n */\nfunction expandTypeDecl(result: TypeDeclResult, project: Project, depth: number): string {\n if (depth < 0) return 'unknown';\n switch (result.kind) {\n case 'class':\n return resolvePropertied(result.decl, result.file, project, depth);\n case 'interface':\n return resolvePropertied(result.decl, result.file, project, depth);\n case 'typeAlias':\n return result.text;\n case 'enum':\n return result.members.join(' | ');\n }\n}\n\n/**\n * Turn a class or interface declaration's properties into a TS object type string like\n * `{ id: string; title: string; page?: number }`.\n */\nfunction resolvePropertied(\n decl: ClassDeclaration | InterfaceDeclaration,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (depth < 0) return 'unknown';\n\n const lines: string[] = [];\n for (const prop of decl.getProperties()) {\n const propName = prop.getName();\n const isOptional = prop.hasQuestionToken();\n const propTypeNode = prop.getTypeNode();\n let propType = 'unknown';\n if (propTypeNode) {\n propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth);\n }\n lines.push(`${propName}${isOptional ? '?' : ''}: ${propType}`);\n }\n return `{ ${lines.join('; ')} }`;\n}\n\n/**\n * Extract the body type from a `@Body()` (no-arg) decorated parameter.\n * Returns a TS type string or null.\n */\nfunction extractBodyType(method: MethodDeclaration, sourceFile: SourceFile, project: Project): string | null {\n for (const param of method.getParameters()) {\n const bodyDecorator = param.getDecorators().find((d) => d.getName() === 'Body');\n if (!bodyDecorator) continue;\n const bodyArgs = bodyDecorator.getArguments();\n if (bodyArgs.length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n return null;\n}\n\n/**\n * Extract the query type from a `@Query()` (no-arg) decorated parameter.\n * Returns a TS type string or null.\n */\nfunction extractQueryType(method: MethodDeclaration, sourceFile: SourceFile, project: Project): string | null {\n for (const param of method.getParameters()) {\n const queryDecorator = param.getDecorators().find((d) => d.getName() === 'Query');\n if (!queryDecorator) continue;\n const queryArgs = queryDecorator.getArguments();\n if (queryArgs.length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n return null;\n}\n\n/**\n * Collect `@Param('name')` decorated parameters into a `{ name: type; ... }` string.\n * Returns a TS type string or null when no @Param decorators are present.\n */\nfunction extractParamsType(method: MethodDeclaration, sourceFile: SourceFile, project: Project): string | null {\n const entries: string[] = [];\n for (const param of method.getParameters()) {\n const paramDecorator = param.getDecorators().find((d) => d.getName() === 'Param');\n if (!paramDecorator) continue;\n const paramArgs = paramDecorator.getArguments();\n if (paramArgs.length === 0) continue;\n const nameArg = paramArgs[0];\n if (!Node.isStringLiteral(nameArg)) continue;\n const paramName = nameArg.getLiteralValue();\n const typeNode = param.getTypeNode();\n const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : 'string';\n entries.push(`${paramName}: ${paramType}`);\n }\n return entries.length > 0 ? `{ ${entries.join('; ')} }` : null;\n}\n\n/**\n * Extract the response type from `@ApiResponse({ type: X })` or `@ApiResponse({ type: [X] })`.\n * Falls back to the method return type annotation (unwrapping `Promise<>`).\n * Returns a TS type string (never null — falls back to 'unknown').\n */\nfunction extractResponseType(method: MethodDeclaration, sourceFile: SourceFile, project: Project): string {\n // 1. Try @ApiResponse\n const apiResponseDecorator = method.getDecorator('ApiResponse');\n if (apiResponseDecorator) {\n const args = apiResponseDecorator.getArguments();\n const optsArg = args[0];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n if (prop.getName() !== 'type') continue;\n const val = prop.getInitializer();\n if (!val) continue;\n\n // type: [PostDto] — array syntax\n if (Node.isArrayLiteralExpression(val)) {\n const elements = val.getElements();\n const firstEl = elements[0];\n if (elements.length > 0 && firstEl !== undefined) {\n const innerType = resolveIdentifierToClassType(firstEl, sourceFile, project, 3);\n return `Array<${innerType}>`;\n }\n return 'Array<unknown>';\n }\n\n // type: PostDto — single class reference\n return resolveIdentifierToClassType(val, sourceFile, project, 3);\n }\n }\n }\n\n // 2. Fall back to return type annotation\n const returnTypeNode = method.getReturnTypeNode();\n if (returnTypeNode) {\n return resolveTypeNodeToString(returnTypeNode, sourceFile, project, 3);\n }\n\n return 'unknown';\n}\n\n/**\n * Resolve an expression (expected to be a class identifier) to its expanded type string.\n * E.g. the `PostDto` identifier in `@ApiResponse({ type: PostDto })`.\n */\nfunction resolveIdentifierToClassType(node: Node, sourceFile: SourceFile, project: Project, depth: number): string {\n if (!Node.isIdentifier(node)) return 'unknown';\n const name = node.getText();\n const resolved = findType(name, sourceFile, project);\n if (resolved) {\n return expandTypeDecl(resolved, project, depth - 1);\n }\n return name;\n}\n\n/**\n * Determine whether a method has any DTO-based contract info worth emitting\n * (body, query, params, or non-unknown response).\n * Returns a ContractSource-shaped object or null.\n */\nexport function extractDtoContract(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): { query: string | null; body: string | null; response: string; params: string | null } | null {\n const body = extractBodyType(method, sourceFile, project);\n const query = extractQueryType(method, sourceFile, project);\n const paramsType = extractParamsType(method, sourceFile, project);\n const response = extractResponseType(method, sourceFile, project);\n\n // Only emit a contract if there is at least something useful\n if (body === null && query === null && paramsType === null && response === 'unknown') {\n return null;\n }\n\n return { query, body, response, params: paramsType };\n}\n\n// ---------------------------------------------------------------------------\n// HTTP method decorator names recognised by the fast path\n// ---------------------------------------------------------------------------\n\nconst HTTP_METHOD_DECORATORS: Record<string, string> = {\n Get: 'GET',\n Post: 'POST',\n Put: 'PUT',\n Patch: 'PATCH',\n Delete: 'DELETE',\n Options: 'OPTIONS',\n Head: 'HEAD',\n All: 'ALL',\n};\n\n// ---------------------------------------------------------------------------\n// Per-file extraction\n// ---------------------------------------------------------------------------\n\nfunction extractFromSourceFile(sourceFile: SourceFile, project: Project): RouteDescriptor[] {\n const routes: RouteDescriptor[] = [];\n // Track derived/assigned names to detect collisions: name → fully-qualified method ref\n const seenNames = new Map<string, string>();\n\n const classes = sourceFile.getClasses();\n\n for (const cls of classes) {\n // Find @Controller(...) decorator\n const controllerDecorator = cls.getDecorator('Controller');\n if (!controllerDecorator) continue;\n\n // Determine controller path prefix\n const controllerArgs = controllerDecorator.getArguments();\n const firstArg = controllerArgs[0];\n const prefix = decoratorStringArg(firstArg) ?? '';\n\n const className = cls.getName() ?? 'Unknown';\n\n // Walk all methods\n for (const method of cls.getMethods()) {\n // ── Determine HTTP method + sub-path from NestJS verb decorators ──────\n let httpMethod: string | undefined;\n let handlerPath = '';\n\n for (const [decoratorName, verb] of Object.entries(HTTP_METHOD_DECORATORS)) {\n const httpDecorator = method.getDecorator(decoratorName);\n if (httpDecorator) {\n httpMethod = verb;\n const httpArgs = httpDecorator.getArguments();\n const pathArg = httpArgs[0];\n handlerPath = decoratorStringArg(pathArg) ?? '';\n break;\n }\n }\n\n // ── Check for @ApplyContract ──────────────────────────────────────────\n const applyContractDecorator = method.getDecorator('ApplyContract');\n\n if (applyContractDecorator) {\n const decoratorArgs = applyContractDecorator.getArguments();\n const firstDecoratorArg = decoratorArgs[0];\n if (!firstDecoratorArg) continue;\n\n // Resolve contract definition from inline call or identifier\n let contractDef: {\n query: string | null;\n body: string | null;\n response: string;\n } | null = null;\n\n if (Node.isCallExpression(firstDecoratorArg)) {\n contractDef = parseDefineContractCall(firstDecoratorArg);\n } else if (Node.isIdentifier(firstDecoratorArg)) {\n const identName = firstDecoratorArg.getText();\n const varDecl = sourceFile.getVariableDeclaration(identName);\n if (!varDecl) {\n console.warn(\n `[nestjs-inertia-codegen/fast] Cannot resolve '${identName}' in ${sourceFile.getFilePath()} (cross-file imports are out-of-scope for v1) — skipping`,\n );\n continue;\n }\n\n const initializer = varDecl.getInitializer();\n if (!initializer) continue;\n\n contractDef = parseDefineContractCall(initializer);\n } else {\n console.warn(\n `[nestjs-inertia-codegen/fast] @ApplyContract arg is not an identifier or call expression in ${sourceFile.getFilePath()} — skipping`,\n );\n continue;\n }\n\n if (!contractDef) continue;\n\n // Method + path always come from NestJS decorators — skip if absent\n if (!httpMethod) continue;\n const resolvedMethod = httpMethod;\n const resolvedPath = joinPaths(prefix, handlerPath);\n\n const combined = resolvedPath;\n const params = extractParams(combined);\n\n // Determine route name: compose class-level @As + method-level @As\n const methodName = method.getName();\n\n // Read class-level @As\n const classAsDecorator = cls.getDecorator('As');\n let classAs: string | undefined;\n if (classAsDecorator) {\n const classAsArgs = classAsDecorator.getArguments();\n const classAsName = decoratorStringArg(classAsArgs[0]);\n if (!classAsName) {\n throw new Error(\n `@As decorator on class ${className} must have a non-empty string argument.`,\n );\n }\n classAs = classAsName;\n }\n\n // Read method-level @As\n const methodAsDecorator = method.getDecorator('As');\n let methodAs: string | undefined;\n if (methodAsDecorator) {\n const methodAsArgs = methodAsDecorator.getArguments();\n const methodAsName = decoratorStringArg(methodAsArgs[0]);\n if (!methodAsName) {\n throw new Error(\n `@As decorator on ${className}.${methodName} must have a non-empty string argument.`,\n );\n }\n methodAs = methodAsName;\n }\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // Collision detection across contracted routes\n const qualifiedRef = `${className}.${methodName}`;\n const existing = seenNames.get(routeName);\n if (existing !== undefined) {\n throw new Error(\n `Route name collision: \"${routeName}\" is used by both \"${existing}\" and \"${qualifiedRef}\". Use @As(...) to give one of them a unique name.`,\n );\n }\n seenNames.set(routeName, qualifiedRef);\n\n routes.push({\n method: resolvedMethod,\n path: combined,\n name: routeName,\n params,\n contract: {\n contractSource: {\n query: contractDef.query,\n body: contractDef.body,\n response: contractDef.response,\n },\n },\n });\n } else {\n // ── Plain HTTP verb decorator (no @ApplyContract) ──────────────────\n if (!httpMethod) continue;\n\n const combined = joinPaths(prefix, handlerPath);\n const params = extractParams(combined);\n\n const methodName = method.getName();\n\n // Read class-level @As\n const classAsDecorator = cls.getDecorator('As');\n let classAs: string | undefined;\n if (classAsDecorator) {\n const classAsArgs = classAsDecorator.getArguments();\n const classAsName = decoratorStringArg(classAsArgs[0]);\n if (classAsName) classAs = classAsName;\n }\n\n // Read method-level @As\n const methodAsDecorator = method.getDecorator('As');\n let methodAs: string | undefined;\n if (methodAsDecorator) {\n const methodAsArgs = methodAsDecorator.getArguments();\n const methodAsName = decoratorStringArg(methodAsArgs[0]);\n if (methodAsName) methodAs = methodAsName;\n }\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // ── DTO-based contract extraction ──────────────────────────────────\n const dtoContract = extractDtoContract(method, sourceFile, project);\n\n routes.push({\n method: httpMethod,\n path: combined,\n name: routeName,\n params,\n // Attach contract if DTO extraction produced useful type info\n ...(dtoContract\n ? {\n contract: {\n contractSource: {\n query: dtoContract.query,\n body: dtoContract.body,\n response: dtoContract.response,\n },\n },\n }\n : {}),\n });\n }\n }\n }\n\n return routes;\n}\n","import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nconst LOCK_FILE = '.watcher.lock';\n\ninterface LockData {\n pid: number;\n startedAt: string;\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Try to acquire an exclusive lock for a watcher in `outDir`.\n *\n * Returns `{ release }` on success.\n * Returns `null` if another live process already holds the lock.\n */\nexport async function acquireLock(\n outDir: string,\n): Promise<{ release: () => Promise<void> } | null> {\n await mkdir(outDir, { recursive: true });\n const lockPath = join(outDir, LOCK_FILE);\n\n // Check for an existing lock\n try {\n const raw = await readFile(lockPath, 'utf8');\n const existing = JSON.parse(raw) as LockData;\n if (isProcessAlive(existing.pid)) {\n // Another live process holds the lock\n return null;\n }\n // Stale lock — fall through to overwrite\n } catch {\n // File doesn't exist or is corrupt — fall through to create\n }\n\n const lockData: LockData = { pid: process.pid, startedAt: new Date().toISOString() };\n await writeFile(lockPath, `${JSON.stringify(lockData, null, 2)}\\n`, 'utf8');\n\n return {\n release: async () => {\n try {\n await unlink(lockPath);\n } catch {\n // Ignore if already removed\n }\n },\n };\n}\n","export const VERSION = '1.0.7';\n\nexport { defineConfig } from './config/define-config.js';\nexport { loadConfig } from './config/load-config.js';\nexport type { UserConfig, ResolvedConfig, ScopeConfig } from './config/types.js';\nexport { ConfigError, CodegenError } from './exceptions.js';\n\nexport { generate } from './generate.js';\nexport { watch } from './watch/watcher.js';\nexport type { Watcher } from './watch/watcher.js';\nexport { acquireLock } from './watch/lock-file.js';\n","import { loadConfig } from '../config/load-config.js';\nimport { discoverContractsFast } from '../discovery/contracts-fast.js';\nimport { generate } from '../generate.js';\nimport { watch } from '../watch/watcher.js';\n\nexport interface RunCodegenOptions {\n watch?: boolean;\n cwd?: string;\n}\n\n/**\n * Programmatic entry point for `nestjs-inertia codegen [--watch]`.\n *\n * - Loads `nestjs-inertia.config.ts` from `cwd`.\n * - In one-shot mode: discovers routes via static AST, then generates all artifacts.\n * - If `watch` is true, delegates entirely to the chokidar watcher (which\n * handles its own route discovery internally) and suspends until SIGINT/SIGTERM.\n *\n * Throws on config or generation errors (the CLI catches and returns exit code 1).\n */\nexport async function runCodegen(opts: RunCodegenOptions = {}): Promise<void> {\n const cwd = opts.cwd ?? process.cwd();\n const config = await loadConfig(cwd);\n\n if (opts.watch) {\n const watcher = await watch(config);\n\n await new Promise<void>((resolve) => {\n function onSignal() {\n watcher.close().then(resolve).catch(resolve);\n }\n process.once('SIGINT', onSignal);\n process.once('SIGTERM', onSignal);\n });\n return;\n }\n\n // One-shot: discover routes via static AST, then generate all artifacts.\n const routes = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n\n await generate(config, routes);\n console.log('✓ Codegen generated artifacts in', config.codegen.outDir);\n}\n","import { execSync } from 'node:child_process';\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { access, mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { createInterface } from 'node:readline';\n\nexport interface RunInitOptions {\n cwd?: string;\n /** Skip running package manager installs (useful for testing). */\n skipInstall?: boolean;\n}\n\ntype Framework = 'react' | 'vue' | 'svelte';\ntype TemplateEngine = 'handlebars' | 'ejs' | 'pug' | 'liquid' | 'html';\ntype PackageManager = 'pnpm' | 'npm' | 'yarn';\n\nconst GITIGNORE_ENTRY = '.nestjs-inertia/';\n\n// ---------------------------------------------------------------------------\n// ANSI color helpers (no external deps)\n// ---------------------------------------------------------------------------\n\nconst green = (s: string) => `\\x1b[32m${s}\\x1b[0m`;\nconst yellow = (s: string) => `\\x1b[33m${s}\\x1b[0m`;\nconst cyan = (s: string) => `\\x1b[36m${s}\\x1b[0m`;\nconst dim = (s: string) => `\\x1b[2m${s}\\x1b[0m`;\nconst bold = (s: string) => `\\x1b[1m${s}\\x1b[0m`;\n\nfunction logCreated(path: string) {\n console.log(` ${green('✓')} ${path} ${dim('(created)')}`);\n}\nfunction logPatched(path: string, detail: string) {\n console.log(` ${green('✓')} ${path} ${dim(`(${detail})`)}`);\n}\nfunction logSkipped(path: string) {\n console.log(` ${cyan('→')} ${path} ${dim('(already exists, skipped)')}`);\n}\nfunction logWarning(msg: string) {\n console.log(` ${yellow('⚠')} ${msg}`);\n}\nfunction logSection(title: string) {\n console.log(`\\n${bold(title)}`);\n}\n\n// ---------------------------------------------------------------------------\n// Detection helpers\n// ---------------------------------------------------------------------------\n\nasync function readPackageJson(cwd: string): Promise<Record<string, unknown>> {\n try {\n const raw = await readFile(join(cwd, 'package.json'), 'utf8');\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nfunction allDeps(pkg: Record<string, unknown>): string[] {\n const deps = (pkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;\n return [...Object.keys(deps), ...Object.keys(devDeps)];\n}\n\nexport async function detectFramework(cwd: string): Promise<Framework | null> {\n const pkg = await readPackageJson(cwd);\n const deps = allDeps(pkg);\n\n if (deps.includes('@inertiajs/react') || deps.includes('react')) return 'react';\n if (deps.includes('@inertiajs/vue3') || deps.includes('vue')) return 'vue';\n if (deps.includes('@inertiajs/svelte') || deps.includes('svelte')) return 'svelte';\n return null;\n}\n\nexport async function detectTemplateEngine(cwd: string): Promise<TemplateEngine> {\n const pkg = await readPackageJson(cwd);\n const deps = allDeps(pkg);\n\n if (deps.includes('handlebars')) return 'handlebars';\n if (deps.includes('ejs')) return 'ejs';\n if (deps.includes('pug')) return 'pug';\n if (deps.includes('liquidjs')) return 'liquid';\n return 'html';\n}\n\nexport async function detectPackageManager(cwd: string): Promise<PackageManager> {\n async function exists(file: string): Promise<boolean> {\n try {\n await access(join(cwd, file));\n return true;\n } catch {\n return false;\n }\n }\n\n if (await exists('pnpm-lock.yaml')) return 'pnpm';\n if (await exists('yarn.lock')) return 'yarn';\n return 'npm';\n}\n\nasync function promptFramework(): Promise<Framework> {\n // If not interactive (CI), default to React\n if (!process.stdin.isTTY) return 'react';\n\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(\n '[nestjs-inertia] Which frontend framework? (react/vue/svelte) [react]: ',\n (answer) => {\n rl.close();\n const trimmed = answer.trim().toLowerCase();\n if (trimmed === 'vue') resolve('vue');\n else if (trimmed === 'svelte') resolve('svelte');\n else resolve('react');\n },\n );\n });\n}\n\n// ---------------------------------------------------------------------------\n// File helpers\n// ---------------------------------------------------------------------------\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function writeIfNotExists(\n filePath: string,\n content: string,\n label: string,\n): Promise<void> {\n if (await fileExists(filePath)) {\n logSkipped(label);\n return;\n }\n // Ensure parent directory exists\n const dir = filePath.substring(0, filePath.lastIndexOf('/'));\n if (dir) {\n await mkdir(dir, { recursive: true });\n }\n await writeFile(filePath, content, 'utf8');\n logCreated(label);\n}\n\n/**\n * Handle vite.config.ts — create if missing, warn if present without nestInertia plugin.\n */\nasync function handleViteConfig(cwd: string, framework: Framework): Promise<void> {\n const filePath = join(cwd, 'vite.config.ts');\n if (await fileExists(filePath)) {\n const existing = await readFile(filePath, 'utf8');\n const hasPlugin =\n existing.includes('nestInertia') || existing.includes('nestjs-inertia-vite/plugin');\n if (!hasPlugin) {\n logSkipped('vite.config.ts');\n logWarning(\n `vite.config.ts exists but nestInertia plugin not detected — add it manually:\\n import nestInertia from '@dudousxd/nestjs-inertia-vite/plugin';\\n plugins: [nestInertia({ ${framework}: true })]`,\n );\n } else {\n logSkipped('vite.config.ts');\n }\n return;\n }\n const dir = filePath.substring(0, filePath.lastIndexOf('/'));\n if (dir) {\n await mkdir(dir, { recursive: true });\n }\n await writeFile(filePath, viteConfigTemplate(framework), 'utf8');\n logCreated('vite.config.ts');\n}\n\nasync function patchGitignore(gitignorePath: string): Promise<void> {\n let existing = '';\n if (await fileExists(gitignorePath)) {\n existing = await readFile(gitignorePath, 'utf8');\n }\n\n if (existing.split('\\n').some((line) => line.trim() === GITIGNORE_ENTRY)) {\n console.log(` ${cyan('→')} .gitignore ${dim('(already contains .nestjs-inertia/, skipped)')}`);\n return;\n }\n\n const newContent =\n existing.endsWith('\\n') || existing === ''\n ? `${existing}${GITIGNORE_ENTRY}\\n`\n : `${existing}\\n${GITIGNORE_ENTRY}\\n`;\n\n await writeFile(gitignorePath, newContent, 'utf8');\n logPatched('.gitignore', 'added .nestjs-inertia/');\n}\n\nexport function installDeps(pkgManager: PackageManager, deps: string[], dev: boolean): void {\n if (deps.length === 0) return;\n\n const flag = dev ? (pkgManager === 'npm' ? '--save-dev' : '-D') : '';\n const cmd =\n pkgManager === 'npm'\n ? `npm install ${flag} ${deps.join(' ')}`\n : pkgManager === 'yarn'\n ? `yarn add ${flag} ${deps.join(' ')}`\n : `pnpm add ${flag} ${deps.join(' ')}`;\n\n logPatched(deps.join(', '), 'installed');\n try {\n execSync(cmd, { stdio: 'inherit' });\n } catch {\n logWarning(`Failed to install deps. Run manually:\\n ${cmd}`);\n }\n}\n\nexport async function patchPackageJsonScripts(\n cwd: string,\n scripts: Record<string, string>,\n): Promise<void> {\n const pkgPath = join(cwd, 'package.json');\n let pkg: Record<string, unknown> = {};\n try {\n pkg = JSON.parse(await readFile(pkgPath, 'utf8')) as Record<string, unknown>;\n } catch {\n return; // no package.json — skip\n }\n\n const existing = (pkg.scripts ?? {}) as Record<string, string>;\n let changed = false;\n\n for (const [key, value] of Object.entries(scripts)) {\n if (!(key in existing)) {\n existing[key] = value;\n changed = true;\n logPatched('package.json', `added ${key} script`);\n } else {\n console.log(` ${cyan('→')} package.json ${dim(`(${key} already defined, skipped)`)}`);\n }\n }\n\n if (!changed) {\n return;\n }\n\n pkg.scripts = existing;\n await writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`, 'utf8');\n}\n\n// ---------------------------------------------------------------------------\n// Module patching helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Find the position just after the last import statement in a file.\n * Handles files where the first line starts with `import` (no leading newline).\n */\nfunction findAfterLastImport(content: string): number {\n // Try \\nimport first (import not on the first line)\n const lastImportIndex = content.lastIndexOf('\\nimport ');\n if (lastImportIndex !== -1) {\n const endOfLine = content.indexOf('\\n', lastImportIndex + 1);\n return endOfLine !== -1 ? endOfLine + 1 : content.length;\n }\n // Fallback: import at the very start of the file\n if (content.startsWith('import ')) {\n const endOfLine = content.indexOf('\\n');\n return endOfLine !== -1 ? endOfLine + 1 : content.length;\n }\n return 0;\n}\n\n/**\n * Patch `src/app.module.ts` to add InertiaModule.forRoot() and HomeController.\n * Returns 'patched' | 'already' | 'skipped'\n */\nexport function patchAppModule(\n filePath: string,\n rootView: string,\n): 'patched' | 'already' | 'skipped' {\n let content: string;\n try {\n content = readFileSync(filePath, 'utf8');\n } catch {\n return 'skipped';\n }\n\n let changed = false;\n\n // --- InertiaModule ---\n if (!content.includes('InertiaModule')) {\n const insertAt = findAfterLastImport(content);\n if (insertAt > 0) {\n content = `${content.slice(0, insertAt)}import { InertiaModule } from '@dudousxd/nestjs-inertia';\\n${content.slice(insertAt)}`;\n }\n\n // Find `imports: [` and insert after the opening bracket\n const importsMatch = content.match(/imports\\s*:\\s*\\[/);\n if (importsMatch?.index !== undefined) {\n const bracketPos = content.indexOf('[', importsMatch.index) + 1;\n const indent = ' ';\n content = `${content.slice(0, bracketPos)}\\n${indent}InertiaModule.forRoot({\\n${indent} rootView: '${rootView}',\\n${indent}}),${content.slice(bracketPos)}`;\n changed = true;\n }\n }\n\n // --- HomeController ---\n if (!content.includes('HomeController')) {\n const insertAt = findAfterLastImport(content);\n if (insertAt > 0) {\n content = `${content.slice(0, insertAt)}import { HomeController } from './home.controller';\\n${content.slice(insertAt)}`;\n }\n\n // Find `controllers: [` and insert after the opening bracket\n const controllersMatch = content.match(/controllers\\s*:\\s*\\[/);\n if (controllersMatch?.index !== undefined) {\n const bracketPos = content.indexOf('[', controllersMatch.index) + 1;\n const indent = ' ';\n content = `${content.slice(0, bracketPos)}\\n${indent}HomeController,${content.slice(bracketPos)}`;\n changed = true;\n }\n }\n\n if (!changed) return 'already';\n\n writeFileSync(filePath, content, 'utf8');\n return 'patched';\n}\n\n/**\n * Patch `src/main.ts` to add setupInertiaVite() call.\n * Returns 'patched' | 'already' | 'skipped'\n */\nexport function patchMainTs(filePath: string): 'patched' | 'already' | 'skipped' {\n let content: string;\n try {\n content = readFileSync(filePath, 'utf8');\n } catch {\n return 'skipped';\n }\n\n if (content.includes('setupInertiaVite')) return 'already';\n\n // Add import after the last import statement\n const insertAt = findAfterLastImport(content);\n if (insertAt > 0) {\n content = `${content.slice(0, insertAt)}import { setupInertiaVite } from '@dudousxd/nestjs-inertia-vite';\\n${content.slice(insertAt)}`;\n }\n\n // Find NestFactory.create assignment line\n const createMatch = content.match(\n /(?:const|let)\\s+(\\w+)\\s*=\\s*await\\s+NestFactory\\.create[^;]+;/,\n );\n if (!createMatch || createMatch.index === undefined) return 'skipped';\n\n const appVarName = createMatch[1];\n const insertAfterPos = createMatch.index + createMatch[0].length;\n\n const viteSetup = `\n // Inertia + Vite integration (dev: HMR middleware, prod: static assets)\n await setupInertiaVite(${appVarName}, {\n mode: process.env.NODE_ENV ?? 'development',\n root: 'inertia',\n publicDir: 'dist/inertia/client',\n outDir: 'dist/inertia',\n });`;\n\n content = `${content.slice(0, insertAfterPos)}\\n${viteSetup}${content.slice(insertAfterPos)}`;\n writeFileSync(filePath, content, 'utf8');\n return 'patched';\n}\n\n// ---------------------------------------------------------------------------\n// Template generators\n// ---------------------------------------------------------------------------\n\nfunction configTemplate(framework: Framework): string {\n const glob =\n framework === 'react'\n ? 'inertia/pages/**/*.tsx'\n : framework === 'vue'\n ? 'inertia/pages/**/*.vue'\n : 'inertia/pages/**/*.svelte';\n\n return `import { defineConfig } from '@dudousxd/nestjs-inertia-codegen';\n\nexport default defineConfig({\n pages: {\n glob: '${glob}',\n },\n});\n`;\n}\n\nconst DTS_TEMPLATE = `// Auto-generated by nestjs-inertia-codegen. Commit this file.\n// Re-run \\`nestjs-inertia codegen\\` to refresh after adding/removing pages.\n\nimport '.nestjs-inertia/index.js';\n\ndeclare module '@dudousxd/nestjs-inertia' {\n interface InertiaRegistry {\n pages: import('.nestjs-inertia/pages.js').InertiaPages;\n shared: import('.nestjs-inertia/shared.js').InertiaSharedProps;\n routes: import('.nestjs-inertia/routes.js').RouteParamsMap;\n }\n}\n`;\n\nfunction htmlShellTemplate(framework: Framework, _engine: TemplateEngine): string {\n const ext = framework === 'react' ? 'tsx' : 'ts';\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>My App</title>\n @inertiaHead\n</head>\n<body>\n @inertia\n @vite('inertia/app.${ext}')\n</body>\n</html>\n`;\n}\n\nfunction viteConfigTemplate(framework: Framework): string {\n const pluginOption = `{ ${framework}: true }`;\n return `import { defineConfig } from 'vite';\nimport nestInertia from '@dudousxd/nestjs-inertia-vite/plugin';\n\nexport default defineConfig({\n plugins: [nestInertia(${pluginOption})],\n});\n`;\n}\n\nfunction entryPointTemplate(framework: Framework): string {\n if (framework === 'react') {\n return `import { createRoot } from 'react-dom/client';\nimport { createInertiaApp } from '@inertiajs/react';\n\ncreateInertiaApp({\n resolve: (name) => {\n const pages = import.meta.glob('./pages/*.tsx', { eager: true });\n return (pages as Record<string, unknown>)[\\`./pages/\\${name}.tsx\\`];\n },\n setup({ el, App, props }) {\n createRoot(el!).render(<App {...props} />);\n },\n});\n`;\n }\n\n if (framework === 'vue') {\n return `import { createApp, h } from 'vue';\nimport { createInertiaApp } from '@inertiajs/vue3';\n\ncreateInertiaApp({\n resolve: (name) => {\n const pages = import.meta.glob('./pages/*.vue', { eager: true });\n return (pages as Record<string, unknown>)[\\`./pages/\\${name}.vue\\`];\n },\n setup({ el, App, props, plugin }) {\n createApp({ render: () => h(App, props) }).use(plugin).mount(el!);\n },\n});\n`;\n }\n\n // svelte\n return `import { mount } from 'svelte';\nimport { createInertiaApp } from '@inertiajs/svelte';\n\ncreateInertiaApp({\n resolve: (name) => {\n const pages = import.meta.glob('./pages/*.svelte', { eager: true });\n return (pages as Record<string, unknown>)[\\`./pages/\\${name}.svelte\\`];\n },\n setup({ el, App, props }) {\n mount(App, { target: el!, props });\n },\n});\n`;\n}\n\nfunction samplePageTemplate(framework: Framework): string {\n if (framework === 'react') {\n return `export type ComponentProps = {\n greeting: string;\n};\n\nexport default function Home({ greeting }: ComponentProps) {\n return (\n <main>\n <h1>{greeting}</h1>\n <p>Edit this page at <code>inertia/pages/Home.tsx</code></p>\n </main>\n );\n}\n`;\n }\n\n if (framework === 'vue') {\n return `<script setup lang=\"ts\">\ndefineProps<{ greeting: string }>();\n</script>\n\n<template>\n <main>\n <h1>{{ greeting }}</h1>\n <p>Edit this page at <code>inertia/pages/Home.vue</code></p>\n </main>\n</template>\n`;\n }\n\n // svelte\n return `<script lang=\"ts\">\n let { greeting } = $props<{ greeting: string }>();\n</script>\n\n<main>\n <h1>{greeting}</h1>\n <p>Edit this page at <code>inertia/pages/Home.svelte</code></p>\n</main>\n`;\n}\n\nconst SAMPLE_CONTROLLER = `import { Controller, Get } from '@nestjs/common';\nimport { Inertia } from '@dudousxd/nestjs-inertia';\n\n@Controller()\nexport class HomeController {\n @Get('/')\n @Inertia('Home')\n index() {\n return { greeting: 'Welcome to NestJS + Inertia.js!' };\n }\n}\n`;\n\n// ---------------------------------------------------------------------------\n// Main entry\n// ---------------------------------------------------------------------------\n\n/**\n * `nestjs-inertia init` — scaffold a full Inertia.js project in `cwd`.\n *\n * Idempotent: each file is only written if it does not already exist.\n * Smart patching: existing files are checked and patched where safe.\n */\nexport async function runInit(opts: RunInitOptions = {}): Promise<void> {\n const cwd = opts.cwd ?? process.cwd();\n\n console.log(`\\n${bold('nestjs-inertia init')}`);\n\n // 1. Detect (or ask for) framework\n let framework = await detectFramework(cwd);\n if (!framework) {\n framework = await promptFramework();\n }\n\n // 2. Detect template engine\n const engine = await detectTemplateEngine(cwd);\n\n const engineLabel = engine === 'html' ? 'plain HTML' : engine;\n const frameworkLabel = framework.charAt(0).toUpperCase() + framework.slice(1);\n console.log(`\\n Detected: ${bold(`${frameworkLabel} + ${engineLabel}`)}`);\n\n // 3. Scaffold files\n const shellFileName =\n engine === 'html' ? 'index.html' : `index.${engine === 'handlebars' ? 'hbs' : engine}`;\n const entryExt = framework === 'react' ? 'tsx' : 'ts';\n const pageExt = framework === 'react' ? 'tsx' : framework === 'vue' ? 'vue' : 'svelte';\n\n logSection('Scaffold files');\n\n await writeIfNotExists(\n join(cwd, 'nestjs-inertia.config.ts'),\n configTemplate(framework),\n 'nestjs-inertia.config.ts',\n );\n\n await writeIfNotExists(join(cwd, 'nestjs-inertia.d.ts'), DTS_TEMPLATE, 'nestjs-inertia.d.ts');\n\n await writeIfNotExists(\n join(cwd, 'inertia', shellFileName),\n htmlShellTemplate(framework, engine),\n `inertia/${shellFileName}`,\n );\n\n await handleViteConfig(cwd, framework);\n\n await writeIfNotExists(\n join(cwd, 'inertia', `app.${entryExt}`),\n entryPointTemplate(framework),\n `inertia/app.${entryExt}`,\n );\n\n await writeIfNotExists(\n join(cwd, 'inertia', 'pages', `Home.${pageExt}`),\n samplePageTemplate(framework),\n `inertia/pages/Home.${pageExt}`,\n );\n\n await writeIfNotExists(\n join(cwd, 'src', 'home.controller.ts'),\n SAMPLE_CONTROLLER,\n 'src/home.controller.ts',\n );\n\n // 4. Patch app.module.ts and main.ts\n logSection('Patch existing files');\n\n const rootView =\n engine === 'html'\n ? 'inertia/index.html'\n : `inertia/index.${engine === 'handlebars' ? 'hbs' : engine}`;\n\n const appModulePath = join(cwd, 'src', 'app.module.ts');\n const appModuleResult = patchAppModule(appModulePath, rootView);\n if (appModuleResult === 'patched') {\n logPatched('src/app.module.ts', 'added InertiaModule.forRoot');\n logPatched('src/app.module.ts', 'added HomeController to controllers');\n } else if (appModuleResult === 'already') {\n console.log(\n ` ${cyan('→')} src/app.module.ts ${dim('(InertiaModule already registered, skipped)')}`,\n );\n } else {\n logWarning('src/app.module.ts not found — add InertiaModule.forRoot() manually');\n }\n\n const mainTsPath = join(cwd, 'src', 'main.ts');\n const mainTsResult = patchMainTs(mainTsPath);\n if (mainTsResult === 'patched') {\n logPatched('src/main.ts', 'added setupInertiaVite after NestFactory.create');\n } else if (mainTsResult === 'already') {\n console.log(` ${cyan('→')} src/main.ts ${dim('(setupInertiaVite already present, skipped)')}`);\n } else {\n logWarning('src/main.ts not found — add setupInertiaVite() manually');\n }\n\n await patchGitignore(join(cwd, '.gitignore'));\n\n // 5. Add build scripts to package.json\n await patchPackageJsonScripts(cwd, {\n 'build:client': 'vite build',\n 'build:ssr': 'VITE_SSR=1 vite build --ssr',\n });\n\n // 6. Install missing deps\n logSection('Install dependencies');\n\n const pkg = await readPackageJson(cwd);\n const installedDeps = allDeps(pkg);\n const pkgManager = await detectPackageManager(cwd);\n\n const commonDeps = ['vite'].filter((d) => !installedDeps.includes(d));\n\n let frameworkDeps: string[] = [];\n let frameworkDevDeps: string[] = [];\n\n if (framework === 'react') {\n const needed = ['@inertiajs/react', 'react', 'react-dom'].filter(\n (d) => !installedDeps.includes(d),\n );\n const neededDev = ['@types/react', '@types/react-dom', '@vitejs/plugin-react'].filter(\n (d) => !installedDeps.includes(d),\n );\n frameworkDeps = needed;\n frameworkDevDeps = neededDev;\n } else if (framework === 'vue') {\n const needed = ['@inertiajs/vue3', 'vue'].filter((d) => !installedDeps.includes(d));\n const neededDev = ['@vitejs/plugin-vue'].filter((d) => !installedDeps.includes(d));\n frameworkDeps = needed;\n frameworkDevDeps = neededDev;\n } else {\n const needed = ['@inertiajs/svelte', 'svelte'].filter((d) => !installedDeps.includes(d));\n const neededDev = ['@sveltejs/vite-plugin-svelte'].filter((d) => !installedDeps.includes(d));\n frameworkDeps = needed;\n frameworkDevDeps = neededDev;\n }\n\n const depsToInstall = [...commonDeps, ...frameworkDeps];\n const devDepsToInstall = frameworkDevDeps;\n\n if (!opts.skipInstall) {\n installDeps(pkgManager, depsToInstall, false);\n installDeps(pkgManager, devDepsToInstall, true);\n }\n\n console.log(`\\n${green('✓')} Setup complete! Run: ${bold('nest start --watch')}\\n`);\n}\n"],"mappings":"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","names":["cac","access","isAbsolute","join","relative","resolve","sep","pathToFileURL","ConfigError","Error","message","options","name","CONFIG_FILE","fileExists","filePath","access","importTs","tsImport","tsxEsm","ConfigError","parentURL","pathToFileURL","href","fileUrl","resolveAbsolute","cwd","p","isAbsolute","resolve","assertInsideCwd","resolvedPath","fieldName","rel","relative","startsWith","sep","applyDefaults","userConfig","outDir","codegen","join","resolvedCwd","app","resolvedEntry","moduleEntry","resolvedTsconfig","tsconfig","pages","glob","propsExport","componentNameStrategy","contracts","debounceMs","scopes","loadConfig","process","configPath","mod","err","cause","modNs","default","readFile","relative","fg","discoverPages","opts","files","fg","glob","cwd","absolute","sort","out","file","rel","relative","name","computeName","componentNameStrategy","source","readFile","propsSource","extractPropsSource","propsExport","push","absolutePath","relativePath","strat","noExt","replace","toLowerCase","exportName","re","RegExp","m","match","start","index","length","i","depth","started","c","slice","mkdir","writeFile","join","emitApi","routes","outDir","mkdir","recursive","content","buildApiFile","writeFile","join","splitName","name","split","toObjectKey","segment","test","JSON","stringify","toCamelCase","s","filter","Boolean","map","word","i","charAt","toLowerCase","slice","toUpperCase","validateNameSegment","seg","fullName","suggested","Error","detectCollisions","tree","key","node","kind","insertIntoTree","segments","leaf","head","rest","length","existing","get","undefined","set","prefixName","branch","children","Map","emitRouterTypeBlock","indent","pad","repeat","lines","objKey","c","method","query","contractSource","body","response","safeMethod","safeUrl","path","push","emitApiObjectBlock","flatName","safePath","fetcherMethod","typeAccess","buildRouterTypeAccess","contracted","r","contract","hasGetRoutes","some","mkdir","stat","writeFile","join","emitCache","pages","outDir","mkdir","recursive","entries","Promise","all","map","p","s","stat","absolutePath","name","relativePath","mtime","toISOString","cache","writeFile","join","JSON","stringify","mkdir","writeFile","join","emitIndex","outDir","hasContracts","mkdir","recursive","exports","push","content","join","writeFile","mkdir","writeFile","join","emitPages","pages","outDir","mkdir","recursive","body","map","p","propType","propsSource","key","needsQuotes","name","JSON","stringify","join","content","writeFile","test","mkdir","writeFile","join","emitRoutes","routes","outDir","mkdir","recursive","content","buildRoutesFile","writeFile","join","length","buildEmpty","entries","map","r","JSON","stringify","name","path","routeNameUnion","lines","generate","config","routes","pages","discoverPages","glob","cwd","codegen","propsExport","componentNameStrategy","emitPages","outDir","emitCache","hasRoutes","length","hasContracts","some","r","contract","emitRoutes","emitIndex","emitApi","readFile","join","chokidar","dirname","join","resolve","fg","Node","Project","SyntaxKind","discoverContractsFast","opts","cwd","glob","tsconfig","tsconfigPath","resolve","join","project","Project","tsConfigFilePath","skipAddingFilesFromTsConfig","skipLoadingLibFiles","skipFileDependencyResolution","compilerOptions","allowJs","resolveJsonModule","strict","files","fg","absolute","onlyFiles","f","addSourceFileAtPath","routes","sourceFile","getSourceFiles","push","extractFromSourceFile","zodAstToTs","node","Node","isCallExpression","expr","getExpression","isPropertyAccessExpression","methodName","getName","receiver","args","getArguments","lit","isStringLiteral","JSON","stringify","getLiteralValue","isNumericLiteral","toString","getKind","SyntaxKind","TrueKeyword","FalseKeyword","arrArg","isArrayLiteralExpression","members","getElements","map","el","inner","objArg","isObjectLiteralExpression","lines","prop","getProperties","isPropertyAssignment","key","valNode","getInitializer","tsType","isOpt","isOptionalChain","valArg","length","decoratorStringArg","decoratorExpr","undefined","first","parseDefineContractCall","callExpr","callee","calleeName","isIdentifier","getText","optsArg","query","body","response","propName","val","deriveClassSegment","className","noSuffix","replace","Error","charAt","toLowerCase","slice","resolveRouteName","methodName","classAs","methodAs","classPortion","methodPortion","joinPaths","prefix","suffix","startsWith","p","endsWith","s","combined","extractParams","path","matches","matchAll","Array","from","map","m","name","source","findTypeInFile","file","cls","getClass","kind","decl","iface","getInterface","alias","getTypeAlias","typeNode","getTypeNode","text","getText","enumDecl","getEnum","members","getMembers","val","getValue","JSON","stringify","getName","resolveImportedType","sourceFile","project","importDecl","getImportDeclarations","namedImport","getNamedImports","find","n","moduleSpecifier","getModuleSpecifierValue","dir","dirname","getFilePath","candidates","resolve","candidate","importedFile","getSourceFile","addSourceFileAtPath","result","findType","local","resolveTypeNodeToString","depth","Node","isArrayTypeNode","elementType","getElementTypeNode","isTypeReference","typeName","getTypeName","isIdentifier","typeArgs","getTypeArguments","firstTypeArg","length","undefined","resolved","expandTypeDecl","getKind","SyntaxKind","StringKeyword","NumberKeyword","BooleanKeyword","UnknownKeyword","AnyKeyword","resolvePropertied","join","lines","prop","getProperties","propName","isOptional","hasQuestionToken","propTypeNode","propType","push","extractBodyType","method","param","getParameters","bodyDecorator","getDecorators","d","bodyArgs","getArguments","extractQueryType","queryDecorator","queryArgs","extractParamsType","entries","paramDecorator","paramArgs","nameArg","isStringLiteral","paramName","getLiteralValue","paramType","extractResponseType","apiResponseDecorator","getDecorator","args","optsArg","isObjectLiteralExpression","isPropertyAssignment","getInitializer","isArrayLiteralExpression","elements","getElements","firstEl","innerType","resolveIdentifierToClassType","returnTypeNode","getReturnTypeNode","node","extractDtoContract","body","query","paramsType","response","params","HTTP_METHOD_DECORATORS","Get","Post","Put","Patch","Delete","Options","Head","All","extractFromSourceFile","routes","seenNames","Map","classes","getClasses","controllerDecorator","controllerArgs","firstArg","decoratorStringArg","getMethods","httpMethod","handlerPath","decoratorName","verb","Object","httpDecorator","httpArgs","pathArg","applyContractDecorator","decoratorArgs","firstDecoratorArg","contractDef","isCallExpression","parseDefineContractCall","identName","varDecl","getVariableDeclaration","console","warn","initializer","resolvedMethod","resolvedPath","classAsDecorator","classAsArgs","classAsName","methodAsDecorator","methodAsArgs","methodAsName","routeName","qualifiedRef","existing","get","set","contract","contractSource","dtoContract","mkdir","readFile","unlink","writeFile","join","LOCK_FILE","isProcessAlive","pid","process","kill","acquireLock","outDir","mkdir","recursive","lockPath","join","raw","readFile","existing","JSON","parse","lockData","startedAt","Date","toISOString","writeFile","stringify","release","unlink","PAGES_DEBOUNCE_MS","NO_OP_WATCHER","close","watch","config","onChange","lock","acquireLock","codegen","outDir","holderPid","raw","readFile","join","data","JSON","parse","pid","undefined","String","console","warn","initialRoutes","discoverContractsFast","cwd","glob","contracts","app","tsconfig","generate","err","Error","message","pagesDebounceTimer","pagesWatcher","chokidar","pages","ignoreInitial","persistent","awaitWriteFinish","stabilityThreshold","pollInterval","schedulePagesRegenerate","clearTimeout","setTimeout","on","contractsDebounceTimer","contractsWatcher","scheduleContractsRegenerate","routes","emitRoutes","hasContracts","some","r","contract","emitIndex","emitApi","debounceMs","release","VERSION","runCodegen","opts","cwd","process","config","loadConfig","watch","watcher","Promise","resolve","onSignal","close","then","catch","once","routes","discoverContractsFast","codegen","glob","contracts","app","tsconfig","generate","console","log","outDir","execSync","readFileSync","writeFileSync","access","mkdir","readFile","writeFile","join","createInterface","GITIGNORE_ENTRY","green","s","yellow","cyan","dim","bold","logCreated","path","console","log","logPatched","detail","logSkipped","logWarning","msg","logSection","title","readPackageJson","cwd","raw","readFile","join","JSON","parse","allDeps","pkg","deps","dependencies","devDeps","devDependencies","Object","keys","detectFramework","includes","detectTemplateEngine","detectPackageManager","exists","file","access","promptFramework","process","stdin","isTTY","Promise","resolve","rl","createInterface","input","output","stdout","question","answer","close","trimmed","trim","toLowerCase","fileExists","filePath","writeIfNotExists","content","label","dir","substring","lastIndexOf","mkdir","recursive","writeFile","handleViteConfig","framework","existing","hasPlugin","viteConfigTemplate","patchGitignore","gitignorePath","split","some","line","newContent","endsWith","installDeps","pkgManager","dev","length","flag","cmd","execSync","stdio","patchPackageJsonScripts","scripts","pkgPath","changed","key","value","entries","stringify","findAfterLastImport","lastImportIndex","endOfLine","indexOf","startsWith","patchAppModule","rootView","readFileSync","insertAt","slice","importsMatch","match","index","undefined","bracketPos","indent","controllersMatch","writeFileSync","patchMainTs","createMatch","appVarName","insertAfterPos","viteSetup","configTemplate","glob","DTS_TEMPLATE","htmlShellTemplate","_engine","ext","pluginOption","entryPointTemplate","samplePageTemplate","SAMPLE_CONTROLLER","runInit","opts","engine","engineLabel","frameworkLabel","charAt","toUpperCase","shellFileName","entryExt","pageExt","appModulePath","appModuleResult","mainTsPath","mainTsResult","installedDeps","commonDeps","filter","d","frameworkDeps","frameworkDevDeps","needed","neededDev","depsToInstall","devDepsToInstall","skipInstall","run","argv","cli","cac","command","option","action","opts","runCodegen","watch","Boolean","cwd","process","runInit","help","version","VERSION","parse","runMatchedCommand","err","message","Error","String","console","error"]}
1
+ {"version":3,"sources":["../../src/cli/main.ts","../../src/config/load-config.ts","../../src/exceptions.ts","../../src/discovery/pages.ts","../../src/emit/emit-api.ts","../../src/emit/emit-cache.ts","../../src/emit/emit-index.ts","../../src/emit/emit-pages.ts","../../src/emit/emit-routes.ts","../../src/generate.ts","../../src/watch/watcher.ts","../../src/discovery/contracts-fast.ts","../../src/watch/lock-file.ts","../../src/index.ts","../../src/cli/codegen.ts","../../src/cli/init.ts"],"sourcesContent":["import { cac } from 'cac';\nimport { VERSION } from '../index.js';\nimport { runCodegen } from './codegen.js';\nimport { runInit } from './init.js';\n\n/**\n * Parse `argv` (everything after `node <bin>`) and execute the matched command.\n *\n * Returns an exit code: 0 = success, 1 = error.\n *\n * Exported so tests can call `run(argv)` directly without spawning a subprocess.\n */\nexport async function run(argv: string[]): Promise<number> {\n const cli = cac('nestjs-inertia');\n\n cli\n .command('codegen', 'Generate typed artifacts from your NestJS + Inertia app')\n .option('--watch', 'Watch for file changes and re-generate automatically')\n .action(async (opts: { watch?: boolean }) => {\n await runCodegen({ watch: Boolean(opts.watch), cwd: process.cwd() });\n });\n\n cli\n .command('init', 'Initialise nestjs-inertia-codegen in the current project')\n .action(async () => {\n await runInit({ cwd: process.cwd() });\n });\n\n cli.help();\n cli.version(VERSION);\n\n try {\n // cac needs the first two argv entries to be 'node' and the binary name\n cli.parse(['node', 'nestjs-inertia', ...argv], { run: false });\n await cli.runMatchedCommand();\n return 0;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`[nestjs-inertia] Error: ${message}`);\n return 1;\n }\n}\n","import { access } from 'node:fs/promises';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { ConfigError } from '../exceptions.js';\nimport type { ResolvedConfig, UserConfig } from './types.js';\n\nconst CONFIG_FILE = 'nestjs-inertia.config.ts';\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function importTs(filePath: string): Promise<unknown> {\n // Use tsx ESM API to load TypeScript config files at runtime\n let tsImport:\n | ((specifier: string, options: string | { parentURL: string }) => Promise<unknown>)\n | undefined;\n try {\n const tsxEsm = await import('tsx/esm/api');\n tsImport = tsxEsm.tsImport;\n } catch {\n throw new ConfigError(\n 'Failed to load config: `tsx` is required for loading TypeScript config files. ' +\n 'Install it as a dev dependency: pnpm add -D tsx',\n );\n }\n\n const parentURL = pathToFileURL(`${filePath}__parent__`).href;\n const fileUrl = pathToFileURL(filePath).href;\n return tsImport(fileUrl, { parentURL });\n}\n\nfunction resolveAbsolute(cwd: string, p: string): string {\n if (isAbsolute(p)) return p;\n return resolve(cwd, p);\n}\n\n/**\n * Validates that `resolvedPath` is contained inside `cwd`.\n * Throws `ConfigError` if the path escapes the project root (e.g. via `..`\n * traversal or an absolute path outside cwd).\n */\nfunction assertInsideCwd(cwd: string, resolvedPath: string, fieldName: string): void {\n const rel = relative(cwd, resolvedPath);\n // relative() returns a path starting with '..' when the target is outside cwd,\n // and isAbsolute() catches platform edge-cases (e.g. Windows drive letters).\n if (rel.startsWith(`..${sep}`) || rel === '..' || isAbsolute(rel)) {\n throw new ConfigError(\n `\\`${fieldName}\\` must be inside the project cwd.\\n Resolved to: ${resolvedPath}\\n Project cwd: ${cwd}\\nIf this is intentional, move the file inside your project directory.`,\n );\n }\n}\n\nfunction applyDefaults(userConfig: UserConfig, cwd: string): ResolvedConfig {\n const outDir = userConfig.codegen?.outDir\n ? resolveAbsolute(cwd, userConfig.codegen.outDir)\n : join(cwd, '.nestjs-inertia');\n\n const resolvedCwd = userConfig.codegen?.cwd ? resolveAbsolute(cwd, userConfig.codegen.cwd) : cwd;\n\n let app: ResolvedConfig['app'] = null;\n if (userConfig.app) {\n const resolvedEntry = resolveAbsolute(cwd, userConfig.app.moduleEntry);\n assertInsideCwd(cwd, resolvedEntry, 'app.moduleEntry');\n\n let resolvedTsconfig: string | null = null;\n if (userConfig.app.tsconfig) {\n resolvedTsconfig = resolveAbsolute(cwd, userConfig.app.tsconfig);\n assertInsideCwd(cwd, resolvedTsconfig, 'app.tsconfig');\n }\n\n app = {\n moduleEntry: resolvedEntry,\n tsconfig: resolvedTsconfig,\n };\n }\n\n return {\n pages: {\n glob: userConfig.pages.glob,\n propsExport: userConfig.pages.propsExport ?? 'ComponentProps',\n componentNameStrategy: userConfig.pages.componentNameStrategy ?? 'relative-no-ext',\n },\n contracts: {\n glob: userConfig.contracts?.glob ?? 'src/**/*.controller.ts',\n debounceMs: userConfig.contracts?.debounceMs ?? 500,\n },\n scopes: userConfig.scopes ?? {},\n codegen: {\n outDir,\n cwd: resolvedCwd,\n },\n app,\n };\n}\n\nexport async function loadConfig(cwd?: string): Promise<ResolvedConfig> {\n const resolvedCwd = cwd ?? process.cwd();\n const configPath = join(resolvedCwd, CONFIG_FILE);\n\n if (!(await fileExists(configPath))) {\n throw new ConfigError(\n `Config file not found: ${configPath}\\nRun \\`nestjs-inertia init\\` to create a starter config.`,\n );\n }\n\n let mod: unknown;\n try {\n mod = await importTs(configPath);\n } catch (err) {\n if (err instanceof ConfigError) throw err;\n throw new ConfigError(`Failed to load config from ${configPath}`, { cause: err });\n }\n\n // tsImport returns a namespace module where `mod.default` is the module namespace object.\n // The actual `export default` value lives at `mod.default.default` (or `mod.default` for CJS interop).\n const modNs = (mod as Record<string, unknown>).default;\n const userConfig =\n modNs != null && typeof modNs === 'object' && 'default' in (modNs as object)\n ? ((modNs as Record<string, unknown>).default as UserConfig)\n : (modNs as UserConfig | undefined);\n\n if (!userConfig || typeof userConfig !== 'object') {\n throw new ConfigError(\n `Config file must have a default export. Did you forget \\`export default defineConfig({...})\\`? (${configPath})`,\n );\n }\n\n if (!userConfig.pages || typeof userConfig.pages.glob !== 'string') {\n throw new ConfigError(`Config validation failed: \\`pages.glob\\` is required (${configPath})`);\n }\n\n return applyDefaults(userConfig, resolvedCwd);\n}\n","export class ConfigError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'ConfigError';\n }\n}\n\nexport class CodegenError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'CodegenError';\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { relative } from 'node:path';\nimport fg from 'fast-glob';\n\nexport interface DiscoveredPage {\n name: string;\n absolutePath: string;\n relativePath: string;\n propsSource: string | null;\n}\n\nexport interface DiscoverPagesOptions {\n glob: string;\n cwd: string;\n propsExport: string;\n componentNameStrategy: 'relative-no-ext' | 'kebab' | ((path: string) => string);\n}\n\nexport async function discoverPages(opts: DiscoverPagesOptions): Promise<DiscoveredPage[]> {\n const files = await fg(opts.glob, { cwd: opts.cwd, absolute: true });\n files.sort();\n const out: DiscoveredPage[] = [];\n for (const file of files) {\n const rel = relative(opts.cwd, file);\n const name = computeName(rel, opts.componentNameStrategy);\n const source = await readFile(file, 'utf8');\n const propsSource = extractPropsSource(source, opts.propsExport);\n out.push({ name, absolutePath: file, relativePath: rel, propsSource });\n }\n return out;\n}\n\nfunction computeName(rel: string, strat: DiscoverPagesOptions['componentNameStrategy']): string {\n if (typeof strat === 'function') return strat(rel);\n const noExt = rel.replace(/\\.(tsx?|vue|svelte)$/, '');\n if (strat === 'kebab') return noExt.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n return noExt;\n}\n\nfunction extractPropsSource(source: string, exportName: string): string | null {\n const re = new RegExp(`export\\\\s+type\\\\s+${exportName}\\\\s*=\\\\s*`, 'm');\n const m = source.match(re);\n if (!m) return null;\n const start = m.index! + m[0].length;\n // Brace counting to capture type body\n let i = start;\n let depth = 0;\n let started = false;\n while (i < source.length) {\n const c = source[i];\n if (c === '{') {\n depth++;\n started = true;\n } else if (c === '}') {\n depth--;\n if (started && depth === 0) {\n return source.slice(start, i + 1);\n }\n } else if (c === ';' && !started) return source.slice(start, i);\n i++;\n }\n return source.slice(start);\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * Emits `api.ts` into `outDir` for all routes that carry a `.contract`.\n * - GET routes get `queryOptions`\n * - POST/PUT/PATCH/DELETE routes get `mutationOptions`\n */\nexport async function emitApi(routes: RouteDescriptor[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const content = buildApiFile(routes);\n await writeFile(join(outDir, 'api.ts'), content, 'utf8');\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Split a dot-notation name into its path segments. */\nfunction splitName(name: string): string[] {\n return name.split('.');\n}\n\n/**\n * Check whether a segment is a valid JS identifier.\n * If not, we wrap it in quotes so it produces a valid object key.\n */\nfunction toObjectKey(segment: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(segment)) {\n return segment;\n }\n return JSON.stringify(segment);\n}\n\n/**\n * Convert an arbitrary string segment to camelCase by splitting on non-alphanumeric chars.\n */\nfunction toCamelCase(s: string): string {\n return s\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((word, i) =>\n i === 0\n ? word.charAt(0).toLowerCase() + word.slice(1)\n : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n )\n .join('');\n}\n\n/**\n * Validate that a single name segment matches camelCase: starts with a lowercase letter,\n * followed only by alphanumeric chars. Throws a descriptive error on invalid segments.\n */\nfunction validateNameSegment(seg: string, fullName: string): void {\n if (!/^[a-z][a-zA-Z0-9]*$/.test(seg)) {\n const suggested = toCamelCase(seg);\n throw new Error(\n `Contract name \"${fullName}\" has invalid segment \"${seg}\". Use camelCase identifiers only (lowercase letter then alphanumeric). Suggested: \"${suggested}\"`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nested tree helpers\n// ---------------------------------------------------------------------------\n\ntype LeafEntry = {\n kind: 'leaf';\n method: string;\n name: string;\n path: string;\n contractSource: {\n query: string | null | undefined;\n body: string | null | undefined;\n response: string;\n };\n};\n\ntype BranchEntry = {\n kind: 'branch';\n children: Map<string, TreeNode>;\n};\n\ntype TreeNode = LeafEntry | BranchEntry;\n\nfunction detectCollisions(tree: Map<string, TreeNode>, name: string): void {\n // Walk to ensure no node that is a leaf also has children (or vice versa).\n // Called after insertion; we scan top-level keys for conflicts.\n for (const [key, node] of tree) {\n if (node.kind === 'leaf') {\n // A leaf at this position is fine\n } else {\n void key; // branch is fine too\n }\n }\n void name;\n}\n\n/**\n * Insert a contracted route into the mutable tree.\n * Throws if a name conflict is detected.\n */\nfunction insertIntoTree(\n tree: Map<string, TreeNode>,\n segments: string[],\n leaf: LeafEntry,\n fullName: string,\n): void {\n const head = segments[0] as string;\n const rest = segments.slice(1);\n\n if (rest.length === 0) {\n // This is the final segment — insert as a leaf\n const existing = tree.get(head);\n if (existing !== undefined && existing.kind === 'branch') {\n throw new Error(\n `Contract name conflict: \"${fullName}\" cannot have both a direct entry and child entries`,\n );\n }\n tree.set(head, leaf);\n } else {\n // Need to recurse into a branch\n const existing = tree.get(head);\n if (existing !== undefined && existing.kind === 'leaf') {\n // The leaf's name is the prefix of fullName\n const prefixName = fullName\n .split('.')\n .slice(0, segments.length - rest.length)\n .join('.');\n throw new Error(\n `Contract name conflict: \"${prefixName}\" cannot have both a direct entry and child entries`,\n );\n }\n let branch: BranchEntry;\n if (existing === undefined) {\n branch = { kind: 'branch', children: new Map() };\n tree.set(head, branch);\n } else {\n branch = existing as BranchEntry;\n }\n insertIntoTree(branch.children, rest, leaf, fullName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Code generation helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Emit the nested ApiRouter type block.\n */\nfunction emitRouterTypeBlock(tree: Map<string, TreeNode>, indent: number): string[] {\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n for (const [key, node] of tree) {\n const objKey = toObjectKey(key);\n if (node.kind === 'leaf') {\n const c = node;\n const method = c.method.toUpperCase();\n const query = c.contractSource.query ?? 'never';\n const body = method === 'GET' ? 'never' : (c.contractSource.body ?? 'never');\n const response = c.contractSource.response;\n const safeMethod = JSON.stringify(method);\n const safeUrl = JSON.stringify(c.path);\n lines.push(\n `${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`,\n );\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitRouterTypeBlock(node.children, indent + 2));\n lines.push(`${pad}};`);\n }\n }\n\n return lines;\n}\n\n/**\n * Emit the nested `api` object body.\n */\nfunction emitApiObjectBlock(tree: Map<string, TreeNode>, indent: number): string[] {\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n for (const [key, node] of tree) {\n const objKey = toObjectKey(key);\n if (node.kind === 'leaf') {\n const c = node;\n const method = c.method.toUpperCase();\n const flatName = JSON.stringify(c.name); // e.g. \"users.list\"\n const safePath = JSON.stringify(c.path);\n const fetcherMethod = method.toLowerCase();\n\n if (method === 'GET') {\n const typeAccess = buildRouterTypeAccess(c.name);\n lines.push(`${pad}${objKey}: {`);\n lines.push(`${pad} queryKey: (query?: ${typeAccess}['query']) => query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);\n lines.push(`${pad} queryOptions: (query?: ${typeAccess}['query']) => ({`);\n lines.push(`${pad} queryKey: query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);\n lines.push(\n `${pad} queryFn: () => fetcher.get<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { query }),`,\n );\n lines.push(`${pad} }),`);\n lines.push(`${pad}},`);\n } else {\n const typeAccess = buildRouterTypeAccess(c.name);\n lines.push(`${pad}${objKey}: {`);\n lines.push(`${pad} queryKey: () => [${flatName}] as const,`);\n lines.push(`${pad} mutationOptions: () => ({`);\n lines.push(\n `${pad} mutationFn: (body: ${typeAccess}['body']) => fetcher.${fetcherMethod}<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { body }),`,\n );\n lines.push(`${pad} }),`);\n lines.push(`${pad}},`);\n }\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitApiObjectBlock(node.children, indent + 2));\n lines.push(`${pad}},`);\n }\n }\n\n return lines;\n}\n\n/**\n * Build the ApiRouter type-access chain for a dot-separated name.\n * e.g. 'users.list' -> \"ApiRouter['users']['list']\"\n */\nfunction buildRouterTypeAccess(name: string): string {\n const segments = splitName(name);\n return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join('')}`;\n}\n\n// ---------------------------------------------------------------------------\n// Main builder\n// ---------------------------------------------------------------------------\n\nfunction buildApiFile(routes: RouteDescriptor[]): string {\n const contracted = routes.filter((r) => r.contract);\n\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.',\n '',\n ];\n\n lines.push(\"import { route } from './routes.js';\");\n lines.push(\"import { createFetcher } from '@dudousxd/nestjs-inertia-client';\");\n lines.push('');\n lines.push('export const fetcher = createFetcher();');\n lines.push('');\n\n if (contracted.length === 0) {\n lines.push('export type ApiRouter = Record<string, never>;');\n lines.push('');\n lines.push('export const api: Record<string, never> = {} as Record<string, never>;');\n lines.push('');\n lines.push('export namespace Route {');\n lines.push(' export type Response<K extends string> = never;');\n lines.push(' export type Body<K extends string> = never;');\n lines.push(' export type Query<K extends string> = never;');\n lines.push(' export type Params<K extends string> = never;');\n lines.push(' export type Error<K extends string> = never;');\n lines.push(\n ' export type Request<K extends string> = { body: never; query: never; params: never };',\n );\n lines.push('}');\n lines.push('');\n lines.push('export namespace Path {');\n lines.push(' export type Response<M extends string, U extends string> = never;');\n lines.push(' export type Body<M extends string, U extends string> = never;');\n lines.push(' export type Query<M extends string, U extends string> = never;');\n lines.push(' export type Params<M extends string, U extends string> = never;');\n lines.push(' export type Error<M extends string, U extends string> = never;');\n lines.push('}');\n lines.push('');\n return lines.join('\\n');\n }\n\n // Build a nested tree from all contracted routes\n const tree = new Map<string, TreeNode>();\n\n for (const r of contracted) {\n const c = r.contract!;\n const name: string = r.name;\n const segments = splitName(name);\n // Validate each segment is a valid camelCase identifier\n for (const seg of segments) {\n validateNameSegment(seg, name);\n }\n const leaf: LeafEntry = {\n kind: 'leaf',\n method: r.method,\n name: name,\n path: r.path,\n contractSource: c.contractSource,\n };\n insertIntoTree(tree, segments, leaf, name);\n }\n\n void detectCollisions; // used inline above\n\n // --- ApiRouter type ---\n lines.push('export type ApiRouter = {');\n lines.push(...emitRouterTypeBlock(tree, 2));\n lines.push('};');\n lines.push('');\n\n // --- api object ---\n lines.push('export const api = {');\n lines.push(...emitApiObjectBlock(tree, 2));\n lines.push('};');\n lines.push('');\n\n // --- Recursive helper type _RouterAt: walks nested ApiRouter by dot-path ---\n lines.push('type _RouterAt<R, P extends string> = P extends `${infer Head}.${infer Tail}`');\n lines.push(' ? Head extends keyof R ? _RouterAt<R[Head], Tail> : never');\n lines.push(' : P extends keyof R ? R[P] : never;');\n lines.push('');\n\n // --- ResolveByName: resolve a field from a dot-path name ---\n lines.push(\n 'type ResolveByName<K extends string, Field extends string> = _RouterAt<ApiRouter, K> extends infer R ? Field extends keyof R ? R[Field] : never : never;',\n );\n lines.push('');\n\n // --- ResolveByPath: scan all leaves for matching method + url ---\n // Flattens ApiRouter recursively and finds the entry whose method === M and url === U.\n lines.push('type _LeafValues<T> = T extends { method: string; url: string }');\n lines.push(' ? T');\n lines.push(' : T extends object ? _LeafValues<T[keyof T]> : never;');\n lines.push('');\n lines.push(\n 'type ResolveByPath<M extends string, U extends string, Field extends string> = _LeafValues<ApiRouter> extends infer L',\n );\n lines.push(' ? L extends { method: M; url: U }');\n lines.push(' ? Field extends keyof L ? L[Field] : never');\n lines.push(' : never');\n lines.push(' : never;');\n lines.push('');\n\n // --- Route namespace ---\n lines.push('export namespace Route {');\n lines.push(' export type Response<K extends string> = ResolveByName<K, \"response\">;');\n lines.push(' export type Body<K extends string> = ResolveByName<K, \"body\">;');\n lines.push(' export type Query<K extends string> = ResolveByName<K, \"query\">;');\n lines.push(' export type Params<K extends string> = ResolveByName<K, \"params\">;');\n lines.push(' export type Error<K extends string> = ResolveByName<K, \"error\">;');\n lines.push(' export type Request<K extends string> = {');\n lines.push(' body: Body<K>;');\n lines.push(' query: Query<K>;');\n lines.push(' params: Params<K>;');\n lines.push(' };');\n lines.push('}');\n lines.push('');\n\n // --- Path namespace ---\n lines.push('export namespace Path {');\n lines.push(\n ' export type Response<M extends string, U extends string> = ResolveByPath<M, U, \"response\">;',\n );\n lines.push(\n ' export type Body<M extends string, U extends string> = ResolveByPath<M, U, \"body\">;',\n );\n lines.push(\n ' export type Query<M extends string, U extends string> = ResolveByPath<M, U, \"query\">;',\n );\n lines.push(\n ' export type Params<M extends string, U extends string> = ResolveByPath<M, U, \"params\">;',\n );\n lines.push(\n ' export type Error<M extends string, U extends string> = ResolveByPath<M, U, \"error\">;',\n );\n lines.push('}');\n lines.push('');\n\n return lines.join('\\n');\n}\n","import { mkdir, stat, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\n\nexport interface CacheEntry {\n name: string;\n relativePath: string;\n mtime: string;\n}\n\nexport interface ComponentsCache {\n pages: CacheEntry[];\n}\n\nexport async function emitCache(pages: DiscoveredPage[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const entries: CacheEntry[] = await Promise.all(\n pages.map(async (p) => {\n const s = await stat(p.absolutePath);\n return {\n name: p.name,\n relativePath: p.relativePath,\n mtime: s.mtime.toISOString(),\n };\n }),\n );\n const cache: ComponentsCache = { pages: entries };\n await writeFile(join(outDir, 'components.json'), `${JSON.stringify(cache, null, 2)}\\n`, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function emitIndex(outDir: string, hasContracts = false): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const exports = [\"export * from './pages.js';\", \"export * from './routes.js';\"];\n if (hasContracts) {\n exports.push(\"export * from './api.js';\");\n }\n const content = [\n '// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.',\n ...exports,\n '',\n ].join('\\n');\n await writeFile(join(outDir, 'index.d.ts'), content, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\n\nexport async function emitPages(pages: DiscoveredPage[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const body = pages\n .map((p) => {\n const propType = p.propsSource ?? 'unknown';\n // Use JSON.stringify for the key so unsafe chars (quotes, backslashes, etc.)\n // are properly escaped. Strip the surrounding double-quotes for TypeScript\n // interface key syntax (TS accepts both 'key' and \"key\" — we use double).\n const key = needsQuotes(p.name) ? JSON.stringify(p.name) : p.name;\n return ` ${key}: ${propType};`;\n })\n .join('\\n');\n const content = `// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.\\nexport interface InertiaPages {\\n${body}\\n}\\n`;\n await writeFile(join(outDir, 'pages.d.ts'), content, 'utf8');\n}\n\nfunction needsQuotes(name: string): boolean {\n return !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * Emits `routes.ts` into `outDir` with:\n * - A `ROUTES` constant mapping name → path\n * - A `RouteName` union type of all route names\n * - A `RouteParams<K>` mapped type using template-literal `infer` to extract `:param` segments\n * - A runtime `route(name, params?)` helper that interpolates path params\n */\nexport async function emitRoutes(routes: RouteDescriptor[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const content = buildRoutesFile(routes);\n await writeFile(join(outDir, 'routes.ts'), content, 'utf8');\n}\n\nfunction buildRoutesFile(routes: RouteDescriptor[]): string {\n if (routes.length === 0) {\n return buildEmpty();\n }\n\n const entries = routes\n .map((r) => ` ${JSON.stringify(r.name)}: ${JSON.stringify(r.path)},`)\n .join('\\n');\n\n const routeNameUnion = routes.map((r) => ` | ${JSON.stringify(r.name)}`).join('\\n');\n\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.',\n '',\n '/** Map of route name → path pattern. */',\n 'export const ROUTES = {',\n entries,\n '} as const;',\n '',\n '/** Union of all known route names. */',\n 'export type RouteName =',\n `${routeNameUnion};`,\n '',\n '/**',\n ' * Extracts path-parameter names from a route path string.',\n ' * `ExtractParams<\"/users/:id\">` → `\"id\"`',\n ' */',\n 'export type ExtractParams<Path extends string> =',\n ' Path extends `${string}:${infer Param}/${infer Rest}`',\n ' ? Param | ExtractParams<`/${Rest}`>',\n ' : Path extends `${string}:${infer Param}`',\n ' ? Param',\n ' : never;',\n '',\n '/**',\n ' * Mapped type: given a `RouteName`, returns an object with each path param as `string`.',\n ' * `RouteParams<\"UsersController.show\">` → `{ id: string }`',\n ' * `RouteParams<\"UsersController.list\">` → `Record<string, never>`',\n ' */',\n 'export type RouteParams<K extends RouteName> =',\n ' ExtractParams<(typeof ROUTES)[K]> extends never',\n ' ? Record<string, never>',\n ' : { [P in ExtractParams<(typeof ROUTES)[K]>]: string };',\n '',\n '/**',\n ' * Map of every route name to its resolved params object.',\n ' * Use this for `InertiaRegistry` module augmentation.',\n ' */',\n 'export type RouteParamsMap = { [K in RouteName]: RouteParams<K> };',\n '',\n '/**',\n ' * Build a URL from a named route, interpolating path params and appending query string.',\n ' *',\n ' * @example',\n \" * route('UsersController.show', { id: '42' }) // → '/users/42'\",\n \" * route('UsersController.list') // → '/users'\",\n \" * route('users.list', undefined, { active: true }) // → '/api/users?active=true'\",\n ' */',\n 'export function route<K extends RouteName>(',\n ' name: K,',\n ' ...args: ExtractParams<(typeof ROUTES)[K]> extends never',\n ' ? [params?: undefined, query?: Record<string, unknown>]',\n ' : [params: RouteParams<K>, query?: Record<string, unknown>]',\n '): string {',\n ' const [params, query] = args as [Record<string, string> | undefined, Record<string, unknown> | undefined];',\n ' const path: string | undefined = ROUTES[name as RouteName];',\n ' if (path === undefined) {',\n \" const available = Object.keys(ROUTES).join(', ');\",\n ' throw new Error(',\n ' `[nestjs-inertia] Route \"${String(name)}\" does not exist.\\\\n\\\\n` +',\n ' `Available routes: ${available}\\\\n\\\\n` +',\n ' `This usually means:\\\\n` +',\n ' ` - The route name has a typo\\\\n` +',\n \" ` - The controller hasn't been scanned by codegen yet (run: nestjs-inertia codegen)\\\\n` +\",\n ' ` - The @As() decorator changed the route name\\\\n`',\n ' );',\n ' }',\n ' let resolvedPath: string = path;',\n ' if (params) {',\n ' resolvedPath = resolvedPath.replace(/:([^/]+)/g, (_, key) => {',\n ' const val = params[key];',\n ' if (val === undefined) throw new Error(`Missing route param: ${key}`);',\n ' return encodeURIComponent(val);',\n ' });',\n ' }',\n ' if (query && Object.keys(query).length > 0) {',\n ' const qs = new URLSearchParams();',\n ' for (const [k, v] of Object.entries(query)) {',\n ' if (v !== undefined && v !== null) qs.append(k, String(v));',\n ' }',\n ' const qStr = qs.toString();',\n ' if (qStr) {',\n \" const sep = resolvedPath.includes('?') ? '&' : '?';\",\n ' resolvedPath = `${resolvedPath}${sep}${qStr}`;',\n ' }',\n ' }',\n ' return resolvedPath;',\n '}',\n '',\n ];\n\n return lines.join('\\n');\n}\n\nfunction buildEmpty(): string {\n return [\n '// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.',\n '',\n 'export const ROUTES = {} as const;',\n 'export type RouteName = never;',\n 'export type ExtractParams<_Path extends string> = never;',\n 'export type RouteParams<_K extends RouteName> = Record<string, never>;',\n 'export function route(_name: never, _params?: undefined, _query?: Record<string, unknown>): string { return \"\"; }',\n '',\n ].join('\\n');\n}\n","import type { ResolvedConfig } from './config/types.js';\nimport { discoverPages } from './discovery/pages.js';\nimport type { RouteDescriptor } from './discovery/types.js';\nimport { emitApi } from './emit/emit-api.js';\nimport { emitCache } from './emit/emit-cache.js';\nimport { emitIndex } from './emit/emit-index.js';\nimport { emitPages } from './emit/emit-pages.js';\nimport { emitRoutes } from './emit/emit-routes.js';\n\n/**\n * Run one full codegen pass: discover pages, emit pages.d.ts, components.json, index.d.ts.\n * Route discovery is deliberately skipped — it requires spawning a Nest app and is\n * not appropriate for the hot path of a file watcher.\n *\n * Optionally accepts pre-discovered routes (e.g. from a full generate + route-discovery pass).\n * When routes are present, emits routes.ts.\n * When routes with contracts are present, also emits api.ts.\n */\nexport async function generate(\n config: ResolvedConfig,\n routes: RouteDescriptor[] = [],\n): Promise<void> {\n const pages = await discoverPages({\n glob: config.pages.glob,\n cwd: config.codegen.cwd,\n propsExport: config.pages.propsExport,\n componentNameStrategy: config.pages.componentNameStrategy,\n });\n\n await emitPages(pages, config.codegen.outDir);\n await emitCache(pages, config.codegen.outDir);\n\n const hasRoutes = routes.length > 0;\n const hasContracts = routes.some((r) => r.contract);\n\n if (hasRoutes) {\n await emitRoutes(routes, config.codegen.outDir);\n }\n\n await emitIndex(config.codegen.outDir, hasContracts);\n\n if (hasContracts) {\n await emitApi(routes, config.codegen.outDir);\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport chokidar from 'chokidar';\nimport type { ResolvedConfig } from '../config/types.js';\nimport { discoverContractsFast } from '../discovery/contracts-fast.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport { emitApi } from '../emit/emit-api.js';\nimport { emitIndex } from '../emit/emit-index.js';\nimport { emitRoutes } from '../emit/emit-routes.js';\nimport { generate } from '../generate.js';\nimport { acquireLock } from './lock-file.js';\n\nconst PAGES_DEBOUNCE_MS = 150;\n\nexport interface Watcher {\n close(): Promise<void>;\n}\n\n/** No-op watcher returned when the lock is already held. */\nconst NO_OP_WATCHER: Watcher = { close: async () => {} };\n\n/**\n * Start two chokidar watchers:\n *\n * 1. **Pages watcher** (`config.pages.glob`, 150 ms debounce) — runs `generate(config)` on\n * any page file change, regenerating `pages.d.ts` and the cache manifest.\n *\n * 2. **Contracts watcher** (`config.contracts.glob`, configurable debounce — default 500 ms) —\n * re-runs static AST route discovery via ts-morph, then re-emits `routes.ts` and (when\n * contracts are present) `api.ts` + `index.d.ts`.\n *\n * Both watchers share a single lock file in `config.codegen.outDir`. If another live process\n * already holds the lock, logs a warning and returns a no-op watcher.\n */\nexport async function watch(config: ResolvedConfig, onChange?: () => void): Promise<Watcher> {\n const lock = await acquireLock(config.codegen.outDir);\n\n if (lock === null) {\n // Read the lock file to include the PID in the warning message\n let holderPid = 'unknown';\n try {\n const raw = await readFile(join(config.codegen.outDir, '.watcher.lock'), 'utf8');\n const data = JSON.parse(raw) as { pid?: number };\n if (data.pid !== undefined) holderPid = String(data.pid);\n } catch {\n // Lock file unreadable — fall back to generic warning\n }\n console.warn(\n `[nestjs-inertia-codegen] auto-watch skipped — another process (PID ${holderPid}) is already running the watcher in ${config.codegen.outDir}. Files will continue to regenerate from that process. To take over, stop the other watcher.`,\n );\n return NO_OP_WATCHER;\n }\n\n // Run an initial full pass: pages + routes + contracts (same as a one-shot `codegen` run)\n try {\n const initialRoutes = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n await generate(config, initialRoutes);\n } catch (err) {\n // Best-effort; don't crash the watcher on initial generation failure\n console.warn(`[nestjs-inertia-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`);\n try { await generate(config); } catch { /* fallback: pages only */ }\n }\n\n // ── Pages watcher (fast path — no route discovery) ──────────────────────────\n let pagesDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n const pagesWatcher = chokidar.watch(join(config.codegen.cwd, config.pages.glob), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n function schedulePagesRegenerate(): void {\n if (pagesDebounceTimer !== undefined) {\n clearTimeout(pagesDebounceTimer);\n }\n pagesDebounceTimer = setTimeout(async () => {\n pagesDebounceTimer = undefined;\n try {\n await generate(config);\n } catch {\n // Swallow errors in watch mode\n }\n onChange?.();\n }, PAGES_DEBOUNCE_MS);\n }\n\n pagesWatcher.on('add', schedulePagesRegenerate);\n pagesWatcher.on('change', schedulePagesRegenerate);\n pagesWatcher.on('unlink', schedulePagesRegenerate);\n\n // ── Contracts watcher (static AST discovery via ts-morph) ────────────────────\n let contractsDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n const contractsWatcher = chokidar.watch(join(config.codegen.cwd, config.contracts.glob), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n function scheduleContractsRegenerate(): void {\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n }\n contractsDebounceTimer = setTimeout(async () => {\n contractsDebounceTimer = undefined;\n try {\n const routes: RouteDescriptor[] = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n\n await emitRoutes(routes, config.codegen.outDir);\n\n const hasContracts = routes.some((r) => r.contract);\n await emitIndex(config.codegen.outDir, hasContracts);\n\n if (hasContracts) {\n await emitApi(routes, config.codegen.outDir);\n }\n } catch {\n // Swallow errors in watch mode\n }\n onChange?.();\n }, config.contracts.debounceMs);\n }\n\n contractsWatcher.on('add', scheduleContractsRegenerate);\n contractsWatcher.on('change', scheduleContractsRegenerate);\n contractsWatcher.on('unlink', scheduleContractsRegenerate);\n\n return {\n close: async () => {\n if (pagesDebounceTimer !== undefined) {\n clearTimeout(pagesDebounceTimer);\n pagesDebounceTimer = undefined;\n }\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n contractsDebounceTimer = undefined;\n }\n await pagesWatcher.close();\n await contractsWatcher.close();\n await lock.release();\n },\n };\n}\n","import { dirname, join, resolve } from 'node:path';\nimport fg from 'fast-glob';\n/**\n * Static AST-based contract discovery using ts-morph.\n * Cold start ~100-500 ms.\n */\nimport {\n type ClassDeclaration,\n type InterfaceDeclaration,\n type MethodDeclaration,\n Node,\n Project,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport type { RouteDescriptor } from './types.js';\n\nexport interface FastDiscoveryOptions {\n /** Absolute path to the project root. */\n cwd: string;\n /** Controllers glob, e.g. 'src/**\\/*.controller.ts' */\n glob: string;\n /** Optional tsconfig.json path; default 'tsconfig.json' in cwd */\n tsconfig?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport async function discoverContractsFast(\n opts: FastDiscoveryOptions,\n): Promise<RouteDescriptor[]> {\n const { cwd, glob, tsconfig } = opts;\n\n const tsconfigPath = tsconfig ? resolve(tsconfig) : join(cwd, 'tsconfig.json');\n\n // Try to use tsconfig if it exists; fall back to bare compiler options\n let project: Project;\n try {\n project = new Project({\n tsConfigFilePath: tsconfigPath,\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n });\n } catch {\n // tsconfig not found — create a minimal project without it\n project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: {\n allowJs: true,\n resolveJsonModule: false,\n strict: false,\n },\n });\n }\n\n // Resolve controller file paths\n const files = await fg(glob, { cwd, absolute: true, onlyFiles: true });\n\n for (const f of files) {\n project.addSourceFileAtPath(f);\n }\n\n const routes: RouteDescriptor[] = [];\n\n for (const sourceFile of project.getSourceFiles()) {\n routes.push(...extractFromSourceFile(sourceFile, project));\n }\n\n return routes;\n}\n\n// ---------------------------------------------------------------------------\n// AST walker — exported so unit tests can import it directly\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a ts-morph Node (expression) representing a Zod schema call to a\n * TypeScript type-source string. Falls back to `'unknown'` for anything\n * unrecognised.\n */\nexport function zodAstToTs(node: Node): string {\n // We only handle call expressions (e.g. z.string(), z.object({…}).optional())\n if (!Node.isCallExpression(node)) return 'unknown';\n\n const expr = node.getExpression();\n\n // ── Chained calls: z.xxx().optional() / .nullable() ──────────────────────\n if (Node.isPropertyAccessExpression(expr)) {\n const methodName = expr.getName();\n const receiver = expr.getExpression();\n\n if (methodName === 'optional') {\n return `${zodAstToTs(receiver)} | undefined`;\n }\n if (methodName === 'nullable') {\n return `${zodAstToTs(receiver)} | null`;\n }\n\n // ── z.<method>(…) top-level calls ────────────────────────────────────────\n const args = node.getArguments();\n\n switch (methodName) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'unknown':\n return 'unknown';\n case 'any':\n return 'unknown';\n\n case 'literal': {\n const lit = args[0];\n if (!lit) return 'unknown';\n if (Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());\n if (Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();\n if (lit.getKind() === SyntaxKind.TrueKeyword) return 'true';\n if (lit.getKind() === SyntaxKind.FalseKeyword) return 'false';\n return 'unknown';\n }\n\n case 'enum': {\n // z.enum([\"a\",\"b\",\"c\"])\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n const members = arrArg\n .getElements()\n .map((el) =>\n Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : 'unknown',\n );\n return members.join(' | ');\n }\n\n case 'array': {\n const inner = args[0];\n if (!inner) return 'unknown';\n return `Array<${zodAstToTs(inner)}>`;\n }\n\n case 'object': {\n const objArg = args[0];\n if (!objArg || !Node.isObjectLiteralExpression(objArg)) return 'unknown';\n const lines: string[] = [];\n for (const prop of objArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const key = prop.getName();\n const valNode = prop.getInitializer();\n if (!valNode) continue;\n const tsType = zodAstToTs(valNode);\n // Mark optional if the value is .optional()\n const isOpt = isOptionalChain(valNode);\n lines.push(`${key}${isOpt ? '?' : ''}: ${tsType}`);\n }\n return `{ ${lines.join('; ')} }`;\n }\n\n case 'union': {\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n return arrArg.getElements().map(zodAstToTs).join(' | ');\n }\n\n case 'record': {\n // z.record(V) or z.record(K, V) — always emit Record<string, V>\n const valArg = args.length === 1 ? args[0] : args[1];\n if (!valArg) return 'unknown';\n return `Record<string, ${zodAstToTs(valArg)}>`;\n }\n\n case 'tuple': {\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n return `[${arrArg.getElements().map(zodAstToTs).join(', ')}]`;\n }\n\n default:\n return 'unknown';\n }\n }\n\n return 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Return true when `node` is a CallExpression ending in `.optional()`. */\nfunction isOptionalChain(node: Node): boolean {\n if (!Node.isCallExpression(node)) return false;\n const expr = node.getExpression();\n return Node.isPropertyAccessExpression(expr) && expr.getName() === 'optional';\n}\n\n/** Extract the string value from a decorator argument that is a string literal. */\nfunction decoratorStringArg(decoratorExpr: Node | undefined): string | undefined {\n if (!decoratorExpr) return undefined;\n if (Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();\n if (Node.isArrayLiteralExpression(decoratorExpr)) {\n const first = decoratorExpr.getElements()[0];\n if (first && Node.isStringLiteral(first)) return first.getLiteralValue();\n }\n return undefined;\n}\n\n/**\n * Parse a defineContract({...}) call expression.\n * Returns { query, body, response } or null if unrecognised.\n */\nfunction parseDefineContractCall(callExpr: Node): {\n query: string | null;\n body: string | null;\n response: string;\n} | null {\n if (!Node.isCallExpression(callExpr)) return null;\n\n const callee = callExpr.getExpression();\n // Accept both `defineContract(...)` and any identifier named defineContract\n const calleeName = Node.isIdentifier(callee)\n ? callee.getText()\n : Node.isPropertyAccessExpression(callee)\n ? callee.getName()\n : '';\n\n if (calleeName !== 'defineContract') return null;\n\n const args = callExpr.getArguments();\n const optsArg = args[0];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\n\n let query: string | null = null;\n let body: string | null = null;\n let response = 'unknown';\n\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const propName = prop.getName();\n const val = prop.getInitializer();\n if (!val) continue;\n\n if (propName === 'query') {\n query = zodAstToTs(val);\n } else if (propName === 'body') {\n body = zodAstToTs(val);\n } else if (propName === 'response') {\n response = zodAstToTs(val);\n }\n }\n\n return { query, body, response };\n}\n\n/**\n * Derive the route name from a controller class name and method name.\n * Strips the `Controller` suffix from the class name and lowercases the first letter.\n * e.g. `UsersController.list` → `users.list`\n */\nexport function deriveRouteName(className: string, methodName: string): string {\n const noSuffix = className.replace(/Controller$/, '');\n if (!noSuffix) {\n throw new Error(\n `Controller class name \"${className}\" derives empty route segment after stripping \"Controller\". Add an @As(...) override.`,\n );\n }\n const segment = noSuffix.charAt(0).toLowerCase() + noSuffix.slice(1);\n return `${segment}.${methodName}`;\n}\n\n/**\n * Derive just the class segment (no method) from a controller class name.\n * Strips the `Controller` suffix and lowercases the first letter.\n */\nexport function deriveClassSegment(className: string): string {\n const noSuffix = className.replace(/Controller$/, '');\n if (!noSuffix) {\n throw new Error(\n `Controller class name \"${className}\" derives empty route segment after stripping \"Controller\". Add an @As(...) override at the class level.`,\n );\n }\n return noSuffix.charAt(0).toLowerCase() + noSuffix.slice(1);\n}\n\n/**\n * Compose the final route name from class-level and method-level @As decorators.\n * Rule:\n * classPortion = class @As value ?? deriveClassSegment(className)\n * methodPortion = method @As value ?? methodName\n * result = `${classPortion}.${methodPortion}`\n */\nexport function resolveRouteName(\n className: string,\n methodName: string,\n classAs: string | undefined,\n methodAs: string | undefined,\n): string {\n const classPortion = classAs ?? deriveClassSegment(className);\n const methodPortion = methodAs ?? methodName;\n return `${classPortion}.${methodPortion}`;\n}\n\n/** Join two URL path segments, normalising duplicate slashes. */\nexport function joinPaths(prefix: string, suffix: string): string {\n if (!prefix && !suffix) return '/';\n if (!prefix) return suffix.startsWith('/') ? suffix : `/${suffix}`;\n if (!suffix) return prefix.startsWith('/') ? prefix : `/${prefix}`;\n\n const p = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const s = suffix.startsWith('/') ? suffix : `/${suffix}`;\n const combined = p + s;\n return combined === '' ? '/' : combined;\n}\n\n/** Extract path params from a URL pattern string, e.g. `/users/:id` → [{name:'id',source:'path'}] */\nfunction extractParams(\n path: string,\n): Array<{ name: string; source: 'path' | 'query' | 'body' | 'header' }> {\n const matches = path.matchAll(/:(\\w+)/g);\n return Array.from(matches).map((m) => ({ name: m[1] as string, source: 'path' as const }));\n}\n\n// ---------------------------------------------------------------------------\n// DTO-based contract extraction (standard NestJS patterns — no defineContract)\n// ---------------------------------------------------------------------------\n\ntype TypeDeclResult =\n | { kind: 'class'; decl: ClassDeclaration; file: SourceFile }\n | { kind: 'interface'; decl: InterfaceDeclaration; file: SourceFile }\n | { kind: 'typeAlias'; text: string }\n | { kind: 'enum'; members: string[] };\n\n/**\n * Try to find a type declaration (class, interface, type alias, enum) in a source file.\n */\nfunction findTypeInFile(name: string, file: SourceFile): TypeDeclResult | null {\n const cls = file.getClass(name);\n if (cls) return { kind: 'class', decl: cls, file };\n\n const iface = file.getInterface(name);\n if (iface) return { kind: 'interface', decl: iface, file };\n\n const alias = file.getTypeAlias(name);\n if (alias) {\n const typeNode = alias.getTypeNode();\n return { kind: 'typeAlias', text: typeNode ? typeNode.getText() : 'unknown' };\n }\n\n const enumDecl = file.getEnum(name);\n if (enumDecl) {\n const members = enumDecl.getMembers().map((m) => {\n const val = m.getValue();\n return typeof val === 'string' ? JSON.stringify(val) : JSON.stringify(m.getName());\n });\n return { kind: 'enum', members };\n }\n\n return null;\n}\n\n/**\n * Follow import declarations to find a type in another file.\n */\nfunction resolveImportedType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);\n if (!namedImport) continue;\n\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n if (!moduleSpecifier.startsWith('.')) return null;\n\n const dir = dirname(sourceFile.getFilePath());\n const candidates = [\n resolve(dir, `${moduleSpecifier}.ts`),\n resolve(dir, moduleSpecifier, 'index.ts'),\n ];\n\n for (const candidate of candidates) {\n let importedFile = project.getSourceFile(candidate);\n if (!importedFile) {\n try {\n importedFile = project.addSourceFileAtPath(candidate);\n } catch {\n continue;\n }\n }\n const result = findTypeInFile(name, importedFile);\n if (result) return result;\n }\n }\n return null;\n}\n\n/**\n * Find a type declaration by name: first in the current file, then by following imports.\n */\nfunction findType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n const local = findTypeInFile(name, sourceFile);\n if (local) return local;\n return resolveImportedType(name, sourceFile, project);\n}\n\n/**\n * Resolve a TypeNode to a TypeScript type-source string.\n * Follows imports across files via the ts-morph Project.\n * `depth` limits recursive expansion (guards against circular references).\n */\nfunction resolveTypeNodeToString(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (depth <= 0) return 'unknown';\n\n // Array<T> or T[] — unwrap and wrap\n if (Node.isArrayTypeNode(typeNode)) {\n const elementType = typeNode.getElementTypeNode();\n return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth)}>`;\n }\n\n // TypeReference: Foo, Foo[], Array<Foo>, Promise<Foo>, etc.\n if (Node.isTypeReference(typeNode)) {\n const typeName = typeNode.getTypeName();\n const name = Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();\n\n // Well-known pass-through primitives and types\n if (name === 'string' || name === 'number' || name === 'boolean') return name;\n if (name === 'Date') return 'string';\n if (name === 'unknown' || name === 'any') return 'unknown';\n\n // Array<T> generic form\n if (name === 'Array') {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return `Array<${resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth)}>`;\n }\n return 'Array<unknown>';\n }\n\n // Promise<T> — unwrap\n if (name === 'Promise') {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);\n }\n return 'unknown';\n }\n\n // Try same file first, then follow imports (class, interface, type alias, enum)\n const resolved = findType(name, sourceFile, project);\n if (resolved) {\n return expandTypeDecl(resolved, project, depth - 1);\n }\n\n // Fall back: use the name as-is\n return name;\n }\n\n // Primitive keyword types\n const kind = typeNode.getKind();\n if (kind === SyntaxKind.StringKeyword) return 'string';\n if (kind === SyntaxKind.NumberKeyword) return 'number';\n if (kind === SyntaxKind.BooleanKeyword) return 'boolean';\n if (kind === SyntaxKind.UnknownKeyword) return 'unknown';\n if (kind === SyntaxKind.AnyKeyword) return 'unknown';\n\n // Fallback: raw text\n return typeNode.getText();\n}\n\n/**\n * Expand a TypeDeclResult into an inline TS type string.\n */\nfunction expandTypeDecl(result: TypeDeclResult, project: Project, depth: number): string {\n if (depth < 0) return 'unknown';\n switch (result.kind) {\n case 'class':\n return resolvePropertied(result.decl, result.file, project, depth);\n case 'interface':\n return resolvePropertied(result.decl, result.file, project, depth);\n case 'typeAlias':\n return result.text;\n case 'enum':\n return result.members.join(' | ');\n }\n}\n\n/**\n * Turn a class or interface declaration's properties into a TS object type string like\n * `{ id: string; title: string; page?: number }`.\n */\nfunction resolvePropertied(\n decl: ClassDeclaration | InterfaceDeclaration,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (depth < 0) return 'unknown';\n\n const lines: string[] = [];\n for (const prop of decl.getProperties()) {\n const propName = prop.getName();\n const isOptional = prop.hasQuestionToken();\n const propTypeNode = prop.getTypeNode();\n let propType = 'unknown';\n if (propTypeNode) {\n propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth);\n }\n lines.push(`${propName}${isOptional ? '?' : ''}: ${propType}`);\n }\n return `{ ${lines.join('; ')} }`;\n}\n\n/**\n * Extract the body type from a `@Body()` (no-arg) decorated parameter.\n * Returns a TS type string or null.\n */\nfunction extractBodyType(method: MethodDeclaration, sourceFile: SourceFile, project: Project): string | null {\n for (const param of method.getParameters()) {\n const bodyDecorator = param.getDecorators().find((d) => d.getName() === 'Body');\n if (!bodyDecorator) continue;\n const bodyArgs = bodyDecorator.getArguments();\n if (bodyArgs.length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n return null;\n}\n\n/**\n * Extract the query type from a `@Query()` (no-arg) decorated parameter.\n * Returns a TS type string or null.\n */\nfunction extractQueryType(method: MethodDeclaration, sourceFile: SourceFile, project: Project): string | null {\n for (const param of method.getParameters()) {\n const queryDecorator = param.getDecorators().find((d) => d.getName() === 'Query');\n if (!queryDecorator) continue;\n const queryArgs = queryDecorator.getArguments();\n if (queryArgs.length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n return null;\n}\n\n/**\n * Collect `@Param('name')` decorated parameters into a `{ name: type; ... }` string.\n * Returns a TS type string or null when no @Param decorators are present.\n */\nfunction extractParamsType(method: MethodDeclaration, sourceFile: SourceFile, project: Project): string | null {\n const entries: string[] = [];\n for (const param of method.getParameters()) {\n const paramDecorator = param.getDecorators().find((d) => d.getName() === 'Param');\n if (!paramDecorator) continue;\n const paramArgs = paramDecorator.getArguments();\n if (paramArgs.length === 0) continue;\n const nameArg = paramArgs[0];\n if (!Node.isStringLiteral(nameArg)) continue;\n const paramName = nameArg.getLiteralValue();\n const typeNode = param.getTypeNode();\n const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : 'string';\n entries.push(`${paramName}: ${paramType}`);\n }\n return entries.length > 0 ? `{ ${entries.join('; ')} }` : null;\n}\n\n/**\n * Extract the response type from `@ApiResponse({ type: X })` or `@ApiResponse({ type: [X] })`.\n * Falls back to the method return type annotation (unwrapping `Promise<>`).\n * Returns a TS type string (never null — falls back to 'unknown').\n */\nfunction extractResponseType(method: MethodDeclaration, sourceFile: SourceFile, project: Project): string {\n // 1. Try @ApiResponse\n const apiResponseDecorator = method.getDecorator('ApiResponse');\n if (apiResponseDecorator) {\n const args = apiResponseDecorator.getArguments();\n const optsArg = args[0];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n if (prop.getName() !== 'type') continue;\n const val = prop.getInitializer();\n if (!val) continue;\n\n // type: [PostDto] — array syntax\n if (Node.isArrayLiteralExpression(val)) {\n const elements = val.getElements();\n const firstEl = elements[0];\n if (elements.length > 0 && firstEl !== undefined) {\n const innerType = resolveIdentifierToClassType(firstEl, sourceFile, project, 3);\n return `Array<${innerType}>`;\n }\n return 'Array<unknown>';\n }\n\n // type: PostDto — single class reference\n return resolveIdentifierToClassType(val, sourceFile, project, 3);\n }\n }\n }\n\n // 2. Fall back to return type annotation\n const returnTypeNode = method.getReturnTypeNode();\n if (returnTypeNode) {\n return resolveTypeNodeToString(returnTypeNode, sourceFile, project, 3);\n }\n\n return 'unknown';\n}\n\n/**\n * Resolve an expression (expected to be a class identifier) to its expanded type string.\n * E.g. the `PostDto` identifier in `@ApiResponse({ type: PostDto })`.\n */\nfunction resolveIdentifierToClassType(node: Node, sourceFile: SourceFile, project: Project, depth: number): string {\n if (!Node.isIdentifier(node)) return 'unknown';\n const name = node.getText();\n const resolved = findType(name, sourceFile, project);\n if (resolved) {\n return expandTypeDecl(resolved, project, depth - 1);\n }\n return name;\n}\n\n/**\n * Determine whether a method has any DTO-based contract info worth emitting\n * (body, query, params, or non-unknown response).\n * Returns a ContractSource-shaped object or null.\n */\nexport function extractDtoContract(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): { query: string | null; body: string | null; response: string; params: string | null } | null {\n const body = extractBodyType(method, sourceFile, project);\n const query = extractQueryType(method, sourceFile, project);\n const paramsType = extractParamsType(method, sourceFile, project);\n const response = extractResponseType(method, sourceFile, project);\n\n // Only emit a contract if there is at least something useful\n if (body === null && query === null && paramsType === null && response === 'unknown') {\n return null;\n }\n\n return { query, body, response, params: paramsType };\n}\n\n// ---------------------------------------------------------------------------\n// HTTP method decorator names recognised by the fast path\n// ---------------------------------------------------------------------------\n\nconst HTTP_METHOD_DECORATORS: Record<string, string> = {\n Get: 'GET',\n Post: 'POST',\n Put: 'PUT',\n Patch: 'PATCH',\n Delete: 'DELETE',\n Options: 'OPTIONS',\n Head: 'HEAD',\n All: 'ALL',\n};\n\n// ---------------------------------------------------------------------------\n// Per-file extraction\n// ---------------------------------------------------------------------------\n\nfunction extractFromSourceFile(sourceFile: SourceFile, project: Project): RouteDescriptor[] {\n const routes: RouteDescriptor[] = [];\n // Track derived/assigned names to detect collisions: name → fully-qualified method ref\n const seenNames = new Map<string, string>();\n\n const classes = sourceFile.getClasses();\n\n for (const cls of classes) {\n // Find @Controller(...) decorator\n const controllerDecorator = cls.getDecorator('Controller');\n if (!controllerDecorator) continue;\n\n // Determine controller path prefix\n const controllerArgs = controllerDecorator.getArguments();\n const firstArg = controllerArgs[0];\n const prefix = decoratorStringArg(firstArg) ?? '';\n\n const className = cls.getName() ?? 'Unknown';\n\n // Walk all methods\n for (const method of cls.getMethods()) {\n // ── Determine HTTP method + sub-path from NestJS verb decorators ──────\n let httpMethod: string | undefined;\n let handlerPath = '';\n\n for (const [decoratorName, verb] of Object.entries(HTTP_METHOD_DECORATORS)) {\n const httpDecorator = method.getDecorator(decoratorName);\n if (httpDecorator) {\n httpMethod = verb;\n const httpArgs = httpDecorator.getArguments();\n const pathArg = httpArgs[0];\n handlerPath = decoratorStringArg(pathArg) ?? '';\n break;\n }\n }\n\n // ── Check for @ApplyContract ──────────────────────────────────────────\n const applyContractDecorator = method.getDecorator('ApplyContract');\n\n if (applyContractDecorator) {\n const decoratorArgs = applyContractDecorator.getArguments();\n const firstDecoratorArg = decoratorArgs[0];\n if (!firstDecoratorArg) continue;\n\n // Resolve contract definition from inline call or identifier\n let contractDef: {\n query: string | null;\n body: string | null;\n response: string;\n } | null = null;\n\n if (Node.isCallExpression(firstDecoratorArg)) {\n contractDef = parseDefineContractCall(firstDecoratorArg);\n } else if (Node.isIdentifier(firstDecoratorArg)) {\n const identName = firstDecoratorArg.getText();\n const varDecl = sourceFile.getVariableDeclaration(identName);\n if (!varDecl) {\n console.warn(\n `[nestjs-inertia-codegen/fast] Cannot resolve '${identName}' in ${sourceFile.getFilePath()} (cross-file imports are out-of-scope for v1) — skipping`,\n );\n continue;\n }\n\n const initializer = varDecl.getInitializer();\n if (!initializer) continue;\n\n contractDef = parseDefineContractCall(initializer);\n } else {\n console.warn(\n `[nestjs-inertia-codegen/fast] @ApplyContract arg is not an identifier or call expression in ${sourceFile.getFilePath()} — skipping`,\n );\n continue;\n }\n\n if (!contractDef) continue;\n\n // Method + path always come from NestJS decorators — skip if absent\n if (!httpMethod) continue;\n const resolvedMethod = httpMethod;\n const resolvedPath = joinPaths(prefix, handlerPath);\n\n const combined = resolvedPath;\n const params = extractParams(combined);\n\n // Determine route name: compose class-level @As + method-level @As\n const methodName = method.getName();\n\n // Read class-level @As\n const classAsDecorator = cls.getDecorator('As');\n let classAs: string | undefined;\n if (classAsDecorator) {\n const classAsArgs = classAsDecorator.getArguments();\n const classAsName = decoratorStringArg(classAsArgs[0]);\n if (!classAsName) {\n throw new Error(\n `@As decorator on class ${className} must have a non-empty string argument.`,\n );\n }\n classAs = classAsName;\n }\n\n // Read method-level @As\n const methodAsDecorator = method.getDecorator('As');\n let methodAs: string | undefined;\n if (methodAsDecorator) {\n const methodAsArgs = methodAsDecorator.getArguments();\n const methodAsName = decoratorStringArg(methodAsArgs[0]);\n if (!methodAsName) {\n throw new Error(\n `@As decorator on ${className}.${methodName} must have a non-empty string argument.`,\n );\n }\n methodAs = methodAsName;\n }\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // Collision detection across contracted routes\n const qualifiedRef = `${className}.${methodName}`;\n const existing = seenNames.get(routeName);\n if (existing !== undefined) {\n throw new Error(\n `Route name collision: \"${routeName}\" is used by both \"${existing}\" and \"${qualifiedRef}\". Use @As(...) to give one of them a unique name.`,\n );\n }\n seenNames.set(routeName, qualifiedRef);\n\n routes.push({\n method: resolvedMethod,\n path: combined,\n name: routeName,\n params,\n contract: {\n contractSource: {\n query: contractDef.query,\n body: contractDef.body,\n response: contractDef.response,\n },\n },\n });\n } else {\n // ── Plain HTTP verb decorator (no @ApplyContract) ──────────────────\n if (!httpMethod) continue;\n\n const combined = joinPaths(prefix, handlerPath);\n const params = extractParams(combined);\n\n const methodName = method.getName();\n\n // Read class-level @As\n const classAsDecorator = cls.getDecorator('As');\n let classAs: string | undefined;\n if (classAsDecorator) {\n const classAsArgs = classAsDecorator.getArguments();\n const classAsName = decoratorStringArg(classAsArgs[0]);\n if (classAsName) classAs = classAsName;\n }\n\n // Read method-level @As\n const methodAsDecorator = method.getDecorator('As');\n let methodAs: string | undefined;\n if (methodAsDecorator) {\n const methodAsArgs = methodAsDecorator.getArguments();\n const methodAsName = decoratorStringArg(methodAsArgs[0]);\n if (methodAsName) methodAs = methodAsName;\n }\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // ── DTO-based contract extraction ──────────────────────────────────\n const dtoContract = extractDtoContract(method, sourceFile, project);\n\n routes.push({\n method: httpMethod,\n path: combined,\n name: routeName,\n params,\n // Attach contract if DTO extraction produced useful type info\n ...(dtoContract\n ? {\n contract: {\n contractSource: {\n query: dtoContract.query,\n body: dtoContract.body,\n response: dtoContract.response,\n },\n },\n }\n : {}),\n });\n }\n }\n }\n\n return routes;\n}\n","import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nconst LOCK_FILE = '.watcher.lock';\n\ninterface LockData {\n pid: number;\n startedAt: string;\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Try to acquire an exclusive lock for a watcher in `outDir`.\n *\n * Returns `{ release }` on success.\n * Returns `null` if another live process already holds the lock.\n */\nexport async function acquireLock(\n outDir: string,\n): Promise<{ release: () => Promise<void> } | null> {\n await mkdir(outDir, { recursive: true });\n const lockPath = join(outDir, LOCK_FILE);\n\n // Check for an existing lock\n try {\n const raw = await readFile(lockPath, 'utf8');\n const existing = JSON.parse(raw) as LockData;\n if (isProcessAlive(existing.pid)) {\n // Another live process holds the lock\n return null;\n }\n // Stale lock — fall through to overwrite\n } catch {\n // File doesn't exist or is corrupt — fall through to create\n }\n\n const lockData: LockData = { pid: process.pid, startedAt: new Date().toISOString() };\n await writeFile(lockPath, `${JSON.stringify(lockData, null, 2)}\\n`, 'utf8');\n\n return {\n release: async () => {\n try {\n await unlink(lockPath);\n } catch {\n // Ignore if already removed\n }\n },\n };\n}\n","export const VERSION = '2.0.1';\n\nexport { defineConfig } from './config/define-config.js';\nexport { loadConfig } from './config/load-config.js';\nexport type { UserConfig, ResolvedConfig, ScopeConfig } from './config/types.js';\nexport { ConfigError, CodegenError } from './exceptions.js';\n\nexport { generate } from './generate.js';\nexport { watch } from './watch/watcher.js';\nexport type { Watcher } from './watch/watcher.js';\nexport { acquireLock } from './watch/lock-file.js';\n","import { loadConfig } from '../config/load-config.js';\nimport { discoverContractsFast } from '../discovery/contracts-fast.js';\nimport { generate } from '../generate.js';\nimport { watch } from '../watch/watcher.js';\n\nexport interface RunCodegenOptions {\n watch?: boolean;\n cwd?: string;\n}\n\n/**\n * Programmatic entry point for `nestjs-inertia codegen [--watch]`.\n *\n * - Loads `nestjs-inertia.config.ts` from `cwd`.\n * - In one-shot mode: discovers routes via static AST, then generates all artifacts.\n * - If `watch` is true, delegates entirely to the chokidar watcher (which\n * handles its own route discovery internally) and suspends until SIGINT/SIGTERM.\n *\n * Throws on config or generation errors (the CLI catches and returns exit code 1).\n */\nexport async function runCodegen(opts: RunCodegenOptions = {}): Promise<void> {\n const cwd = opts.cwd ?? process.cwd();\n const config = await loadConfig(cwd);\n\n if (opts.watch) {\n const watcher = await watch(config);\n\n await new Promise<void>((resolve) => {\n function onSignal() {\n watcher.close().then(resolve).catch(resolve);\n }\n process.once('SIGINT', onSignal);\n process.once('SIGTERM', onSignal);\n });\n return;\n }\n\n // One-shot: discover routes via static AST, then generate all artifacts.\n const routes = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n\n await generate(config, routes);\n console.log('✓ Codegen generated artifacts in', config.codegen.outDir);\n}\n","import { execSync } from 'node:child_process';\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { access, mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { createInterface } from 'node:readline';\n\nexport interface RunInitOptions {\n cwd?: string;\n /** Skip running package manager installs (useful for testing). */\n skipInstall?: boolean;\n}\n\ntype Framework = 'react' | 'vue' | 'svelte';\ntype TemplateEngine = 'handlebars' | 'ejs' | 'pug' | 'liquid' | 'html';\ntype PackageManager = 'pnpm' | 'npm' | 'yarn';\n\nconst GITIGNORE_ENTRY = '.nestjs-inertia/';\n\n// ---------------------------------------------------------------------------\n// ANSI color helpers (no external deps)\n// ---------------------------------------------------------------------------\n\nconst green = (s: string) => `\\x1b[32m${s}\\x1b[0m`;\nconst yellow = (s: string) => `\\x1b[33m${s}\\x1b[0m`;\nconst cyan = (s: string) => `\\x1b[36m${s}\\x1b[0m`;\nconst dim = (s: string) => `\\x1b[2m${s}\\x1b[0m`;\nconst bold = (s: string) => `\\x1b[1m${s}\\x1b[0m`;\n\nfunction logCreated(path: string) {\n console.log(` ${green('✓')} ${path} ${dim('(created)')}`);\n}\nfunction logPatched(path: string, detail: string) {\n console.log(` ${green('✓')} ${path} ${dim(`(${detail})`)}`);\n}\nfunction logSkipped(path: string) {\n console.log(` ${cyan('→')} ${path} ${dim('(already exists, skipped)')}`);\n}\nfunction logWarning(msg: string) {\n console.log(` ${yellow('⚠')} ${msg}`);\n}\nfunction logSection(title: string) {\n console.log(`\\n${bold(title)}`);\n}\n\n// ---------------------------------------------------------------------------\n// Detection helpers\n// ---------------------------------------------------------------------------\n\nasync function readPackageJson(cwd: string): Promise<Record<string, unknown>> {\n try {\n const raw = await readFile(join(cwd, 'package.json'), 'utf8');\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nfunction allDeps(pkg: Record<string, unknown>): string[] {\n const deps = (pkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;\n return [...Object.keys(deps), ...Object.keys(devDeps)];\n}\n\nexport async function detectFramework(cwd: string): Promise<Framework | null> {\n const pkg = await readPackageJson(cwd);\n const deps = allDeps(pkg);\n\n if (deps.includes('@inertiajs/react') || deps.includes('react')) return 'react';\n if (deps.includes('@inertiajs/vue3') || deps.includes('vue')) return 'vue';\n if (deps.includes('@inertiajs/svelte') || deps.includes('svelte')) return 'svelte';\n return null;\n}\n\nexport async function detectTemplateEngine(cwd: string): Promise<TemplateEngine> {\n const pkg = await readPackageJson(cwd);\n const deps = allDeps(pkg);\n\n if (deps.includes('handlebars')) return 'handlebars';\n if (deps.includes('ejs')) return 'ejs';\n if (deps.includes('pug')) return 'pug';\n if (deps.includes('liquidjs')) return 'liquid';\n return 'html';\n}\n\nexport async function detectPackageManager(cwd: string): Promise<PackageManager> {\n async function exists(file: string): Promise<boolean> {\n try {\n await access(join(cwd, file));\n return true;\n } catch {\n return false;\n }\n }\n\n if (await exists('pnpm-lock.yaml')) return 'pnpm';\n if (await exists('yarn.lock')) return 'yarn';\n return 'npm';\n}\n\nasync function promptFramework(): Promise<Framework> {\n // If not interactive (CI), default to React\n if (!process.stdin.isTTY) return 'react';\n\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(\n '[nestjs-inertia] Which frontend framework? (react/vue/svelte) [react]: ',\n (answer) => {\n rl.close();\n const trimmed = answer.trim().toLowerCase();\n if (trimmed === 'vue') resolve('vue');\n else if (trimmed === 'svelte') resolve('svelte');\n else resolve('react');\n },\n );\n });\n}\n\n// ---------------------------------------------------------------------------\n// File helpers\n// ---------------------------------------------------------------------------\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function writeIfNotExists(\n filePath: string,\n content: string,\n label: string,\n): Promise<void> {\n if (await fileExists(filePath)) {\n logSkipped(label);\n return;\n }\n // Ensure parent directory exists\n const dir = filePath.substring(0, filePath.lastIndexOf('/'));\n if (dir) {\n await mkdir(dir, { recursive: true });\n }\n await writeFile(filePath, content, 'utf8');\n logCreated(label);\n}\n\n/**\n * Handle vite.config.ts — create if missing, warn if present without nestInertia plugin.\n */\nasync function handleViteConfig(cwd: string, framework: Framework): Promise<void> {\n const filePath = join(cwd, 'vite.config.ts');\n if (await fileExists(filePath)) {\n const existing = await readFile(filePath, 'utf8');\n const hasPlugin =\n existing.includes('nestInertia') || existing.includes('nestjs-inertia-vite/plugin');\n if (!hasPlugin) {\n logSkipped('vite.config.ts');\n logWarning(\n `vite.config.ts exists but nestInertia plugin not detected — add it manually:\\n import nestInertia from '@dudousxd/nestjs-inertia-vite/plugin';\\n plugins: [nestInertia({ ${framework}: true })]`,\n );\n } else {\n logSkipped('vite.config.ts');\n }\n return;\n }\n const dir = filePath.substring(0, filePath.lastIndexOf('/'));\n if (dir) {\n await mkdir(dir, { recursive: true });\n }\n await writeFile(filePath, viteConfigTemplate(framework), 'utf8');\n logCreated('vite.config.ts');\n}\n\nasync function patchGitignore(gitignorePath: string): Promise<void> {\n let existing = '';\n if (await fileExists(gitignorePath)) {\n existing = await readFile(gitignorePath, 'utf8');\n }\n\n if (existing.split('\\n').some((line) => line.trim() === GITIGNORE_ENTRY)) {\n console.log(` ${cyan('→')} .gitignore ${dim('(already contains .nestjs-inertia/, skipped)')}`);\n return;\n }\n\n const newContent =\n existing.endsWith('\\n') || existing === ''\n ? `${existing}${GITIGNORE_ENTRY}\\n`\n : `${existing}\\n${GITIGNORE_ENTRY}\\n`;\n\n await writeFile(gitignorePath, newContent, 'utf8');\n logPatched('.gitignore', 'added .nestjs-inertia/');\n}\n\nexport function installDeps(pkgManager: PackageManager, deps: string[], dev: boolean): void {\n if (deps.length === 0) return;\n\n const flag = dev ? (pkgManager === 'npm' ? '--save-dev' : '-D') : '';\n const cmd =\n pkgManager === 'npm'\n ? `npm install ${flag} ${deps.join(' ')}`\n : pkgManager === 'yarn'\n ? `yarn add ${flag} ${deps.join(' ')}`\n : `pnpm add ${flag} ${deps.join(' ')}`;\n\n logPatched(deps.join(', '), 'installed');\n try {\n execSync(cmd, { stdio: 'inherit' });\n } catch {\n logWarning(`Failed to install deps. Run manually:\\n ${cmd}`);\n }\n}\n\nexport async function patchPackageJsonScripts(\n cwd: string,\n scripts: Record<string, string>,\n): Promise<void> {\n const pkgPath = join(cwd, 'package.json');\n let pkg: Record<string, unknown> = {};\n try {\n pkg = JSON.parse(await readFile(pkgPath, 'utf8')) as Record<string, unknown>;\n } catch {\n return; // no package.json — skip\n }\n\n const existing = (pkg.scripts ?? {}) as Record<string, string>;\n let changed = false;\n\n for (const [key, value] of Object.entries(scripts)) {\n if (!(key in existing)) {\n existing[key] = value;\n changed = true;\n logPatched('package.json', `added ${key} script`);\n } else {\n console.log(` ${cyan('→')} package.json ${dim(`(${key} already defined, skipped)`)}`);\n }\n }\n\n if (!changed) {\n return;\n }\n\n pkg.scripts = existing;\n await writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`, 'utf8');\n}\n\n// ---------------------------------------------------------------------------\n// Module patching helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Find the position just after the last import statement in a file.\n * Handles files where the first line starts with `import` (no leading newline).\n */\nfunction findAfterLastImport(content: string): number {\n // Try \\nimport first (import not on the first line)\n const lastImportIndex = content.lastIndexOf('\\nimport ');\n if (lastImportIndex !== -1) {\n const endOfLine = content.indexOf('\\n', lastImportIndex + 1);\n return endOfLine !== -1 ? endOfLine + 1 : content.length;\n }\n // Fallback: import at the very start of the file\n if (content.startsWith('import ')) {\n const endOfLine = content.indexOf('\\n');\n return endOfLine !== -1 ? endOfLine + 1 : content.length;\n }\n return 0;\n}\n\n/**\n * Patch `src/app.module.ts` to add InertiaModule.forRoot() and HomeController.\n * Returns 'patched' | 'already' | 'skipped'\n */\nexport function patchAppModule(\n filePath: string,\n rootView: string,\n): 'patched' | 'already' | 'skipped' {\n let content: string;\n try {\n content = readFileSync(filePath, 'utf8');\n } catch {\n return 'skipped';\n }\n\n let changed = false;\n\n // --- InertiaModule ---\n if (!content.includes('InertiaModule')) {\n const insertAt = findAfterLastImport(content);\n if (insertAt > 0) {\n content = `${content.slice(0, insertAt)}import { InertiaModule } from '@dudousxd/nestjs-inertia';\\n${content.slice(insertAt)}`;\n }\n\n // Find `imports: [` and insert after the opening bracket\n const importsMatch = content.match(/imports\\s*:\\s*\\[/);\n if (importsMatch?.index !== undefined) {\n const bracketPos = content.indexOf('[', importsMatch.index) + 1;\n const indent = ' ';\n content = `${content.slice(0, bracketPos)}\\n${indent}InertiaModule.forRoot({\\n${indent} rootView: '${rootView}',\\n${indent}}),${content.slice(bracketPos)}`;\n changed = true;\n }\n }\n\n // --- HomeController ---\n if (!content.includes('HomeController')) {\n const insertAt = findAfterLastImport(content);\n if (insertAt > 0) {\n content = `${content.slice(0, insertAt)}import { HomeController } from './home.controller';\\n${content.slice(insertAt)}`;\n }\n\n // Find `controllers: [` and insert after the opening bracket\n const controllersMatch = content.match(/controllers\\s*:\\s*\\[/);\n if (controllersMatch?.index !== undefined) {\n const bracketPos = content.indexOf('[', controllersMatch.index) + 1;\n const indent = ' ';\n content = `${content.slice(0, bracketPos)}\\n${indent}HomeController,${content.slice(bracketPos)}`;\n changed = true;\n }\n }\n\n if (!changed) return 'already';\n\n writeFileSync(filePath, content, 'utf8');\n return 'patched';\n}\n\n/**\n * Patch `src/main.ts` to add setupInertiaVite() call.\n * Returns 'patched' | 'already' | 'skipped'\n */\nexport function patchMainTs(filePath: string): 'patched' | 'already' | 'skipped' {\n let content: string;\n try {\n content = readFileSync(filePath, 'utf8');\n } catch {\n return 'skipped';\n }\n\n if (content.includes('setupInertiaVite')) return 'already';\n\n // Add import after the last import statement\n const insertAt = findAfterLastImport(content);\n if (insertAt > 0) {\n content = `${content.slice(0, insertAt)}import { setupInertiaVite } from '@dudousxd/nestjs-inertia-vite';\\n${content.slice(insertAt)}`;\n }\n\n // Find NestFactory.create assignment line\n const createMatch = content.match(\n /(?:const|let)\\s+(\\w+)\\s*=\\s*await\\s+NestFactory\\.create[^;]+;/,\n );\n if (!createMatch || createMatch.index === undefined) return 'skipped';\n\n const appVarName = createMatch[1];\n const insertAfterPos = createMatch.index + createMatch[0].length;\n\n const viteSetup = `\n // Inertia + Vite integration (dev: HMR middleware, prod: static assets)\n await setupInertiaVite(${appVarName}, {\n mode: process.env.NODE_ENV ?? 'development',\n root: 'inertia',\n publicDir: 'dist/inertia/client',\n outDir: 'dist/inertia',\n });`;\n\n content = `${content.slice(0, insertAfterPos)}\\n${viteSetup}${content.slice(insertAfterPos)}`;\n writeFileSync(filePath, content, 'utf8');\n return 'patched';\n}\n\n// ---------------------------------------------------------------------------\n// Template generators\n// ---------------------------------------------------------------------------\n\nfunction configTemplate(framework: Framework): string {\n const glob =\n framework === 'react'\n ? 'inertia/pages/**/*.tsx'\n : framework === 'vue'\n ? 'inertia/pages/**/*.vue'\n : 'inertia/pages/**/*.svelte';\n\n return `import { defineConfig } from '@dudousxd/nestjs-inertia-codegen';\n\nexport default defineConfig({\n pages: {\n glob: '${glob}',\n },\n});\n`;\n}\n\nconst DTS_TEMPLATE = `// Auto-generated by nestjs-inertia-codegen. Commit this file.\n// Re-run \\`nestjs-inertia codegen\\` to refresh after adding/removing pages.\n\nimport '.nestjs-inertia/index.js';\n\ndeclare module '@dudousxd/nestjs-inertia' {\n interface InertiaRegistry {\n pages: import('.nestjs-inertia/pages.js').InertiaPages;\n shared: import('.nestjs-inertia/shared.js').InertiaSharedProps;\n routes: import('.nestjs-inertia/routes.js').RouteParamsMap;\n }\n}\n`;\n\nfunction htmlShellTemplate(framework: Framework, _engine: TemplateEngine): string {\n const ext = framework === 'react' ? 'tsx' : 'ts';\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>My App</title>\n @inertiaHead\n</head>\n<body>\n @inertia\n @vite('inertia/app.${ext}')\n</body>\n</html>\n`;\n}\n\nfunction viteConfigTemplate(framework: Framework): string {\n const pluginOption = `{ ${framework}: true }`;\n return `import { defineConfig } from 'vite';\nimport nestInertia from '@dudousxd/nestjs-inertia-vite/plugin';\n\nexport default defineConfig({\n plugins: [nestInertia(${pluginOption})],\n});\n`;\n}\n\nfunction entryPointTemplate(framework: Framework): string {\n if (framework === 'react') {\n return `import { createRoot } from 'react-dom/client';\nimport { createInertiaApp } from '@inertiajs/react';\n\ncreateInertiaApp({\n resolve: (name) => {\n const pages = import.meta.glob('./pages/*.tsx', { eager: true });\n return (pages as Record<string, unknown>)[\\`./pages/\\${name}.tsx\\`];\n },\n setup({ el, App, props }) {\n createRoot(el!).render(<App {...props} />);\n },\n});\n`;\n }\n\n if (framework === 'vue') {\n return `import { createApp, h } from 'vue';\nimport { createInertiaApp } from '@inertiajs/vue3';\n\ncreateInertiaApp({\n resolve: (name) => {\n const pages = import.meta.glob('./pages/*.vue', { eager: true });\n return (pages as Record<string, unknown>)[\\`./pages/\\${name}.vue\\`];\n },\n setup({ el, App, props, plugin }) {\n createApp({ render: () => h(App, props) }).use(plugin).mount(el!);\n },\n});\n`;\n }\n\n // svelte\n return `import { mount } from 'svelte';\nimport { createInertiaApp } from '@inertiajs/svelte';\n\ncreateInertiaApp({\n resolve: (name) => {\n const pages = import.meta.glob('./pages/*.svelte', { eager: true });\n return (pages as Record<string, unknown>)[\\`./pages/\\${name}.svelte\\`];\n },\n setup({ el, App, props }) {\n mount(App, { target: el!, props });\n },\n});\n`;\n}\n\nfunction samplePageTemplate(framework: Framework): string {\n if (framework === 'react') {\n return `export type ComponentProps = {\n greeting: string;\n};\n\nexport default function Home({ greeting }: ComponentProps) {\n return (\n <main>\n <h1>{greeting}</h1>\n <p>Edit this page at <code>inertia/pages/Home.tsx</code></p>\n </main>\n );\n}\n`;\n }\n\n if (framework === 'vue') {\n return `<script setup lang=\"ts\">\ndefineProps<{ greeting: string }>();\n</script>\n\n<template>\n <main>\n <h1>{{ greeting }}</h1>\n <p>Edit this page at <code>inertia/pages/Home.vue</code></p>\n </main>\n</template>\n`;\n }\n\n // svelte\n return `<script lang=\"ts\">\n let { greeting } = $props<{ greeting: string }>();\n</script>\n\n<main>\n <h1>{greeting}</h1>\n <p>Edit this page at <code>inertia/pages/Home.svelte</code></p>\n</main>\n`;\n}\n\nconst SAMPLE_CONTROLLER = `import { Controller, Get } from '@nestjs/common';\nimport { Inertia } from '@dudousxd/nestjs-inertia';\n\n@Controller()\nexport class HomeController {\n @Get('/')\n @Inertia('Home')\n index() {\n return { greeting: 'Welcome to NestJS + Inertia.js!' };\n }\n}\n`;\n\n// ---------------------------------------------------------------------------\n// Main entry\n// ---------------------------------------------------------------------------\n\n/**\n * `nestjs-inertia init` — scaffold a full Inertia.js project in `cwd`.\n *\n * Idempotent: each file is only written if it does not already exist.\n * Smart patching: existing files are checked and patched where safe.\n */\nexport async function runInit(opts: RunInitOptions = {}): Promise<void> {\n const cwd = opts.cwd ?? process.cwd();\n\n console.log(`\\n${bold('nestjs-inertia init')}`);\n\n // 1. Detect (or ask for) framework\n let framework = await detectFramework(cwd);\n if (!framework) {\n framework = await promptFramework();\n }\n\n // 2. Detect template engine\n const engine = await detectTemplateEngine(cwd);\n\n const engineLabel = engine === 'html' ? 'plain HTML' : engine;\n const frameworkLabel = framework.charAt(0).toUpperCase() + framework.slice(1);\n console.log(`\\n Detected: ${bold(`${frameworkLabel} + ${engineLabel}`)}`);\n\n // 3. Scaffold files\n const shellFileName =\n engine === 'html' ? 'index.html' : `index.${engine === 'handlebars' ? 'hbs' : engine}`;\n const entryExt = framework === 'react' ? 'tsx' : 'ts';\n const pageExt = framework === 'react' ? 'tsx' : framework === 'vue' ? 'vue' : 'svelte';\n\n logSection('Scaffold files');\n\n await writeIfNotExists(\n join(cwd, 'nestjs-inertia.config.ts'),\n configTemplate(framework),\n 'nestjs-inertia.config.ts',\n );\n\n await writeIfNotExists(join(cwd, 'nestjs-inertia.d.ts'), DTS_TEMPLATE, 'nestjs-inertia.d.ts');\n\n await writeIfNotExists(\n join(cwd, 'inertia', shellFileName),\n htmlShellTemplate(framework, engine),\n `inertia/${shellFileName}`,\n );\n\n await handleViteConfig(cwd, framework);\n\n await writeIfNotExists(\n join(cwd, 'inertia', `app.${entryExt}`),\n entryPointTemplate(framework),\n `inertia/app.${entryExt}`,\n );\n\n await writeIfNotExists(\n join(cwd, 'inertia', 'pages', `Home.${pageExt}`),\n samplePageTemplate(framework),\n `inertia/pages/Home.${pageExt}`,\n );\n\n await writeIfNotExists(\n join(cwd, 'src', 'home.controller.ts'),\n SAMPLE_CONTROLLER,\n 'src/home.controller.ts',\n );\n\n // 4. Patch app.module.ts and main.ts\n logSection('Patch existing files');\n\n const rootView =\n engine === 'html'\n ? 'inertia/index.html'\n : `inertia/index.${engine === 'handlebars' ? 'hbs' : engine}`;\n\n const appModulePath = join(cwd, 'src', 'app.module.ts');\n const appModuleResult = patchAppModule(appModulePath, rootView);\n if (appModuleResult === 'patched') {\n logPatched('src/app.module.ts', 'added InertiaModule.forRoot');\n logPatched('src/app.module.ts', 'added HomeController to controllers');\n } else if (appModuleResult === 'already') {\n console.log(\n ` ${cyan('→')} src/app.module.ts ${dim('(InertiaModule already registered, skipped)')}`,\n );\n } else {\n logWarning('src/app.module.ts not found — add InertiaModule.forRoot() manually');\n }\n\n const mainTsPath = join(cwd, 'src', 'main.ts');\n const mainTsResult = patchMainTs(mainTsPath);\n if (mainTsResult === 'patched') {\n logPatched('src/main.ts', 'added setupInertiaVite after NestFactory.create');\n } else if (mainTsResult === 'already') {\n console.log(` ${cyan('→')} src/main.ts ${dim('(setupInertiaVite already present, skipped)')}`);\n } else {\n logWarning('src/main.ts not found — add setupInertiaVite() manually');\n }\n\n await patchGitignore(join(cwd, '.gitignore'));\n\n // 5. Add build scripts to package.json\n await patchPackageJsonScripts(cwd, {\n 'build:client': 'vite build',\n 'build:ssr': 'VITE_SSR=1 vite build --ssr',\n });\n\n // 6. Install missing deps\n logSection('Install dependencies');\n\n const pkg = await readPackageJson(cwd);\n const installedDeps = allDeps(pkg);\n const pkgManager = await detectPackageManager(cwd);\n\n const commonDeps = ['vite'].filter((d) => !installedDeps.includes(d));\n\n let frameworkDeps: string[] = [];\n let frameworkDevDeps: string[] = [];\n\n if (framework === 'react') {\n const needed = ['@inertiajs/react', 'react', 'react-dom'].filter(\n (d) => !installedDeps.includes(d),\n );\n const neededDev = ['@types/react', '@types/react-dom', '@vitejs/plugin-react'].filter(\n (d) => !installedDeps.includes(d),\n );\n frameworkDeps = needed;\n frameworkDevDeps = neededDev;\n } else if (framework === 'vue') {\n const needed = ['@inertiajs/vue3', 'vue'].filter((d) => !installedDeps.includes(d));\n const neededDev = ['@vitejs/plugin-vue'].filter((d) => !installedDeps.includes(d));\n frameworkDeps = needed;\n frameworkDevDeps = neededDev;\n } else {\n const needed = ['@inertiajs/svelte', 'svelte'].filter((d) => !installedDeps.includes(d));\n const neededDev = ['@sveltejs/vite-plugin-svelte'].filter((d) => !installedDeps.includes(d));\n frameworkDeps = needed;\n frameworkDevDeps = neededDev;\n }\n\n const depsToInstall = [...commonDeps, ...frameworkDeps];\n const devDepsToInstall = frameworkDevDeps;\n\n if (!opts.skipInstall) {\n installDeps(pkgManager, depsToInstall, false);\n installDeps(pkgManager, devDepsToInstall, true);\n }\n\n console.log(`\\n${green('✓')} Setup complete! Run: ${bold('nest start --watch')}\\n`);\n}\n"],"mappings":"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","names":["cac","access","isAbsolute","join","relative","resolve","sep","pathToFileURL","ConfigError","Error","message","options","name","CONFIG_FILE","fileExists","filePath","access","importTs","tsImport","tsxEsm","ConfigError","parentURL","pathToFileURL","href","fileUrl","resolveAbsolute","cwd","p","isAbsolute","resolve","assertInsideCwd","resolvedPath","fieldName","rel","relative","startsWith","sep","applyDefaults","userConfig","outDir","codegen","join","resolvedCwd","app","resolvedEntry","moduleEntry","resolvedTsconfig","tsconfig","pages","glob","propsExport","componentNameStrategy","contracts","debounceMs","scopes","loadConfig","process","configPath","mod","err","cause","modNs","default","readFile","relative","fg","discoverPages","opts","files","fg","glob","cwd","absolute","sort","out","file","rel","relative","name","computeName","componentNameStrategy","source","readFile","propsSource","extractPropsSource","propsExport","push","absolutePath","relativePath","strat","noExt","replace","toLowerCase","exportName","re","RegExp","m","match","start","index","length","i","depth","started","c","slice","mkdir","writeFile","join","emitApi","routes","outDir","mkdir","recursive","content","buildApiFile","writeFile","join","splitName","name","split","toObjectKey","segment","test","JSON","stringify","toCamelCase","s","filter","Boolean","map","word","i","charAt","toLowerCase","slice","toUpperCase","validateNameSegment","seg","fullName","suggested","Error","detectCollisions","tree","key","node","kind","insertIntoTree","segments","leaf","head","rest","length","existing","get","undefined","set","prefixName","branch","children","Map","emitRouterTypeBlock","indent","pad","repeat","lines","objKey","c","method","query","contractSource","body","response","safeMethod","safeUrl","path","push","emitApiObjectBlock","flatName","safePath","fetcherMethod","typeAccess","buildRouterTypeAccess","contracted","r","contract","mkdir","stat","writeFile","join","emitCache","pages","outDir","mkdir","recursive","entries","Promise","all","map","p","s","stat","absolutePath","name","relativePath","mtime","toISOString","cache","writeFile","join","JSON","stringify","mkdir","writeFile","join","emitIndex","outDir","hasContracts","mkdir","recursive","exports","push","content","join","writeFile","mkdir","writeFile","join","emitPages","pages","outDir","mkdir","recursive","body","map","p","propType","propsSource","key","needsQuotes","name","JSON","stringify","join","content","writeFile","test","mkdir","writeFile","join","emitRoutes","routes","outDir","mkdir","recursive","content","buildRoutesFile","writeFile","join","length","buildEmpty","entries","map","r","JSON","stringify","name","path","routeNameUnion","lines","generate","config","routes","pages","discoverPages","glob","cwd","codegen","propsExport","componentNameStrategy","emitPages","outDir","emitCache","hasRoutes","length","hasContracts","some","r","contract","emitRoutes","emitIndex","emitApi","readFile","join","chokidar","dirname","join","resolve","fg","Node","Project","SyntaxKind","discoverContractsFast","opts","cwd","glob","tsconfig","tsconfigPath","resolve","join","project","Project","tsConfigFilePath","skipAddingFilesFromTsConfig","skipLoadingLibFiles","skipFileDependencyResolution","compilerOptions","allowJs","resolveJsonModule","strict","files","fg","absolute","onlyFiles","f","addSourceFileAtPath","routes","sourceFile","getSourceFiles","push","extractFromSourceFile","zodAstToTs","node","Node","isCallExpression","expr","getExpression","isPropertyAccessExpression","methodName","getName","receiver","args","getArguments","lit","isStringLiteral","JSON","stringify","getLiteralValue","isNumericLiteral","toString","getKind","SyntaxKind","TrueKeyword","FalseKeyword","arrArg","isArrayLiteralExpression","members","getElements","map","el","inner","objArg","isObjectLiteralExpression","lines","prop","getProperties","isPropertyAssignment","key","valNode","getInitializer","tsType","isOpt","isOptionalChain","valArg","length","decoratorStringArg","decoratorExpr","undefined","first","parseDefineContractCall","callExpr","callee","calleeName","isIdentifier","getText","optsArg","query","body","response","propName","val","deriveClassSegment","className","noSuffix","replace","Error","charAt","toLowerCase","slice","resolveRouteName","methodName","classAs","methodAs","classPortion","methodPortion","joinPaths","prefix","suffix","startsWith","p","endsWith","s","combined","extractParams","path","matches","matchAll","Array","from","map","m","name","source","findTypeInFile","file","cls","getClass","kind","decl","iface","getInterface","alias","getTypeAlias","typeNode","getTypeNode","text","getText","enumDecl","getEnum","members","getMembers","val","getValue","JSON","stringify","getName","resolveImportedType","sourceFile","project","importDecl","getImportDeclarations","namedImport","getNamedImports","find","n","moduleSpecifier","getModuleSpecifierValue","dir","dirname","getFilePath","candidates","resolve","candidate","importedFile","getSourceFile","addSourceFileAtPath","result","findType","local","resolveTypeNodeToString","depth","Node","isArrayTypeNode","elementType","getElementTypeNode","isTypeReference","typeName","getTypeName","isIdentifier","typeArgs","getTypeArguments","firstTypeArg","length","undefined","resolved","expandTypeDecl","getKind","SyntaxKind","StringKeyword","NumberKeyword","BooleanKeyword","UnknownKeyword","AnyKeyword","resolvePropertied","join","lines","prop","getProperties","propName","isOptional","hasQuestionToken","propTypeNode","propType","push","extractBodyType","method","param","getParameters","bodyDecorator","getDecorators","d","bodyArgs","getArguments","extractQueryType","queryDecorator","queryArgs","extractParamsType","entries","paramDecorator","paramArgs","nameArg","isStringLiteral","paramName","getLiteralValue","paramType","extractResponseType","apiResponseDecorator","getDecorator","args","optsArg","isObjectLiteralExpression","isPropertyAssignment","getInitializer","isArrayLiteralExpression","elements","getElements","firstEl","innerType","resolveIdentifierToClassType","returnTypeNode","getReturnTypeNode","node","extractDtoContract","body","query","paramsType","response","params","HTTP_METHOD_DECORATORS","Get","Post","Put","Patch","Delete","Options","Head","All","extractFromSourceFile","routes","seenNames","Map","classes","getClasses","controllerDecorator","controllerArgs","firstArg","decoratorStringArg","getMethods","httpMethod","handlerPath","decoratorName","verb","Object","httpDecorator","httpArgs","pathArg","applyContractDecorator","decoratorArgs","firstDecoratorArg","contractDef","isCallExpression","parseDefineContractCall","identName","varDecl","getVariableDeclaration","console","warn","initializer","resolvedMethod","resolvedPath","classAsDecorator","classAsArgs","classAsName","methodAsDecorator","methodAsArgs","methodAsName","routeName","qualifiedRef","existing","get","set","contract","contractSource","dtoContract","mkdir","readFile","unlink","writeFile","join","LOCK_FILE","isProcessAlive","pid","process","kill","acquireLock","outDir","mkdir","recursive","lockPath","join","raw","readFile","existing","JSON","parse","lockData","startedAt","Date","toISOString","writeFile","stringify","release","unlink","PAGES_DEBOUNCE_MS","NO_OP_WATCHER","close","watch","config","onChange","lock","acquireLock","codegen","outDir","holderPid","raw","readFile","join","data","JSON","parse","pid","undefined","String","console","warn","initialRoutes","discoverContractsFast","cwd","glob","contracts","app","tsconfig","generate","err","Error","message","pagesDebounceTimer","pagesWatcher","chokidar","pages","ignoreInitial","persistent","awaitWriteFinish","stabilityThreshold","pollInterval","schedulePagesRegenerate","clearTimeout","setTimeout","on","contractsDebounceTimer","contractsWatcher","scheduleContractsRegenerate","routes","emitRoutes","hasContracts","some","r","contract","emitIndex","emitApi","debounceMs","release","VERSION","runCodegen","opts","cwd","process","config","loadConfig","watch","watcher","Promise","resolve","onSignal","close","then","catch","once","routes","discoverContractsFast","codegen","glob","contracts","app","tsconfig","generate","console","log","outDir","execSync","readFileSync","writeFileSync","access","mkdir","readFile","writeFile","join","createInterface","GITIGNORE_ENTRY","green","s","yellow","cyan","dim","bold","logCreated","path","console","log","logPatched","detail","logSkipped","logWarning","msg","logSection","title","readPackageJson","cwd","raw","readFile","join","JSON","parse","allDeps","pkg","deps","dependencies","devDeps","devDependencies","Object","keys","detectFramework","includes","detectTemplateEngine","detectPackageManager","exists","file","access","promptFramework","process","stdin","isTTY","Promise","resolve","rl","createInterface","input","output","stdout","question","answer","close","trimmed","trim","toLowerCase","fileExists","filePath","writeIfNotExists","content","label","dir","substring","lastIndexOf","mkdir","recursive","writeFile","handleViteConfig","framework","existing","hasPlugin","viteConfigTemplate","patchGitignore","gitignorePath","split","some","line","newContent","endsWith","installDeps","pkgManager","dev","length","flag","cmd","execSync","stdio","patchPackageJsonScripts","scripts","pkgPath","changed","key","value","entries","stringify","findAfterLastImport","lastImportIndex","endOfLine","indexOf","startsWith","patchAppModule","rootView","readFileSync","insertAt","slice","importsMatch","match","index","undefined","bracketPos","indent","controllersMatch","writeFileSync","patchMainTs","createMatch","appVarName","insertAfterPos","viteSetup","configTemplate","glob","DTS_TEMPLATE","htmlShellTemplate","_engine","ext","pluginOption","entryPointTemplate","samplePageTemplate","SAMPLE_CONTROLLER","runInit","opts","engine","engineLabel","frameworkLabel","charAt","toUpperCase","shellFileName","entryExt","pageExt","appModulePath","appModuleResult","mainTsPath","mainTsResult","installedDeps","commonDeps","filter","d","frameworkDeps","frameworkDevDeps","needed","neededDev","depsToInstall","devDepsToInstall","skipInstall","run","argv","cli","cac","command","option","action","opts","runCodegen","watch","Boolean","cwd","process","runInit","help","version","VERSION","parse","runMatchedCommand","err","message","Error","String","console","error"]}