@dudousxd/nestjs-codegen 0.3.0 → 0.4.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/adapters/registry.ts","../../src/generate.ts","../../src/discovery/pages.ts","../../src/discovery/shared-props.ts","../../src/emit/emit-api.ts","../../src/extension/registry.ts","../../src/extension/types.ts","../../src/emit/emit-cache.ts","../../src/emit/emit-forms.ts","../../src/emit/emit-index.ts","../../src/emit/emit-pages.ts","../../src/emit/emit-routes.ts","../../src/watch/watcher.ts","../../src/discovery/contracts-fast.ts","../../src/discovery/dto-type-resolver.ts","../../src/discovery/dto-to-ir.ts","../../src/discovery/type-ref-resolution.ts","../../src/discovery/filter-for.ts","../../src/discovery/filter-field-types.ts","../../src/discovery/enum-resolution.ts","../../src/discovery/zod-ast-to-ts.ts","../../src/watch/lock-file.ts","../../src/index.ts","../../src/cli/codegen.ts","../../src/cli/doctor.ts","../../src/cli/init.ts","../../src/cli/patch-utils.ts"],"sourcesContent":["import { cac } from 'cac';\nimport { VERSION } from '../index.js';\nimport { runCodegen } from './codegen.js';\nimport { runDoctor } from './doctor.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-codegen');\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.command('init', 'Initialise nestjs-codegen in the current project').action(async () => {\n await runInit({ cwd: process.cwd() });\n });\n\n cli\n .command('doctor', 'Diagnose your nestjs-inertia setup')\n .option('--fix', 'Auto-fix issues where possible')\n .action(async (opts: { fix?: boolean }) => {\n const code = await runDoctor({ cwd: process.cwd(), fix: Boolean(opts.fix) });\n process.exitCode = code;\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-codegen] 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 { resolveAdapter } from '../adapters/registry.js';\nimport { ConfigError } from '../exceptions.js';\nimport type { ResolvedConfig, UserConfig } from './types.js';\n\n/** Config file names, in lookup order. The legacy `nestjs-inertia.config.ts` is\n * still accepted for back-compat with projects migrating from nestjs-inertia. */\nconst CONFIG_FILES = ['nestjs-codegen.config.ts', 'nestjs-inertia.config.ts'] as const;\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\n/**\n * Resolve a {@link UserConfig} (e.g. `NestjsCodegenModule.forRoot()` options) into a\n * fully-defaulted {@link ResolvedConfig} — without reading a config file. Used by the\n * Nest module and any programmatic caller that already holds the config in memory.\n *\n * @param userConfig the raw user config (forRoot options minus module-only fields)\n * @param cwd project root used to resolve globs / outDir. Defaults to `process.cwd()`.\n */\nexport function resolveConfig(userConfig: UserConfigInput, cwd?: string): ResolvedConfig {\n return applyDefaults(userConfig, cwd ?? process.cwd());\n}\n\n/**\n * Loosened {@link UserConfig} where `validation` may be absent. Both config entry\n * points accept this shape and enforce `validation` at runtime (it throws a clear\n * {@link ConfigError} when missing) — letting callers like the Nest module pass\n * partial options without a compile-time `validation` requirement.\n */\ntype UserConfigInput = Omit<UserConfig, 'validation'> & {\n validation?: UserConfig['validation'];\n};\n\n/**\n * Input validation shared by both config entry points ({@link loadConfig} and\n * {@link resolveConfig}). Guards user-provided fields before defaults are applied so\n * the file path and the programmatic `forRoot()` path reject the same bad input.\n */\nfunction validateUserConfig(userConfig: UserConfigInput): void {\n // `validation` is required — no adapter is bundled in core.\n if (userConfig.validation == null) {\n throw new ConfigError(\n 'validation adapter is required — install @dudousxd/nestjs-codegen-zod and pass zodAdapter, or use @dudousxd/nestjs-codegen-valibot / -arktype',\n );\n }\n // `pages` is Inertia-only and optional — but if present, `glob` must be a string.\n if (userConfig.pages && typeof userConfig.pages.glob !== 'string') {\n throw new ConfigError(\n 'Config validation failed: `pages.glob` must be a string when `pages` is set',\n );\n }\n}\n\nfunction applyDefaults(userConfig: UserConfigInput, cwd: string): ResolvedConfig {\n validateUserConfig(userConfig);\n\n const outDir = userConfig.codegen?.outDir\n ? resolveAbsolute(cwd, userConfig.codegen.outDir)\n : join(cwd, '.nestjs-codegen');\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 extensions: userConfig.extensions ?? [],\n // Non-null: validateUserConfig() above throws when `validation` is absent.\n validation: resolveAdapter(userConfig.validation as NonNullable<typeof userConfig.validation>),\n pages: userConfig.pages\n ? {\n glob: userConfig.pages.glob,\n propsExport: userConfig.pages.propsExport ?? 'ComponentProps',\n componentNameStrategy: userConfig.pages.componentNameStrategy ?? 'relative-no-ext',\n }\n : null,\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 fetcher: userConfig.fetcher ?? null,\n forms: {\n enabled: userConfig.forms?.enabled ?? true,\n watch: userConfig.forms?.watch ?? 'src/**/*.dto.ts',\n zodImport: userConfig.forms?.zodImport ?? 'zod',\n },\n };\n}\n\nexport async function loadConfig(cwd?: string): Promise<ResolvedConfig> {\n const resolvedCwd = cwd ?? process.cwd();\n\n let configPath: string | undefined;\n for (const name of CONFIG_FILES) {\n const candidate = join(resolvedCwd, name);\n if (await fileExists(candidate)) {\n configPath = candidate;\n break;\n }\n }\n\n if (!configPath) {\n throw new ConfigError(\n `Config file not found in ${resolvedCwd} (looked for ${CONFIG_FILES.join(', ')})\\nRun \\`nestjs-codegen 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 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 { ConfigError } from '../exceptions.js';\nimport type { ValidationAdapter } from './types.js';\n\n/** A built-in adapter name or a custom adapter instance. */\nexport type ValidationOption = 'zod' | 'valibot' | 'arktype' | ValidationAdapter;\n\n/**\n * Resolve a `validation` config value to a {@link ValidationAdapter}. No adapter is\n * bundled in core — the zod/valibot/arktype adapters ship as their own packages.\n * Import the adapter instance and pass it directly (it passes through here). A\n * custom adapter object also passes through.\n *\n * @example\n * import { zodAdapter } from '@dudousxd/nestjs-codegen-zod';\n * defineConfig({ validation: zodAdapter });\n */\nexport function resolveAdapter(option: ValidationOption): ValidationAdapter {\n if (typeof option !== 'string') return option;\n const pkg = `@dudousxd/nestjs-codegen-${option}`;\n const named = `${option}Adapter`;\n throw new ConfigError(\n `Validation adapter \"${option}\" is not bundled in core. Install ${pkg} and pass the adapter instance instead of the string:\\n\\n import { ${named} } from '${pkg}';\\n defineConfig({ validation: ${named} });`,\n );\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport type { ResolvedConfig } from './config/types.js';\nimport { discoverPages } from './discovery/pages.js';\nimport { discoverSharedPropsFromConfig } from './discovery/shared-props.js';\nimport type { RouteDescriptor } from './discovery/types.js';\nimport { emitApi } from './emit/emit-api.js';\nimport { emitCache } from './emit/emit-cache.js';\nimport { emitForms } from './emit/emit-forms.js';\nimport { emitIndex } from './emit/emit-index.js';\nimport { emitPages } from './emit/emit-pages.js';\nimport { emitRoutes } from './emit/emit-routes.js';\nimport {\n applyTransformRoutes,\n collectEmittedFiles,\n createExtensionContext,\n} from './extension/registry.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 inputRoutes: RouteDescriptor[] = [],\n): Promise<void> {\n // Extensions: run transformRoutes (chained) before any emit so routes.ts/api.ts/\n // forms.ts all see the augmented IR. ctx.routes is a live getter over the active set.\n const extensions = config.extensions ?? [];\n let routes = inputRoutes;\n const ctx = createExtensionContext(config, () => routes);\n if (extensions.length > 0) {\n routes = await applyTransformRoutes(routes, extensions, ctx);\n }\n\n // Inertia page discovery is opt-in — skip entirely when `pages` isn't configured.\n if (config.pages) {\n const pagesConfig = config.pages;\n const pages = await discoverPages({\n glob: pagesConfig.glob,\n cwd: config.codegen.cwd,\n propsExport: pagesConfig.propsExport,\n componentNameStrategy: pagesConfig.componentNameStrategy,\n });\n\n const sharedProps = discoverSharedPropsFromConfig(config);\n\n await emitPages(pages, config.codegen.outDir, {\n propsExport: pagesConfig.propsExport,\n sharedProps,\n });\n await emitCache(pages, config.codegen.outDir);\n }\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 if (hasContracts) {\n await emitApi(routes, config.codegen.outDir, {\n ...(config.fetcher?.importPath ? { fetcherImportPath: config.fetcher.importPath } : {}),\n extensions,\n ctx,\n });\n }\n\n const hasForms = await emitForms(routes, config.codegen.outDir, config.forms, config.validation);\n\n await emitIndex(config.codegen.outDir, hasContracts, hasForms);\n\n // Extensions: write any extra files (collision-checked against each other + core files).\n if (extensions.length > 0) {\n const extraFiles = await collectEmittedFiles(extensions, ctx);\n for (const file of extraFiles) {\n const dest = join(config.codegen.outDir, file.path);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, file.contents, 'utf8');\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { join, 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\n// Files matching these patterns are never treated as Inertia pages even if\n// they sit inside the pages directory and would match the user's glob.\n// Without this filter, vitest test files (`*.test.tsx`) get registered as\n// pages, their imports get pulled into the typecheck graph, and any\n// transitive matcher errors leak into the user's project.\nconst NON_PAGE_FILE_RE = /\\.(?:test|spec|stories|story)\\.(?:tsx?|jsx?|vue|svelte)$/i;\n\nexport async function discoverPages(opts: DiscoverPagesOptions): Promise<DiscoveredPage[]> {\n const allFiles = await fg(opts.glob, { cwd: opts.cwd, absolute: true });\n const files = allFiles.filter((f) => !NON_PAGE_FILE_RE.test(f));\n files.sort();\n // Extract the static prefix from the glob to make page names relative to the pages directory\n // e.g. glob 'inertia/pages/**/*.tsx' → pagesBase 'inertia/pages'\n const globStatic = opts.glob.split('*')[0]?.replace(/\\/$/, '') ?? '';\n const pagesBase = join(opts.cwd, globStatic);\n const out: DiscoveredPage[] = [];\n for (const file of files) {\n const rel = relative(opts.cwd, file);\n const nameRel = relative(pagesBase, file);\n const name = computeName(nameRel, 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","/**\n * Static AST-based discovery of shared props from `InertiaModule.forRoot({ share: ... })`.\n *\n * Analyzes the `share` property in the forRoot call to infer the return type\n * of the share function and generate typed shared props.\n *\n * Gracefully returns null when the share function cannot be analyzed\n * (complex logic, service calls, external references, etc.).\n */\nimport { join } from 'node:path';\nimport { Node, Project, type SourceFile, SyntaxKind } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\n\nexport interface SharedPropsResult {\n /** The TS type string — either `Awaited<ReturnType<typeof import('...').fn>>` or an inline object type */\n typeString: string;\n /** Individual property entries for emitting into an interface body (null when using ReturnType) */\n properties: Array<{ name: string; type: string }> | null;\n /** When true, typeString is a ReturnType<import(...)> expression (not inline) */\n isImportRef: boolean;\n}\n\n/**\n * Discover shared props by analyzing `InertiaModule.forRoot({ share: ... })` in the given module entry file.\n *\n * @param project - ts-morph Project (caller creates it)\n * @param moduleEntry - Absolute path to the NestJS module entry file (e.g. `src/app.module.ts`)\n * @returns SharedPropsResult or null if no share function found or it can't be inferred\n */\nexport function discoverSharedProps(\n project: Project,\n moduleEntry: string,\n): SharedPropsResult | null {\n try {\n let sourceFile = project.getSourceFile(moduleEntry);\n if (!sourceFile) {\n try {\n sourceFile = project.addSourceFileAtPath(moduleEntry);\n } catch {\n return null;\n }\n }\n\n const forRootCall = findForRootCall(sourceFile);\n if (!forRootCall) return null;\n\n const initializer = findShareInitializer(forRootCall);\n if (!initializer) return null;\n\n return extractShareType(initializer, sourceFile, project);\n } catch {\n // Graceful fallback — any unexpected error means we skip shared props typing\n return null;\n }\n}\n\n/**\n * Resolve shared props from a fully-resolved config: builds the ts-morph Project,\n * resolves the tsconfig path, and analyzes the module entry's `forRoot({ share })`.\n *\n * Returns null (swallowing any error) when `app.moduleEntry` isn't configured or\n * anything goes wrong while constructing the project / discovering props — preserving\n * the previous graceful-fallback behavior of the generate orchestrator.\n */\nexport function discoverSharedPropsFromConfig(config: ResolvedConfig): SharedPropsResult | null {\n if (!config.app?.moduleEntry) return null;\n\n try {\n const tsconfigPath = config.app.tsconfig ?? join(config.codegen.cwd, 'tsconfig.json');\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 project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: { allowJs: true, strict: false },\n });\n }\n return discoverSharedProps(project, config.app.moduleEntry);\n } catch {\n // Graceful fallback — skip shared props if anything goes wrong\n return null;\n }\n}\n\n/**\n * Find `InertiaModule.forRoot(...)` call expression in a source file.\n * Searches all call expressions in the file.\n */\nfunction findForRootCall(sourceFile: SourceFile): Node | null {\n const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);\n\n for (const call of callExpressions) {\n const expr = call.getExpression();\n if (!Node.isPropertyAccessExpression(expr)) continue;\n\n const methodName = expr.getName();\n const objectExpr = expr.getExpression();\n\n if (methodName === 'forRoot' && Node.isIdentifier(objectExpr)) {\n const name = objectExpr.getText();\n if (name === 'InertiaModule') {\n return call;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Extract the initializer of the `share` property from the first argument of `forRoot(...)`.\n * Returns the initializer node (the value assigned to `share`), or null if not found.\n */\nfunction findShareInitializer(forRootCall: Node): Node | null {\n if (!Node.isCallExpression(forRootCall)) return null;\n\n const args = forRootCall.getArguments();\n const firstArg = args[0];\n if (!firstArg || !Node.isObjectLiteralExpression(firstArg)) return null;\n\n for (const prop of firstArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'share') {\n return prop.getInitializer() ?? null;\n }\n }\n\n return null;\n}\n\n/**\n * Extract the return type of the share value.\n * Handles:\n * - Arrow functions: `(req) => ({ ... })`\n * - Arrow functions with block body: `(req) => { return { ... }; }`\n * - Function expressions: `function(req) { return { ... }; }`\n * - Async variants of the above\n * - Object literals (plain `share: { ... }`)\n * - Functions with explicit return type annotations\n */\nfunction extractShareType(\n node: Node,\n sourceFile: SourceFile,\n project: Project,\n): SharedPropsResult | null {\n // Priority 1: Reference to a named function → use ReturnType<typeof import(...)>\n if (Node.isIdentifier(node)) {\n const ref = resolveIdentifierToImportRef(node, sourceFile, project);\n if (ref) {\n return {\n typeString: `Awaited<ReturnType<typeof import('${ref.importPath}').${ref.exportName}>>`,\n properties: null,\n isImportRef: true,\n };\n }\n }\n\n // Priority 2: Arrow function → try inline extraction\n if (Node.isArrowFunction(node)) {\n const result = extractFromFunctionLike(node, sourceFile);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n // Priority 3: Function expression → try inline extraction\n if (Node.isFunctionExpression(node)) {\n const result = extractFromFunctionLike(node, sourceFile);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n // Priority 4: Object literal (share: { key: value })\n if (Node.isObjectLiteralExpression(node)) {\n const result = extractFromObjectLiteral(node);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n return null;\n}\n\nfunction resolveIdentifierToImportRef(\n id: Node,\n sourceFile: SourceFile,\n project: Project,\n): { importPath: string; exportName: string } | null {\n if (!Node.isIdentifier(id)) return null;\n const name = id.getText();\n\n const localFunc = sourceFile.getFunction(name);\n if (localFunc?.isExported()) {\n const filePath = sourceFile.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: name };\n }\n\n const localVar = sourceFile.getVariableDeclaration(name);\n if (localVar?.isExported()) {\n const filePath = sourceFile.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: name };\n }\n\n for (const imp of sourceFile.getImportDeclarations()) {\n for (const named of imp.getNamedImports()) {\n const importedName = named.getAliasNode()?.getText() ?? named.getName();\n if (importedName !== name) continue;\n const resolvedSource = imp.getModuleSpecifierSourceFile();\n if (!resolvedSource) continue;\n const originalName = named.getName();\n const fn = resolvedSource.getFunction(originalName);\n if (fn?.isExported()) {\n const filePath = resolvedSource.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: originalName };\n }\n const v = resolvedSource.getVariableDeclaration(originalName);\n if (v?.isExported()) {\n const filePath = resolvedSource.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: originalName };\n }\n }\n }\n\n return null;\n}\n\n/**\n * Extract shared props type from an arrow function or function expression.\n * First tries the return type annotation; falls back to inferring from the return value.\n */\nfunction extractFromFunctionLike(node: Node, _sourceFile: SourceFile): SharedPropsResult | null {\n // Check for explicit return type annotation\n const returnTypeNode =\n Node.isArrowFunction(node) || Node.isFunctionExpression(node) ? node.getReturnTypeNode() : null;\n\n if (returnTypeNode) {\n return extractFromReturnTypeAnnotation(returnTypeNode);\n }\n\n // Infer from body\n if (Node.isArrowFunction(node)) {\n const body = node.getBody();\n\n // Concise body: (req) => ({ auth: ..., flash: ... })\n if (Node.isParenthesizedExpression(body)) {\n const inner = body.getExpression();\n if (Node.isObjectLiteralExpression(inner)) {\n return extractFromObjectLiteral(inner);\n }\n }\n\n // Direct object literal (less common but possible with as const)\n if (Node.isObjectLiteralExpression(body)) {\n return extractFromObjectLiteral(body);\n }\n\n // Block body: (req) => { return { ... }; }\n if (Node.isBlock(body)) {\n return extractFromBlockReturn(body);\n }\n }\n\n if (Node.isFunctionExpression(node)) {\n const body = node.getBody();\n if (Node.isBlock(body)) {\n return extractFromBlockReturn(body);\n }\n }\n\n return null;\n}\n\n/**\n * Extract type from a return type annotation on the share function.\n * e.g. `(req): { auth: User | null; flash: {} } => ...`\n */\nfunction extractFromReturnTypeAnnotation(typeNode: Node): SharedPropsResult | null {\n // Unwrap Promise<T> if async\n if (Node.isTypeReference(typeNode)) {\n const typeName = typeNode.getTypeName();\n if (Node.isIdentifier(typeName) && typeName.getText() === 'Promise') {\n const typeArgs = typeNode.getTypeArguments();\n const firstArg = typeArgs[0];\n if (firstArg) {\n return extractFromReturnTypeAnnotation(firstArg);\n }\n return null;\n }\n }\n\n // TypeLiteral: { auth: ...; flash: ... }\n if (Node.isTypeLiteral(typeNode)) {\n const properties: Array<{ name: string; type: string }> = [];\n for (const member of typeNode.getMembers()) {\n if (Node.isPropertySignature(member)) {\n const name = member.getName();\n const memberTypeNode = member.getTypeNode();\n const type = memberTypeNode ? memberTypeNode.getText() : 'unknown';\n properties.push({ name, type });\n }\n }\n if (properties.length === 0) return null;\n const typeString = `{ ${properties.map((p) => `${p.name}: ${p.type}`).join('; ')} }`;\n return { typeString, properties, isImportRef: false };\n }\n\n return null;\n}\n\n/**\n * Extract shared props from a block body's return statement.\n * Only handles the simple case: a single return statement with an object literal.\n */\nfunction extractFromBlockReturn(block: Node): SharedPropsResult | null {\n if (!Node.isBlock(block)) return null;\n\n const statements = block.getStatements();\n // Find the last return statement\n for (let i = statements.length - 1; i >= 0; i--) {\n const stmt = statements[i];\n if (!Node.isReturnStatement(stmt)) continue;\n\n const expr = stmt.getExpression();\n if (!expr) continue;\n\n if (Node.isObjectLiteralExpression(expr)) {\n return extractFromObjectLiteral(expr);\n }\n\n // Parenthesized: return ({ ... })\n if (Node.isParenthesizedExpression(expr)) {\n const inner = expr.getExpression();\n if (Node.isObjectLiteralExpression(inner)) {\n return extractFromObjectLiteral(inner);\n }\n }\n\n break;\n }\n\n return null;\n}\n\n/**\n * Infer shared props type from an object literal expression.\n * Each property key becomes a shared prop; the value type is inferred from the value expression.\n */\nfunction extractFromObjectLiteral(objLiteral: Node): SharedPropsResult | null {\n if (!Node.isObjectLiteralExpression(objLiteral)) return null;\n\n const properties: Array<{ name: string; type: string }> = [];\n\n for (const prop of objLiteral.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n\n const name = prop.getName();\n const initializer = prop.getInitializer();\n if (!initializer) continue;\n\n const type = inferExpressionType(initializer);\n properties.push({ name, type });\n }\n\n if (properties.length === 0) return null;\n\n const typeString = `{ ${properties.map((p) => `${p.name}: ${p.type}`).join('; ')} }`;\n return { typeString, properties, isImportRef: false };\n}\n\n/**\n * Infer the TypeScript type of an expression.\n * Handles common patterns found in share functions:\n * - Object literals → `{ key: type; ... }`\n * - String literals → `string`\n * - Number literals → `number`\n * - Boolean literals → `boolean`\n * - Null → `null`\n * - Array literals → `Array<type>`\n * - Ternary expressions → `trueType | falseType`\n * - Property accesses and complex expressions → `unknown`\n * - Empty object literal → `Record<string, unknown>`\n */\nfunction inferExpressionType(node: Node): string {\n // String literal\n if (Node.isStringLiteral(node)) return 'string';\n\n // Template literal (backtick)\n if (Node.isTemplateExpression(node) || Node.isNoSubstitutionTemplateLiteral(node))\n return 'string';\n\n // Number literal\n if (Node.isNumericLiteral(node)) return 'number';\n\n // Boolean literal\n if (node.getKind() === SyntaxKind.TrueKeyword || node.getKind() === SyntaxKind.FalseKeyword) {\n return 'boolean';\n }\n\n // Null literal\n if (node.getKind() === SyntaxKind.NullKeyword) return 'null';\n\n // Undefined\n if (Node.isIdentifier(node) && node.getText() === 'undefined') return 'undefined';\n\n // Object literal\n if (Node.isObjectLiteralExpression(node)) {\n const props = node.getProperties();\n if (props.length === 0) return 'Record<string, unknown>';\n\n const entries: string[] = [];\n for (const prop of props) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const key = prop.getName();\n const init = prop.getInitializer();\n if (!init) continue;\n entries.push(`${key}: ${inferExpressionType(init)}`);\n }\n if (entries.length === 0) return 'Record<string, unknown>';\n return `{ ${entries.join('; ')} }`;\n }\n\n // Array literal\n if (Node.isArrayLiteralExpression(node)) {\n const elements = node.getElements();\n if (elements.length === 0) return 'Array<unknown>';\n // Infer from first element\n const first = elements[0];\n if (first) return `Array<${inferExpressionType(first)}>`;\n return 'Array<unknown>';\n }\n\n // Ternary (conditional) expression: x ? A : B → A | B\n if (Node.isConditionalExpression(node)) {\n const whenTrue = inferExpressionType(node.getWhenTrue());\n const whenFalse = inferExpressionType(node.getWhenFalse());\n if (whenTrue === whenFalse) return whenTrue;\n return `${whenTrue} | ${whenFalse}`;\n }\n\n // Parenthesized expression — unwrap\n if (Node.isParenthesizedExpression(node)) {\n return inferExpressionType(node.getExpression());\n }\n\n // As expression (type assertion): expr as Type → use the asserted type\n if (Node.isAsExpression(node)) {\n const typeNode = node.getTypeNode();\n if (typeNode) return typeNode.getText();\n }\n\n // For any other expression (property access, function calls, etc.), fall back to unknown\n return 'unknown';\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative } from 'node:path';\nimport type {\n ContractSource,\n ControllerRef,\n FieldTypeKind,\n FilterFieldType,\n RouteDescriptor,\n} from '../discovery/types.js';\nimport { mergeExclusive, resolveApiSlots } from '../extension/registry.js';\nimport { requestShape } from '../extension/types.js';\nimport type {\n ApiClientLayer,\n CodegenExtension,\n ExtensionContext,\n LeafModel,\n RequestModel,\n} from '../extension/types.js';\n\n/**\n * Emits `api.ts` into `outDir` for all routes that carry a `.contract`.\n *\n * By default each leaf is a bare typed-fetch callable. Registered extensions shape the\n * output: an `apiClientLayer` (e.g. `@dudousxd/nestjs-codegen-tanstack`) turns leaves into\n * handles wrapping the neutral fetcher request; `apiMembers` add handle members; `apiHeader`\n * contributes top-level imports/statements.\n */\nexport interface ApiEmitOptions {\n fetcherImportPath?: string;\n /** Registered extensions. Their api.ts hooks (transport/layer/members/header) are applied. */\n extensions?: CodegenExtension[];\n /** Shared extension context (from `generate()`). When omitted, a minimal one is built from routes. */\n ctx?: ExtensionContext;\n}\n\nexport async function emitApi(\n routes: RouteDescriptor[],\n outDir: string,\n opts: ApiEmitOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const content = buildApiFile(routes, outDir, opts);\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 params: Array<{ name: string; source: string }>;\n controllerRef?: ControllerRef | undefined;\n // Reference the canonical discovery type directly rather than re-declaring a\n // parallel hand-maintained shape. The leaf is always built from a real\n // `ContractSource` (`contractSource: r.contract.contractSource`), so the extra\n // form/zod fields it carries are simply unused here.\n contractSource: ContractSource;\n // The real, un-narrowed `RouteDescriptor` this leaf was built from. Stored so\n // extension hooks receive the canonical route with no reconstruction/force-cast.\n route: RouteDescriptor;\n};\n\ntype BranchEntry = {\n kind: 'branch';\n children: Map<string, TreeNode>;\n};\n\ntype TreeNode = LeafEntry | BranchEntry;\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// Params helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build a TypeScript type literal for path params.\n * Returns 'never' when the route has no path params.\n */\nfunction buildParamsType(params: Array<{ name: string; source: string }>): string {\n const pathParams = params.filter((p) => p.source === 'path');\n if (pathParams.length === 0) return 'never';\n return `{ ${pathParams.map((p) => `${p.name}: string`).join('; ')} }`;\n}\n\n/**\n * Check whether a route has any path params.\n */\nfunction hasPathParams(params: Array<{ name: string; source: string }>): boolean {\n return params.some((p) => p.source === 'path');\n}\n\n// ---------------------------------------------------------------------------\n// Code generation helpers\n// ---------------------------------------------------------------------------\n\n/** Map a classified field kind (+ enum members) to a TS type literal. */\nfunction kindToTs(kind: FieldTypeKind, enumValues?: string[], numericEnum?: boolean): string {\n if (enumValues && enumValues.length > 0) {\n return enumValues.map((v) => (numericEnum ? v : JSON.stringify(v))).join(' | ');\n }\n switch (kind) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'date':\n return 'Date';\n case 'json':\n return 'Record<string, unknown>';\n default:\n return 'unknown';\n }\n}\n\n/**\n * Emit the per-field type map literal: `{ \"age\": number; \"status\": \"A\" | \"B\" }`.\n * This is the SOLE emit-side reader of `FilterFieldType` — it owns the `typeRef`\n * precedence invariant (a named ref wins over `kind`/`enumValues`; see the\n * `FilterFieldType` doc). No other emit code branches on `typeRef` vs `kind`.\n */\nfunction emitFieldTypesLiteral(fts: FilterFieldType[]): string {\n const entries = fts.map((f) => {\n // A named typeRef (enum / type alias / interface inferred from a @FilterFor\n // method parameter) wins — reference it by name; the import is emitted at\n // the top of the file by buildApiFile.\n let t = f.typeRef ? f.typeRef.name : kindToTs(f.kind, f.enumValues, f.numericEnum);\n if (f.nullable) t = `${t} | null`;\n return `${JSON.stringify(f.name)}: ${t}`;\n });\n return `{ ${entries.join('; ')} }`;\n}\n\n/** Build the type args for `_filterQueryTyped` — single union, or union + field-type map. */\nfunction emitFilterQueryTypeArgs(c: LeafEntry): string {\n const fieldsUnion = (c.contractSource.filterFields ?? [])\n .map((f) => JSON.stringify(f))\n .join(' | ');\n const fts = c.contractSource.filterFieldTypes;\n return fts?.length ? `${fieldsUnion}, ${emitFieldTypesLiteral(fts)}` : fieldsUnion;\n}\n\n/**\n * Build the `TypedFilterQuery<...>` TYPE for a query-source `@ApplyFilter` route's\n * `query` position. Built from the SAME `emitFilterQueryTypeArgs` used by the\n * `_filterQueryTyped<...>` factory so the two are byte-identical.\n */\nfunction emitFilterQueryType(c: LeafEntry): string {\n return `import('@dudousxd/nestjs-filter-client').TypedFilterQuery<${emitFilterQueryTypeArgs(c)}>`;\n}\n\n/**\n * Emit the nested ApiRouter type block.\n */\nfunction buildResponseType(c: LeafEntry, outDir: string): string {\n if (c.controllerRef) {\n let relPath = relative(outDir, c.controllerRef.filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n return `Awaited<ReturnType<import('${relPath}').${c.controllerRef.className}['${c.controllerRef.methodName}']>>`;\n }\n const respRef = c.contractSource.responseRef;\n if (respRef) {\n return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;\n }\n return c.contractSource.response;\n}\n\nfunction emitRouterTypeBlock(\n tree: Map<string, TreeNode>,\n indent: number,\n outDir: string,\n): 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 queryRef = c.contractSource.queryRef;\n // A query-source `@ApplyFilter` route renders its `TypedFilterQuery<...>`\n // type here — from the same `filterFields`/`filterFieldTypes` data the\n // `_filterQueryTyped<...>` factory uses — so both are byte-identical.\n const isFilterQuery =\n c.contractSource.filterSource === 'query' && !!c.contractSource.filterFields?.length;\n const query = queryRef\n ? queryRef.isArray\n ? `Array<${queryRef.name}>`\n : queryRef.name\n : isFilterQuery\n ? emitFilterQueryType(c)\n : (c.contractSource.query ?? 'never');\n const bodyRef = c.contractSource.bodyRef;\n const body =\n method === 'GET'\n ? 'never'\n : bodyRef\n ? bodyRef.isArray\n ? `Array<${bodyRef.name}>`\n : bodyRef.name\n : (c.contractSource.body ?? 'never');\n const response = buildResponseType(c, outDir);\n const params = buildParamsType(c.params);\n const safeMethod = JSON.stringify(method);\n const safeUrl = JSON.stringify(c.path);\n // Filterable fields (from @dudousxd/nestjs-filter) as a string-literal\n // union, or `never` for routes without a filter. Purely type-level — no\n // runtime dependency on nestjs-filter is introduced by this member.\n const filterFields = c.contractSource.filterFields?.length\n ? c.contractSource.filterFields.map((f) => JSON.stringify(f)).join(' | ')\n : 'never';\n lines.push(\n `${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; params: ${params}; query: ${query}; body: ${body}; response: ${response}; filterFields: ${filterFields} };`,\n );\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));\n lines.push(`${pad}};`);\n }\n }\n\n return lines;\n}\n\n/**\n * Build the neutral per-leaf {@link RequestModel} from a discovered leaf. This is the\n * input every transport/layer/member-contributor reads — the seam the extension system\n * plugs into. Pure string-building; no I/O.\n */\nfunction buildRequestModel(c: LeafEntry): RequestModel {\n const m = c.method.toLowerCase() as RequestModel['method'];\n const flat = JSON.stringify(c.name);\n const path = JSON.stringify(c.path);\n const TA = buildRouterTypeAccess(c.name);\n const withParams = hasPathParams(c.params);\n // Request-shape flags (\"filter-search POST counts as a read\") computed in one place.\n const { isGet, isQuery, hasBody, hasQuery } = requestShape(c.route);\n\n const fields: string[] = [];\n if (withParams) fields.push(`params: ${TA}['params']`);\n if (hasQuery) fields.push(`query?: ${TA}['query']`);\n if (hasBody) fields.push(`body?: ${TA}['body']`);\n const inputType = fields.length ? `{ ${fields.join('; ')} }` : 'Record<string, never>';\n\n const urlExpr = withParams\n ? `route(${flat} as never, input?.params as never) || ${path}`\n : `route(${flat} as never) || ${path}`;\n const optsParts: string[] = [];\n if (hasQuery) optsParts.push('query: input?.query as Record<string, unknown> | undefined');\n if (hasBody) optsParts.push('body: input?.body');\n const optsExpr = optsParts.length ? `{ ${optsParts.join(', ')} }` : '{}';\n\n return {\n routeName: c.name,\n method: m,\n isGet,\n isQuery,\n hasParams: withParams,\n hasBody,\n inputType,\n urlExpr,\n optsExpr,\n responseType: `${TA}['response']`,\n queryKeyExpr: `[${flat}, input] as const`,\n };\n}\n\n/**\n * The neutral fetcher request: a typed call on the injected `fetcher`. Every leaf is built\n * on this; a registered `apiClientLayer` wraps it (e.g. into a TanStack handle), otherwise\n * the leaf is the bare awaitable callable.\n */\nfunction renderFetcherRequest(req: RequestModel): string {\n return `fetcher.${req.method}<${req.responseType}>(${req.urlExpr}, ${req.optsExpr})`;\n}\n\n/**\n * The `__req` runtime helper, emitted once per `api.ts`. Wraps a request thunk into an\n * **awaitable handle**: `await api.x.y({...})` runs the fetch (Tuyau-style), memoized so\n * repeated awaits hit the network once. Client-layer extensions (e.g. TanStack) spread\n * extra members (`queryOptions`/`mutationOptions`/…) onto the same handle.\n */\nfunction emitReqHelper(): string[] {\n return [\n '/** Awaitable request handle. `await api.x.y({...})` runs the fetch; extensions add query/mutation helpers. */',\n 'type __Req<R> = {',\n ' then<T1 = R, T2 = never>(',\n ' onfulfilled?: ((value: R) => T1 | PromiseLike<T1>) | null,',\n ' onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null,',\n ' ): Promise<T1 | T2>;',\n ' catch<T = never>(onrejected?: ((reason: unknown) => T | PromiseLike<T>) | null): Promise<R | T>;',\n ' finally(onfinally?: (() => void) | null): Promise<R>;',\n ' fetch(): Promise<R>;',\n '};',\n 'function __req<R>(run: () => Promise<R>): __Req<R> {',\n ' let __p: Promise<R> | undefined;',\n ' const __promise = () => {',\n ' __p ??= run();',\n ' return __p;',\n ' };',\n ' return {',\n ' then: (onfulfilled, onrejected) => __promise().then(onfulfilled, onrejected),',\n ' catch: (onrejected) => __promise().catch(onrejected),',\n ' finally: (onfinally) => __promise().finally(onfinally),',\n ' fetch: run,',\n ' };',\n '}',\n '',\n ];\n}\n\n/**\n * Render one leaf. Every leaf is an **awaitable handle**: the `__req(...)` base makes\n * `await api.x.y({...})` perform the request; any client-layer/member contributions\n * (TanStack options, filterQuery, …) are spread on alongside it.\n */\nfunction renderLeaf(\n pad: string,\n objKey: string,\n req: RequestModel,\n requestExpr: string,\n members: Record<string, string>,\n): string[] {\n const lines = [`${pad}${objKey}: (input?: ${req.inputType}) => ({`];\n lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);\n for (const [name, value] of Object.entries(members)) {\n lines.push(`${pad} ${name}: ${value},`);\n }\n lines.push(`${pad}}),`);\n return lines;\n}\n\n/** Resolved api.ts pipeline pieces, threaded through the recursive emit. */\ninterface ApiPipeline {\n layer?: ApiClientLayer;\n memberExts: CodegenExtension[];\n ctx: ExtensionContext;\n}\n\n/**\n * Emit the nested `api` object body via the LeafModel pipeline:\n * build model → neutral fetcher request → layer (when a client layer is registered)\n * → member contributors (bundled filter + extensions' apiMembers) → render. With no layer\n * a leaf is a bare typed-fetch callable; a layer flips it into a handle.\n */\nfunction emitApiObjectBlock(tree: Map<string, TreeNode>, indent: number, p: ApiPipeline): 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 === 'branch') {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitApiObjectBlock(node.children, indent + 2, p));\n lines.push(`${pad}},`);\n continue;\n }\n\n const req = buildRequestModel(node);\n // Hand extension hooks the real, un-narrowed RouteDescriptor stored on the leaf —\n // no reconstruction or force-cast.\n const leaf: LeafModel = {\n route: node.route,\n request: req,\n requestExpr: renderFetcherRequest(req),\n };\n\n // Every leaf is an awaitable handle (the __req base). A client layer (TanStack) spreads\n // query/mutation helpers on top; extension apiMembers (e.g. nestjs-filter's filterQuery)\n // add further members. Member-name collisions across extensions are an error — enforced\n // by the same exclusive-ownership policy as file collisions.\n const owned = new Map<string, { value: string; owner: string }>();\n if (p.layer) {\n mergeExclusive(owned, Object.entries(p.layer.buildMembers(leaf.requestExpr, leaf, p.ctx)), {\n owner: p.layer.name,\n describe: (name, prevOwner, owner) =>\n `api member \"${name}\" on route \"${req.routeName}\" is contributed by more than one extension (conflict between \"${prevOwner}\" and \"${owner}\").`,\n });\n }\n for (const ext of p.memberExts) {\n const extra = ext.apiMembers?.(leaf, p.ctx);\n if (!extra) continue;\n mergeExclusive(owned, Object.entries(extra), {\n owner: ext.name,\n describe: (name, prevOwner, owner) =>\n `api member \"${name}\" on route \"${req.routeName}\" is contributed by more than one extension (conflict between \"${prevOwner}\" and \"${owner}\").`,\n });\n }\n const members: Record<string, string> = {};\n for (const [name, { value }] of owned) members[name] = value;\n\n lines.push(...renderLeaf(pad, objKey, req, leaf.requestExpr, members));\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// Static api.ts text blocks\n// ---------------------------------------------------------------------------\n//\n// These are pure constants — the same bytes in every emitted api.ts — so they\n// live here as module-level templates rather than being assembled line-by-line\n// inside `buildApiFile`. `RESOLVER_HELPERS` + `ROUTE_NAMESPACE` + `PATH_NAMESPACE`\n// are the populated form (resolver-backed). `EMPTY_*` are the no-routes form,\n// where there is nothing to resolve so the namespaces collapse to `never` stubs\n// and the resolver helpers are omitted entirely. The two forms are intentionally\n// distinct text (the empty `Request` is a one-liner, the populated one is not),\n// so they are separate constants rather than one parameterised template.\n\n/** Recursive resolver helpers (`_RouterAt`/`ResolveByName`/`_LeafValues`/`ResolveByPath`). */\nconst RESOLVER_HELPERS: readonly string[] = [\n // --- Recursive helper type _RouterAt: walks nested ApiRouter by dot-path ---\n 'type _RouterAt<R, P extends string> = P extends `${infer Head}.${infer Tail}`',\n ' ? Head extends keyof R ? _RouterAt<R[Head], Tail> : never',\n ' : P extends keyof R ? R[P] : never;',\n '',\n // --- ResolveByName: resolve a field from a dot-path name ---\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 // --- ResolveByPath: scan all leaves for matching method + url ---\n // Flattens ApiRouter recursively and finds the entry whose method === M and url === U.\n 'type _LeafValues<T> = T extends { method: string; url: string }',\n ' ? T',\n ' : T extends object ? _LeafValues<T[keyof T]> : never;',\n '',\n 'type ResolveByPath<M extends string, U extends string, Field extends string> = _LeafValues<ApiRouter> extends infer L',\n ' ? L extends { method: M; url: U }',\n ' ? Field extends keyof L ? L[Field] : never',\n ' : never',\n ' : never;',\n '',\n];\n\n/** Populated `Route` namespace — resolves fields by dot-path name. */\nconst ROUTE_NAMESPACE: readonly string[] = [\n 'export namespace Route {',\n ' export type Response<K extends string> = ResolveByName<K, \"response\">;',\n ' export type Body<K extends string> = ResolveByName<K, \"body\">;',\n ' export type Query<K extends string> = ResolveByName<K, \"query\">;',\n ' export type Params<K extends string> = ResolveByName<K, \"params\">;',\n ' export type Error<K extends string> = ResolveByName<K, \"error\">;',\n ' export type FilterFields<K extends string> = ResolveByName<K, \"filterFields\">;',\n ' export type Request<K extends string> = {',\n ' body: Body<K>;',\n ' query: Query<K>;',\n ' params: Params<K>;',\n ' };',\n '}',\n '',\n];\n\n/** Populated `Path` namespace — resolves fields by method + url. */\nconst PATH_NAMESPACE: readonly string[] = [\n 'export namespace Path {',\n ' export type Response<M extends string, U extends string> = ResolveByPath<M, U, \"response\">;',\n ' export type Body<M extends string, U extends string> = ResolveByPath<M, U, \"body\">;',\n ' export type Query<M extends string, U extends string> = ResolveByPath<M, U, \"query\">;',\n ' export type Params<M extends string, U extends string> = ResolveByPath<M, U, \"params\">;',\n ' export type Error<M extends string, U extends string> = ResolveByPath<M, U, \"error\">;',\n ' export type FilterFields<M extends string, U extends string> = ResolveByPath<M, U, \"filterFields\">;',\n '}',\n '',\n];\n\n/** Empty-routes form: nothing to resolve, so every namespace member is `never`. */\nconst EMPTY_ROUTE_NAMESPACE: readonly string[] = [\n 'export namespace Route {',\n ' export type Response<K extends string> = never;',\n ' export type Body<K extends string> = never;',\n ' export type Query<K extends string> = never;',\n ' export type Params<K extends string> = never;',\n ' export type Error<K extends string> = never;',\n ' export type FilterFields<K extends string> = never;',\n ' export type Request<K extends string> = { body: never; query: never; params: never };',\n '}',\n '',\n];\n\nconst EMPTY_PATH_NAMESPACE: readonly string[] = [\n 'export namespace Path {',\n ' export type Response<M extends string, U extends string> = never;',\n ' export type Body<M extends string, U extends string> = never;',\n ' export type Query<M extends string, U extends string> = never;',\n ' export type Params<M extends string, U extends string> = never;',\n ' export type Error<M extends string, U extends string> = never;',\n ' export type FilterFields<M extends string, U extends string> = never;',\n '}',\n '',\n];\n\n// ---------------------------------------------------------------------------\n// Main builder\n// ---------------------------------------------------------------------------\n\nfunction buildApiFile(\n routes: RouteDescriptor[],\n outDir?: string,\n opts: ApiEmitOptions = {},\n): string {\n const fetcherImportPath = opts.fetcherImportPath;\n const extensions = opts.extensions ?? [];\n const { layer } = resolveApiSlots(extensions);\n const memberExts = extensions.filter((e) => e.apiMembers);\n const headerExts = extensions.filter((e) => e.apiHeader);\n const contracted = routes.filter((r) => r.contract);\n\n // Extension context for the api.ts hooks. `generate()` passes the real one; standalone\n // `emitApi` calls (tests) get a minimal context exposing the routes (all the bundled\n // layer/transport read). `project()` is unavailable in the standalone path.\n const ctx: ExtensionContext =\n opts.ctx ??\n ({\n cwd: outDir ?? '',\n outDir: outDir ?? '',\n routes,\n config: {} as never,\n project: () => {\n throw new Error('ExtensionContext.project() is unavailable in standalone emitApi.');\n },\n } satisfies ExtensionContext);\n\n // Collect all type refs for import generation\n const importsByFile = new Map<string, Set<string>>();\n for (const r of contracted) {\n const cs = r.contract?.contractSource;\n if (!cs) continue;\n // When controllerRef exists, response uses ReturnType<import(...)> — skip response import\n const refs = r.controllerRef\n ? [cs.queryRef, cs.bodyRef]\n : [cs.queryRef, cs.bodyRef, cs.responseRef];\n for (const ref of refs) {\n if (!ref) continue;\n let names = importsByFile.get(ref.filePath);\n if (!names) {\n names = new Set();\n importsByFile.set(ref.filePath, names);\n }\n names.add(ref.name);\n }\n // Named enum / type-alias / interface refs inferred from @FilterFor method\n // params (the type map M references them by name → emit `import type` too).\n for (const ft of cs.filterFieldTypes ?? []) {\n if (!ft.typeRef) continue;\n let names = importsByFile.get(ft.typeRef.filePath);\n if (!names) {\n names = new Set();\n importsByFile.set(ft.typeRef.filePath, names);\n }\n names.add(ft.typeRef.name);\n }\n }\n\n const lines: string[] = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.', ''];\n\n // Extension-contributed module imports (client layer + apiHeader), deduped and emitted\n // in order. e.g. the TanStack layer emits its queryOptions/mutationOptions import here.\n const extImports: string[] = [];\n const seenImports = new Set<string>();\n const pushImport = (imp: string): void => {\n if (seenImports.has(imp)) return;\n seenImports.add(imp);\n extImports.push(imp);\n };\n for (const imp of layer?.imports?.(ctx) ?? []) pushImport(imp);\n for (const ext of headerExts) {\n for (const imp of ext.apiHeader?.(ctx)?.imports ?? []) pushImport(imp);\n }\n lines.push(...extImports);\n\n lines.push(\n \"import { route, ROUTES, type RouteName, type ExtractParams, type RouteParams } from './routes.js';\",\n );\n // Tuyau-style: the api is a factory that takes the fetcher at runtime, so the\n // app injects its own client (custom transport/axios, baseUrl, superjson) —\n // rather than the codegen hardcoding `import { fetcher } from '<path>'`.\n const runtimeImport = fetcherImportPath ?? '@dudousxd/nestjs-client';\n lines.push(`import type { Fetcher } from '${runtimeImport}';`);\n\n // Emit type imports from source files.\n // When two different files export the same type name, alias the duplicate\n // to avoid `Identifier has already been declared` parse errors.\n if (importsByFile.size > 0 && outDir) {\n lines.push('');\n const emittedNames = new Set<string>();\n for (const [filePath, names] of importsByFile) {\n // Bare module specifier (node_modules package) → import as-is. Local\n // source files are always absolute paths → compute a relative import.\n let relPath: string;\n if (isAbsolute(filePath)) {\n relPath = relative(outDir, filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n } else {\n relPath = filePath;\n }\n const specifiers: string[] = [];\n for (const name of [...names].sort()) {\n if (emittedNames.has(name)) {\n const alias = `${name}_${emittedNames.size}`;\n specifiers.push(`${name} as ${alias}`);\n emittedNames.add(alias);\n } else {\n specifiers.push(name);\n emittedNames.add(name);\n }\n }\n lines.push(`import type { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n }\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 function createApi(_fetcher: Fetcher): Record<string, never> {');\n lines.push(' return {};');\n lines.push('}');\n lines.push('export type Api = ReturnType<typeof createApi>;');\n lines.push('');\n lines.push(...EMPTY_ROUTE_NAMESPACE);\n lines.push(...EMPTY_PATH_NAMESPACE);\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 params: r.params,\n controllerRef: r.controllerRef,\n contractSource: c.contractSource,\n route: r,\n };\n insertIntoTree(tree, segments, leaf, name);\n }\n\n // --- ApiRouter type ---\n lines.push('export type ApiRouter = {');\n lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ''));\n lines.push('};');\n lines.push('');\n\n // --- awaitable request handle helper ---\n lines.push(...emitReqHelper());\n\n // --- api factory (inject your fetcher at runtime) ---\n lines.push('export function createApi(fetcher: Fetcher) {');\n lines.push(' return {');\n lines.push(\n ...emitApiObjectBlock(tree, 4, {\n ...(layer ? { layer } : {}),\n memberExts,\n ctx,\n }),\n );\n lines.push(' };');\n lines.push('}');\n lines.push('');\n lines.push('export type Api = ReturnType<typeof createApi>;');\n lines.push('');\n\n lines.push(...RESOLVER_HELPERS);\n lines.push(...ROUTE_NAMESPACE);\n lines.push(...PATH_NAMESPACE);\n\n // Extension-contributed top-level statements (e.g. the Inertia extension's navigate()).\n for (const ext of headerExts) {\n const statements = ext.apiHeader?.(ctx)?.statements;\n if (statements?.length) {\n lines.push(...statements, '');\n }\n }\n\n return lines.join('\\n');\n}\n","import { Project } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport { CodegenError } from '../exceptions.js';\nimport type { ApiClientLayer, CodegenExtension, EmittedFile, ExtensionContext } from './types.js';\n\n/**\n * Resolve the single-slot `apiClientLayer` hook. At most one extension may claim it;\n * a second claimer throws a {@link CodegenError} naming both extensions. An unclaimed\n * `apiClientLayer` means leaves stay bare callables backed by the neutral fetcher.\n */\nexport function resolveApiSlots(extensions: readonly CodegenExtension[]): {\n layer?: ApiClientLayer;\n} {\n let layer: ApiClientLayer | undefined;\n let layerOwner: string | undefined;\n\n for (const ext of extensions) {\n if (ext.apiClientLayer) {\n if (layer) {\n throw new CodegenError(\n `api client layer claimed by both \"${layerOwner}\" and \"${ext.name}\" — only one extension may set apiClientLayer.`,\n );\n }\n layer = ext.apiClientLayer;\n layerOwner = ext.name;\n }\n }\n\n return {\n ...(layer ? { layer } : {}),\n };\n}\n\n/** Output filenames the core always owns — an extension emitting one of these is an error. */\nconst CORE_FILES = new Set(['routes.ts', 'api.ts', 'forms.ts', 'index.d.ts', 'pages.d.ts']);\n\n/**\n * Merge `incoming` entries into `target`, enforcing a single exclusive-ownership policy:\n * a key already present in `target` is a collision and throws, naming the prior owner and\n * the offending extension. One collision format for every \"two extensions both produced X\"\n * case (api members, emitted files, …).\n *\n * @param target the accumulating map (key → value); also records ownership.\n * @param incoming entries the current extension contributes.\n * @param owner the extension currently contributing (named in the error).\n * @param describe builds the error message given the colliding key, prior owner and owner.\n */\nexport function mergeExclusive<V>(\n target: Map<string, { value: V; owner: string }>,\n incoming: Iterable<readonly [string, V]>,\n {\n owner,\n describe,\n }: {\n owner: string;\n describe: (key: string, prevOwner: string, owner: string) => string;\n },\n): void {\n for (const [key, value] of incoming) {\n const prev = target.get(key);\n if (prev !== undefined) {\n throw new CodegenError(describe(key, prev.owner, owner));\n }\n target.set(key, { value, owner });\n }\n}\n\n/**\n * Build the shared {@link ExtensionContext}. `routes` is exposed as a live getter so an\n * extension reading `ctx.routes` during `emitFiles` sees the post-`transformRoutes` IR.\n * The ts-morph `Project` is created lazily on first `project()` call (extensions that do\n * no AST work never pay for it).\n */\nexport function createExtensionContext(\n config: ResolvedConfig,\n getRoutes: () => readonly RouteDescriptor[],\n): ExtensionContext {\n let project: Project | undefined;\n return {\n cwd: config.codegen.cwd,\n outDir: config.codegen.outDir,\n config,\n get routes() {\n return getRoutes();\n },\n project() {\n if (!project) {\n project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: { allowJs: true, strict: false },\n });\n }\n return project;\n },\n };\n}\n\n/**\n * Run every extension's `transformRoutes` hook in registration order, chaining the\n * result (each sees the previous output). An extension may mutate in place and return\n * void, or return a new array.\n */\nexport async function applyTransformRoutes(\n routes: RouteDescriptor[],\n extensions: readonly CodegenExtension[],\n ctx: ExtensionContext,\n): Promise<RouteDescriptor[]> {\n let current = routes;\n for (const ext of extensions) {\n if (!ext.transformRoutes) continue;\n const result = await ext.transformRoutes(current, ctx);\n if (Array.isArray(result)) current = result;\n }\n return current;\n}\n\n/**\n * Run every extension's `emitFiles` hook and return the accumulated files. Throws a\n * {@link CodegenError} if two extensions emit the same path, or if an extension tries to\n * emit a core-owned file. Paths are normalized to forward slashes for collision checks.\n */\nexport async function collectEmittedFiles(\n extensions: readonly CodegenExtension[],\n ctx: ExtensionContext,\n): Promise<EmittedFile[]> {\n const files: EmittedFile[] = [];\n const owners = new Map<string, { value: EmittedFile; owner: string }>();\n\n for (const ext of extensions) {\n if (!ext.emitFiles) continue;\n const emitted = await ext.emitFiles(ctx);\n for (const file of emitted) {\n const key = file.path.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n if (CORE_FILES.has(key)) {\n throw new CodegenError(\n `Extension \"${ext.name}\" tried to emit the core-owned file \"${file.path}\". Core files (${[...CORE_FILES].join(', ')}) cannot be produced by extensions.`,\n );\n }\n mergeExclusive(owners, [[key, file] as const], {\n owner: ext.name,\n describe: (_key, prevOwner, owner) =>\n `Output file \"${file.path}\" is emitted by both \"${prevOwner}\" and \"${owner}\". Two extensions cannot write the same file.`,\n });\n files.push(file);\n }\n }\n\n return files;\n}\n","import type { Project } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * The published, versioned extension contract for `@dudousxd/nestjs-codegen`.\n *\n * Extensions are **build-time** objects (usually returned by a factory so they can take\n * options) registered explicitly via `forRoot({ extensions: [...] })`. The host runs them\n * around the core discovery → IR → emit pipeline.\n *\n * Hooks split into **multi** (every extension runs; results accumulate or chain) and\n * **single-slot** (at most one extension may claim it — two claimers is a hard error).\n *\n * @remarks Semver 0.x — the shape may change until 1.0. Out-of-repo extensions should pin\n * a compatible `@dudousxd/nestjs-codegen` peer range.\n */\nexport interface CodegenExtension {\n /** Unique id. Used in conflict/collision errors and for deterministic ordering. */\n name: string;\n\n // ── multi hooks (every extension runs) ────────────────────────────────────\n\n /**\n * Mutate/augment the route IR before emit. Runs in registration order, chained\n * (each extension sees the previous one's output). Return the new array, or mutate\n * in place and return void. Example: the filter extension attaches `filterFields` to\n * matching routes here.\n */\n transformRoutes?(\n routes: RouteDescriptor[],\n ctx: ExtensionContext,\n ): RouteDescriptor[] | undefined | Promise<RouteDescriptor[] | undefined>;\n\n /**\n * Contribute extra output files (additive). Paths are relative to `outDir`; a path\n * claimed by two extensions is a hard error. Example: the Inertia extension does its\n * own page discovery via `ctx.project()` and emits `pages.d.ts` + `components.json`.\n */\n emitFiles?(ctx: ExtensionContext): EmittedFile[] | Promise<EmittedFile[]>;\n\n /**\n * Contribute top-level code to `api.ts` (imports + statements). Runs in registration\n * order; imports are deduped by the host. Example: the Inertia extension adds\n * `import { router } from '@inertiajs/react'` and the `navigate()` helper.\n */\n apiHeader?(ctx: ExtensionContext): ApiHeaderContribution | undefined;\n\n /**\n * Add named members to a **handle** leaf. Only runs when a client layer is active\n * (i.e. the leaf is a handle, not a bare callable). Member-name collisions across\n * extensions are a hard error. Example: the filter extension adds `filterQuery` to\n * leaves whose route carries `filterFields`.\n */\n apiMembers?(leaf: LeafModel, ctx: ExtensionContext): Record<string, string> | undefined;\n\n // ── single-slot hooks (at most one extension) ─────────────────────────────\n\n /**\n * Claims **what** a leaf returns and **how** it issues its request. At most one extension\n * may claim it. When unset, a leaf is a bare awaitable callable backed by the neutral\n * fetcher. Example: the TanStack extension wraps each leaf into a handle exposing\n * `{ fetch, queryKey, queryOptions | mutationOptions }`, composing with the fetcher\n * request the host passes in.\n */\n apiClientLayer?: ApiClientLayer;\n}\n\n/** Shared, read-only context handed to every extension hook. */\nexport interface ExtensionContext {\n cwd: string;\n outDir: string;\n routes: readonly RouteDescriptor[];\n config: ResolvedConfig;\n /** Lazily-created shared ts-morph Project for AST work (pages, custom decorators). */\n project(): Project;\n}\n\n/** A file contributed by an extension's `emitFiles` hook. */\nexport interface EmittedFile {\n /** Path relative to `outDir`. A collision across extensions throws. */\n path: string;\n contents: string;\n}\n\n/** Top-level `api.ts` contributions from an extension's `apiHeader` hook. */\nexport interface ApiHeaderContribution {\n /** Raw import lines (e.g. `import { router } from '@inertiajs/react';`), deduped by the host. */\n imports?: string[];\n /** Top-level statements appended after the api factory (e.g. the `navigate()` helper). */\n statements?: string[];\n}\n\n/**\n * The neutral, per-endpoint request model the host builds for each leaf before any\n * transport/layer runs. Extensions read this to render their output.\n */\nexport interface RequestModel {\n /** Dot-path route name, e.g. `users.show`. */\n routeName: string;\n method: 'get' | 'post' | 'put' | 'patch' | 'delete';\n isGet: boolean;\n /** True for reads: a GET, or a filter-search route (has `filterFields`) even when POST.\n * Client layers use this (not `isGet`) to decide query vs mutation helpers. */\n isQuery: boolean;\n hasParams: boolean;\n hasBody: boolean;\n /** Type of the leaf's `input` arg, e.g. `{ params: ...; query?: ... }` or `Record<string, never>`. */\n inputType: string;\n /** URL expression, e.g. `route('users.show', input?.params) || '/api/users/:id'`. */\n urlExpr: string;\n /** Request-options expression, e.g. `{ query: ... }` or `{ body: input?.body }`. */\n optsExpr: string;\n /** Response type access, e.g. `ApiRouter['users']['show']['response']`. */\n responseType: string;\n /** Stable query-key expression, e.g. `[\"users.show\", input] as const`. */\n queryKeyExpr: string;\n}\n\n/**\n * Per-leaf model passed through the api.ts pipeline: layer → member contributors → render.\n * `requestExpr` is the host's neutral fetcher request; `members`, when present, flips the\n * leaf from a bare callable to a handle.\n */\nexport interface LeafModel {\n route: RouteDescriptor;\n request: RequestModel;\n /** The expression that issues the request (the host's neutral fetcher call). */\n requestExpr: string;\n /** When present, the leaf renders as a handle exposing these members (ordered). */\n members?: Record<string, string>;\n}\n\n/**\n * Top-level `api.ts` imports a client layer depends on. A function of the context so it can\n * be route-aware (e.g. only import `mutationOptions` when a mutation exists). Imports are\n * deduped by the host across all extensions.\n */\nexport interface ApiModuleDeps {\n /** Raw import lines (e.g. `import { queryOptions as _q } from '@tanstack/react-query';`). */\n imports?(ctx: ExtensionContext): string[];\n}\n\n/** Single-slot: decides what a leaf returns (the handle members). */\nexport interface ApiClientLayer extends ApiModuleDeps {\n name: string;\n /**\n * Given the request expression (from the transport) and the leaf, return the handle's\n * members as an ordered `name → value` map (value is the expression after `name: `).\n * Returning members flips the leaf from a bare callable to a handle.\n */\n buildMembers(requestExpr: string, leaf: LeafModel, ctx: ExtensionContext): Record<string, string>;\n}\n\n/**\n * The four request-shape flags derived from a route's method + contract. Computed in ONE\n * place ({@link requestShape}) and read by both the host emitter and client-layer\n * extensions, so the \"filter-search POST counts as a read\" rule is encoded exactly once.\n */\nexport interface RequestShape {\n /** The route is a `GET`. */\n isGet: boolean;\n /** True for reads: a GET, or a filter-search route (carries `filterFields`) even when POST.\n * Client layers use this (not `isGet`) to decide query vs mutation helpers. */\n isQuery: boolean;\n /** The route carries a body contract (a mutation payload). */\n hasBody: boolean;\n /** The route can take a query string — always for GET; a mutation may too (query + body). */\n hasQuery: boolean;\n}\n\n/**\n * Compute the {@link RequestShape} flags for a route from its method and contract. This is\n * the SINGLE source of truth for these flags — `buildRequestModel`, the TanStack layer's\n * `imports()`, and any other reader must call this rather than re-deriving. The\n * \"filter-search POST counts as a read\" rule lives here and nowhere else.\n */\nexport function requestShape(route: RouteDescriptor): RequestShape {\n const cs = route.contract?.contractSource;\n const isGet = route.method.toUpperCase() === 'GET';\n const isQuery = isGet || !!cs?.filterFields?.length;\n const hasBody = !!cs?.bodyRef || (cs?.body != null && cs.body !== 'never');\n const hasQuery = isGet || !!cs?.queryRef || (cs?.query != null && cs.query !== 'never');\n return { isGet, isQuery, hasBody, hasQuery };\n}\n\n/** Identity helper for authoring extensions with full type inference. */\nexport function defineExtension(ext: CodegenExtension): CodegenExtension {\n return ext;\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, relative } from 'node:path';\nimport type { ValidationAdapter } from '../adapters/types.js';\nimport type { ResolvedFormsConfig } from '../config/types.js';\nimport type { RouteDescriptor, TypeRef } from '../discovery/types.js';\n\n/**\n * Emits `forms.ts` into `outDir`. Every validatable route is rendered through a\n * single {@link ValidationAdapter} path (IR → `adapter.renderModule`). The adapter\n * is required — `validation` is a mandatory config field.\n *\n * Two schema sources exist per route:\n * - Neutral IR (`bodySchema`/`querySchema`) synthesized from class-validator\n * DTOs — renderable through ANY adapter.\n * - Hand-written zod from `defineContract` (`bodyZodText`/`queryZodText` raw\n * source, or `bodyZodRef`/`queryZodRef` re-exports). This is genuine zod\n * source with no IR; it passes through verbatim only when the adapter sets\n * `acceptsRawZodSource` (the zod adapter), and is skipped with a warning\n * under any other adapter.\n *\n * Returns `true` when a `forms.ts` was written (drives the index export).\n */\nexport async function emitForms(\n routes: RouteDescriptor[],\n outDir: string,\n config: ResolvedFormsConfig | undefined,\n adapter: ValidationAdapter,\n): Promise<boolean> {\n if (config && config.enabled === false) return false;\n\n const content = buildFormsFileWithAdapter(routes, outDir, adapter, config);\n if (content === null) return false;\n await mkdir(outDir, { recursive: true });\n await writeFile(join(outDir, 'forms.ts'), content, 'utf8');\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** PascalCase from a single dot/identifier segment. */\nfunction pascal(segment: string): string {\n return segment\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('');\n}\n\n/**\n * PascalCase base name for a route. Uses the method segment (last dot-part);\n * the full dotted name is used to disambiguate collisions.\n */\nfunction deriveBaseName(routeName: string): { method: string; full: string } {\n const segments = routeName.split('.');\n const method = pascal(segments[segments.length - 1] ?? routeName);\n const full = segments.map(pascal).join('');\n return { method, full };\n}\n\n/** Relative import specifier from outDir to a source file (no extension). */\nfunction relImport(outDir: string, filePath: string): string {\n let relPath = relative(outDir, filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n return relPath;\n}\n\n/** The root identifier of a ref name like `loginContract.body` → `loginContract`. */\nfunction refRootIdentifier(refName: string): string {\n return refName.split('.')[0] ?? refName;\n}\n\n/**\n * A renderable form schema source. The IR is preferred (works through any\n * adapter); `zodText`/`zodRef` are the zod-only `defineContract` fallbacks.\n */\ninterface FormSource {\n /** Neutral IR — rendered via the active adapter. */\n schema?: import('../ir/schema-node.js').SchemaModule | null;\n /** Raw zod source text (defineContract inline / synthesized). */\n zodText?: string | null;\n /** Importable named const re-export (defineContract Path A). */\n zodRef?: TypeRef | null;\n}\n\nfunction hasSource(src: FormSource): boolean {\n return !!(src.schema || src.zodText || src.zodRef);\n}\n\n// ---------------------------------------------------------------------------\n// Nested-schema hoisting: dedup + collision disambiguation + recursion guard.\n// (Used for the zod-only `formNestedSchemas` text path.)\n// ---------------------------------------------------------------------------\n\ninterface FormEntry {\n routeName: string;\n baseName: string;\n body: FormSource | undefined;\n query: FormSource | undefined;\n /** zod-only nested schemas (name → zod text) for the text path. */\n nestedSchemas: Record<string, string> | null;\n warnings: string[];\n}\n\ninterface NestedSchemaPlan {\n globalSchemas: Map<string, string>;\n renamesByEntry: Map<FormEntry, Map<string, string>>;\n}\n\nfunction applyRenames(text: string, renames: Map<string, string> | null): string {\n if (!renames || renames.size === 0) return text;\n let out = text;\n for (const [from, to] of renames) {\n if (from === to) continue;\n out = out.replace(new RegExp(`\\\\b${escapeRegExp(from)}\\\\b`, 'g'), to);\n }\n return out;\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isSelfReferential(name: string, text: string): boolean {\n return new RegExp(`\\\\b${escapeRegExp(name)}\\\\b`).test(text);\n}\n\n/**\n * Build the global hoist registry + per-entry renames for zod-only nested\n * schema texts. See the original design notes: each unique (name, shape) is\n * declared once; same-name different-shape is suffixed; recursion is degraded.\n */\nfunction planNestedSchemas(entries: FormEntry[]): NestedSchemaPlan {\n const globalSchemas = new Map<string, string>();\n const renamesByEntry = new Map<FormEntry, Map<string, string>>();\n\n for (const entry of entries) {\n if (!entry.nestedSchemas) continue;\n const local = Object.entries(entry.nestedSchemas);\n if (local.length === 0) continue;\n\n const rename = new Map<string, string>();\n for (const [name] of local) rename.set(name, name);\n\n const textFor = (name: string): string => {\n const raw = entry.nestedSchemas?.[name] ?? '';\n return applyRenames(raw, rename);\n };\n\n let changed = true;\n let guard = 0;\n while (changed && guard < local.length + 2) {\n changed = false;\n guard += 1;\n for (const [name] of local) {\n const finalName = rename.get(name) ?? name;\n const text = textFor(name);\n const existing = globalSchemas.get(finalName);\n if (existing === undefined) continue;\n if (existing === text) continue;\n let i = 2;\n let candidate = `${name}_${i}`;\n while (\n (globalSchemas.has(candidate) && globalSchemas.get(candidate) !== textFor(name)) ||\n [...rename.values()].includes(candidate)\n ) {\n i += 1;\n candidate = `${name}_${i}`;\n }\n rename.set(name, candidate);\n changed = true;\n }\n }\n\n for (const [name] of local) {\n const finalName = rename.get(name) ?? name;\n let text = textFor(name);\n if (isSelfReferential(finalName, text)) {\n text = 'z.unknown() /* recursive type — not expanded */';\n }\n const existing = globalSchemas.get(finalName);\n if (existing === undefined) {\n globalSchemas.set(finalName, text);\n }\n }\n\n renamesByEntry.set(entry, rename);\n }\n\n return { globalSchemas, renamesByEntry };\n}\n\n// ---------------------------------------------------------------------------\n// Single adapter-driven forms builder\n// ---------------------------------------------------------------------------\n\n/**\n * Render `forms.ts` from the neutral validation IR via `adapter`, plus the\n * zod-only `defineContract` text/ref fallbacks (zod adapter only). Returns\n * `null` when nothing to emit.\n */\nfunction buildFormsFileWithAdapter(\n routes: RouteDescriptor[],\n outDir: string,\n adapter: ValidationAdapter,\n config?: ResolvedFormsConfig,\n): string | null {\n const acceptsRawZod = adapter.acceptsRawZodSource === true;\n const sorted = [...routes].filter((r) => r.contract).sort((a, b) => a.name.localeCompare(b.name));\n\n // Base-name collision pass (method-only name vs full dotted name).\n const methodNameCounts = new Map<string, number>();\n const candidates: FormEntry[] = [];\n for (const route of sorted) {\n const cs = route.contract!.contractSource;\n const body: FormSource = {\n schema: cs.bodySchema ?? null,\n zodText: cs.bodyZodText ?? null,\n zodRef: cs.bodyZodRef ?? null,\n };\n const query: FormSource = {\n schema: cs.querySchema ?? null,\n zodText: cs.queryZodText ?? null,\n zodRef: cs.queryZodRef ?? null,\n };\n if (!hasSource(body) && !hasSource(query)) continue;\n const { method, full } = deriveBaseName(route.name);\n methodNameCounts.set(method, (methodNameCounts.get(method) ?? 0) + 1);\n candidates.push({\n routeName: route.name,\n baseName: full, // resolved below\n body: hasSource(body) ? body : undefined,\n query: hasSource(query) ? query : undefined,\n nestedSchemas: cs.formNestedSchemas ?? null,\n warnings: cs.formWarnings ?? [],\n });\n }\n\n const entries: FormEntry[] = candidates.map((c) => {\n const { method, full } = deriveBaseName(c.routeName);\n const collision = (methodNameCounts.get(method) ?? 0) > 1;\n return { ...c, baseName: collision ? full : method };\n });\n\n if (entries.length === 0) return null;\n\n // Re-export imports (zod-only refs without inline text), grouped by file.\n const importsByFile = new Map<string, Set<string>>();\n const refAlias = new Map<string, string>();\n for (const entry of entries) {\n for (const src of [entry.body, entry.query]) {\n if (src?.zodRef && !src.zodText && !src.schema) {\n const root = refRootIdentifier(src.zodRef.name);\n const set = importsByFile.get(src.zodRef.filePath) ?? new Set<string>();\n set.add(root);\n importsByFile.set(src.zodRef.filePath, set);\n }\n }\n }\n\n const importLines: string[] = [];\n if (importsByFile.size > 0) {\n const emitted = new Set<string>();\n for (const [filePath, roots] of [...importsByFile.entries()].sort()) {\n const relPath = relImport(outDir, filePath);\n const specifiers: string[] = [];\n for (const root of [...roots].sort()) {\n if (emitted.has(root)) {\n const alias = `${root}_${emitted.size}`;\n specifiers.push(`${root} as ${alias}`);\n emitted.add(alias);\n refAlias.set(`${filePath}\\0${root}`, alias);\n } else {\n specifiers.push(root);\n emitted.add(root);\n refAlias.set(`${filePath}\\0${root}`, root);\n }\n }\n importLines.push(`import { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n }\n\n // Hoist zod-only nested schemas (text path) once, with collision handling.\n const { globalSchemas, renamesByEntry } = planNestedSchemas(entries);\n\n // Hoisted IR nested schemas (rendered via adapter, deduped by name).\n const irNamed = new Map<string, string>();\n const decls: string[] = [];\n const mapEntries: string[] = [];\n let used = false;\n\n const renderSource = (\n src: FormSource,\n rename: Map<string, string> | null,\n ): { text: string; warn?: string } | null => {\n // Prefer the neutral IR — works through any adapter.\n if (src.schema) {\n const r = adapter.renderModule(src.schema);\n for (const [n, t] of r.namedNestedSchemas) irNamed.set(n, t);\n return { text: r.schemaText };\n }\n // zod-only defineContract fallbacks: text or re-export ref.\n if (src.zodText) {\n if (!acceptsRawZod) {\n return {\n text: '',\n warn: `is a defineContract (zod) schema; not translated to ${adapter.name} — use the zod adapter.`,\n };\n }\n return { text: applyRenames(src.zodText, rename) };\n }\n if (src.zodRef) {\n if (!acceptsRawZod) {\n return {\n text: '',\n warn: `is a defineContract (zod) schema; not translated to ${adapter.name} — use the zod adapter.`,\n };\n }\n const root = refRootIdentifier(src.zodRef.name);\n const alias = refAlias.get(`${src.zodRef.filePath}\\0${root}`) ?? root;\n const member = src.zodRef.name.slice(root.length);\n return { text: `${alias}${member}` };\n }\n return null;\n };\n\n for (const entry of entries) {\n const block: string[] = [];\n const rename = renamesByEntry.get(entry) ?? null;\n let bodyConst: string | undefined;\n\n if (entry.warnings && entry.warnings.length > 0) {\n for (const w of entry.warnings) block.push(`// warning: ${w}`);\n }\n\n if (entry.body) {\n const rendered = renderSource(entry.body, rename);\n if (rendered?.warn) {\n block.push(`// warning: ${entry.routeName} body ${rendered.warn}`);\n } else if (rendered) {\n used = true;\n bodyConst = `${entry.baseName}BodySchema`;\n block.push(`export const ${bodyConst} = ${rendered.text};`);\n block.push(`export type ${entry.baseName}Body = ${adapter.inferType(bodyConst)};`);\n }\n }\n if (entry.query) {\n const rendered = renderSource(entry.query, rename);\n if (rendered?.warn) {\n block.push(`// warning: ${entry.routeName} query ${rendered.warn}`);\n } else if (rendered) {\n used = true;\n const queryConst = `${entry.baseName}QuerySchema`;\n block.push(`export const ${queryConst} = ${rendered.text};`);\n block.push(`export type ${entry.baseName}Query = ${adapter.inferType(queryConst)};`);\n }\n }\n\n if (block.length === 0) continue;\n decls.push(`// ${entry.routeName}`, ...block, '');\n if (bodyConst) mapEntries.push(` ${JSON.stringify(entry.routeName)}: ${bodyConst},`);\n }\n\n if (!used) return null;\n\n const lines: string[] = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.'];\n if (acceptsRawZod) {\n const zodImport = config?.zodImport ?? 'zod';\n lines.push(`import { z } from '${zodImport}';`);\n } else {\n for (const imp of adapter.importStatements({ used: true })) lines.push(imp);\n }\n lines.push(...importLines);\n lines.push('');\n\n // Merge hoisted nested schemas: zod-only text path + IR-rendered nested.\n const allNested = new Map<string, string>();\n for (const [n, t] of globalSchemas) allNested.set(n, t);\n for (const [n, t] of irNamed) if (!allNested.has(n)) allNested.set(n, t);\n\n if (allNested.size > 0) {\n lines.push('// Hoisted nested schemas (shared across endpoints).');\n for (const [n, t] of allNested) lines.push(`const ${n} = ${t};`);\n lines.push('');\n }\n\n lines.push(...decls);\n lines.push('/** Route name → body schema map. */');\n lines.push('export const formSchemas = {');\n lines.push(...mapEntries);\n lines.push('} as const;');\n lines.push('');\n return lines.join('\\n');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function emitIndex(\n outDir: string,\n hasContracts = false,\n hasForms = false,\n): 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 if (hasForms) {\n exports.push(\"export * from './forms.js';\");\n }\n const content = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.', ...exports, ''].join(\n '\\n',\n );\n await writeFile(join(outDir, 'index.d.ts'), content, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\nimport type { SharedPropsResult } from '../discovery/shared-props.js';\n\nexport interface EmitPagesOptions {\n /** The export name to reference in import() type expressions (default: 'ComponentProps'). */\n propsExport?: string;\n /** When true, infer props from the default export's first parameter instead of a named export. */\n inferFromDefault?: boolean;\n /** When provided, emit an InertiaSharedProps augmentation alongside the pages. */\n sharedProps?: SharedPropsResult | null;\n}\n\nexport async function emitPages(\n pages: DiscoveredPage[],\n outDir: string,\n _options: EmitPagesOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const pageNameUnion =\n pages.length > 0 ? pages.map((p) => JSON.stringify(p.name)).join(' | ') : 'never';\n\n const augBody = pages\n .map((p) => {\n const key = needsQuotes(p.name) ? JSON.stringify(p.name) : p.name;\n const valueType = buildAugmentationType(p, outDir);\n return ` ${key}: ${valueType};`;\n })\n .join('\\n');\n\n const propsHelper =\n \"\\nexport type InertiaProps<K extends InertiaPageName> = import('@dudousxd/nestjs-inertia').InertiaPages[K];\\n\";\n\n const sharedPropsBlock = buildSharedPropsBlock(_options.sharedProps ?? null);\n\n const content = `// Generated by @dudousxd/nestjs-codegen. Do not edit.\\n\\nexport type InertiaPageName = ${pageNameUnion};\\n${propsHelper}\\ndeclare module '@dudousxd/nestjs-inertia' {\\n interface InertiaPages {\\n${augBody}\\n }\\n${sharedPropsBlock}}\\n`;\n\n await writeFile(join(outDir, 'pages.d.ts'), content, 'utf8');\n}\n\n/**\n * Build the `InertiaSharedProps` interface augmentation block.\n * Returns an empty string when sharedProps is null (graceful fallback).\n *\n * When `isImportRef` is true, the type is expressed as a mapped type from an import reference.\n * When `properties` are available, they are emitted as individual interface members.\n */\nfunction buildSharedPropsBlock(sharedProps: SharedPropsResult | null): string {\n if (!sharedProps) return '';\n\n // isImportRef case: emit a type alias that re-exports the external type\n if (sharedProps.isImportRef) {\n return `\\n // eslint-disable-next-line @typescript-eslint/no-empty-interface\\n interface InertiaSharedProps extends ${sharedProps.typeString} {}\\n`;\n }\n\n // Inline properties case\n if (!sharedProps.properties || sharedProps.properties.length === 0) return '';\n\n const propsBody = sharedProps.properties.map((p) => ` ${p.name}: ${p.type};`).join('\\n');\n\n return `\\n interface InertiaSharedProps {\\n${propsBody}\\n }\\n`;\n}\n\n/**\n * Build the type for a page in the module augmentation.\n * Uses `Parameters<typeof import('...').default>[0]` to infer props\n * directly from the default export — no named export needed.\n */\nfunction buildAugmentationType(page: DiscoveredPage, outDir: string): string {\n let importPath = relative(outDir, page.absolutePath).replace(/\\.(tsx?|vue|svelte)$/, '');\n if (!importPath.startsWith('.')) {\n importPath = `./${importPath}`;\n }\n return `Parameters<typeof import('${importPath}').default>[0]`;\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-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-codegen] 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-codegen 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-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 { 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 { 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-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(\n `[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`,\n );\n try {\n await generate(config);\n } catch {\n /* fallback: pages only */\n }\n }\n\n // ── Pages watcher (fast path — no route discovery) ──────────────────────────\n let pagesDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n // No `pages` config → watch a path that matches nothing (pages are Inertia-only).\n const pagesGlob = config.pages?.glob ?? '.nestjs-codegen-no-pages';\n const pagesWatcher = chokidar.watch(join(config.codegen.cwd, pagesGlob), {\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 (err) {\n console.error(\n '[nestjs-codegen] Pages generation failed:',\n err instanceof Error ? err.message : err,\n );\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 // Route through generate() so the incremental pass honors the SAME emit\n // options as the initial pass (query / mutationClient / queryImport / fetcher\n // importPath + the validation adapter). Emitting api.ts/forms.ts directly here\n // would silently drop those settings on every contract edit.\n await generate(config, routes);\n } catch (err) {\n console.error(\n '[nestjs-codegen] Contracts generation failed:',\n err instanceof Error ? err.message : err,\n );\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 // ── DTO watcher (forms.ts synthesis from class-validator DTOs) ───────────────\n // DTO classes live in *.dto.ts files (not matched by the controller glob), but\n // changes to them affect the synthesized form schemas. Re-run discovery (which\n // re-emits forms.ts) on any DTO change, reusing the contracts debounce.\n const formsWatcher = chokidar.watch(join(config.codegen.cwd, config.forms.watch), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n formsWatcher.on('add', scheduleContractsRegenerate);\n formsWatcher.on('change', scheduleContractsRegenerate);\n formsWatcher.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 formsWatcher.close();\n await lock.release();\n },\n };\n}\n","import { 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 MethodDeclaration,\n Node,\n Project,\n type SourceFile,\n} from 'ts-morph';\nimport { extractDtoContract } from './dto-type-resolver.js';\nimport { loadTsconfigPaths, setDiscoveryContext } from './type-ref-resolution.js';\nimport type { ContractSource, RouteDescriptor, TypeRef } from './types.js';\nimport { type ParsedContractDef, parseDefineContractCall } from './zod-ast-to-ts.js';\n\n// Re-export so existing test import paths (`../discovery/contracts-fast.js`)\n// keep resolving these symbols after the decomposition into sibling modules.\nexport { extractDtoContract } from './dto-type-resolver.js';\nexport { zodAstToTs } from './zod-ast-to-ts.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 // Bind the discovery context to this invocation's Project. Each call owns its\n // own Project, so concurrent callers never share or corrupt context.\n setDiscoveryContext(project, {\n projectRoot: cwd,\n tsconfigPaths: loadTsconfigPaths(tsconfigPath),\n });\n\n for (const sourceFile of project.getSourceFiles()) {\n routes.push(...extractFromSourceFile(sourceFile, project));\n }\n\n return routes;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\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 * 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// 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\n/** Resolved HTTP verb + handler sub-path read from a method's NestJS verb decorator. */\ninterface ResolvedVerb {\n httpMethod: string;\n handlerPath: string;\n}\n\n/**\n * Read the HTTP verb + sub-path from a method's NestJS verb decorator\n * (`@Get`/`@Post`/…). Returns null when the method carries no verb decorator.\n */\nfunction resolveVerb(method: MethodDeclaration): ResolvedVerb | null {\n for (const [decoratorName, verb] of Object.entries(HTTP_METHOD_DECORATORS)) {\n const httpDecorator = method.getDecorator(decoratorName);\n if (httpDecorator) {\n const httpArgs = httpDecorator.getArguments();\n const pathArg = httpArgs[0];\n return { httpMethod: verb, handlerPath: decoratorStringArg(pathArg) ?? '' };\n }\n }\n return null;\n}\n\n/**\n * Read an `@As(...)` decorator value off a node (class or method).\n * Throws when the decorator is present but its argument is empty — preserving\n * the @ApplyContract arm's strict policy, unified across both route arms.\n * Returns undefined when no `@As` decorator is present.\n */\nfunction readAsDecorator(\n node: ClassDeclaration | MethodDeclaration,\n label: string,\n): string | undefined {\n const asDecorator = node.getDecorator('As');\n if (!asDecorator) return undefined;\n const asName = decoratorStringArg(asDecorator.getArguments()[0]);\n if (!asName) {\n throw new Error(`@As decorator on ${label} must have a non-empty string argument.`);\n }\n return asName;\n}\n\n/**\n * Build a {@link RouteDescriptor} and register its name for collision detection.\n * Throws on a duplicate route name across the file's contracted/plain routes.\n */\nfunction buildRoute(args: {\n className: string;\n methodName: string;\n resolvedMethod: string;\n combinedPath: string;\n classAs: string | undefined;\n methodAs: string | undefined;\n sourceFile: SourceFile;\n seenNames: Map<string, string>;\n contractSource: ContractSource;\n}): RouteDescriptor {\n const {\n className,\n methodName,\n resolvedMethod,\n combinedPath,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource,\n } = args;\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // Collision detection across routes in the same file.\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 return {\n method: resolvedMethod,\n path: combinedPath,\n name: routeName,\n params: extractParams(combinedPath),\n controllerRef: { className, methodName, filePath: sourceFile.getFilePath() },\n contract: { contractSource },\n };\n}\n\n/**\n * Build a route from an `@ApplyContract` method. Returns null when the contract\n * cannot be resolved or the method lacks an HTTP verb decorator.\n */\nfunction extractContractRoute(args: {\n cls: ClassDeclaration;\n method: MethodDeclaration;\n applyContractDecorator: import('ts-morph').Decorator;\n verb: ResolvedVerb | null;\n prefix: string;\n className: string;\n sourceFile: SourceFile;\n seenNames: Map<string, string>;\n}): RouteDescriptor | null {\n const { cls, method, applyContractDecorator, verb, prefix, className, sourceFile, seenNames } =\n args;\n\n const firstDecoratorArg = applyContractDecorator.getArguments()[0];\n if (!firstDecoratorArg) return null;\n\n // Resolve contract definition from inline call or identifier.\n let contractDef: ParsedContractDef | null = null;\n // When the contract is a named const we can import, re-export its members\n // (`<const>.body` / `<const>.query`) for perfect parity.\n let bodyZodRef: TypeRef | null = null;\n let queryZodRef: TypeRef | 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-codegen/fast] Cannot resolve '${identName}' in ${sourceFile.getFilePath()} (cross-file imports are out-of-scope for v1) — skipping`,\n );\n return null;\n }\n\n const initializer = varDecl.getInitializer();\n if (!initializer) return null;\n\n contractDef = parseDefineContractCall(initializer);\n // Re-export the named contract's schema members (Path A). Only when the\n // const is exported so forms.ts can import it.\n if (contractDef && varDecl.isExported()) {\n const filePath = sourceFile.getFilePath();\n if (contractDef.body !== null) {\n bodyZodRef = { name: `${identName}.body`, filePath };\n }\n if (contractDef.query !== null) {\n queryZodRef = { name: `${identName}.query`, filePath };\n }\n }\n } else {\n console.warn(\n `[nestjs-codegen/fast] @ApplyContract arg is not an identifier or call expression in ${sourceFile.getFilePath()} — skipping`,\n );\n return null;\n }\n\n if (!contractDef) return null;\n\n // Method + path always come from NestJS decorators — skip if absent.\n if (!verb) return null;\n const resolvedPath = joinPaths(prefix, verb.handlerPath);\n const methodName = method.getName();\n\n const classAs = readAsDecorator(cls, `class ${className}`);\n const methodAs = readAsDecorator(method, `${className}.${methodName}`);\n\n return buildRoute({\n className,\n methodName,\n resolvedMethod: verb.httpMethod,\n combinedPath: resolvedPath,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource: {\n query: contractDef.query,\n body: contractDef.body,\n response: contractDef.response,\n // Path A: capture both the importable ref and the raw text. The emitter\n // prefers inlining the text (client-safe — re-exporting from a controller\n // would drag server-only deps into the client bundle).\n bodyZodRef,\n bodyZodText: contractDef.bodyZodText,\n queryZodRef,\n queryZodText: contractDef.queryZodText,\n },\n });\n}\n\n/**\n * Build a route from a plain HTTP-verb method (no `@ApplyContract`), extracting\n * any DTO-based contract info. Returns null when the method lacks a verb.\n */\nfunction extractDtoRoute(args: {\n cls: ClassDeclaration;\n method: MethodDeclaration;\n verb: ResolvedVerb | null;\n prefix: string;\n className: string;\n sourceFile: SourceFile;\n project: Project;\n seenNames: Map<string, string>;\n}): RouteDescriptor | null {\n const { cls, method, verb, prefix, className, sourceFile, project, seenNames } = args;\n\n if (!verb) return null;\n\n const combined = joinPaths(prefix, verb.handlerPath);\n const methodName = method.getName();\n\n const classAs = readAsDecorator(cls, `class ${className}`);\n const methodAs = readAsDecorator(method, `${className}.${methodName}`);\n\n const dtoContract = extractDtoContract(method, sourceFile, project);\n\n return buildRoute({\n className,\n methodName,\n resolvedMethod: verb.httpMethod,\n combinedPath: combined,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource: {\n query: dtoContract?.query ?? null,\n body: dtoContract?.body ?? null,\n response: dtoContract?.response ?? 'unknown',\n queryRef: dtoContract?.queryRef ?? null,\n bodyRef: dtoContract?.bodyRef ?? null,\n responseRef: dtoContract?.responseRef ?? null,\n filterFields: dtoContract?.filterFields ?? null,\n filterFieldTypes: dtoContract?.filterFieldTypes ?? null,\n filterSource: dtoContract?.filterSource ?? null,\n formWarnings: dtoContract?.formWarnings ?? [],\n bodySchema: dtoContract?.bodySchema ?? null,\n querySchema: dtoContract?.querySchema ?? null,\n },\n });\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 for (const cls of sourceFile.getClasses()) {\n // Find @Controller(...) decorator\n const controllerDecorator = cls.getDecorator('Controller');\n if (!controllerDecorator) continue;\n\n // Determine controller path prefix\n const firstArg = controllerDecorator.getArguments()[0];\n const prefix = decoratorStringArg(firstArg) ?? '';\n\n const className = cls.getName() ?? 'Unknown';\n\n for (const method of cls.getMethods()) {\n const verb = resolveVerb(method);\n const applyContractDecorator = method.getDecorator('ApplyContract');\n\n const route = applyContractDecorator\n ? extractContractRoute({\n cls,\n method,\n applyContractDecorator,\n verb,\n prefix,\n className,\n sourceFile,\n seenNames,\n })\n : extractDtoRoute({\n cls,\n method,\n verb,\n prefix,\n className,\n sourceFile,\n project,\n seenNames,\n });\n\n if (route) routes.push(route);\n }\n }\n\n return routes;\n}\n","import {\n type ClassDeclaration,\n type InterfaceDeclaration,\n type MethodDeclaration,\n Node,\n type Project,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport { extractSchemaFromDto } from './dto-to-ir.js';\nimport { extractApplyFilterInfo } from './filter-for.js';\nimport {\n type TypeDeclResult,\n dbg,\n findType,\n resolveImportedType,\n resolveTypeRef,\n} from './type-ref-resolution.js';\nimport type { FilterFieldType, TypeRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// DTO-based contract extraction (standard NestJS patterns — no defineContract)\n// ---------------------------------------------------------------------------\n\n/**\n * Wrapper type names whose wire shape reduces to their first type argument.\n * - `unwrap` → emit the type-arg as-is (e.g. Promise<T> → T)\n * - `arrayOf` → wrap the type-arg in `Array<>` (e.g. Collection<T> → Array<T>)\n */\nconst WRAPPER_TYPES: Record<string, 'unwrap' | 'arrayOf'> = {\n // MikroORM Ref/Reference/LoadedReference/IdentifiedReference are server-side\n // wrappers around related entities; the wire shape is just the referenced\n // entity. Unwrap to the type argument.\n Ref: 'unwrap',\n Reference: 'unwrap',\n LoadedReference: 'unwrap',\n IdentifiedReference: 'unwrap',\n // MikroORM Opt<T> is a marker, Loaded<T, ...> is a wrapper; both reduce to T.\n Opt: 'unwrap',\n Loaded: 'unwrap',\n // Promise<T> — unwrap\n Promise: 'unwrap',\n // MikroORM Collection<T> serializes as an array of T on the wire.\n Collection: 'arrayOf',\n // Array<T> generic form\n Array: 'arrayOf',\n};\n\n/** Well-known utility types — preserve full text with type args. */\nconst PASSTHROUGH_UTILITY = new Set([\n 'Record',\n 'Omit',\n 'Pick',\n 'Partial',\n 'Required',\n 'Readonly',\n 'Map',\n 'Set',\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 // Union: A | B | C — resolve each member so named refs get inlined\n if (Node.isUnionTypeNode(typeNode)) {\n return typeNode\n .getTypeNodes()\n .map((t) => resolveTypeNodeToString(t, sourceFile, project, depth))\n .join(' | ');\n }\n\n // Intersection: A & B — same treatment\n if (Node.isIntersectionTypeNode(typeNode)) {\n return typeNode\n .getTypeNodes()\n .map((t) => resolveTypeNodeToString(t, sourceFile, project, depth))\n .join(' & ');\n }\n\n // Parenthesized: ( ... ) — unwrap\n if (Node.isParenthesizedTypeNode(typeNode)) {\n return `(${resolveTypeNodeToString(typeNode.getTypeNode(), 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' || name === 'void') return 'unknown';\n // Server-only types that don't make sense on the client\n if (name === 'StreamableFile' || name === 'Observable' || name === 'ReadableStream')\n return 'unknown';\n\n // Known wrapper types — unwrap (or array-wrap) their first type argument.\n const wrapperMode = WRAPPER_TYPES[name];\n if (wrapperMode) {\n return unwrapFirstTypeArg(typeNode, sourceFile, project, depth, wrapperMode);\n }\n\n // Well-known utility types — preserve full text with type args\n if (PASSTHROUGH_UTILITY.has(name)) {\n return typeNode.getText();\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 // Unresolvable type — use unknown instead of bare name to avoid TS errors in generated code\n dbg('unresolvable type:', name, 'in', sourceFile.getFilePath());\n return 'unknown';\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 * Unwrap the first type argument of a wrapper TypeReference. In `unwrap` mode\n * the type-arg is emitted as-is; in `arrayOf` mode it is wrapped in `Array<>`.\n * Falls back to `'unknown'` / `'Array<unknown>'` when no type-arg is present.\n */\nfunction unwrapFirstTypeArg(\n typeNode: import('ts-morph').TypeReferenceNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n mode: 'unwrap' | 'arrayOf',\n): string {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n const inner = resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);\n return mode === 'arrayOf' ? `Array<${inner}>` : inner;\n }\n return mode === 'arrayOf' ? 'Array<unknown>' : 'unknown';\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 // Recursively resolve the alias body so that any named types it\n // references (e.g. `A | B | C`) are expanded inline rather than left\n // as bare identifiers, which would be undefined in the emitted code.\n if (result.typeNode) {\n return resolveTypeNodeToString(result.typeNode, result.file, project, depth);\n }\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(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): 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(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): 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(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): 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\n ? resolveTypeNodeToString(typeNode, sourceFile, project, 3)\n : '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(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): 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(\n node: Node,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): 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 * Resolve a `@Body()` / `@Query()` param or return-type `TypeNode` to a named\n * exported class/interface ref (unwrapping `Promise<T>` / `Array<T>` / `T[]`).\n * Thin wrapper over the shared {@link resolveTypeRef}.\n */\nfunction resolveBodyQueryResponseRef(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n): TypeRef | null {\n return resolveTypeRef(typeNode, sourceFile, project, {\n kinds: ['class', 'interface'],\n unwrapContainers: true,\n });\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): {\n query: string | null;\n body: string | null;\n response: string;\n params: string | null;\n queryRef?: TypeRef | null;\n bodyRef?: TypeRef | null;\n responseRef?: TypeRef | null;\n filterFields?: string[] | null;\n filterFieldTypes?: FilterFieldType[] | null;\n filterSource?: 'body' | 'query' | null;\n formWarnings?: string[];\n bodySchema?: import('../ir/schema-node.js').SchemaModule | null;\n querySchema?: import('../ir/schema-node.js').SchemaModule | null;\n} | null {\n let body = extractBodyType(method, sourceFile, project);\n const filterInfo = extractApplyFilterInfo(method, sourceFile, project);\n const query = extractQueryType(method, sourceFile, project);\n\n // Place filter type on the correct field based on @ApplyFilter source. The\n // body-source case still pre-renders a fixed `FilterQueryResult` here; the\n // query-source TypedFilterQuery TYPE is rendered in emit-api.ts (from\n // filterFields + filterFieldTypes) so it is byte-identical to the\n // `_filterQueryTyped<...>` factory args.\n if (filterInfo && filterInfo.source === 'body') {\n const bodyType = \"import('@dudousxd/nestjs-filter-client').FilterQueryResult\";\n body = body ?? bodyType;\n }\n\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. A query-source\n // `@ApplyFilter` route carries no pre-rendered `query` string anymore (the\n // TypedFilterQuery type is rendered in emit-api), so it must be kept alive via\n // `filterInfo` even when every other field is empty.\n if (\n body === null &&\n query === null &&\n paramsType === null &&\n response === 'unknown' &&\n filterInfo === null\n ) {\n return null;\n }\n\n // Capture type references for import generation\n let bodyRef: TypeRef | null = null;\n let queryRef: TypeRef | null = null;\n let responseRef: TypeRef | null = null;\n\n for (const param of method.getParameters()) {\n if (param.getDecorators().some((d) => d.getName() === 'Body') && param.getTypeNode()) {\n bodyRef = resolveBodyQueryResponseRef(param.getTypeNode()!, sourceFile, project);\n }\n if (param.getDecorators().some((d) => d.getName() === 'Query') && param.getTypeNode()) {\n queryRef = resolveBodyQueryResponseRef(param.getTypeNode()!, sourceFile, project);\n }\n }\n\n const returnTypeNode = method.getReturnTypeNode();\n if (returnTypeNode) {\n responseRef = resolveBodyQueryResponseRef(returnTypeNode, sourceFile, project);\n }\n // Also check @ApiResponse\n if (!responseRef) {\n const apiResp = method.getDecorator('ApiResponse');\n if (apiResp) {\n const args = apiResp.getArguments();\n const optsArg = args[0];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n for (const prop of optsArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'type') {\n const val = prop.getInitializer();\n if (val && Node.isIdentifier(val)) {\n const name = val.getText();\n const localDecl =\n sourceFile.getInterface(name) ||\n sourceFile.getClass(name) ||\n sourceFile.getTypeAlias(name);\n if (localDecl?.isExported()) {\n responseRef = { name, filePath: sourceFile.getFilePath() };\n } else {\n const resolved = resolveImportedType(name, sourceFile, project);\n if (\n resolved &&\n (resolved.kind === 'class' || resolved.kind === 'interface') &&\n resolved.decl.isExported()\n ) {\n responseRef = { name, filePath: resolved.file.getFilePath() };\n }\n }\n }\n }\n }\n }\n }\n }\n\n // ── Synthesize the neutral validation IR from class-validator DTOs (Path B) ─\n // Resolve the @Body()/@Query() param to a class declaration and translate its\n // decorators into the neutral IR, which emit-forms renders via any adapter\n // (zod included). A defineContract schema always wins, so this only runs on\n // the plain-verb path where no contract schema is present.\n let bodySchema: import('../ir/schema-node.js').SchemaModule | null = null;\n let querySchema: import('../ir/schema-node.js').SchemaModule | null = null;\n const formWarnings: string[] = [];\n\n const bodyClass = resolveParamClass(method, 'Body', sourceFile, project);\n if (bodyClass) {\n bodySchema = extractSchemaFromDto(bodyClass.decl, bodyClass.file, project);\n formWarnings.push(...bodySchema.warnings);\n }\n const queryClass = resolveParamClass(method, 'Query', sourceFile, project);\n if (queryClass) {\n querySchema = extractSchemaFromDto(queryClass.decl, queryClass.file, project);\n formWarnings.push(...querySchema.warnings);\n }\n\n return {\n query,\n body,\n response,\n params: paramsType,\n queryRef,\n bodyRef,\n responseRef,\n filterFields: filterInfo?.fieldNames ?? null,\n filterFieldTypes: filterInfo?.fieldTypes ?? null,\n filterSource: filterInfo?.source ?? null,\n formWarnings,\n bodySchema,\n querySchema,\n };\n}\n\n/**\n * Resolve a `@Body()` / `@Query()` parameter's TS type to a class declaration\n * (following imports). Returns null for interfaces / plain types / unresolved.\n */\nfunction resolveParamClass(\n method: MethodDeclaration,\n decoratorName: 'Body' | 'Query',\n sourceFile: SourceFile,\n project: Project,\n): { decl: ClassDeclaration; file: SourceFile } | null {\n for (const param of method.getParameters()) {\n if (!param.getDecorators().some((d) => d.getName() === decoratorName)) continue;\n const typeNode = param.getTypeNode();\n if (!typeNode) continue;\n // Strip array suffix — translate the element class.\n const text = typeNode.getText().replace(/\\[\\]$/, '');\n if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(text)) continue;\n const resolved = findType(text, sourceFile, project);\n if (resolved && resolved.kind === 'class') {\n return { decl: resolved.decl, file: resolved.file };\n }\n }\n return null;\n}\n","/**\n * Pure-AST translation of class-validator-decorated DTO classes into the neutral\n * {@link SchemaModule} IR. Reads decorator names + literal args via ts-morph — it\n * never imports class-validator at runtime. A `ValidationAdapter` renders the IR.\n *\n * This is the sole DTO translator: it emits neutral `SchemaNode` IR (replacing\n * the former `dto-to-zod.ts` text path). A `ValidationAdapter` renders the IR;\n * the bundled zod adapter reproduces the original zod-text output byte-for-byte.\n */\nimport {\n type ClassDeclaration,\n type Decorator,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport type { NumberCheck, SchemaModule, SchemaNode, StringCheck } from '../ir/schema-node.js';\nimport { findType } from './type-ref-resolution.js';\n\ninterface BuildContext {\n sourceFile: SourceFile;\n project: Project;\n named: Map<string, SchemaNode>;\n warnings: string[];\n warnedDecorators: Set<string>;\n emittedClasses: Map<string, string>;\n visiting: Set<string>;\n recursiveSchemas: Set<string>;\n depth: number;\n}\n\nconst KNOWN_DECORATORS = new Set([\n 'IsString',\n 'IsNumber',\n 'IsInt',\n 'IsBoolean',\n 'IsDate',\n 'IsEmail',\n 'IsUrl',\n 'IsUUID',\n 'MinLength',\n 'MaxLength',\n 'Length',\n 'Min',\n 'Max',\n 'IsPositive',\n 'IsNegative',\n 'Matches',\n 'IsEnum',\n 'IsIn',\n 'IsOptional',\n 'IsNotEmpty',\n 'IsArray',\n 'ValidateNested',\n 'Type',\n 'IsObject',\n 'Allow',\n 'IsDefined',\n]);\n\nexport function extractSchemaFromDto(\n classDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): SchemaModule {\n const ctx: BuildContext = {\n sourceFile,\n project,\n named: new Map(),\n warnings: [],\n warnedDecorators: new Set(),\n emittedClasses: new Map(),\n visiting: new Set(),\n recursiveSchemas: new Set(),\n depth: 0,\n };\n const root = buildObject(classDecl, sourceFile, ctx);\n // Recursive schemas cannot be hoisted as a plain `const X = (... X ...)` without\n // a type annotation. Degrade any self-referential nested schema to a neutral\n // `unknown` placeholder; each adapter renders its own lib's `unknown` + comment.\n for (const schemaName of ctx.recursiveSchemas) {\n ctx.named.set(schemaName, { kind: 'unknown', note: 'recursive type — not expanded' });\n }\n return { root, named: ctx.named, warnings: ctx.warnings };\n}\n\n// ---------------------------------------------------------------------------\n// Object builder\n// ---------------------------------------------------------------------------\n\nfunction buildObject(\n classDecl: ClassDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n const props = classDecl.getProperties();\n if (props.length === 0) {\n return { kind: 'object', fields: [], passthrough: true };\n }\n const fields: Array<{ key: string; value: SchemaNode }> = [];\n for (const prop of props) {\n fields.push({ key: prop.getName(), value: buildProperty(prop, classFile, ctx) });\n }\n return { kind: 'object', fields, passthrough: false };\n}\n\n// ---------------------------------------------------------------------------\n// Property builder — the §2.2 mapping table lives here.\n// ---------------------------------------------------------------------------\n\nfunction buildProperty(\n prop: PropertyDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n const decorators = new Map<string, Decorator>();\n for (const d of prop.getDecorators()) decorators.set(d.getName(), d);\n const has = (n: string): boolean => decorators.has(n);\n const dec = (n: string): Decorator | undefined => decorators.get(n);\n\n const typeNode = prop.getTypeNode();\n const typeText = typeNode?.getText() ?? 'unknown';\n const isArrayType = !!typeNode && typeNode.getText().endsWith('[]');\n\n // ── Nested / array-of-nested via @ValidateNested + @Type ────────────────\n const typeRefName = resolveTypeFactoryName(dec('Type'));\n if (has('ValidateNested') || typeRefName) {\n const childName = typeRefName ?? singularClassName(typeText);\n if (childName) {\n const childNode = buildNestedReference(childName, classFile, ctx);\n const wrapArray = has('IsArray') || isArrayType;\n const node: SchemaNode = wrapArray ? { kind: 'array', element: childNode } : childNode;\n return applyPresence(node, decorators);\n }\n }\n\n // ── Base type (TS property type), then decorator refinements ────────────\n let base = baseFromType(typeText, isArrayType);\n const stringChecks: StringCheck[] = [];\n const numberChecks: NumberCheck[] = [];\n\n // Type overrides\n if (has('IsString')) base = { kind: 'string', checks: stringChecks };\n if (has('IsBoolean')) base = { kind: 'boolean' };\n if (has('IsDate')) base = { kind: 'date' };\n if (has('IsNumber')) base = { kind: 'number', checks: numberChecks };\n if (has('IsInt')) {\n base = { kind: 'number', checks: numberChecks };\n numberChecks.push({ check: 'int' });\n }\n if (has('IsObject') && !has('ValidateNested')) {\n base = { kind: 'object', fields: [], passthrough: true };\n }\n if (has('Allow')) base = { kind: 'unknown' };\n\n const ensureString = (): void => {\n if (base.kind !== 'string') base = { kind: 'string', checks: stringChecks };\n };\n\n // String format refinements (these also imply string base).\n if (has('IsEmail')) {\n ensureString();\n const m = messageRaw(dec('IsEmail'));\n stringChecks.push(m === undefined ? { check: 'email' } : { check: 'email', messageRaw: m });\n }\n if (has('IsUrl')) {\n ensureString();\n const m = messageRaw(dec('IsUrl'));\n stringChecks.push(m === undefined ? { check: 'url' } : { check: 'url', messageRaw: m });\n }\n if (has('IsUUID')) {\n ensureString();\n const m = messageRaw(dec('IsUUID'));\n stringChecks.push(m === undefined ? { check: 'uuid' } : { check: 'uuid', messageRaw: m });\n }\n if (has('Matches')) {\n const re = firstArgText(dec('Matches'));\n if (re) {\n ensureString();\n stringChecks.push({ check: 'regex', pattern: re });\n }\n }\n\n // Length / size refinements\n if (has('MinLength')) {\n const n = numericArg(dec('MinLength'));\n if (n !== null) stringChecks.push({ check: 'min', value: n });\n }\n if (has('MaxLength')) {\n const n = numericArg(dec('MaxLength'));\n if (n !== null) stringChecks.push({ check: 'max', value: n });\n }\n if (has('Length')) {\n const [min, max] = numericArgs(dec('Length'));\n if (min !== null) stringChecks.push({ check: 'min', value: min });\n if (max !== null) stringChecks.push({ check: 'max', value: max });\n }\n if (has('Min')) {\n const n = numericArg(dec('Min'));\n if (n !== null) numberChecks.push({ check: 'min', value: n });\n }\n if (has('Max')) {\n const n = numericArg(dec('Max'));\n if (n !== null) numberChecks.push({ check: 'max', value: n });\n }\n if (has('IsPositive')) numberChecks.push({ check: 'positive' });\n if (has('IsNegative')) numberChecks.push({ check: 'negative' });\n if (has('IsNotEmpty') && base.kind === 'string') stringChecks.push({ check: 'min', value: '1' });\n\n // Enum / membership (replaces base).\n if (has('IsEnum')) {\n const enumNode = enumSchemaFromDecorator(dec('IsEnum'), classFile, ctx);\n if (enumNode) base = enumNode;\n }\n if (has('IsIn')) {\n const inNode = inSchemaFromDecorator(dec('IsIn'));\n if (inNode) base = inNode;\n }\n\n // ── Unmappable decorators → warn + comment, keep base ───────────────────\n const unmappable: string[] = [];\n for (const name of decorators.keys()) {\n if (!KNOWN_DECORATORS.has(name)) {\n unmappable.push(name);\n if (!ctx.warnedDecorators.has(name)) {\n ctx.warnedDecorators.add(name);\n const msg = `@${name} is not translatable to a client validation schema and was skipped (server-only validation).`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n }\n }\n\n // Attach the collected refinements to the base. `base` may have been created\n // by `baseFromType` (with its own empty checks array) or by an override, so\n // rebuild it here to guarantee the accumulated checks are the ones emitted.\n if (base.kind === 'string') base = { kind: 'string', checks: stringChecks };\n else if (base.kind === 'number') base = { kind: 'number', checks: numberChecks };\n\n let node: SchemaNode = base;\n\n // Array wrapping when the TS type is `T[]` and no nested handling occurred.\n if (isArrayType && node.kind !== 'array') {\n node = { kind: 'array', element: node };\n }\n\n node = applyPresence(node, decorators);\n\n if (unmappable.length > 0) {\n node = { kind: 'annotated', inner: node, unmappable };\n }\n return node;\n}\n\n/** `.optional()` / required handling from @IsOptional / @IsDefined. */\nfunction applyPresence(node: SchemaNode, decorators: Map<string, Decorator>): SchemaNode {\n if (decorators.has('IsDefined')) return node; // explicitly required\n if (decorators.has('IsOptional')) return { kind: 'optional', inner: node };\n return node;\n}\n\n// ---------------------------------------------------------------------------\n// Base type from the TS property type\n// ---------------------------------------------------------------------------\n\nfunction baseFromType(typeText: string, isArrayType: boolean): SchemaNode {\n const inner = isArrayType ? typeText.slice(0, -2).trim() : typeText;\n switch (inner) {\n case 'string':\n return { kind: 'string', checks: [] };\n case 'number':\n return { kind: 'number', checks: [] };\n case 'boolean':\n return { kind: 'boolean' };\n case 'Date':\n return { kind: 'date' };\n case 'File':\n case 'Express.Multer.File':\n return { kind: 'instanceof', ctor: 'File' };\n default:\n return { kind: 'unknown' };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nested DTO references (hoisted named consts)\n// ---------------------------------------------------------------------------\n\nfunction buildNestedReference(\n className: string,\n fromFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n // Recursion guard FIRST.\n if (ctx.visiting.has(className) || ctx.depth >= 8) {\n const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);\n ctx.emittedClasses.set(className, reserved);\n ctx.recursiveSchemas.add(reserved);\n if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {\n ctx.warnedDecorators.add(`recursive:${reserved}`);\n const msg = `${className} is a recursive type and was not expanded; the generated schema uses unknown for it.`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'lazyRef', name: reserved };\n }\n\n const existing = ctx.emittedClasses.get(className);\n if (existing) return { kind: 'ref', name: existing };\n\n const schemaName = aliasFor(className, ctx);\n const resolved = findType(className, fromFile, ctx.project);\n if (!resolved || resolved.kind !== 'class') {\n return { kind: 'object', fields: [], passthrough: true };\n }\n\n ctx.emittedClasses.set(className, schemaName);\n ctx.visiting.add(className);\n ctx.depth += 1;\n const childNode = buildObject(resolved.decl, resolved.file, ctx);\n ctx.depth -= 1;\n ctx.visiting.delete(className);\n\n ctx.named.set(schemaName, childNode);\n return { kind: 'ref', name: schemaName };\n}\n\nfunction aliasFor(className: string, ctx: BuildContext): string {\n const baseName = `${className}Schema`;\n let candidate = baseName;\n let i = 1;\n const used = new Set(ctx.named.keys());\n for (const v of ctx.emittedClasses.values()) used.add(v);\n while (used.has(candidate)) {\n candidate = `${baseName}_${i}`;\n i += 1;\n }\n return candidate;\n}\n\n// ---------------------------------------------------------------------------\n// Decorator argument readers (pure AST)\n// ---------------------------------------------------------------------------\n\nfunction firstArg(decorator: Decorator | undefined): Node | undefined {\n return decorator?.getArguments()[0];\n}\n\nfunction firstArgText(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n return arg ? arg.getText() : null;\n}\n\nfunction numericArg(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (arg && Node.isNumericLiteral(arg)) return arg.getText();\n return null;\n}\n\nfunction numericArgs(decorator: Decorator | undefined): [string | null, string | null] {\n const args = decorator?.getArguments() ?? [];\n const num = (n: Node | undefined): string | null =>\n n && Node.isNumericLiteral(n) ? n.getText() : null;\n return [num(args[0]), num(args[1])];\n}\n\n/** Reads a `{ message: '...' }` options object → the verbatim message literal text. */\nfunction messageRaw(decorator: Decorator | undefined): string | undefined {\n const args = decorator?.getArguments() ?? [];\n for (const arg of args) {\n if (Node.isObjectLiteralExpression(arg)) {\n for (const prop of arg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'message') {\n const init = prop.getInitializer();\n if (init && Node.isStringLiteral(init)) return init.getText();\n }\n }\n }\n }\n return undefined;\n}\n\n/** Resolve `@Type(() => Child)` → `'Child'`. */\nfunction resolveTypeFactoryName(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) return body.getText();\n }\n return null;\n}\n\n/** Drop array suffix from a type text → class name (`Child[]` → `Child`). */\nfunction singularClassName(typeText: string): string | null {\n const inner = typeText.endsWith('[]') ? typeText.slice(0, -2).trim() : typeText;\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(inner) ? inner : null;\n}\n\n/** `@IsEnum(E)` → enum node (or verbatim fallback when unresolvable). */\nfunction enumSchemaFromDecorator(\n decorator: Decorator | undefined,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isIdentifier(arg)) {\n const name = arg.getText();\n const resolved = findType(name, classFile, ctx.project);\n if (resolved && resolved.kind === 'enum') {\n return { kind: 'enum', literals: resolved.members };\n }\n const msg = `@IsEnum(${name}): enum could not be resolved to literal members and is not importable into the generated schema; falling back to unknown.`;\n if (!ctx.warnedDecorators.has(`IsEnum:${name}`)) {\n ctx.warnedDecorators.add(`IsEnum:${name}`);\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'unknown', note: `@IsEnum(${name}): enum not resolvable to literals` };\n }\n if (Node.isObjectLiteralExpression(arg)) {\n const values: string[] = [];\n for (const p of arg.getProperties()) {\n if (!Node.isPropertyAssignment(p)) continue;\n const init = p.getInitializer();\n if (init && Node.isStringLiteral(init)) values.push(init.getText());\n }\n if (values.length > 0) return { kind: 'enum', literals: values };\n }\n return null;\n}\n\n/** `@IsIn(['a','b'])` → enum node; non-string members → union of literals. */\nfunction inSchemaFromDecorator(decorator: Decorator | undefined): SchemaNode | null {\n const arg = firstArg(decorator);\n if (arg && Node.isArrayLiteralExpression(arg)) {\n const elements = arg.getElements();\n const allStrings = elements.every((e) => Node.isStringLiteral(e));\n if (allStrings && elements.length > 0) {\n return { kind: 'enum', literals: elements.map((e) => e.getText()) };\n }\n if (elements.length > 0) {\n return {\n kind: 'union',\n options: elements.map((e) => ({ kind: 'literal', raw: e.getText() })),\n };\n }\n }\n return null;\n}\n","import { readFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport {\n type ClassDeclaration,\n type InterfaceDeclaration,\n Node,\n type Project,\n type SourceFile,\n type TypeNode,\n} from 'ts-morph';\nimport type { TypeRef } from './types.js';\n\n/**\n * Type-reference resolution: the leaf module of the discovery DAG. Owns the\n * per-invocation discovery context (project root + tsconfig path aliases) and\n * the \"follow a name/TypeNode to its declaring file\" machinery shared by every\n * other discovery module.\n */\n\n// ---------------------------------------------------------------------------\n// Discovery context — scoped per `discoverContractsFast` invocation.\n// Keyed off the per-invocation ts-morph `Project` (every resolution entry point\n// already threads it), so concurrent invocations each get an isolated context\n// with no shared mutable global to corrupt.\n// ---------------------------------------------------------------------------\n\nexport interface DiscoveryContext {\n projectRoot: string;\n tsconfigPaths: Record<string, string[]> | null;\n}\n\nconst _EMPTY_CTX: DiscoveryContext = { projectRoot: '', tsconfigPaths: null };\n\n/** Per-`Project` discovery context. WeakMap so contexts die with their project. */\nconst _ctxByProject = new WeakMap<Project, DiscoveryContext>();\n\n/** Associate a discovery context with a `Project` for the duration of a run. */\nexport function setDiscoveryContext(project: Project, ctx: DiscoveryContext): void {\n _ctxByProject.set(project, ctx);\n}\n\nfunction _ctxFor(project: Project): DiscoveryContext {\n return _ctxByProject.get(project) ?? _EMPTY_CTX;\n}\n\nconst _debug = process.env.NESTJS_INERTIA_DEBUG === '1';\nexport function dbg(...args: unknown[]) {\n if (_debug) console.log('[codegen:debug]', ...args);\n}\n\nexport function loadTsconfigPaths(tsconfigPath: string): Record<string, string[]> | null {\n try {\n const raw = readFileSync(tsconfigPath, 'utf8');\n // Strip single-line comments (tsconfig allows them)\n const stripped = raw.replace(/\\/\\/.*$/gm, '');\n const parsed = JSON.parse(stripped) as {\n compilerOptions?: { paths?: Record<string, string[]> };\n };\n return parsed.compilerOptions?.paths ?? null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type-declaration lookup\n// ---------------------------------------------------------------------------\n\nexport type TypeDeclResult =\n | { kind: 'class'; decl: ClassDeclaration; file: SourceFile }\n | { kind: 'interface'; decl: InterfaceDeclaration; file: SourceFile }\n | { kind: 'typeAlias'; typeNode: TypeNode | undefined; file: SourceFile; 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 */\nexport function 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 {\n kind: 'typeAlias',\n typeNode,\n file,\n text: typeNode ? typeNode.getText() : 'unknown',\n };\n }\n\n const enumDecl = file.getEnum(name);\n if (enumDecl) {\n const members = enumDecl.getMembers().map((m) => {\n const val = m.getValue();\n // String value → quoted literal (\"active\"); numeric value → numeric\n // literal (1). Fall back to the member NAME only when the value can't be\n // resolved statically (e.g. a computed member).\n if (typeof val === 'string' || typeof val === 'number') return JSON.stringify(val);\n return 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 */\nexport function resolveModuleSpecifier(\n moduleSpecifier: string,\n sourceFile: SourceFile,\n project: Project,\n): string[] {\n if (moduleSpecifier.startsWith('.')) {\n const dir = dirname(sourceFile.getFilePath());\n // Strip an explicit ESM `.js`/`.ts` extension so `./x.dto.js` resolves to\n // `./x.dto.ts` (NodeNext import style).\n const noExt = moduleSpecifier.replace(/\\.(js|ts)$/, '');\n return [\n resolve(dir, `${noExt}.ts`),\n resolve(dir, `${moduleSpecifier}.ts`),\n resolve(dir, moduleSpecifier, 'index.ts'),\n ];\n }\n\n // Try to resolve path aliases via tsconfig paths (read directly from JSON)\n const ctx = _ctxFor(project);\n const baseUrl = ctx.projectRoot;\n const tsconfigPaths = ctx.tsconfigPaths;\n\n dbg(\n 'resolveModuleSpecifier',\n moduleSpecifier,\n 'paths:',\n JSON.stringify(tsconfigPaths),\n 'baseUrl:',\n baseUrl,\n );\n\n if (tsconfigPaths) {\n for (const [pattern, mappings] of Object.entries(tsconfigPaths)) {\n const prefix = pattern.replace('*', '');\n if (moduleSpecifier.startsWith(prefix)) {\n const rest = moduleSpecifier.slice(prefix.length);\n const candidates: string[] = [];\n for (const mapping of mappings) {\n const resolved = resolve(baseUrl, mapping.replace('*', rest));\n candidates.push(`${resolved}.ts`, resolve(resolved, 'index.ts'));\n }\n dbg(' resolved candidates:', candidates);\n return candidates;\n }\n }\n }\n\n return [];\n}\n\nexport function 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 const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);\n if (candidates.length === 0) continue;\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 // The target module may itself re-export the symbol from elsewhere\n // (`export { X } from './mod'` or `import { X } ...; export { X }`).\n const viaReExport = resolveReExportedType(name, importedFile, project, new Set());\n if (viaReExport) return viaReExport;\n }\n }\n // The current file may re-export the symbol from another module.\n return resolveReExportedType(name, sourceFile, project, new Set());\n}\n\n/**\n * Follow `export { X } from './mod'` / `export * from './mod'` re-exports, and\n * bare `export { X }` statements that re-publish a previously-imported symbol,\n * to find a type declaration in a sibling module. Guards against import cycles\n * via `seen`.\n */\nfunction resolveReExportedType(\n name: string,\n file: SourceFile,\n project: Project,\n seen: Set<string>,\n): TypeDeclResult | null {\n const filePath = file.getFilePath();\n if (seen.has(filePath)) return null;\n seen.add(filePath);\n\n for (const exportDecl of file.getExportDeclarations()) {\n const moduleSpecifier = exportDecl.getModuleSpecifierValue();\n const namedExports = exportDecl.getNamedExports();\n\n // `export { X } from './mod'` — only follow when X (or its alias source) matches.\n if (moduleSpecifier) {\n const hasStar = namedExports.length === 0; // `export * from './mod'`\n const reExportsName = namedExports.some(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!hasStar && !reExportsName) continue;\n // The source-side name (before any alias rename).\n const sourceName = hasStar\n ? name\n : (namedExports\n .find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)\n ?.getName() ?? name);\n const target = followModuleForType(sourceName, moduleSpecifier, file, project, seen);\n if (target) return target;\n continue;\n }\n\n // `export { X }` (no module specifier) — X was imported above into this file.\n const reExportsName = namedExports.some(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!reExportsName) continue;\n const sourceName =\n namedExports.find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)?.getName() ??\n name;\n const local = findTypeInFile(sourceName, file);\n if (local) return local;\n const imported = resolveImportedType(sourceName, file, project);\n if (imported) return imported;\n }\n return null;\n}\n\nfunction followModuleForType(\n name: string,\n moduleSpecifier: string,\n fromFile: SourceFile,\n project: Project,\n seen: Set<string>,\n): TypeDeclResult | null {\n const candidates = resolveModuleSpecifier(moduleSpecifier, fromFile, project);\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 const viaReExport = resolveReExportedType(name, importedFile, project, seen);\n if (viaReExport) return viaReExport;\n }\n return null;\n}\n\n/**\n * Find a type declaration by name: first in the current file, then by following imports.\n */\nexport function 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// Importable named-ref resolution\n// ---------------------------------------------------------------------------\n\n/** The declaration kinds a `resolveTypeRef` call will accept as an importable ref. */\nexport type TypeRefKind = 'class' | 'interface' | 'typeAlias' | 'enum';\n\nexport interface ResolveTypeRefOptions {\n /**\n * Declaration kinds accepted as an importable named ref (applied identically\n * to local and imported declarations). The two call sites differ only here:\n * - body/query/response refs accept class + interface;\n * - `@FilterFor` param refs also accept enum + type alias.\n */\n kinds: TypeRefKind[];\n /**\n * Honour a bare (node_modules) import specifier — emit `{ name, filePath: spec }`\n * so the emitter imports straight from the package. tsconfig path aliases are\n * excluded (they resolve to files instead). Off for the body/query/response\n * path (which only ever points at project source files).\n */\n allowBareSpecifier?: boolean;\n /**\n * Unwrap `Promise<T>`, `Array<T>` and `T[]` to the inner named type (marking\n * array forms with `isArray`). Used for the body/query/response path which\n * receives a raw return/param `TypeNode`; the `@FilterFor` path passes a bare\n * symbol name and needs no unwrapping.\n */\n unwrapContainers?: boolean;\n}\n\n/** Skip-list of primitive / well-known names that never resolve to a named ref. */\nconst _NON_REF_NAMES = new Set(['string', 'number', 'boolean', 'void', 'unknown', 'any', 'Date']);\n\n/** Does an exported declaration found by `findTypeInFile` match the accepted kinds? */\nfunction _localDeclForKinds(name: string, file: SourceFile, kinds: TypeRefKind[]): boolean {\n if (kinds.includes('class') && file.getClass(name)?.isExported()) return true;\n if (kinds.includes('interface') && file.getInterface(name)?.isExported()) return true;\n if (kinds.includes('typeAlias') && file.getTypeAlias(name)?.isExported()) return true;\n if (kinds.includes('enum') && file.getEnum(name)?.isExported()) return true;\n return false;\n}\n\n/**\n * Resolve a type reference to an importable `TypeRef` — the symbol name plus the\n * absolute path of its declaring source file (for a relative import) OR the bare\n * module specifier (for a node_modules package). Accepts either a raw `TypeNode`\n * (with `unwrapContainers` to peel `Promise`/`Array`) or a bare symbol name.\n *\n * Walks: local exported decl → `{ name, thisFile }`; else the file's import\n * declarations to a matching exported decl → `{ name, importedFile }`. The\n * accepted declaration kinds (and bare-specifier / container-unwrap support) are\n * controlled by `opts`, letting both former resolvers share this one body.\n * Returns null when the symbol is not exported, not resolvable, or its import\n * path cannot be safely computed.\n */\nexport function resolveTypeRef(\n nodeOrName: TypeNode | string,\n sourceFile: SourceFile,\n project: Project,\n opts: ResolveTypeRefOptions,\n): TypeRef | null {\n // ── Resolve the bare symbol name (peeling containers for the TypeNode form) ──\n let name: string;\n if (typeof nodeOrName === 'string') {\n name = nodeOrName;\n } else {\n const typeNode = nodeOrName;\n\n if (opts.unwrapContainers && Node.isArrayTypeNode(typeNode)) {\n const inner = resolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project, opts);\n return inner ? { ...inner, isArray: true } : null;\n }\n\n if (!Node.isTypeReference(typeNode)) return null;\n const typeName = typeNode.getTypeName();\n const refName = Node.isIdentifier(typeName) ? typeName.getText() : null;\n if (!refName) return null;\n\n if (opts.unwrapContainers && refName === 'Promise') {\n const first = typeNode.getTypeArguments()[0];\n return first ? resolveTypeRef(first, sourceFile, project, opts) : null;\n }\n if (opts.unwrapContainers && refName === 'Array') {\n const first = typeNode.getTypeArguments()[0];\n if (!first) return null;\n const inner = resolveTypeRef(first, sourceFile, project, opts);\n return inner ? { ...inner, isArray: true } : null;\n }\n\n if (_NON_REF_NAMES.has(refName)) return null;\n name = refName;\n }\n\n // 1. Declared (and exported) in the current file → relative import to it.\n if (_localDeclForKinds(name, sourceFile, opts.kinds)) {\n return { name, filePath: sourceFile.getFilePath() };\n }\n\n // 2. Imported from another module — follow the import declaration.\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);\n if (!namedImport) continue;\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n\n // Bare specifier (node_modules package) → import directly by specifier.\n if (\n opts.allowBareSpecifier &&\n !moduleSpecifier.startsWith('.') &&\n !moduleSpecifier.startsWith('/')\n ) {\n // Only honour it if not a tsconfig path alias (those resolve to files).\n const tsconfigPaths = _ctxFor(project).tsconfigPaths;\n const isAlias =\n tsconfigPaths != null &&\n Object.keys(tsconfigPaths).some((p) => {\n const prefix = p.replace('*', '');\n return moduleSpecifier.startsWith(prefix);\n });\n if (!isAlias) {\n return { name, filePath: moduleSpecifier };\n }\n }\n\n // Local / aliased source file → resolve to its absolute path so the emitter\n // can compute a relative import from the generated output dir.\n const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);\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 if (_localDeclForKinds(name, importedFile, opts.kinds)) {\n return { name, filePath: importedFile.getFilePath() };\n }\n }\n }\n\n return null;\n}\n","import {\n type ClassDeclaration,\n type MethodDeclaration,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport {\n type ClassifyResult,\n classifyFieldType,\n classifyTypeNode,\n toFilterFieldType,\n} from './filter-field-types.js';\nimport { findType, resolveTypeRef } from './type-ref-resolution.js';\nimport type { FilterFieldType } from './types.js';\n\n/**\n * `@FilterFor` / `@ApplyFilter` discovery: resolve the virtual + entity-derived\n * filter fields (with their classified types) for a filter class referenced by\n * an `@ApplyFilter(FilterClass)` parameter.\n */\n\n/**\n * Map a single `@FilterFor` `type` hint token (read statically from the AST) to a\n * `ClassifyResult`. Supports the four primitive tokens plus a string-literal\n * array (enum) → literal string union. Returns null for anything unrecognised so\n * the caller falls back to the current permissive (`unknown`) behavior.\n */\nexport function classifyFilterForHint(typeInit: Node): ClassifyResult | null {\n // Primitive token: 'string' | 'number' | 'boolean' | 'Date'\n if (Node.isStringLiteral(typeInit)) {\n switch (typeInit.getLiteralValue()) {\n case 'string':\n return { kind: 'string' };\n case 'number':\n return { kind: 'number' };\n case 'boolean':\n return { kind: 'boolean' };\n case 'Date':\n return { kind: 'date' };\n default:\n return null;\n }\n }\n\n // Enum: a readonly array of string literals → literal string union.\n if (Node.isArrayLiteralExpression(typeInit)) {\n const values: string[] = [];\n for (const el of typeInit.getElements()) {\n if (!Node.isStringLiteral(el)) return null; // non-literal → bail to permissive\n values.push(el.getLiteralValue());\n }\n if (values.length === 0) return null;\n return { kind: 'string', enumValues: values };\n }\n\n return null;\n}\n\n/**\n * Classify the type of the FIRST parameter of a `@FilterFor` method (the new\n * primary inference mechanism). Precedence inside this function:\n * - primitive `number`/`string`/`boolean`/`Date` → emit directly.\n * - literal unions (`'a' | 'b'`, `1 | 2`) → emit the union text.\n * - named enum / type alias / interface → emit a `typeRef` (named import,\n * option B) when an import path is resolvable; otherwise fall back to\n * literal-union expansion for enums/unions, else skip.\n * - any/unknown/no-param/unresolvable → null (caller falls back).\n */\nexport function classifyFilterForParam(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult | null {\n const param = method.getParameters()[0];\n if (!param) return null;\n const typeNode = param.getTypeNode();\n if (!typeNode) return null;\n\n // Classify ONCE. `resolveRef` attaches an importable named ref (option B) when\n // the symbol resolves to an exported enum / type alias / interface / class with\n // a safe import path; the emitter prefers that `typeRef` over the `kind`. The\n // best-effort `kind` is still recorded so non-emit consumers (tests) see a\n // sensible classification.\n const wellKnown = ['string', 'number', 'boolean', 'Date', 'any', 'unknown'];\n const result = classifyTypeNode(typeNode, sourceFile, project, {\n resolveRef: (refName) => {\n if (wellKnown.includes(refName)) return null;\n // Only attempt a named import for symbols we can resolve to a declaration.\n if (!findType(refName, sourceFile, project)) return null;\n return resolveTypeRef(refName, sourceFile, project, {\n kinds: ['class', 'interface', 'typeAlias', 'enum'],\n allowBareSpecifier: true,\n });\n },\n });\n\n // A resolved `typeRef` is always usable (even with kind 'unknown' — the emitter\n // references the ref by name). Otherwise skip permissive `unknown` results.\n if (result.typeRef) return result;\n return result.kind === 'unknown' ? null : result;\n}\n\n/**\n * Discover virtual filter fields declared via `@FilterFor('key', { type })`\n * method decorators on the filter class. Field-type resolution precedence (high\n * wins): (1) explicit `{ type }` hint, (2) the method's first-parameter type\n * (named enums/aliases → real `import type` refs), (3+) fall back to existing\n * class-property / entity-column / `unknown` behavior (handled by the caller).\n *\n * Returns a map of inputKey → classified type for every `@FilterFor` that\n * carries a usable hint OR a usable first-parameter type. Keys with neither are\n * intentionally omitted here (they remain permissive / fall back).\n */\nexport function extractFilterForHints(\n classDecl: ClassDeclaration,\n project: Project,\n): Map<string, ClassifyResult> {\n const hints = new Map<string, ClassifyResult>();\n const sourceFile = classDecl.getSourceFile();\n for (const method of classDecl.getMethods()) {\n const filterForDec = method.getDecorators().find((d) => d.getName() === 'FilterFor');\n if (!filterForDec) continue;\n\n const args = filterForDec.getArguments();\n // inputKey: first string-literal arg, else the method name.\n const keyArg = args[0];\n const inputKey =\n keyArg && Node.isStringLiteral(keyArg) ? keyArg.getLiteralValue() : method.getName();\n\n // (1) Explicit `{ type }` hint — highest precedence, unchanged behavior.\n const optsArg = args[1];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n const typeProp = optsArg.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const typeInit = typeProp.getInitializer();\n if (typeInit) {\n const classified = classifyFilterForHint(typeInit);\n if (classified) {\n hints.set(inputKey, classified);\n continue;\n }\n }\n }\n }\n\n // (2) Method first-parameter type — the new primary inference mechanism.\n const fromParam = classifyFilterForParam(method, sourceFile, project);\n if (fromParam) hints.set(inputKey, fromParam);\n }\n return hints;\n}\n\n/**\n * Extract the filter field data from an `@ApplyFilter(FilterClass)` decorated\n * parameter. Resolves the filter class and reads its properties (excluding\n * inherited base class members). Returns the field names + classified types +\n * filter source, or null when no resolvable filter is present.\n */\nexport function extractApplyFilterInfo(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): {\n fieldNames: string[];\n fieldTypes: FilterFieldType[];\n source: 'body' | 'query';\n} | null {\n for (const param of method.getParameters()) {\n const filterDecorator = param.getDecorators().find((d) => d.getName() === 'ApplyFilter');\n if (!filterDecorator) continue;\n const args = filterDecorator.getArguments();\n if (args.length === 0) continue;\n const filterClassArg = args[0];\n if (!filterClassArg || !Node.isIdentifier(filterClassArg)) continue;\n\n // Read { source: \"body\" | \"query\" } from second argument\n let source: 'body' | 'query' = 'query';\n const optionsArg = args[1];\n if (optionsArg && Node.isObjectLiteralExpression(optionsArg)) {\n const sourceProp = optionsArg.getProperty('source');\n if (sourceProp && Node.isPropertyAssignment(sourceProp)) {\n const init = sourceProp.getInitializer();\n if (init && Node.isStringLiteral(init) && init.getLiteralValue() === 'body') {\n source = 'body';\n }\n }\n }\n\n const filterClassName = filterClassArg.getText();\n const resolved = findType(filterClassName, sourceFile, project);\n if (resolved && resolved.kind === 'class') {\n const classDecl = resolved.decl as ClassDeclaration;\n let fieldTypes = extractClassPropertyTypes(classDecl, project);\n\n // autoFields: if the filter class has no properties, resolve fields\n // from the entity referenced in @Filterable({ entity: X })\n if (fieldTypes.length === 0) {\n fieldTypes = extractFilterableEntityFields(classDecl, project);\n }\n\n // Merge in explicit @FilterFor('key', { type }) hints. An explicit hint\n // WINS over entity-column / class-property inference for the same key;\n // genuinely-virtual keys (no property, no column) are appended so they\n // appear in the Fields union and the type map M.\n const filterForHints = extractFilterForHints(classDecl, project);\n if (filterForHints.size > 0) {\n const byName = new Map(fieldTypes.map((f) => [f.name, f] as const));\n for (const [key, classified] of filterForHints) {\n byName.set(key, toFilterFieldType(key, classified));\n }\n fieldTypes = [...byName.values()];\n }\n\n if (fieldTypes.length === 0) return null;\n const fieldNames = fieldTypes.map((f) => f.name);\n return {\n fieldNames,\n fieldTypes,\n source,\n };\n }\n }\n return null;\n}\n\nconst RELATION_DECORATORS = new Set(['OneToMany', 'ManyToOne', 'ManyToMany', 'OneToOne']);\n\n/**\n * Recursively collect entity fields including dot-notation relation fields.\n * e.g. for PipelineRun with tasks: OneToMany<Task>, produces:\n * [\"id\", \"name\", \"status\", ..., \"tasks.id\", \"tasks.name\", ...]\n */\nfunction collectEntityFields(\n entityDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n prefix: string,\n visited: Set<string>,\n): FilterFieldType[] {\n const entityName = entityDecl.getName() ?? '';\n if (visited.has(entityName)) return [];\n visited.add(entityName);\n\n const fields: FilterFieldType[] = [];\n for (const prop of entityDecl.getProperties()) {\n const name = prop.getName();\n if (name.startsWith('$') || name.startsWith('_') || name.startsWith('[')) continue;\n if (prop.isStatic()) continue;\n\n const fullName = prefix ? `${prefix}.${name}` : name;\n const isRelation = prop.getDecorators().some((d) => RELATION_DECORATORS.has(d.getName()));\n\n if (isRelation) {\n const relEntity = resolveRelationEntity(prop, sourceFile, project);\n if (relEntity) {\n // Classify each relation leaf against the relation's own source file.\n fields.push(\n ...collectEntityFields(relEntity, relEntity.getSourceFile(), project, fullName, visited),\n );\n }\n } else {\n fields.push(toFilterFieldType(fullName, classifyFieldType(prop, sourceFile, project)));\n }\n }\n return fields;\n}\n\n/**\n * Given a relation property (e.g. `tasks = new Collection<Task>(this)`),\n * resolve the target entity class declaration.\n */\nfunction resolveRelationEntity(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassDeclaration | null {\n // Try from decorator argument: @OneToMany({ entity: () => Task, ... })\n for (const dec of prop.getDecorators()) {\n if (!RELATION_DECORATORS.has(dec.getName())) continue;\n const args = dec.getArguments();\n if (args.length === 0) continue;\n const arg = args[0];\n if (Node.isObjectLiteralExpression(arg)) {\n const entityProp = arg.getProperty('entity');\n if (entityProp && Node.isPropertyAssignment(entityProp)) {\n const init = entityProp.getInitializer();\n // () => Task\n if (init && Node.isArrowFunction(init)) {\n const body = init.getBody();\n if (Node.isIdentifier(body)) {\n const resolved = findType(body.getText(), prop.getSourceFile(), project);\n if (resolved?.kind === 'class') return resolved.decl as ClassDeclaration;\n }\n }\n }\n }\n // @ManyToOne(() => Task)\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) {\n const resolved = findType(body.getText(), prop.getSourceFile(), project);\n if (resolved?.kind === 'class') return resolved.decl as ClassDeclaration;\n }\n }\n }\n return null;\n}\n\n/** Classify each property of a filter DTO class into a FilterFieldType. */\nfunction extractClassPropertyTypes(\n classDecl: ClassDeclaration,\n project: Project,\n): FilterFieldType[] {\n const sourceFile = classDecl.getSourceFile();\n const fields: FilterFieldType[] = [];\n for (const prop of classDecl.getProperties()) {\n const name = prop.getName();\n if (name.startsWith('$') || name.startsWith('_')) continue;\n fields.push(toFilterFieldType(name, classifyFieldType(prop, sourceFile, project)));\n }\n return fields;\n}\n\n/**\n * When a filter class uses `@Filterable({ entity: X, autoFields: true })`,\n * resolve entity X and extract its property names (fields decorated with\n * `@Property`, `@PrimaryKey`, `@Enum`, etc. — skipping relations).\n */\nfunction extractFilterableEntityFields(\n filterClass: ClassDeclaration,\n project: Project,\n): FilterFieldType[] {\n const filterableDecorator = filterClass.getDecorators().find((d) => d.getName() === 'Filterable');\n if (!filterableDecorator) return [];\n const args = filterableDecorator.getArguments();\n if (args.length === 0) return [];\n\n const optionsArg = args[0];\n if (!Node.isObjectLiteralExpression(optionsArg)) return [];\n\n const entityProp = optionsArg.getProperty('entity');\n if (!entityProp || !Node.isPropertyAssignment(entityProp)) return [];\n\n const entityInit = entityProp.getInitializer();\n if (!entityInit || !Node.isIdentifier(entityInit)) return [];\n\n const entityName = entityInit.getText();\n const filterSourceFile = filterClass.getSourceFile();\n const resolvedEntity = findType(entityName, filterSourceFile, project);\n if (!resolvedEntity || resolvedEntity.kind !== 'class') return [];\n\n const entityDecl = resolvedEntity.decl as ClassDeclaration;\n const fields = collectEntityFields(\n entityDecl,\n entityDecl.getSourceFile(),\n project,\n '',\n new Set(),\n );\n\n // Also include keys declared via @Relations({ rel: { keys: [...] } }).\n // These string keys carry no resolvable type → kind: 'unknown'.\n const relationsDecorator = filterClass.getDecorators().find((d) => d.getName() === 'Relations');\n if (relationsDecorator) {\n const relArgs = relationsDecorator.getArguments();\n if (relArgs.length > 0 && Node.isObjectLiteralExpression(relArgs[0])) {\n for (const relProp of relArgs[0].getProperties()) {\n if (!Node.isPropertyAssignment(relProp)) continue;\n const relInit = relProp.getInitializer();\n if (!relInit || !Node.isObjectLiteralExpression(relInit)) continue;\n const keysProp = relInit.getProperty('keys');\n if (!keysProp || !Node.isPropertyAssignment(keysProp)) continue;\n const keysInit = keysProp.getInitializer();\n if (!keysInit || !Node.isArrayLiteralExpression(keysInit)) continue;\n for (const el of keysInit.getElements()) {\n if (Node.isStringLiteral(el)) {\n // Route through the single constructor (keeps the typeRef invariant\n // enforced in one place); these relation keys carry no type → unknown.\n fields.push(toFilterFieldType(el.getLiteralValue(), { kind: 'unknown' }));\n }\n }\n }\n }\n }\n\n return fields;\n}\n","import {\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport { resolveEnumValues } from './enum-resolution.js';\nimport type { FieldTypeKind, FilterFieldType, TypeRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Field-type classification (mirrors mapTypeOrmType / mapMikroOrmType so codegen\n// and the runtime adapters can never diverge). See nestjs-filter\n// packages/typeorm/src/typeorm.adapter.ts:190 (mapTypeOrmType).\n// ---------------------------------------------------------------------------\n\n/** Reference: typeorm.adapter.ts keyword tables (kept in sync intentionally). */\nconst STRING_TYPE_KEYWORDS = ['varchar', 'text', 'string', 'char', 'uuid', 'enum'];\nconst NUMBER_TYPE_KEYWORDS = ['int', 'float', 'double', 'decimal', 'number', 'numeric', 'real'];\nconst BOOLEAN_TYPE_KEYWORDS = ['bool', 'boolean', 'bit'];\nconst DATE_TYPE_KEYWORDS = ['date', 'time', 'timestamp', 'datetime'];\nconst JSON_TYPE_KEYWORDS = ['json', 'jsonb'];\n\n/** Classify a column/property type literal (e.g. 'varchar') the same way mapTypeOrmType does. */\nexport function classifyTypeKeyword(raw: string): FieldTypeKind | null {\n const t = raw.toLowerCase();\n if (STRING_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'string';\n if (NUMBER_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'number';\n if (BOOLEAN_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'boolean';\n if (DATE_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'date';\n if (JSON_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'json';\n return null;\n}\n\nexport interface ClassifyResult {\n kind: FieldTypeKind;\n enumValues?: string[];\n nullable?: boolean;\n numericEnum?: boolean;\n /** Importable reference to a named enum / type alias / interface (option B). */\n typeRef?: TypeRef;\n}\n\n/**\n * Return `r` with `nullable: true` set only when `nullable` is true.\n * Avoids assigning `undefined` to an optional prop under exactOptionalPropertyTypes.\n */\nexport function markNullable(r: ClassifyResult, nullable: boolean): ClassifyResult {\n return nullable ? { ...r, nullable: true } : r;\n}\n\n/**\n * Options for {@link classifyTypeNode}. When `resolveRef` is supplied and the\n * type node is a named reference (not a primitive / well-known name), it is\n * called with the symbol name; a non-null result is attached as `typeRef` on the\n * returned `ClassifyResult`. This lets `classifyFilterForParam` classify ONCE and\n * pick up the importable ref in the same pass.\n */\nexport interface ClassifyTypeNodeOptions {\n resolveRef?: (refName: string) => TypeRef | null;\n}\n\n/** Classify a TS type node into a field-type kind (+ enum members / nullable). */\nexport function classifyTypeNode(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n opts?: ClassifyTypeNodeOptions,\n): ClassifyResult {\n // Union: strip null/undefined, collect literal members, recurse otherwise.\n if (Node.isUnionTypeNode(typeNode)) {\n let nullable = false;\n const stringLits: string[] = [];\n const numberLits: string[] = [];\n const others: TypeNode[] = [];\n for (const member of typeNode.getTypeNodes()) {\n const kind = member.getKind();\n if (kind === SyntaxKind.NullKeyword || kind === SyntaxKind.UndefinedKeyword) {\n nullable = true;\n continue;\n }\n if (Node.isLiteralTypeNode(member)) {\n const lit = member.getLiteral();\n if (Node.isStringLiteral(lit)) {\n stringLits.push(lit.getLiteralValue());\n continue;\n }\n if (Node.isNumericLiteral(lit)) {\n numberLits.push(lit.getText());\n continue;\n }\n if (lit.getKind() === SyntaxKind.NullKeyword) {\n nullable = true;\n continue;\n }\n }\n others.push(member);\n }\n\n if (others.length === 0 && stringLits.length > 0 && numberLits.length === 0) {\n return markNullable({ kind: 'string', enumValues: stringLits }, nullable);\n }\n if (others.length === 0 && numberLits.length > 0 && stringLits.length === 0) {\n return markNullable({ kind: 'number', enumValues: numberLits, numericEnum: true }, nullable);\n }\n if (others.length === 1) {\n const inner = classifyTypeNode(others[0]!, sourceFile, project, opts);\n return markNullable(inner, nullable || inner.nullable === true);\n }\n return markNullable({ kind: 'unknown' }, nullable);\n }\n\n switch (typeNode.getKind()) {\n case SyntaxKind.StringKeyword:\n return { kind: 'string' };\n case SyntaxKind.NumberKeyword:\n return { kind: 'number' };\n case SyntaxKind.BooleanKeyword:\n return { kind: 'boolean' };\n case SyntaxKind.AnyKeyword:\n case SyntaxKind.UnknownKeyword:\n return { kind: 'unknown' };\n default:\n break;\n }\n\n if (Node.isTypeReference(typeNode)) {\n const refName = typeNode.getTypeName().getText();\n if (refName === 'Date') return { kind: 'date' };\n if (refName === 'Record' || refName === 'Object') return { kind: 'json' };\n // An importable named ref (enum / type alias / interface / class) wins for\n // emit when the caller supplied a resolver and a safe import path exists.\n const typeRef = opts?.resolveRef?.(refName) ?? null;\n // Possibly an enum type used as a property type.\n const en = resolveEnumValues(refName, sourceFile, project);\n if (en) {\n const base: ClassifyResult = en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n return typeRef ? { ...base, typeRef } : base;\n }\n if (typeRef) return { kind: 'unknown', typeRef };\n return { kind: 'unknown' };\n }\n\n if (Node.isTypeLiteral(typeNode)) return { kind: 'json' };\n\n return { kind: 'unknown' };\n}\n\n/** Resolve an enum from @Enum decorator args: `() => Status` or `{ items: () => Status }`. */\nexport function enumFromDecoratorArgs(\n args: Node[],\n sourceFile: SourceFile,\n project: Project,\n): { values: string[]; numeric: boolean } | null {\n for (const arg of args) {\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) {\n const en = resolveEnumValues(body.getText(), sourceFile, project);\n if (en) return en;\n }\n }\n if (Node.isObjectLiteralExpression(arg)) {\n const itemsProp = arg.getProperty('items');\n if (itemsProp && Node.isPropertyAssignment(itemsProp)) {\n const init = itemsProp.getInitializer();\n if (init && Node.isArrowFunction(init)) {\n const body = init.getBody();\n if (Node.isIdentifier(body)) {\n const en = resolveEnumValues(body.getText(), sourceFile, project);\n if (en) return en;\n }\n }\n }\n }\n }\n return null;\n}\n\n/** Classify a property from `@Column`/`@Property`/`@Enum` decorator options. */\nexport function classifyFromColumnDecorator(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult | null {\n for (const dec of prop.getDecorators()) {\n const decName = dec.getName();\n if (decName !== 'Column' && decName !== 'Property' && decName !== 'Enum') continue;\n const args = dec.getArguments();\n\n // @Enum({ items: () => Status }) or @Enum(() => Status)\n if (decName === 'Enum') {\n const en = enumFromDecoratorArgs(args, sourceFile, project);\n if (en) {\n return en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n }\n return { kind: 'string' };\n }\n\n for (const arg of args) {\n // @Column('varchar')\n if (Node.isStringLiteral(arg)) {\n const raw = arg.getLiteralValue();\n const kind = classifyTypeKeyword(raw);\n if (kind) {\n // @Column('enum', { enum: Status }) → resolve via the options object below\n if (kind === 'string' && raw.toLowerCase().includes('enum')) continue;\n return { kind };\n }\n }\n // @Column({ type: 'datetime' }) / @Property({ type: 'int' }) / { enum: Status }\n if (Node.isObjectLiteralExpression(arg)) {\n const enumProp = arg.getProperty('enum');\n if (enumProp && Node.isPropertyAssignment(enumProp)) {\n const init = enumProp.getInitializer();\n if (init && Node.isIdentifier(init)) {\n const en = resolveEnumValues(init.getText(), sourceFile, project);\n if (en) {\n return en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n }\n return { kind: 'string' };\n }\n }\n const typeProp = arg.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const init = typeProp.getInitializer();\n if (init && Node.isStringLiteral(init)) {\n const kind = classifyTypeKeyword(init.getLiteralValue());\n if (kind) return { kind };\n }\n }\n }\n }\n // Decorator present but no recognisable type info.\n return null;\n }\n return null;\n}\n\n/**\n * Classify a single entity/DTO property into a ClassifyResult (kind + enum + nullable),\n * mirroring the runtime ORM type mapping. Falls back to 'unknown' when unresolvable.\n */\nexport function classifyFieldType(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult {\n let nullable = prop.hasQuestionToken();\n const typeNode = prop.getTypeNode();\n\n if (typeNode) {\n const r = classifyTypeNode(typeNode, sourceFile, project);\n if (r.nullable) nullable = true;\n if (r.kind !== 'unknown') return markNullable(r, nullable);\n }\n\n const fromDecorator = classifyFromColumnDecorator(prop, sourceFile, project);\n if (fromDecorator) {\n return markNullable(fromDecorator, nullable || fromDecorator.nullable === true);\n }\n\n return markNullable({ kind: 'unknown' }, nullable);\n}\n\n/**\n * The single normalizing constructor for a {@link FilterFieldType} from a\n * classification. Concentrates the `typeRef` precedence invariant (see the\n * `FilterFieldType` doc): `kind`/`enumValues`/`numericEnum` are always recorded\n * best-effort, and `typeRef` (when present) is what the emitter actually uses.\n * Build `FilterFieldType` values through here — not inline — so the convention\n * has exactly one enforcement point.\n */\nexport function toFilterFieldType(name: string, r: ClassifyResult): FilterFieldType {\n const ft: FilterFieldType = { name, kind: r.kind };\n if (r.enumValues && r.enumValues.length > 0) ft.enumValues = r.enumValues;\n if (r.nullable) ft.nullable = true;\n if (r.numericEnum) ft.numericEnum = true;\n if (r.typeRef) ft.typeRef = r.typeRef;\n return ft;\n}\n","import type { Project, SourceFile } from 'ts-morph';\nimport { findType } from './type-ref-resolution.js';\n\n/**\n * Resolve an enum identifier to its raw member values + numeric flag.\n *\n * KNOWN LIMITATION — mixed enums with a computed member: `findType` serializes\n * each enum member with `JSON.stringify` of its static value, falling back to the\n * QUOTED member NAME for any member whose value can't be resolved statically\n * (e.g. a computed member). Here we re-derive `numeric` by `JSON.parse`-ing each\n * member: any string member (including that quoted-name fallback) flips `numeric`\n * to `false` for the WHOLE enum. So a primarily-numeric enum that contains a\n * single computed member is treated as a string enum, and its numeric members\n * are emitted as quoted string literals. This is a rare edge case; fixing it\n * would require threading per-member numeric-ness out of `findType` rather than\n * inferring it from the stringified members. Pure numeric and pure string enums\n * (the overwhelmingly common cases) are unaffected.\n */\nexport function resolveEnumValues(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): { values: string[]; numeric: boolean } | null {\n const resolved = findType(name, sourceFile, project);\n if (!resolved || resolved.kind !== 'enum') return null;\n // members are JSON.stringify'd (\"A\" / \"0\"); strip quotes to raw values.\n let numeric = true;\n const values = resolved.members.map((m) => {\n const parsed = JSON.parse(m) as string | number;\n if (typeof parsed === 'string') numeric = false;\n return String(parsed);\n });\n if (values.length === 0) return null;\n return { values, numeric };\n}\n","import { Node, SyntaxKind } from 'ts-morph';\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/** 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/**\n * Parse a defineContract({...}) call expression.\n * Returns { query, body, response } or null if unrecognised.\n */\nexport interface ParsedContractDef {\n query: string | null;\n body: string | null;\n response: string;\n /** Raw zod source text of the body initializer (for inline forms emit). */\n bodyZodText: string | null;\n /** Raw zod source text of the query initializer (for inline forms emit). */\n queryZodText: string | null;\n}\n\nexport function parseDefineContractCall(callExpr: Node): ParsedContractDef | 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 let bodyZodText: string | null = null;\n let queryZodText: string | null = null;\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 queryZodText = val.getText();\n } else if (propName === 'body') {\n body = zodAstToTs(val);\n bodyZodText = val.getText();\n } else if (propName === 'response') {\n response = zodAstToTs(val);\n }\n }\n\n return { query, body, response, bodyZodText, queryZodText };\n}\n","import { open } from 'node:fs/promises';\nimport { mkdir, readFile, unlink } 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 * Uses O_CREAT | O_EXCL (via 'wx' flag) for atomic file creation to prevent\n * TOCTOU race conditions between concurrent processes.\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 const lockData: LockData = { pid: process.pid, startedAt: new Date().toISOString() };\n\n // Try atomic creation first (O_WRONLY | O_CREAT | O_EXCL)\n try {\n const fd = await open(lockPath, 'wx');\n await fd.writeFile(`${JSON.stringify(lockData, null, 2)}\\n`, 'utf8');\n await fd.close();\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n // File exists — check if holder is alive\n try {\n const raw = await readFile(lockPath, 'utf8');\n const existing = JSON.parse(raw) as LockData;\n if (isProcessAlive(existing.pid)) return null;\n // Stale lock — remove and retry\n await unlink(lockPath);\n return acquireLock(outDir);\n } catch {\n return null;\n }\n }\n return null;\n }\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 = '0.3.0';\n\n// Codegen pipeline (migrated from nestjs-inertia)\nexport { defineConfig } from './config/define-config.js';\nexport { loadConfig, resolveConfig } 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\n// Validation IR + pluggable adapters\nexport type {\n SchemaModule,\n SchemaNode,\n StringCheck,\n NumberCheck,\n} from './ir/schema-node.js';\nexport type {\n ValidationAdapter,\n AdapterUsage,\n RenderContext,\n RenderedModule,\n} from './adapters/types.js';\nexport { resolveAdapter } from './adapters/registry.js';\nexport type { ValidationOption } from './adapters/registry.js';\n\n// class-validator DTO → SchemaModule IR (consumed by the validation adapters)\nexport { extractSchemaFromDto } from './discovery/dto-to-ir.js';\n\n// Discovery + emit (programmatic API)\nexport type {\n RouteDescriptor,\n ContractDescriptor,\n ContractSource,\n ControllerRef,\n TypeRef,\n} from './discovery/types.js';\nexport { emitForms } from './emit/emit-forms.js';\nexport { emitApi } from './emit/emit-api.js';\nexport { emitRoutes } from './emit/emit-routes.js';\nexport { discoverContractsFast } from './discovery/contracts-fast.js';\nexport type { FastDiscoveryOptions } from './discovery/contracts-fast.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-codegen 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 { execFileSync } from 'node:child_process';\nimport { appendFileSync, existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { runCodegen } from './codegen.js';\nimport {\n INERTIA_TSCONFIG_TEMPLATE,\n TSCONFIG_INERTIA_TEMPLATE,\n patchNestCliJson,\n patchTsconfigExclude,\n runInit,\n} from './init.js';\n\ninterface Check {\n name: string;\n pass: boolean;\n fix?: string | undefined;\n autoFix?: (() => void | Promise<void>) | undefined;\n}\n\nfunction checkFileExists(cwd: string, file: string): boolean {\n return existsSync(join(cwd, file));\n}\n\nfunction readJson(path: string): Record<string, unknown> | null {\n try {\n const raw = readFileSync(path, 'utf8').replace(/\\/\\/.*$/gm, '');\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction writeJsonField(filePath: string, dotPath: string[], value: unknown): void {\n const raw = readFileSync(filePath, 'utf8');\n const stripped = raw.replace(/\\/\\/.*$/gm, '');\n const obj = JSON.parse(stripped) as Record<string, unknown>;\n let target = obj as Record<string, unknown>;\n for (let i = 0; i < dotPath.length - 1; i++) {\n const key = dotPath[i] as string;\n if (!target[key] || typeof target[key] !== 'object') {\n target[key] = {};\n }\n target = target[key] as Record<string, unknown>;\n }\n const lastKey = dotPath[dotPath.length - 1] as string;\n if (\n typeof value === 'object' &&\n value !== null &&\n typeof target[lastKey] === 'object' &&\n target[lastKey] !== null\n ) {\n target[lastKey] = {\n ...(target[lastKey] as Record<string, unknown>),\n ...(value as Record<string, unknown>),\n };\n } else {\n target[lastKey] = value;\n }\n writeFileSync(filePath, `${JSON.stringify(obj, null, 2)}\\n`, 'utf8');\n}\n\nfunction getPackageVersion(cwd: string, pkg: string): string | null {\n try {\n const pkgJson = readJson(join(cwd, 'node_modules', pkg, 'package.json'));\n return (pkgJson?.version as string) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction detectPkgManager(cwd: string): string {\n if (existsSync(join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';\n if (existsSync(join(cwd, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nexport async function runDoctor(opts: { cwd: string; fix?: boolean }): Promise<number> {\n const { cwd, fix = false } = opts;\n const checks: Check[] = [];\n const pm = detectPkgManager(cwd);\n\n // 1. Config file\n checks.push({\n name: 'nestjs-inertia.config.ts exists',\n pass: checkFileExists(cwd, 'nestjs-inertia.config.ts'),\n fix: 'Run: nestjs-inertia init',\n autoFix: () => runInit({ cwd }),\n });\n\n // 2. Shell template exists\n const shellExtensions = ['html', 'htm', 'hbs', 'ejs', 'pug', 'liquid'];\n const shellDirs = ['inertia', 'views'];\n let foundShellPath: string | null = null;\n let foundShellDir: string | null = null;\n for (const dir of shellDirs) {\n for (const ext of shellExtensions) {\n const candidates = [`${dir}/index.${ext}`, `${dir}/shell.${ext}`];\n for (const candidate of candidates) {\n if (checkFileExists(cwd, candidate)) {\n foundShellPath = candidate;\n foundShellDir = dir;\n break;\n }\n }\n if (foundShellPath) break;\n }\n if (foundShellPath) break;\n }\n checks.push({\n name: 'Shell template (rootView) exists',\n pass: !!foundShellPath,\n fix: 'Run: nestjs-inertia init (creates inertia/index.html)',\n autoFix: () => runInit({ cwd }),\n });\n\n // 3. nest-cli.json copies shell template to dist/\n if (foundShellDir) {\n const nestCliPath = join(cwd, 'nest-cli.json');\n const nestCli = readJson(nestCliPath);\n const compiler = (nestCli?.compilerOptions ?? {}) as Record<string, unknown>;\n const assets = (compiler.assets ?? []) as Array<string | Record<string, unknown>>;\n const hasCopy = assets.some((a) => {\n if (typeof a === 'string') return a.includes(foundShellDir!);\n return String(a.include ?? '').includes(foundShellDir!);\n });\n checks.push({\n name: `nest-cli.json copies ${foundShellDir}/ to dist/ (needed for Docker)`,\n pass: hasCopy,\n fix: `Add asset entry for ${foundShellDir}/ in nest-cli.json compilerOptions.assets`,\n autoFix: () => {\n patchNestCliJson(cwd, foundShellDir!);\n },\n });\n }\n\n // 4. Entry point exists at the correct path\n const entryExtensions = ['tsx', 'ts'];\n const correctEntryExists = entryExtensions.some((ext) =>\n checkFileExists(cwd, `inertia/app/client.${ext}`),\n );\n const legacyEntryExists = entryExtensions.some((ext) =>\n checkFileExists(cwd, `inertia/app.${ext}`),\n );\n checks.push({\n name: 'Entry point at inertia/app/client.tsx (matches Vite plugin default)',\n pass: correctEntryExists,\n fix: legacyEntryExists\n ? 'Move inertia/app.tsx → inertia/app/client.tsx (the Vite plugin resolves inertia/app/client.tsx by default)'\n : 'Run: nestjs-inertia init',\n autoFix: !correctEntryExists ? () => runInit({ cwd }) : undefined,\n });\n\n // 5. Codegen output\n const hasApi = checkFileExists(cwd, '.nestjs-inertia/api.ts');\n const hasRoutes = checkFileExists(cwd, '.nestjs-inertia/routes.ts');\n const hasPages = checkFileExists(cwd, '.nestjs-inertia/pages.d.ts');\n checks.push({\n name: '.nestjs-inertia/ codegen output exists',\n pass: hasApi && hasRoutes && hasPages,\n fix: 'Run: nestjs-codegen codegen',\n autoFix: () => runCodegen({ cwd }),\n });\n\n // 5. tsconfig paths\n const tsconfigPath = join(cwd, 'tsconfig.json');\n const tsconfig = readJson(tsconfigPath);\n const paths = (tsconfig?.compilerOptions as Record<string, unknown>)?.paths as\n | Record<string, string[]>\n | undefined;\n checks.push({\n name: 'tsconfig.json has @/* path alias',\n pass: !!paths?.['@/*'],\n fix: 'Add @/* path alias to tsconfig.json',\n autoFix: () =>\n writeJsonField(tsconfigPath, ['compilerOptions', 'paths'], { '@/*': ['./src/*'] }),\n });\n\n // 6. tsconfig.json and tsconfig.build.json exclude inertia/ from server build\n const inertiaDir = foundShellDir ?? 'inertia';\n for (const tsconfigFile of ['tsconfig.json', 'tsconfig.build.json']) {\n const tsc = readJson(join(cwd, tsconfigFile));\n if (!tsc) continue; // file doesn't exist, skip\n const excl = (tsc.exclude ?? []) as string[];\n const excludesIt = excl.includes(inertiaDir);\n checks.push({\n name: `${tsconfigFile} excludes ${inertiaDir}/ from server compilation`,\n pass: excludesIt,\n fix: `Add \"${inertiaDir}\" to ${tsconfigFile} exclude array (Vite-only APIs like import.meta.glob break nest build)`,\n autoFix: () => {\n patchTsconfigExclude(cwd, inertiaDir, tsconfigFile);\n },\n });\n }\n\n // 7. Root tsconfig.json excludes `dist` so the server typecheck doesn't\n // walk compiled artifacts under dist/inertia/* (would surface ~thousands\n // of phantom errors about unresolved aliases in the compiled tree).\n {\n const tsc = readJson(tsconfigPath);\n const excl = (tsc?.exclude ?? []) as string[];\n const excludesDist = excl.includes('dist');\n checks.push({\n name: 'tsconfig.json excludes dist/ (avoids phantom errors in compiled output)',\n pass: excludesDist,\n fix: 'Add \"dist\" to tsconfig.json exclude array',\n autoFix: () => {\n patchTsconfigExclude(cwd, 'dist', 'tsconfig.json');\n },\n });\n }\n\n // 8. Dedicated inertia tsconfig — required so the inertia/ tree + codegen\n // output can be typechecked without breaking the server tsconfig.\n const inertiaTsconfigPath = join(cwd, 'tsconfig.inertia.json');\n const inertiaTsconfig = readJson(inertiaTsconfigPath);\n checks.push({\n name: 'tsconfig.inertia.json exists',\n pass: !!inertiaTsconfig,\n fix: 'Create tsconfig.inertia.json (typechecks inertia/ + .nestjs-inertia/)',\n autoFix: () => {\n writeFileSync(inertiaTsconfigPath, TSCONFIG_INERTIA_TEMPLATE, 'utf8');\n },\n });\n\n if (inertiaTsconfig) {\n const inertiaOpts = (inertiaTsconfig.compilerOptions as Record<string, unknown>) ?? {};\n const inertiaPaths = (inertiaOpts.paths as Record<string, string[]> | undefined) ?? {};\n const at = inertiaPaths['@/*'] ?? [];\n const missingTilde = !inertiaPaths['~/*'];\n const missingCodegen = !inertiaPaths['~codegen/*'];\n const missingDualAt = !at.includes('./inertia/*') || !at.includes('./src/*');\n checks.push({\n name: 'tsconfig.inertia.json has ~/*, ~codegen/*, and @/* (inertia + src) aliases',\n pass: !missingTilde && !missingCodegen && !missingDualAt,\n fix: '@/* must include both ./inertia/* and ./src/* so codegen-resolved controllers + inertia user code both resolve',\n autoFix: () => {\n const additions: Record<string, string[]> = {};\n if (missingDualAt) additions['@/*'] = ['./inertia/*', './src/*'];\n if (missingTilde) additions['~/*'] = ['./inertia/*'];\n if (missingCodegen) additions['~codegen/*'] = ['./.nestjs-inertia/*'];\n writeJsonField(inertiaTsconfigPath, ['compilerOptions', 'paths'], additions);\n },\n });\n // experimentalDecorators is required: codegen api.ts imports controllers\n // (via Awaited<ReturnType<...>>) which TS has to parse for decorators.\n checks.push({\n name: 'tsconfig.inertia.json has experimentalDecorators: true',\n pass: inertiaOpts.experimentalDecorators === true,\n fix: 'Set compilerOptions.experimentalDecorators = true',\n autoFix: () => {\n writeJsonField(inertiaTsconfigPath, ['compilerOptions', 'experimentalDecorators'], true);\n },\n });\n // Without emitDecoratorMetadata: OFF, every src/ file pulled in\n // transitively complains with TS1272 unless it uses `import type`.\n checks.push({\n name: 'tsconfig.inertia.json has emitDecoratorMetadata: false',\n pass: inertiaOpts.emitDecoratorMetadata === false,\n fix: 'Set compilerOptions.emitDecoratorMetadata = false (avoids TS1272 spam from transitively-loaded src/ files)',\n autoFix: () => {\n writeJsonField(inertiaTsconfigPath, ['compilerOptions', 'emitDecoratorMetadata'], false);\n },\n });\n // Must include nestjs-inertia.d.ts so the InertiaRegistry augmentation\n // resolves Link route params, page names, and shared props.\n const include = (inertiaTsconfig.include as string[] | undefined) ?? [];\n checks.push({\n name: 'tsconfig.inertia.json includes nestjs-inertia.d.ts',\n pass: include.some((p) => p.includes('nestjs-inertia.d.ts')),\n fix: 'Add \"nestjs-inertia.d.ts\" to include array (resolves InertiaRegistry augmentation)',\n });\n }\n\n // 9. inertia/tsconfig.json — thin extends so VSCode/editors that walk up\n // to find the closest tsconfig pick up the inertia-aware aliases.\n const innerTsconfigPath = join(cwd, 'inertia', 'tsconfig.json');\n checks.push({\n name: 'inertia/tsconfig.json exists (VSCode picks up ~codegen alias)',\n pass: existsSync(innerTsconfigPath),\n fix: 'Create inertia/tsconfig.json that extends ../tsconfig.inertia.json',\n autoFix: () => {\n writeFileSync(innerTsconfigPath, INERTIA_TSCONFIG_TEMPLATE, 'utf8');\n },\n });\n\n // 7. Vite config\n if (checkFileExists(cwd, 'vite.config.ts')) {\n const viteContent = readFileSync(join(cwd, 'vite.config.ts'), 'utf8');\n checks.push({\n name: 'vite.config.ts has resolve.alias',\n pass: viteContent.includes('resolve') && viteContent.includes('alias'),\n fix: 'Add resolve.alias to vite.config.ts (manual — complex file)',\n });\n checks.push({\n name: 'vite.config.ts references nestjs-inertia',\n pass:\n viteContent.includes('nestInertia') ||\n viteContent.includes('nestjs-inertia') ||\n viteContent.includes('setupInertiaVite'),\n fix: \"Add: import nestInertia from '@dudousxd/nestjs-inertia-vite/plugin'\",\n });\n }\n\n // 8. Package versions\n const requiredPkgs = [\n '@dudousxd/nestjs-inertia',\n '@dudousxd/nestjs-codegen',\n '@dudousxd/nestjs-inertia-client',\n ];\n const missingRequired = requiredPkgs.filter((pkg) => !getPackageVersion(cwd, pkg));\n checks.push({\n name: 'Core packages installed (core + codegen + client)',\n pass: missingRequired.length === 0,\n fix: `Missing: ${missingRequired.join(', ')}`,\n autoFix:\n missingRequired.length > 0\n ? () => {\n const addCmd = pm === 'npm' ? 'install' : 'add';\n execFileSync(pm, [addCmd, ...missingRequired], { cwd, stdio: 'inherit' });\n }\n : undefined,\n });\n\n const libPackages = [\n '@dudousxd/nestjs-inertia',\n '@dudousxd/nestjs-codegen',\n '@dudousxd/nestjs-inertia-client',\n '@dudousxd/nestjs-inertia-vite',\n '@dudousxd/nestjs-inertia-testing',\n ];\n const versions = libPackages.map((pkg) => ({ pkg, version: getPackageVersion(cwd, pkg) }));\n const installed = versions.filter((v) => v.version !== null);\n const uniqueVersions = new Set(installed.map((v) => v.version));\n if (installed.length > 1) {\n checks.push({\n name: 'All packages on same version',\n pass: uniqueVersions.size === 1,\n fix: `Versions: ${installed.map((v) => `${v.pkg.replace('@dudousxd/', '')}@${v.version}`).join(', ')}`,\n });\n }\n\n // 9. Inertia.js version\n const inertiaReact = getPackageVersion(cwd, '@inertiajs/react');\n const inertiaVue = getPackageVersion(cwd, '@inertiajs/vue3');\n const inertiaSvelte = getPackageVersion(cwd, '@inertiajs/svelte');\n const inertiaVersion = inertiaReact ?? inertiaVue ?? inertiaSvelte;\n const inertiaFramework = inertiaReact\n ? 'react'\n : inertiaVue\n ? 'vue'\n : inertiaSvelte\n ? 'svelte'\n : null;\n\n if (inertiaVersion) {\n const majorVersion = Number.parseInt(inertiaVersion.split('.')[0] ?? '0', 10);\n checks.push({\n name: `@inertiajs/${inertiaFramework} is v3+`,\n pass: majorVersion >= 3,\n fix: `Current: v${inertiaVersion}`,\n autoFix:\n majorVersion < 3\n ? () => {\n const addCmd = pm === 'npm' ? 'install' : 'add';\n execFileSync(pm, [addCmd, `@inertiajs/${inertiaFramework}@^3.0.0`], {\n cwd,\n stdio: 'inherit',\n });\n }\n : undefined,\n });\n }\n\n // 10. .gitignore\n if (checkFileExists(cwd, '.gitignore')) {\n const gitignorePath = join(cwd, '.gitignore');\n const gitignore = readFileSync(gitignorePath, 'utf8');\n checks.push({\n name: '.gitignore includes .nestjs-inertia/',\n pass: gitignore.includes('.nestjs-inertia'),\n fix: 'Add .nestjs-inertia/ to .gitignore',\n autoFix: () => appendFileSync(gitignorePath, '\\n.nestjs-inertia/\\n'),\n });\n }\n\n // 11. Build scripts\n const pkgJsonPath = join(cwd, 'package.json');\n const pkgJson = readJson(pkgJsonPath);\n const scripts = (pkgJson?.scripts as Record<string, string>) ?? {};\n checks.push({\n name: 'package.json has build:client script',\n pass: !!scripts['build:client'],\n fix: 'Add build:client script',\n autoFix: () => writeJsonField(pkgJsonPath, ['scripts'], { 'build:client': 'vite build' }),\n });\n checks.push({\n name: 'package.json has typecheck:inertia script',\n pass: !!scripts['typecheck:inertia'],\n fix: 'Add: \"typecheck:inertia\": \"tsc --noEmit -p tsconfig.inertia.json\"',\n autoFix: () =>\n writeJsonField(pkgJsonPath, ['scripts'], {\n 'typecheck:inertia': 'tsc --noEmit -p tsconfig.inertia.json',\n }),\n });\n\n // Print results + auto-fix\n console.log('');\n console.log(`\\x1b[1mnestjs-inertia doctor${fix ? ' --fix' : ''}\\x1b[0m`);\n console.log('');\n\n let hasFailures = false;\n let fixed = 0;\n\n for (const check of checks) {\n if (check.pass) {\n console.log(` \\x1b[32m✓\\x1b[0m ${check.name}`);\n continue;\n }\n\n if (fix && check.autoFix) {\n try {\n check.autoFix();\n console.log(` \\x1b[34m⚡\\x1b[0m ${check.name} \\x1b[34m(fixed)\\x1b[0m`);\n fixed++;\n continue;\n } catch (err) {\n console.log(` \\x1b[31m✗\\x1b[0m ${check.name} \\x1b[31m(auto-fix failed)\\x1b[0m`);\n if (check.fix) console.log(` \\x1b[2m${check.fix}\\x1b[0m`);\n hasFailures = true;\n continue;\n }\n }\n\n console.log(` \\x1b[31m✗\\x1b[0m ${check.name}`);\n if (check.fix) {\n const hint = check.autoFix ? `${check.fix} (fixable with --fix)` : check.fix;\n console.log(` \\x1b[2m${hint}\\x1b[0m`);\n }\n hasFailures = true;\n }\n\n console.log('');\n const failCount = checks.filter((c) => !c.pass).length - fixed;\n if (fixed > 0) console.log(`\\x1b[34m${fixed} issue(s) auto-fixed\\x1b[0m`);\n if (failCount > 0) {\n console.log(`\\x1b[33m${failCount} issue(s) remaining\\x1b[0m`);\n } else if (!hasFailures) {\n console.log('\\x1b[32mAll checks passed!\\x1b[0m');\n }\n console.log('');\n\n return hasFailures ? 1 : 0;\n}\n","import { execFileSync } 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';\nimport { findAfterLastImport, insertImport, patchJsonFile } from './patch-utils.js';\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-codegen] 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 args: string[] = [];\n if (pkgManager === 'npm') {\n args.push('install');\n if (dev) args.push('--save-dev');\n } else {\n args.push('add');\n if (dev) args.push('-D');\n }\n args.push(...deps);\n\n logPatched(deps.join(', '), 'installed');\n try {\n execFileSync(pkgManager, args, { stdio: 'inherit' });\n } catch {\n logWarning(`Failed to install: ${deps.join(', ')}`);\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 * 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 content = insertImport(content, \"import { InertiaModule } from '@dudousxd/nestjs-inertia';\");\n\n // Ensure `resolve` from node:path is imported (needed for rootView).\n // Inserted unconditionally (even at offset 0, prepending) — matches the\n // original behaviour for files that have no other imports.\n if (!content.includes(\"from 'node:path'\") && !content.includes('from \"node:path\"')) {\n const insertAt2 = findAfterLastImport(content);\n content = `${content.slice(0, insertAt2)}import { resolve } from 'node:path';\\n${content.slice(insertAt2)}`;\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: resolve(__dirname, '../${rootView}'),\\n${indent}}),${content.slice(bracketPos)}`;\n changed = true;\n }\n }\n\n // --- HomeController ---\n if (!content.includes('HomeController')) {\n content = insertImport(content, \"import { HomeController } from './home.controller';\");\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 content = insertImport(\n content,\n \"import { setupInertiaVite } from '@dudousxd/nestjs-inertia-vite';\",\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-codegen';\n\nexport default defineConfig({\n pages: {\n glob: '${glob}',\n },\n});\n`;\n}\n\n/**\n * Standalone tsconfig that typechecks the inertia/ frontend + the codegen\n * output under .nestjs-inertia/. Lives at the project root and is invoked\n * via `pnpm typecheck:inertia` (or equivalent).\n *\n * Why a separate file:\n * - The server tsconfig excludes inertia/ (Vite-only APIs break nest build)\n * - The codegen emits imports like `import('../src/.../foo.controller')`,\n * so we need `experimentalDecorators` here to parse those controllers.\n * Decorator metadata is OFF so users don't get TS1272 leaks from src/.\n * - `@/*` resolves to BOTH `inertia/*` AND `src/*` because the codegen's\n * transitive imports use `@/` to mean `src/`, while inertia/ user code\n * uses `@/` to mean `inertia/`.\n */\nexport const TSCONFIG_INERTIA_TEMPLATE = `{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"module\": \"esnext\",\n \"moduleResolution\": \"bundler\",\n \"jsx\": \"react-jsx\",\n \"lib\": [\"DOM\", \"DOM.Iterable\", \"ESNext\"],\n \"types\": [\"vite/client\", \"node\"],\n \"allowImportingTsExtensions\": false,\n \"allowSyntheticDefaultImports\": true,\n \"esModuleInterop\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": false,\n \"resolveJsonModule\": true,\n \"isolatedModules\": true,\n \"noEmit\": true,\n \"incremental\": true,\n \"skipLibCheck\": true,\n \"strict\": false,\n \"strictNullChecks\": true,\n \"noUnusedLocals\": false,\n \"noUnusedParameters\": false,\n \"noFallthroughCasesInSwitch\": false,\n \"useUnknownInCatchVariables\": false,\n \"noImplicitAny\": false,\n \"ignoreDeprecations\": \"6.0\",\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./inertia/*\", \"./src/*\"],\n \"~/*\": [\"./inertia/*\"],\n \"~codegen/*\": [\"./.nestjs-inertia/*\"]\n }\n },\n \"include\": [\n \"inertia/**/*\",\n \".nestjs-inertia/**/*\",\n \"nestjs-inertia.d.ts\"\n ],\n \"exclude\": [\n \"node_modules\",\n \"dist\",\n \"inertia/**/*.test.ts\",\n \"inertia/**/*.test.tsx\",\n \"inertia/**/*.spec.ts\",\n \"inertia/**/*.spec.tsx\"\n ]\n}\n`;\n\n/**\n * Thin tsconfig inside inertia/ that just extends the root config. Lets\n * VSCode (and other editors that walk up to find a tsconfig) pick up the\n * inertia-aware aliases automatically when opening files in inertia/.\n */\nexport const INERTIA_TSCONFIG_TEMPLATE = `{\n \"extends\": \"../tsconfig.inertia.json\",\n \"include\": [\n \"**/*\",\n \"../.nestjs-inertia/**/*\",\n \"../nestjs-inertia.d.ts\"\n ],\n \"exclude\": [\n \"node_modules\",\n \"**/*.test.ts\",\n \"**/*.test.tsx\",\n \"**/*.spec.ts\",\n \"**/*.spec.tsx\"\n ]\n}\n`;\n\nconst DTS_TEMPLATE = `// Auto-generated by nestjs-codegen. Commit this file.\n// Re-run \\`nestjs-codegen 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('app/client.${ext}')\n</body>\n</html>\n`;\n}\n\nfunction viteConfigTemplate(framework: Framework): string {\n const pluginOption = `{ ${framework}: true }`;\n return `import { resolve } from 'node:path';\nimport { defineConfig } from 'vite';\nimport nestInertia from '@dudousxd/nestjs-inertia-vite/plugin';\n\nexport default defineConfig({\n plugins: [nestInertia(${pluginOption})],\n resolve: {\n alias: {\n '@': resolve(__dirname, 'src'),\n '~': resolve(__dirname, 'inertia'),\n '~codegen': resolve(__dirname, '.nestjs-inertia'),\n },\n },\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 * Patch `tsconfig.json` to exclude `inertia/` from the server-side TypeScript compilation.\n * Without this, `nest build` fails because `inertia/` files use Vite-only APIs like\n * `import.meta.glob` that are invalid in a Node.js/CommonJS context.\n */\nexport function patchTsconfigExclude(\n cwd: string,\n dir: string,\n filename = 'tsconfig.json',\n): 'patched' | 'already' | 'skipped' {\n const filePath = join(cwd, filename);\n return patchJsonFile(\n filePath,\n (json) => {\n const exclude = (json.exclude ?? []) as string[];\n if (exclude.includes(dir)) return false;\n exclude.push(dir);\n json.exclude = exclude;\n return true;\n },\n // Strip single-line comments before JSON.parse\n (raw) => raw.replace(/\\/\\/.*$/gm, ''),\n );\n}\n\n/**\n * Patch `nest-cli.json` so `nest build` copies the shell template into `dist/`.\n * Without this, Docker images that only ship `dist/` would be missing the rootView file.\n */\nexport function patchNestCliJson(cwd: string, shellDir: string): 'patched' | 'already' | 'skipped' {\n const filePath = join(cwd, 'nest-cli.json');\n return patchJsonFile(filePath, (json) => {\n const compiler = (json.compilerOptions ?? {}) as Record<string, unknown>;\n const assets = (compiler.assets ?? []) as Array<string | Record<string, unknown>>;\n\n const alreadyHas = assets.some((a) => {\n if (typeof a === 'string') return a.includes(shellDir);\n return String(a.include ?? '').includes(shellDir);\n });\n if (alreadyHas) return false;\n\n assets.push({\n include: `../${shellDir}/**/*`,\n outDir: `dist/${shellDir}`,\n watchAssets: true,\n });\n compiler.assets = assets;\n json.compilerOptions = compiler;\n return true;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Main entry — ordered init steps + runner\n// ---------------------------------------------------------------------------\n\n/**\n * Shared context threaded through every init step. Computed once up front so\n * the steps stay pure functions of detected framework/engine + derived paths.\n */\ninterface InitContext {\n opts: RunInitOptions;\n cwd: string;\n framework: Framework;\n engine: TemplateEngine;\n /** Shell file name inside inertia/ (e.g. `index.html`, `index.hbs`). */\n shellFileName: string;\n /** Entry-point extension (`tsx` for react, `ts` otherwise). */\n entryExt: string;\n /** Sample page extension (`tsx` | `vue` | `svelte`). */\n pageExt: string;\n /** Project-relative rootView path (e.g. `inertia/index.html`). */\n rootView: string;\n /** Top-level shell dir (e.g. `inertia`). */\n shellDir: string;\n}\n\ninterface InitStep {\n /** Human-readable label, logged by the runner before the step runs. */\n label: string;\n run: (ctx: InitContext) => void | Promise<void>;\n}\n\n/** Scaffold config, d.ts, tsconfigs, shell, vite config, entry, page, controller. */\nasync function scaffoldFiles(ctx: InitContext): Promise<void> {\n const { cwd, framework, engine, shellFileName, entryExt, pageExt } = ctx;\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 // Dedicated tsconfig for the inertia/ frontend + codegen output. The\n // server tsconfig.json can't typecheck inertia/ because Vite-only APIs\n // (import.meta.glob etc.) break nest build; this one fills that gap.\n await writeIfNotExists(\n join(cwd, 'tsconfig.inertia.json'),\n TSCONFIG_INERTIA_TEMPLATE,\n 'tsconfig.inertia.json',\n );\n\n // Thin tsconfig under inertia/ so VSCode/editors that walk up looking\n // for the closest tsconfig pick up the inertia-aware aliases (~codegen,\n // ~/*) when opening files in inertia/.\n await writeIfNotExists(\n join(cwd, 'inertia', 'tsconfig.json'),\n INERTIA_TSCONFIG_TEMPLATE,\n 'inertia/tsconfig.json',\n );\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', `client.${entryExt}`),\n entryPointTemplate(framework),\n `inertia/app/client.${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\n/** Patch src/app.module.ts (InertiaModule.forRoot + HomeController). */\nfunction patchServerAppModule(ctx: InitContext): void {\n const { cwd, rootView } = ctx;\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\n/** Patch src/main.ts (setupInertiaVite after NestFactory.create). */\nfunction patchServerMainTs(ctx: InitContext): void {\n const mainTsPath = join(ctx.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\n/** Patch nest-cli.json + both tsconfigs (exclude inertia/, then dist/). */\nfunction patchBuildConfigs(ctx: InitContext): void {\n const { cwd, shellDir } = ctx;\n\n // Patch nest-cli.json so `nest build` copies the shell template into dist/\n const nestCliResult = patchNestCliJson(cwd, shellDir);\n if (nestCliResult === 'patched') {\n logPatched('nest-cli.json', `added asset copy for ${shellDir}/ → dist/${shellDir}/`);\n } else if (nestCliResult === 'already') {\n console.log(\n ` ${cyan('→')} nest-cli.json ${dim(`(${shellDir}/ asset already configured, skipped)`)}`,\n );\n } else {\n logWarning('nest-cli.json not found — copy the shell template into dist/ manually');\n }\n\n // Patch tsconfig.json and tsconfig.build.json to exclude the inertia/ dir\n // from the server build. tsconfig.build.json's own `exclude` array overrides\n // the base tsconfig.json when present, so both must be patched.\n for (const tsconfigFile of ['tsconfig.json', 'tsconfig.build.json']) {\n const result = patchTsconfigExclude(cwd, shellDir, tsconfigFile);\n if (result === 'patched') {\n logPatched(tsconfigFile, `excluded ${shellDir}/ from server compilation`);\n } else if (result === 'already') {\n console.log(\n ` ${cyan('→')} ${tsconfigFile} ${dim(`(${shellDir}/ already excluded, skipped)`)}`,\n );\n }\n // 'skipped' = file doesn't exist, silently move on\n }\n}\n\n/** Patch .gitignore, then exclude dist/ from tsconfig.json. */\nasync function patchGitignoreAndDist(ctx: InitContext): Promise<void> {\n const { cwd } = ctx;\n\n await patchGitignore(join(cwd, '.gitignore'));\n\n // Patch tsconfig.json to also exclude `dist` so the server typecheck\n // doesn't walk compiled artifacts under dist/inertia/* and report\n // phantom errors about unresolved aliases in the compiled tree.\n const tsconfigDistResult = patchTsconfigExclude(cwd, 'dist', 'tsconfig.json');\n if (tsconfigDistResult === 'patched') {\n logPatched('tsconfig.json', 'excluded dist/ from server compilation');\n } else if (tsconfigDistResult === 'already') {\n console.log(` ${cyan('→')} tsconfig.json ${dim('(dist/ already excluded, skipped)')}`);\n }\n}\n\n/** Add build:client / build:ssr / typecheck:inertia scripts to package.json. */\nasync function scaffoldPackageScripts(ctx: InitContext): Promise<void> {\n await patchPackageJsonScripts(ctx.cwd, {\n 'build:client': 'vite build',\n 'build:ssr': 'VITE_SSR=1 vite build --ssr',\n 'typecheck:inertia': 'tsc --noEmit -p tsconfig.inertia.json',\n });\n}\n\n/** Install the missing common + framework deps (unless skipInstall). */\nasync function installMissingDeps(ctx: InitContext): Promise<void> {\n const { cwd, framework, opts } = ctx;\n\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\n/**\n * Ordered list of init steps. The first patch step prints the \"Patch existing\n * files\" section header so it appears exactly once, before the first patcher.\n */\nconst INIT_STEPS: InitStep[] = [\n { label: 'scaffold files', run: scaffoldFiles },\n {\n label: 'patch app.module.ts',\n run: (ctx) => {\n logSection('Patch existing files');\n patchServerAppModule(ctx);\n },\n },\n { label: 'patch main.ts', run: patchServerMainTs },\n { label: 'patch build configs', run: patchBuildConfigs },\n { label: 'patch .gitignore + dist exclude', run: patchGitignoreAndDist },\n { label: 'add package.json scripts', run: scaffoldPackageScripts },\n { label: 'install dependencies', run: installMissingDeps },\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. Derive the paths every step needs, build the shared context.\n const shellFileName =\n engine === 'html' ? 'index.html' : `index.${engine === 'handlebars' ? 'hbs' : engine}`;\n const rootView =\n engine === 'html'\n ? 'inertia/index.html'\n : `inertia/index.${engine === 'handlebars' ? 'hbs' : engine}`;\n const ctx: InitContext = {\n opts,\n cwd,\n framework,\n engine,\n shellFileName,\n entryExt: framework === 'react' ? 'tsx' : 'ts',\n pageExt: framework === 'react' ? 'tsx' : framework === 'vue' ? 'vue' : 'svelte',\n rootView,\n shellDir: rootView.split('/')[0]!, // e.g. \"inertia\" from \"inertia/index.html\"\n };\n\n // 4. Run the ordered steps. Each step's label is traced only when\n // NESTJS_CODEGEN_DEBUG is set, so default stdout stays byte-identical.\n for (const step of INIT_STEPS) {\n if (process.env.NESTJS_CODEGEN_DEBUG) {\n console.log(dim(` · ${step.label}`));\n }\n await step.run(ctx);\n }\n\n console.log(`\\n${green('✓')} Setup complete! Run: ${bold('nest start --watch')}\\n`);\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\n\n/**\n * Read a JSON file, run a mutator over the parsed object, and write it back\n * (2-space indent + trailing newline) only when the mutator reports a change.\n *\n * The mutator receives the parsed JSON object and returns:\n * - `true` → the object was changed, rewrite the file → 'patched'\n * - `false` → the object already had what we wanted, leave it → 'already'\n *\n * If the file is missing/unreadable, returns 'skipped' and never writes.\n *\n * `parse` lets a caller pre-process the raw text before JSON.parse (e.g. to\n * strip `//` comments from a tsconfig). Defaults to the identity transform.\n */\nexport function patchJsonFile(\n filePath: string,\n mutator: (json: Record<string, unknown>) => boolean,\n parse: (raw: string) => string = (raw) => raw,\n): 'patched' | 'already' | 'skipped' {\n let raw: string;\n try {\n raw = readFileSync(filePath, 'utf8');\n } catch {\n return 'skipped';\n }\n\n const json = JSON.parse(parse(raw)) as Record<string, unknown>;\n if (!mutator(json)) return 'already';\n\n writeFileSync(filePath, `${JSON.stringify(json, null, 2)}\\n`, 'utf8');\n return 'patched';\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 */\nexport function 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 * Splice an import statement into `content` just after the last existing\n * import. `stmt` must be the bare statement without a trailing newline; a\n * newline is appended. If there is no insertion point (offset 0, i.e. no\n * imports and content doesn't start with `import `), `content` is returned\n * unchanged — matching the original inline guard `if (insertAt > 0)`.\n */\nexport function insertImport(content: string, stmt: string): string {\n const insertAt = findAfterLastImport(content);\n if (insertAt <= 0) return content;\n return `${content.slice(0, insertAt)}${stmt}\\n${content.slice(insertAt)}`;\n}\n"],"mappings":"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","names":["import_promises","import_node_path","import_promises","import_node_path","fg","import_node_path","firstArg","import_promises","import_node_path","import_ts_morph","import_promises","import_node_path","import_promises","import_node_path","import_promises","import_node_path","exports","import_promises","import_node_path","import_promises","import_node_path","import_promises","import_node_path","import_node_path","import_fast_glob","import_ts_morph","import_ts_morph","import_ts_morph","import_node_path","import_ts_morph","reExportsName","sourceName","node","import_ts_morph","import_ts_morph","import_ts_morph","fg","firstArg","import_promises","import_node_path","chokidar","resolve","import_node_child_process","import_node_fs","import_node_path","import_node_fs","import_promises","import_node_path","import_node_fs","resolve","fileExists"]}
1
+ {"version":3,"sources":["../../src/cli/main.ts","../../src/config/load-config.ts","../../src/exceptions.ts","../../src/adapters/registry.ts","../../src/generate.ts","../../src/discovery/pages.ts","../../src/discovery/shared-props.ts","../../src/emit/emit-api.ts","../../src/extension/registry.ts","../../src/extension/types.ts","../../src/emit/emit-cache.ts","../../src/emit/emit-forms.ts","../../src/emit/emit-index.ts","../../src/emit/emit-pages.ts","../../src/emit/emit-routes.ts","../../src/watch/watcher.ts","../../src/discovery/contracts-fast.ts","../../src/discovery/dto-type-resolver.ts","../../src/discovery/dto-to-ir.ts","../../src/discovery/type-ref-resolution.ts","../../src/discovery/filter-for.ts","../../src/discovery/filter-field-types.ts","../../src/discovery/enum-resolution.ts","../../src/discovery/zod-ast-to-ts.ts","../../src/watch/lock-file.ts","../../src/index.ts","../../src/cli/codegen.ts","../../src/cli/doctor.ts","../../src/cli/init.ts","../../src/cli/patch-utils.ts"],"sourcesContent":["import { cac } from 'cac';\nimport { VERSION } from '../index.js';\nimport { runCodegen } from './codegen.js';\nimport { runDoctor } from './doctor.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-codegen');\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.command('init', 'Initialise nestjs-codegen in the current project').action(async () => {\n await runInit({ cwd: process.cwd() });\n });\n\n cli\n .command('doctor', 'Diagnose your nestjs-inertia setup')\n .option('--fix', 'Auto-fix issues where possible')\n .action(async (opts: { fix?: boolean }) => {\n const code = await runDoctor({ cwd: process.cwd(), fix: Boolean(opts.fix) });\n process.exitCode = code;\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-codegen] 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 { resolveAdapter } from '../adapters/registry.js';\nimport { ConfigError } from '../exceptions.js';\nimport type { ResolvedConfig, UserConfig } from './types.js';\n\n/** Config file names, in lookup order. The legacy `nestjs-inertia.config.ts` is\n * still accepted for back-compat with projects migrating from nestjs-inertia. */\nconst CONFIG_FILES = ['nestjs-codegen.config.ts', 'nestjs-inertia.config.ts'] as const;\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\n/**\n * Resolve a {@link UserConfig} (e.g. `NestjsCodegenModule.forRoot()` options) into a\n * fully-defaulted {@link ResolvedConfig} — without reading a config file. Used by the\n * Nest module and any programmatic caller that already holds the config in memory.\n *\n * @param userConfig the raw user config (forRoot options minus module-only fields)\n * @param cwd project root used to resolve globs / outDir. Defaults to `process.cwd()`.\n */\nexport function resolveConfig(userConfig: UserConfigInput, cwd?: string): ResolvedConfig {\n return applyDefaults(userConfig, cwd ?? process.cwd());\n}\n\n/**\n * Loosened {@link UserConfig} where `validation` may be absent. Both config entry\n * points accept this shape and enforce `validation` at runtime (it throws a clear\n * {@link ConfigError} when missing) — letting callers like the Nest module pass\n * partial options without a compile-time `validation` requirement.\n */\ntype UserConfigInput = Omit<UserConfig, 'validation'> & {\n validation?: UserConfig['validation'];\n};\n\n/**\n * Input validation shared by both config entry points ({@link loadConfig} and\n * {@link resolveConfig}). Guards user-provided fields before defaults are applied so\n * the file path and the programmatic `forRoot()` path reject the same bad input.\n */\nfunction validateUserConfig(userConfig: UserConfigInput): void {\n // `validation` is required — no adapter is bundled in core.\n if (userConfig.validation == null) {\n throw new ConfigError(\n 'validation adapter is required — install @dudousxd/nestjs-codegen-zod and pass zodAdapter, or use @dudousxd/nestjs-codegen-valibot / -arktype',\n );\n }\n // `pages` is Inertia-only and optional — but if present, `glob` must be a string.\n if (userConfig.pages && typeof userConfig.pages.glob !== 'string') {\n throw new ConfigError(\n 'Config validation failed: `pages.glob` must be a string when `pages` is set',\n );\n }\n}\n\nfunction applyDefaults(userConfig: UserConfigInput, cwd: string): ResolvedConfig {\n validateUserConfig(userConfig);\n\n const outDir = userConfig.codegen?.outDir\n ? resolveAbsolute(cwd, userConfig.codegen.outDir)\n : join(cwd, '.nestjs-codegen');\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 extensions: userConfig.extensions ?? [],\n // Non-null: validateUserConfig() above throws when `validation` is absent.\n validation: resolveAdapter(userConfig.validation as NonNullable<typeof userConfig.validation>),\n pages: userConfig.pages\n ? {\n glob: userConfig.pages.glob,\n propsExport: userConfig.pages.propsExport ?? 'ComponentProps',\n componentNameStrategy: userConfig.pages.componentNameStrategy ?? 'relative-no-ext',\n }\n : null,\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 fetcher: userConfig.fetcher ?? null,\n forms: {\n enabled: userConfig.forms?.enabled ?? true,\n watch: userConfig.forms?.watch ?? 'src/**/*.dto.ts',\n zodImport: userConfig.forms?.zodImport ?? 'zod',\n },\n };\n}\n\nexport async function loadConfig(cwd?: string): Promise<ResolvedConfig> {\n const resolvedCwd = cwd ?? process.cwd();\n\n let configPath: string | undefined;\n for (const name of CONFIG_FILES) {\n const candidate = join(resolvedCwd, name);\n if (await fileExists(candidate)) {\n configPath = candidate;\n break;\n }\n }\n\n if (!configPath) {\n throw new ConfigError(\n `Config file not found in ${resolvedCwd} (looked for ${CONFIG_FILES.join(', ')})\\nRun \\`nestjs-codegen 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 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 { ConfigError } from '../exceptions.js';\nimport type { ValidationAdapter } from './types.js';\n\n/** A built-in adapter name or a custom adapter instance. */\nexport type ValidationOption = 'zod' | 'valibot' | 'arktype' | ValidationAdapter;\n\n/**\n * Resolve a `validation` config value to a {@link ValidationAdapter}. No adapter is\n * bundled in core — the zod/valibot/arktype adapters ship as their own packages.\n * Import the adapter instance and pass it directly (it passes through here). A\n * custom adapter object also passes through.\n *\n * @example\n * import { zodAdapter } from '@dudousxd/nestjs-codegen-zod';\n * defineConfig({ validation: zodAdapter });\n */\nexport function resolveAdapter(option: ValidationOption): ValidationAdapter {\n if (typeof option !== 'string') return option;\n const pkg = `@dudousxd/nestjs-codegen-${option}`;\n const named = `${option}Adapter`;\n throw new ConfigError(\n `Validation adapter \"${option}\" is not bundled in core. Install ${pkg} and pass the adapter instance instead of the string:\\n\\n import { ${named} } from '${pkg}';\\n defineConfig({ validation: ${named} });`,\n );\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport type { ResolvedConfig } from './config/types.js';\nimport { discoverPages } from './discovery/pages.js';\nimport { discoverSharedPropsFromConfig } from './discovery/shared-props.js';\nimport type { RouteDescriptor } from './discovery/types.js';\nimport { emitApi } from './emit/emit-api.js';\nimport { emitCache } from './emit/emit-cache.js';\nimport { emitForms } from './emit/emit-forms.js';\nimport { emitIndex } from './emit/emit-index.js';\nimport { emitPages } from './emit/emit-pages.js';\nimport { emitRoutes } from './emit/emit-routes.js';\nimport {\n applyTransformRoutes,\n collectEmittedFiles,\n createExtensionContext,\n} from './extension/registry.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 inputRoutes: RouteDescriptor[] = [],\n): Promise<void> {\n // Extensions: run transformRoutes (chained) before any emit so routes.ts/api.ts/\n // forms.ts all see the augmented IR. ctx.routes is a live getter over the active set.\n const extensions = config.extensions ?? [];\n let routes = inputRoutes;\n const ctx = createExtensionContext(config, () => routes);\n if (extensions.length > 0) {\n routes = await applyTransformRoutes(routes, extensions, ctx);\n }\n\n // Inertia page discovery is opt-in — skip entirely when `pages` isn't configured.\n if (config.pages) {\n const pagesConfig = config.pages;\n const pages = await discoverPages({\n glob: pagesConfig.glob,\n cwd: config.codegen.cwd,\n propsExport: pagesConfig.propsExport,\n componentNameStrategy: pagesConfig.componentNameStrategy,\n });\n\n const sharedProps = discoverSharedPropsFromConfig(config);\n\n await emitPages(pages, config.codegen.outDir, {\n propsExport: pagesConfig.propsExport,\n sharedProps,\n });\n await emitCache(pages, config.codegen.outDir);\n }\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 if (hasContracts) {\n await emitApi(routes, config.codegen.outDir, {\n ...(config.fetcher?.importPath ? { fetcherImportPath: config.fetcher.importPath } : {}),\n extensions,\n ctx,\n });\n }\n\n const hasForms = await emitForms(routes, config.codegen.outDir, config.forms, config.validation);\n\n await emitIndex(config.codegen.outDir, hasContracts, hasForms);\n\n // Extensions: write any extra files (collision-checked against each other + core files).\n if (extensions.length > 0) {\n const extraFiles = await collectEmittedFiles(extensions, ctx);\n for (const file of extraFiles) {\n const dest = join(config.codegen.outDir, file.path);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, file.contents, 'utf8');\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { join, 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\n// Files matching these patterns are never treated as Inertia pages even if\n// they sit inside the pages directory and would match the user's glob.\n// Without this filter, vitest test files (`*.test.tsx`) get registered as\n// pages, their imports get pulled into the typecheck graph, and any\n// transitive matcher errors leak into the user's project.\nconst NON_PAGE_FILE_RE = /\\.(?:test|spec|stories|story)\\.(?:tsx?|jsx?|vue|svelte)$/i;\n\nexport async function discoverPages(opts: DiscoverPagesOptions): Promise<DiscoveredPage[]> {\n const allFiles = await fg(opts.glob, { cwd: opts.cwd, absolute: true });\n const files = allFiles.filter((f) => !NON_PAGE_FILE_RE.test(f));\n files.sort();\n // Extract the static prefix from the glob to make page names relative to the pages directory\n // e.g. glob 'inertia/pages/**/*.tsx' → pagesBase 'inertia/pages'\n const globStatic = opts.glob.split('*')[0]?.replace(/\\/$/, '') ?? '';\n const pagesBase = join(opts.cwd, globStatic);\n const out: DiscoveredPage[] = [];\n for (const file of files) {\n const rel = relative(opts.cwd, file);\n const nameRel = relative(pagesBase, file);\n const name = computeName(nameRel, 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","/**\n * Static AST-based discovery of shared props from `InertiaModule.forRoot({ share: ... })`.\n *\n * Analyzes the `share` property in the forRoot call to infer the return type\n * of the share function and generate typed shared props.\n *\n * Gracefully returns null when the share function cannot be analyzed\n * (complex logic, service calls, external references, etc.).\n */\nimport { join } from 'node:path';\nimport { Node, Project, type SourceFile, SyntaxKind } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\n\nexport interface SharedPropsResult {\n /** The TS type string — either `Awaited<ReturnType<typeof import('...').fn>>` or an inline object type */\n typeString: string;\n /** Individual property entries for emitting into an interface body (null when using ReturnType) */\n properties: Array<{ name: string; type: string }> | null;\n /** When true, typeString is a ReturnType<import(...)> expression (not inline) */\n isImportRef: boolean;\n}\n\n/**\n * Discover shared props by analyzing `InertiaModule.forRoot({ share: ... })` in the given module entry file.\n *\n * @param project - ts-morph Project (caller creates it)\n * @param moduleEntry - Absolute path to the NestJS module entry file (e.g. `src/app.module.ts`)\n * @returns SharedPropsResult or null if no share function found or it can't be inferred\n */\nexport function discoverSharedProps(\n project: Project,\n moduleEntry: string,\n): SharedPropsResult | null {\n try {\n let sourceFile = project.getSourceFile(moduleEntry);\n if (!sourceFile) {\n try {\n sourceFile = project.addSourceFileAtPath(moduleEntry);\n } catch {\n return null;\n }\n }\n\n const forRootCall = findForRootCall(sourceFile);\n if (!forRootCall) return null;\n\n const initializer = findShareInitializer(forRootCall);\n if (!initializer) return null;\n\n return extractShareType(initializer, sourceFile, project);\n } catch {\n // Graceful fallback — any unexpected error means we skip shared props typing\n return null;\n }\n}\n\n/**\n * Resolve shared props from a fully-resolved config: builds the ts-morph Project,\n * resolves the tsconfig path, and analyzes the module entry's `forRoot({ share })`.\n *\n * Returns null (swallowing any error) when `app.moduleEntry` isn't configured or\n * anything goes wrong while constructing the project / discovering props — preserving\n * the previous graceful-fallback behavior of the generate orchestrator.\n */\nexport function discoverSharedPropsFromConfig(config: ResolvedConfig): SharedPropsResult | null {\n if (!config.app?.moduleEntry) return null;\n\n try {\n const tsconfigPath = config.app.tsconfig ?? join(config.codegen.cwd, 'tsconfig.json');\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 project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: { allowJs: true, strict: false },\n });\n }\n return discoverSharedProps(project, config.app.moduleEntry);\n } catch {\n // Graceful fallback — skip shared props if anything goes wrong\n return null;\n }\n}\n\n/**\n * Find `InertiaModule.forRoot(...)` call expression in a source file.\n * Searches all call expressions in the file.\n */\nfunction findForRootCall(sourceFile: SourceFile): Node | null {\n const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);\n\n for (const call of callExpressions) {\n const expr = call.getExpression();\n if (!Node.isPropertyAccessExpression(expr)) continue;\n\n const methodName = expr.getName();\n const objectExpr = expr.getExpression();\n\n if (methodName === 'forRoot' && Node.isIdentifier(objectExpr)) {\n const name = objectExpr.getText();\n if (name === 'InertiaModule') {\n return call;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Extract the initializer of the `share` property from the first argument of `forRoot(...)`.\n * Returns the initializer node (the value assigned to `share`), or null if not found.\n */\nfunction findShareInitializer(forRootCall: Node): Node | null {\n if (!Node.isCallExpression(forRootCall)) return null;\n\n const args = forRootCall.getArguments();\n const firstArg = args[0];\n if (!firstArg || !Node.isObjectLiteralExpression(firstArg)) return null;\n\n for (const prop of firstArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'share') {\n return prop.getInitializer() ?? null;\n }\n }\n\n return null;\n}\n\n/**\n * Extract the return type of the share value.\n * Handles:\n * - Arrow functions: `(req) => ({ ... })`\n * - Arrow functions with block body: `(req) => { return { ... }; }`\n * - Function expressions: `function(req) { return { ... }; }`\n * - Async variants of the above\n * - Object literals (plain `share: { ... }`)\n * - Functions with explicit return type annotations\n */\nfunction extractShareType(\n node: Node,\n sourceFile: SourceFile,\n project: Project,\n): SharedPropsResult | null {\n // Priority 1: Reference to a named function → use ReturnType<typeof import(...)>\n if (Node.isIdentifier(node)) {\n const ref = resolveIdentifierToImportRef(node, sourceFile, project);\n if (ref) {\n return {\n typeString: `Awaited<ReturnType<typeof import('${ref.importPath}').${ref.exportName}>>`,\n properties: null,\n isImportRef: true,\n };\n }\n }\n\n // Priority 2: Arrow function → try inline extraction\n if (Node.isArrowFunction(node)) {\n const result = extractFromFunctionLike(node, sourceFile);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n // Priority 3: Function expression → try inline extraction\n if (Node.isFunctionExpression(node)) {\n const result = extractFromFunctionLike(node, sourceFile);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n // Priority 4: Object literal (share: { key: value })\n if (Node.isObjectLiteralExpression(node)) {\n const result = extractFromObjectLiteral(node);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n return null;\n}\n\nfunction resolveIdentifierToImportRef(\n id: Node,\n sourceFile: SourceFile,\n project: Project,\n): { importPath: string; exportName: string } | null {\n if (!Node.isIdentifier(id)) return null;\n const name = id.getText();\n\n const localFunc = sourceFile.getFunction(name);\n if (localFunc?.isExported()) {\n const filePath = sourceFile.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: name };\n }\n\n const localVar = sourceFile.getVariableDeclaration(name);\n if (localVar?.isExported()) {\n const filePath = sourceFile.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: name };\n }\n\n for (const imp of sourceFile.getImportDeclarations()) {\n for (const named of imp.getNamedImports()) {\n const importedName = named.getAliasNode()?.getText() ?? named.getName();\n if (importedName !== name) continue;\n const resolvedSource = imp.getModuleSpecifierSourceFile();\n if (!resolvedSource) continue;\n const originalName = named.getName();\n const fn = resolvedSource.getFunction(originalName);\n if (fn?.isExported()) {\n const filePath = resolvedSource.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: originalName };\n }\n const v = resolvedSource.getVariableDeclaration(originalName);\n if (v?.isExported()) {\n const filePath = resolvedSource.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: originalName };\n }\n }\n }\n\n return null;\n}\n\n/**\n * Extract shared props type from an arrow function or function expression.\n * First tries the return type annotation; falls back to inferring from the return value.\n */\nfunction extractFromFunctionLike(node: Node, _sourceFile: SourceFile): SharedPropsResult | null {\n // Check for explicit return type annotation\n const returnTypeNode =\n Node.isArrowFunction(node) || Node.isFunctionExpression(node) ? node.getReturnTypeNode() : null;\n\n if (returnTypeNode) {\n return extractFromReturnTypeAnnotation(returnTypeNode);\n }\n\n // Infer from body\n if (Node.isArrowFunction(node)) {\n const body = node.getBody();\n\n // Concise body: (req) => ({ auth: ..., flash: ... })\n if (Node.isParenthesizedExpression(body)) {\n const inner = body.getExpression();\n if (Node.isObjectLiteralExpression(inner)) {\n return extractFromObjectLiteral(inner);\n }\n }\n\n // Direct object literal (less common but possible with as const)\n if (Node.isObjectLiteralExpression(body)) {\n return extractFromObjectLiteral(body);\n }\n\n // Block body: (req) => { return { ... }; }\n if (Node.isBlock(body)) {\n return extractFromBlockReturn(body);\n }\n }\n\n if (Node.isFunctionExpression(node)) {\n const body = node.getBody();\n if (Node.isBlock(body)) {\n return extractFromBlockReturn(body);\n }\n }\n\n return null;\n}\n\n/**\n * Extract type from a return type annotation on the share function.\n * e.g. `(req): { auth: User | null; flash: {} } => ...`\n */\nfunction extractFromReturnTypeAnnotation(typeNode: Node): SharedPropsResult | null {\n // Unwrap Promise<T> if async\n if (Node.isTypeReference(typeNode)) {\n const typeName = typeNode.getTypeName();\n if (Node.isIdentifier(typeName) && typeName.getText() === 'Promise') {\n const typeArgs = typeNode.getTypeArguments();\n const firstArg = typeArgs[0];\n if (firstArg) {\n return extractFromReturnTypeAnnotation(firstArg);\n }\n return null;\n }\n }\n\n // TypeLiteral: { auth: ...; flash: ... }\n if (Node.isTypeLiteral(typeNode)) {\n const properties: Array<{ name: string; type: string }> = [];\n for (const member of typeNode.getMembers()) {\n if (Node.isPropertySignature(member)) {\n const name = member.getName();\n const memberTypeNode = member.getTypeNode();\n const type = memberTypeNode ? memberTypeNode.getText() : 'unknown';\n properties.push({ name, type });\n }\n }\n if (properties.length === 0) return null;\n const typeString = `{ ${properties.map((p) => `${p.name}: ${p.type}`).join('; ')} }`;\n return { typeString, properties, isImportRef: false };\n }\n\n return null;\n}\n\n/**\n * Extract shared props from a block body's return statement.\n * Only handles the simple case: a single return statement with an object literal.\n */\nfunction extractFromBlockReturn(block: Node): SharedPropsResult | null {\n if (!Node.isBlock(block)) return null;\n\n const statements = block.getStatements();\n // Find the last return statement\n for (let i = statements.length - 1; i >= 0; i--) {\n const stmt = statements[i];\n if (!Node.isReturnStatement(stmt)) continue;\n\n const expr = stmt.getExpression();\n if (!expr) continue;\n\n if (Node.isObjectLiteralExpression(expr)) {\n return extractFromObjectLiteral(expr);\n }\n\n // Parenthesized: return ({ ... })\n if (Node.isParenthesizedExpression(expr)) {\n const inner = expr.getExpression();\n if (Node.isObjectLiteralExpression(inner)) {\n return extractFromObjectLiteral(inner);\n }\n }\n\n break;\n }\n\n return null;\n}\n\n/**\n * Infer shared props type from an object literal expression.\n * Each property key becomes a shared prop; the value type is inferred from the value expression.\n */\nfunction extractFromObjectLiteral(objLiteral: Node): SharedPropsResult | null {\n if (!Node.isObjectLiteralExpression(objLiteral)) return null;\n\n const properties: Array<{ name: string; type: string }> = [];\n\n for (const prop of objLiteral.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n\n const name = prop.getName();\n const initializer = prop.getInitializer();\n if (!initializer) continue;\n\n const type = inferExpressionType(initializer);\n properties.push({ name, type });\n }\n\n if (properties.length === 0) return null;\n\n const typeString = `{ ${properties.map((p) => `${p.name}: ${p.type}`).join('; ')} }`;\n return { typeString, properties, isImportRef: false };\n}\n\n/**\n * Infer the TypeScript type of an expression.\n * Handles common patterns found in share functions:\n * - Object literals → `{ key: type; ... }`\n * - String literals → `string`\n * - Number literals → `number`\n * - Boolean literals → `boolean`\n * - Null → `null`\n * - Array literals → `Array<type>`\n * - Ternary expressions → `trueType | falseType`\n * - Property accesses and complex expressions → `unknown`\n * - Empty object literal → `Record<string, unknown>`\n */\nfunction inferExpressionType(node: Node): string {\n // String literal\n if (Node.isStringLiteral(node)) return 'string';\n\n // Template literal (backtick)\n if (Node.isTemplateExpression(node) || Node.isNoSubstitutionTemplateLiteral(node))\n return 'string';\n\n // Number literal\n if (Node.isNumericLiteral(node)) return 'number';\n\n // Boolean literal\n if (node.getKind() === SyntaxKind.TrueKeyword || node.getKind() === SyntaxKind.FalseKeyword) {\n return 'boolean';\n }\n\n // Null literal\n if (node.getKind() === SyntaxKind.NullKeyword) return 'null';\n\n // Undefined\n if (Node.isIdentifier(node) && node.getText() === 'undefined') return 'undefined';\n\n // Object literal\n if (Node.isObjectLiteralExpression(node)) {\n const props = node.getProperties();\n if (props.length === 0) return 'Record<string, unknown>';\n\n const entries: string[] = [];\n for (const prop of props) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const key = prop.getName();\n const init = prop.getInitializer();\n if (!init) continue;\n entries.push(`${key}: ${inferExpressionType(init)}`);\n }\n if (entries.length === 0) return 'Record<string, unknown>';\n return `{ ${entries.join('; ')} }`;\n }\n\n // Array literal\n if (Node.isArrayLiteralExpression(node)) {\n const elements = node.getElements();\n if (elements.length === 0) return 'Array<unknown>';\n // Infer from first element\n const first = elements[0];\n if (first) return `Array<${inferExpressionType(first)}>`;\n return 'Array<unknown>';\n }\n\n // Ternary (conditional) expression: x ? A : B → A | B\n if (Node.isConditionalExpression(node)) {\n const whenTrue = inferExpressionType(node.getWhenTrue());\n const whenFalse = inferExpressionType(node.getWhenFalse());\n if (whenTrue === whenFalse) return whenTrue;\n return `${whenTrue} | ${whenFalse}`;\n }\n\n // Parenthesized expression — unwrap\n if (Node.isParenthesizedExpression(node)) {\n return inferExpressionType(node.getExpression());\n }\n\n // As expression (type assertion): expr as Type → use the asserted type\n if (Node.isAsExpression(node)) {\n const typeNode = node.getTypeNode();\n if (typeNode) return typeNode.getText();\n }\n\n // For any other expression (property access, function calls, etc.), fall back to unknown\n return 'unknown';\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative } from 'node:path';\nimport type {\n ContractSource,\n ControllerRef,\n FieldTypeKind,\n FilterFieldType,\n RouteDescriptor,\n} from '../discovery/types.js';\nimport { mergeExclusive, resolveApiSlots } from '../extension/registry.js';\nimport { requestShape } from '../extension/types.js';\nimport type {\n ApiClientLayer,\n CodegenExtension,\n ExtensionContext,\n LeafModel,\n RequestModel,\n} from '../extension/types.js';\n\n/**\n * Emits `api.ts` into `outDir` for all routes that carry a `.contract`.\n *\n * By default each leaf is a bare typed-fetch callable. Registered extensions shape the\n * output: an `apiClientLayer` (e.g. `@dudousxd/nestjs-codegen-tanstack`) turns leaves into\n * handles wrapping the neutral fetcher request; `apiMembers` add handle members; `apiHeader`\n * contributes top-level imports/statements.\n */\nexport interface ApiEmitOptions {\n fetcherImportPath?: string;\n /** Registered extensions. Their api.ts hooks (transport/layer/members/header) are applied. */\n extensions?: CodegenExtension[];\n /** Shared extension context (from `generate()`). When omitted, a minimal one is built from routes. */\n ctx?: ExtensionContext;\n}\n\nexport async function emitApi(\n routes: RouteDescriptor[],\n outDir: string,\n opts: ApiEmitOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const content = buildApiFile(routes, outDir, opts);\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 params: Array<{ name: string; source: string }>;\n controllerRef?: ControllerRef | undefined;\n // Reference the canonical discovery type directly rather than re-declaring a\n // parallel hand-maintained shape. The leaf is always built from a real\n // `ContractSource` (`contractSource: r.contract.contractSource`), so the extra\n // form/zod fields it carries are simply unused here.\n contractSource: ContractSource;\n // The real, un-narrowed `RouteDescriptor` this leaf was built from. Stored so\n // extension hooks receive the canonical route with no reconstruction/force-cast.\n route: RouteDescriptor;\n};\n\ntype BranchEntry = {\n kind: 'branch';\n children: Map<string, TreeNode>;\n};\n\ntype TreeNode = LeafEntry | BranchEntry;\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// Params helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build a TypeScript type literal for path params.\n * Returns 'never' when the route has no path params.\n */\nfunction buildParamsType(params: Array<{ name: string; source: string }>): string {\n const pathParams = params.filter((p) => p.source === 'path');\n if (pathParams.length === 0) return 'never';\n return `{ ${pathParams.map((p) => `${p.name}: string`).join('; ')} }`;\n}\n\n/**\n * Check whether a route has any path params.\n */\nfunction hasPathParams(params: Array<{ name: string; source: string }>): boolean {\n return params.some((p) => p.source === 'path');\n}\n\n// ---------------------------------------------------------------------------\n// Code generation helpers\n// ---------------------------------------------------------------------------\n\n/** Map a classified field kind (+ enum members) to a TS type literal. */\nfunction kindToTs(kind: FieldTypeKind, enumValues?: string[], numericEnum?: boolean): string {\n if (enumValues && enumValues.length > 0) {\n return enumValues.map((v) => (numericEnum ? v : JSON.stringify(v))).join(' | ');\n }\n switch (kind) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'date':\n return 'Date';\n case 'json':\n return 'Record<string, unknown>';\n default:\n return 'unknown';\n }\n}\n\n/**\n * Emit the per-field type map literal: `{ \"age\": number; \"status\": \"A\" | \"B\" }`.\n * This is the SOLE emit-side reader of `FilterFieldType` — it owns the `typeRef`\n * precedence invariant (a named ref wins over `kind`/`enumValues`; see the\n * `FilterFieldType` doc). No other emit code branches on `typeRef` vs `kind`.\n */\nfunction emitFieldTypesLiteral(fts: FilterFieldType[]): string {\n const entries = fts.map((f) => {\n // A named typeRef (enum / type alias / interface inferred from a @FilterFor\n // method parameter) wins — reference it by name; the import is emitted at\n // the top of the file by buildApiFile.\n let t = f.typeRef ? f.typeRef.name : kindToTs(f.kind, f.enumValues, f.numericEnum);\n if (f.nullable) t = `${t} | null`;\n return `${JSON.stringify(f.name)}: ${t}`;\n });\n return `{ ${entries.join('; ')} }`;\n}\n\n/** Build the type args for `_filterQueryTyped` — single union, or union + field-type map. */\nfunction emitFilterQueryTypeArgs(c: LeafEntry): string {\n const fieldsUnion = (c.contractSource.filterFields ?? [])\n .map((f) => JSON.stringify(f))\n .join(' | ');\n const fts = c.contractSource.filterFieldTypes;\n return fts?.length ? `${fieldsUnion}, ${emitFieldTypesLiteral(fts)}` : fieldsUnion;\n}\n\n/**\n * Build the `TypedFilterQuery<...>` TYPE for a query-source `@ApplyFilter` route's\n * `query` position. Built from the SAME `emitFilterQueryTypeArgs` used by the\n * `_filterQueryTyped<...>` factory so the two are byte-identical.\n */\nfunction emitFilterQueryType(c: LeafEntry): string {\n return `import('@dudousxd/nestjs-filter-client').TypedFilterQuery<${emitFilterQueryTypeArgs(c)}>`;\n}\n\n/**\n * Emit the nested ApiRouter type block.\n */\nfunction buildResponseType(c: LeafEntry, outDir: string): string {\n if (c.controllerRef) {\n let relPath = relative(outDir, c.controllerRef.filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n return `Awaited<ReturnType<import('${relPath}').${c.controllerRef.className}['${c.controllerRef.methodName}']>>`;\n }\n const respRef = c.contractSource.responseRef;\n if (respRef) {\n return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;\n }\n return c.contractSource.response;\n}\n\nfunction emitRouterTypeBlock(\n tree: Map<string, TreeNode>,\n indent: number,\n outDir: string,\n): 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 queryRef = c.contractSource.queryRef;\n // A query-source `@ApplyFilter` route renders its `TypedFilterQuery<...>`\n // type here — from the same `filterFields`/`filterFieldTypes` data the\n // `_filterQueryTyped<...>` factory uses — so both are byte-identical.\n const isFilterQuery =\n c.contractSource.filterSource === 'query' && !!c.contractSource.filterFields?.length;\n const query = queryRef\n ? queryRef.isArray\n ? `Array<${queryRef.name}>`\n : queryRef.name\n : isFilterQuery\n ? emitFilterQueryType(c)\n : (c.contractSource.query ?? 'never');\n const bodyRef = c.contractSource.bodyRef;\n const body =\n method === 'GET'\n ? 'never'\n : bodyRef\n ? bodyRef.isArray\n ? `Array<${bodyRef.name}>`\n : bodyRef.name\n : (c.contractSource.body ?? 'never');\n const response = buildResponseType(c, outDir);\n const params = buildParamsType(c.params);\n const safeMethod = JSON.stringify(method);\n const safeUrl = JSON.stringify(c.path);\n // Filterable fields (from @dudousxd/nestjs-filter) as a string-literal\n // union, or `never` for routes without a filter. Purely type-level — no\n // runtime dependency on nestjs-filter is introduced by this member.\n const filterFields = c.contractSource.filterFields?.length\n ? c.contractSource.filterFields.map((f) => JSON.stringify(f)).join(' | ')\n : 'never';\n lines.push(\n `${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; params: ${params}; query: ${query}; body: ${body}; response: ${response}; filterFields: ${filterFields} };`,\n );\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));\n lines.push(`${pad}};`);\n }\n }\n\n return lines;\n}\n\n/**\n * Build the neutral per-leaf {@link RequestModel} from a discovered leaf. This is the\n * input every transport/layer/member-contributor reads — the seam the extension system\n * plugs into. Pure string-building; no I/O.\n */\nfunction buildRequestModel(c: LeafEntry): RequestModel {\n const m = c.method.toLowerCase() as RequestModel['method'];\n const flat = JSON.stringify(c.name);\n const path = JSON.stringify(c.path);\n const TA = buildRouterTypeAccess(c.name);\n const withParams = hasPathParams(c.params);\n // Request-shape flags (\"filter-search POST counts as a read\") computed in one place.\n const { isGet, isQuery, hasBody, hasQuery } = requestShape(c.route);\n\n const fields: string[] = [];\n if (withParams) fields.push(`params: ${TA}['params']`);\n if (hasQuery) fields.push(`query?: ${TA}['query']`);\n if (hasBody) fields.push(`body?: ${TA}['body']`);\n const inputType = fields.length ? `{ ${fields.join('; ')} }` : 'Record<string, never>';\n\n const urlExpr = withParams\n ? `route(${flat} as never, input?.params as never) || ${path}`\n : `route(${flat} as never) || ${path}`;\n const optsParts: string[] = [];\n if (hasQuery) optsParts.push('query: input?.query as Record<string, unknown> | undefined');\n if (hasBody) optsParts.push('body: input?.body');\n const optsExpr = optsParts.length ? `{ ${optsParts.join(', ')} }` : '{}';\n\n return {\n routeName: c.name,\n method: m,\n isGet,\n isQuery,\n hasParams: withParams,\n hasBody,\n inputType,\n urlExpr,\n optsExpr,\n responseType: `${TA}['response']`,\n queryKeyExpr: `[${flat}, input] as const`,\n };\n}\n\n/**\n * The neutral fetcher request: a typed call on the injected `fetcher`. Every leaf is built\n * on this; a registered `apiClientLayer` wraps it (e.g. into a TanStack handle), otherwise\n * the leaf is the bare awaitable callable.\n */\nfunction renderFetcherRequest(req: RequestModel): string {\n return `fetcher.${req.method}<${req.responseType}>(${req.urlExpr}, ${req.optsExpr})`;\n}\n\n/**\n * The `__req` runtime helper, emitted once per `api.ts`. Wraps a request thunk into an\n * **awaitable handle**: `await api.x.y({...})` runs the fetch (Tuyau-style), memoized so\n * repeated awaits hit the network once. Client-layer extensions (e.g. TanStack) spread\n * extra members (`queryOptions`/`mutationOptions`/…) onto the same handle.\n */\nfunction emitReqHelper(): string[] {\n return [\n '/** Awaitable request handle. `await api.x.y({...})` runs the fetch; extensions add query/mutation helpers. */',\n 'type __Req<R> = {',\n ' then<T1 = R, T2 = never>(',\n ' onfulfilled?: ((value: R) => T1 | PromiseLike<T1>) | null,',\n ' onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null,',\n ' ): Promise<T1 | T2>;',\n ' catch<T = never>(onrejected?: ((reason: unknown) => T | PromiseLike<T>) | null): Promise<R | T>;',\n ' finally(onfinally?: (() => void) | null): Promise<R>;',\n ' fetch(): Promise<R>;',\n '};',\n 'function __req<R>(run: () => Promise<R>): __Req<R> {',\n ' let __p: Promise<R> | undefined;',\n ' const __promise = () => {',\n ' __p ??= run();',\n ' return __p;',\n ' };',\n ' return {',\n ' then: (onfulfilled, onrejected) => __promise().then(onfulfilled, onrejected),',\n ' catch: (onrejected) => __promise().catch(onrejected),',\n ' finally: (onfinally) => __promise().finally(onfinally),',\n ' fetch: run,',\n ' };',\n '}',\n '',\n ];\n}\n\n/**\n * Render one leaf. Every leaf is an **awaitable handle**: the `__req(...)` base makes\n * `await api.x.y({...})` perform the request; any client-layer/member contributions\n * (TanStack options, filterQuery, …) are spread on alongside it.\n */\nfunction renderLeaf(\n pad: string,\n objKey: string,\n req: RequestModel,\n requestExpr: string,\n members: Record<string, string>,\n): string[] {\n const lines = [`${pad}${objKey}: (input?: ${req.inputType}) => ({`];\n lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);\n for (const [name, value] of Object.entries(members)) {\n lines.push(`${pad} ${name}: ${value},`);\n }\n lines.push(`${pad}}),`);\n return lines;\n}\n\n/** Resolved api.ts pipeline pieces, threaded through the recursive emit. */\ninterface ApiPipeline {\n layer?: ApiClientLayer;\n memberExts: CodegenExtension[];\n ctx: ExtensionContext;\n}\n\n/**\n * Emit the nested `api` object body via the LeafModel pipeline:\n * build model → neutral fetcher request → layer (when a client layer is registered)\n * → member contributors (bundled filter + extensions' apiMembers) → render. With no layer\n * a leaf is a bare typed-fetch callable; a layer flips it into a handle.\n */\nfunction emitApiObjectBlock(tree: Map<string, TreeNode>, indent: number, p: ApiPipeline): 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 === 'branch') {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitApiObjectBlock(node.children, indent + 2, p));\n lines.push(`${pad}},`);\n continue;\n }\n\n const req = buildRequestModel(node);\n // Hand extension hooks the real, un-narrowed RouteDescriptor stored on the leaf —\n // no reconstruction or force-cast.\n const leaf: LeafModel = {\n route: node.route,\n request: req,\n requestExpr: renderFetcherRequest(req),\n };\n\n // Every leaf is an awaitable handle (the __req base). A client layer (TanStack) spreads\n // query/mutation helpers on top; extension apiMembers (e.g. nestjs-filter's filterQuery)\n // add further members. Member-name collisions across extensions are an error — enforced\n // by the same exclusive-ownership policy as file collisions.\n const owned = new Map<string, { value: string; owner: string }>();\n if (p.layer) {\n mergeExclusive(owned, Object.entries(p.layer.buildMembers(leaf.requestExpr, leaf, p.ctx)), {\n owner: p.layer.name,\n describe: (name, prevOwner, owner) =>\n `api member \"${name}\" on route \"${req.routeName}\" is contributed by more than one extension (conflict between \"${prevOwner}\" and \"${owner}\").`,\n });\n }\n for (const ext of p.memberExts) {\n const extra = ext.apiMembers?.(leaf, p.ctx);\n if (!extra) continue;\n mergeExclusive(owned, Object.entries(extra), {\n owner: ext.name,\n describe: (name, prevOwner, owner) =>\n `api member \"${name}\" on route \"${req.routeName}\" is contributed by more than one extension (conflict between \"${prevOwner}\" and \"${owner}\").`,\n });\n }\n const members: Record<string, string> = {};\n for (const [name, { value }] of owned) members[name] = value;\n\n lines.push(...renderLeaf(pad, objKey, req, leaf.requestExpr, members));\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// Static api.ts text blocks\n// ---------------------------------------------------------------------------\n//\n// These are pure constants — the same bytes in every emitted api.ts — so they\n// live here as module-level templates rather than being assembled line-by-line\n// inside `buildApiFile`. `RESOLVER_HELPERS` + `ROUTE_NAMESPACE` + `PATH_NAMESPACE`\n// are the populated form (resolver-backed). `EMPTY_*` are the no-routes form,\n// where there is nothing to resolve so the namespaces collapse to `never` stubs\n// and the resolver helpers are omitted entirely. The two forms are intentionally\n// distinct text (the empty `Request` is a one-liner, the populated one is not),\n// so they are separate constants rather than one parameterised template.\n\n/** Recursive resolver helpers (`_RouterAt`/`ResolveByName`/`_LeafValues`/`ResolveByPath`). */\nconst RESOLVER_HELPERS: readonly string[] = [\n // --- Recursive helper type _RouterAt: walks nested ApiRouter by dot-path ---\n 'type _RouterAt<R, P extends string> = P extends `${infer Head}.${infer Tail}`',\n ' ? Head extends keyof R ? _RouterAt<R[Head], Tail> : never',\n ' : P extends keyof R ? R[P] : never;',\n '',\n // --- ResolveByName: resolve a field from a dot-path name ---\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 // --- ResolveByPath: scan all leaves for matching method + url ---\n // Flattens ApiRouter recursively and finds the entry whose method === M and url === U.\n 'type _LeafValues<T> = T extends { method: string; url: string }',\n ' ? T',\n ' : T extends object ? _LeafValues<T[keyof T]> : never;',\n '',\n 'type ResolveByPath<M extends string, U extends string, Field extends string> = _LeafValues<ApiRouter> extends infer L',\n ' ? L extends { method: M; url: U }',\n ' ? Field extends keyof L ? L[Field] : never',\n ' : never',\n ' : never;',\n '',\n];\n\n/** Populated `Route` namespace — resolves fields by dot-path name. */\nconst ROUTE_NAMESPACE: readonly string[] = [\n 'export namespace Route {',\n ' export type Response<K extends string> = ResolveByName<K, \"response\">;',\n ' export type Body<K extends string> = ResolveByName<K, \"body\">;',\n ' export type Query<K extends string> = ResolveByName<K, \"query\">;',\n ' export type Params<K extends string> = ResolveByName<K, \"params\">;',\n ' export type Error<K extends string> = ResolveByName<K, \"error\">;',\n ' export type FilterFields<K extends string> = ResolveByName<K, \"filterFields\">;',\n ' export type Request<K extends string> = {',\n ' body: Body<K>;',\n ' query: Query<K>;',\n ' params: Params<K>;',\n ' };',\n '}',\n '',\n];\n\n/** Populated `Path` namespace — resolves fields by method + url. */\nconst PATH_NAMESPACE: readonly string[] = [\n 'export namespace Path {',\n ' export type Response<M extends string, U extends string> = ResolveByPath<M, U, \"response\">;',\n ' export type Body<M extends string, U extends string> = ResolveByPath<M, U, \"body\">;',\n ' export type Query<M extends string, U extends string> = ResolveByPath<M, U, \"query\">;',\n ' export type Params<M extends string, U extends string> = ResolveByPath<M, U, \"params\">;',\n ' export type Error<M extends string, U extends string> = ResolveByPath<M, U, \"error\">;',\n ' export type FilterFields<M extends string, U extends string> = ResolveByPath<M, U, \"filterFields\">;',\n '}',\n '',\n];\n\n/** Empty-routes form: nothing to resolve, so every namespace member is `never`. */\nconst EMPTY_ROUTE_NAMESPACE: readonly string[] = [\n 'export namespace Route {',\n ' export type Response<K extends string> = never;',\n ' export type Body<K extends string> = never;',\n ' export type Query<K extends string> = never;',\n ' export type Params<K extends string> = never;',\n ' export type Error<K extends string> = never;',\n ' export type FilterFields<K extends string> = never;',\n ' export type Request<K extends string> = { body: never; query: never; params: never };',\n '}',\n '',\n];\n\nconst EMPTY_PATH_NAMESPACE: readonly string[] = [\n 'export namespace Path {',\n ' export type Response<M extends string, U extends string> = never;',\n ' export type Body<M extends string, U extends string> = never;',\n ' export type Query<M extends string, U extends string> = never;',\n ' export type Params<M extends string, U extends string> = never;',\n ' export type Error<M extends string, U extends string> = never;',\n ' export type FilterFields<M extends string, U extends string> = never;',\n '}',\n '',\n];\n\n// ---------------------------------------------------------------------------\n// Main builder\n// ---------------------------------------------------------------------------\n\nfunction buildApiFile(\n routes: RouteDescriptor[],\n outDir?: string,\n opts: ApiEmitOptions = {},\n): string {\n const fetcherImportPath = opts.fetcherImportPath;\n const extensions = opts.extensions ?? [];\n const { layer } = resolveApiSlots(extensions);\n const memberExts = extensions.filter((e) => e.apiMembers);\n const headerExts = extensions.filter((e) => e.apiHeader);\n const contracted = routes.filter((r) => r.contract);\n\n // Extension context for the api.ts hooks. `generate()` passes the real one; standalone\n // `emitApi` calls (tests) get a minimal context exposing the routes (all the bundled\n // layer/transport read). `project()` is unavailable in the standalone path.\n const ctx: ExtensionContext =\n opts.ctx ??\n ({\n cwd: outDir ?? '',\n outDir: outDir ?? '',\n routes,\n config: {} as never,\n project: () => {\n throw new Error('ExtensionContext.project() is unavailable in standalone emitApi.');\n },\n } satisfies ExtensionContext);\n\n // Collect all type refs for import generation\n const importsByFile = new Map<string, Set<string>>();\n for (const r of contracted) {\n const cs = r.contract?.contractSource;\n if (!cs) continue;\n // When controllerRef exists, response uses ReturnType<import(...)> — skip response import\n const refs = r.controllerRef\n ? [cs.queryRef, cs.bodyRef]\n : [cs.queryRef, cs.bodyRef, cs.responseRef];\n for (const ref of refs) {\n if (!ref) continue;\n let names = importsByFile.get(ref.filePath);\n if (!names) {\n names = new Set();\n importsByFile.set(ref.filePath, names);\n }\n names.add(ref.name);\n }\n // Named enum / type-alias / interface refs inferred from @FilterFor method\n // params (the type map M references them by name → emit `import type` too).\n for (const ft of cs.filterFieldTypes ?? []) {\n if (!ft.typeRef) continue;\n let names = importsByFile.get(ft.typeRef.filePath);\n if (!names) {\n names = new Set();\n importsByFile.set(ft.typeRef.filePath, names);\n }\n names.add(ft.typeRef.name);\n }\n }\n\n const lines: string[] = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.', ''];\n\n // Extension-contributed module imports (client layer + apiHeader), deduped and emitted\n // in order. e.g. the TanStack layer emits its queryOptions/mutationOptions import here.\n const extImports: string[] = [];\n const seenImports = new Set<string>();\n const pushImport = (imp: string): void => {\n if (seenImports.has(imp)) return;\n seenImports.add(imp);\n extImports.push(imp);\n };\n for (const imp of layer?.imports?.(ctx) ?? []) pushImport(imp);\n for (const ext of headerExts) {\n for (const imp of ext.apiHeader?.(ctx)?.imports ?? []) pushImport(imp);\n }\n lines.push(...extImports);\n\n lines.push(\n \"import { route, ROUTES, type RouteName, type ExtractParams, type RouteParams } from './routes.js';\",\n );\n // Tuyau-style: the api is a factory that takes the fetcher at runtime, so the\n // app injects its own client (custom transport/axios, baseUrl, superjson) —\n // rather than the codegen hardcoding `import { fetcher } from '<path>'`.\n const runtimeImport = fetcherImportPath ?? '@dudousxd/nestjs-client';\n lines.push(`import type { Fetcher } from '${runtimeImport}';`);\n\n // Emit type imports from source files.\n // When two different files export the same type name, alias the duplicate\n // to avoid `Identifier has already been declared` parse errors.\n if (importsByFile.size > 0 && outDir) {\n lines.push('');\n const emittedNames = new Set<string>();\n for (const [filePath, names] of importsByFile) {\n // Bare module specifier (node_modules package) → import as-is. Local\n // source files are always absolute paths → compute a relative import.\n let relPath: string;\n if (isAbsolute(filePath)) {\n relPath = relative(outDir, filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n } else {\n relPath = filePath;\n }\n const specifiers: string[] = [];\n for (const name of [...names].sort()) {\n if (emittedNames.has(name)) {\n const alias = `${name}_${emittedNames.size}`;\n specifiers.push(`${name} as ${alias}`);\n emittedNames.add(alias);\n } else {\n specifiers.push(name);\n emittedNames.add(name);\n }\n }\n lines.push(`import type { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n }\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 function createApi(_fetcher: Fetcher): Record<string, never> {');\n lines.push(' return {};');\n lines.push('}');\n lines.push('export type Api = ReturnType<typeof createApi>;');\n lines.push('');\n lines.push(...EMPTY_ROUTE_NAMESPACE);\n lines.push(...EMPTY_PATH_NAMESPACE);\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 params: r.params,\n controllerRef: r.controllerRef,\n contractSource: c.contractSource,\n route: r,\n };\n insertIntoTree(tree, segments, leaf, name);\n }\n\n // --- ApiRouter type ---\n lines.push('export type ApiRouter = {');\n lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ''));\n lines.push('};');\n lines.push('');\n\n // --- awaitable request handle helper ---\n lines.push(...emitReqHelper());\n\n // --- api factory (inject your fetcher at runtime) ---\n lines.push('export function createApi(fetcher: Fetcher) {');\n lines.push(' return {');\n lines.push(\n ...emitApiObjectBlock(tree, 4, {\n ...(layer ? { layer } : {}),\n memberExts,\n ctx,\n }),\n );\n lines.push(' };');\n lines.push('}');\n lines.push('');\n lines.push('export type Api = ReturnType<typeof createApi>;');\n lines.push('');\n\n lines.push(...RESOLVER_HELPERS);\n lines.push(...ROUTE_NAMESPACE);\n lines.push(...PATH_NAMESPACE);\n\n // Extension-contributed top-level statements (e.g. the Inertia extension's navigate()).\n for (const ext of headerExts) {\n const statements = ext.apiHeader?.(ctx)?.statements;\n if (statements?.length) {\n lines.push(...statements, '');\n }\n }\n\n return lines.join('\\n');\n}\n","import { Project } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport { CodegenError } from '../exceptions.js';\nimport type { ApiClientLayer, CodegenExtension, EmittedFile, ExtensionContext } from './types.js';\n\n/**\n * Resolve the single-slot `apiClientLayer` hook. At most one extension may claim it;\n * a second claimer throws a {@link CodegenError} naming both extensions. An unclaimed\n * `apiClientLayer` means leaves stay bare callables backed by the neutral fetcher.\n */\nexport function resolveApiSlots(extensions: readonly CodegenExtension[]): {\n layer?: ApiClientLayer;\n} {\n let layer: ApiClientLayer | undefined;\n let layerOwner: string | undefined;\n\n for (const ext of extensions) {\n if (ext.apiClientLayer) {\n if (layer) {\n throw new CodegenError(\n `api client layer claimed by both \"${layerOwner}\" and \"${ext.name}\" — only one extension may set apiClientLayer.`,\n );\n }\n layer = ext.apiClientLayer;\n layerOwner = ext.name;\n }\n }\n\n return {\n ...(layer ? { layer } : {}),\n };\n}\n\n/** Output filenames the core always owns — an extension emitting one of these is an error. */\nconst CORE_FILES = new Set(['routes.ts', 'api.ts', 'forms.ts', 'index.d.ts', 'pages.d.ts']);\n\n/**\n * Merge `incoming` entries into `target`, enforcing a single exclusive-ownership policy:\n * a key already present in `target` is a collision and throws, naming the prior owner and\n * the offending extension. One collision format for every \"two extensions both produced X\"\n * case (api members, emitted files, …).\n *\n * @param target the accumulating map (key → value); also records ownership.\n * @param incoming entries the current extension contributes.\n * @param owner the extension currently contributing (named in the error).\n * @param describe builds the error message given the colliding key, prior owner and owner.\n */\nexport function mergeExclusive<V>(\n target: Map<string, { value: V; owner: string }>,\n incoming: Iterable<readonly [string, V]>,\n {\n owner,\n describe,\n }: {\n owner: string;\n describe: (key: string, prevOwner: string, owner: string) => string;\n },\n): void {\n for (const [key, value] of incoming) {\n const prev = target.get(key);\n if (prev !== undefined) {\n throw new CodegenError(describe(key, prev.owner, owner));\n }\n target.set(key, { value, owner });\n }\n}\n\n/**\n * Build the shared {@link ExtensionContext}. `routes` is exposed as a live getter so an\n * extension reading `ctx.routes` during `emitFiles` sees the post-`transformRoutes` IR.\n * The ts-morph `Project` is created lazily on first `project()` call (extensions that do\n * no AST work never pay for it).\n */\nexport function createExtensionContext(\n config: ResolvedConfig,\n getRoutes: () => readonly RouteDescriptor[],\n): ExtensionContext {\n let project: Project | undefined;\n return {\n cwd: config.codegen.cwd,\n outDir: config.codegen.outDir,\n config,\n get routes() {\n return getRoutes();\n },\n project() {\n if (!project) {\n project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: { allowJs: true, strict: false },\n });\n }\n return project;\n },\n };\n}\n\n/**\n * Run every extension's `transformRoutes` hook in registration order, chaining the\n * result (each sees the previous output). An extension may mutate in place and return\n * void, or return a new array.\n */\nexport async function applyTransformRoutes(\n routes: RouteDescriptor[],\n extensions: readonly CodegenExtension[],\n ctx: ExtensionContext,\n): Promise<RouteDescriptor[]> {\n let current = routes;\n for (const ext of extensions) {\n if (!ext.transformRoutes) continue;\n const result = await ext.transformRoutes(current, ctx);\n if (Array.isArray(result)) current = result;\n }\n return current;\n}\n\n/**\n * Run every extension's `emitFiles` hook and return the accumulated files. Throws a\n * {@link CodegenError} if two extensions emit the same path, or if an extension tries to\n * emit a core-owned file. Paths are normalized to forward slashes for collision checks.\n */\nexport async function collectEmittedFiles(\n extensions: readonly CodegenExtension[],\n ctx: ExtensionContext,\n): Promise<EmittedFile[]> {\n const files: EmittedFile[] = [];\n const owners = new Map<string, { value: EmittedFile; owner: string }>();\n\n for (const ext of extensions) {\n if (!ext.emitFiles) continue;\n const emitted = await ext.emitFiles(ctx);\n for (const file of emitted) {\n const key = file.path.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n if (CORE_FILES.has(key)) {\n throw new CodegenError(\n `Extension \"${ext.name}\" tried to emit the core-owned file \"${file.path}\". Core files (${[...CORE_FILES].join(', ')}) cannot be produced by extensions.`,\n );\n }\n mergeExclusive(owners, [[key, file] as const], {\n owner: ext.name,\n describe: (_key, prevOwner, owner) =>\n `Output file \"${file.path}\" is emitted by both \"${prevOwner}\" and \"${owner}\". Two extensions cannot write the same file.`,\n });\n files.push(file);\n }\n }\n\n return files;\n}\n","import type { Project } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * The published, versioned extension contract for `@dudousxd/nestjs-codegen`.\n *\n * Extensions are **build-time** objects (usually returned by a factory so they can take\n * options) registered explicitly via `forRoot({ extensions: [...] })`. The host runs them\n * around the core discovery → IR → emit pipeline.\n *\n * Hooks split into **multi** (every extension runs; results accumulate or chain) and\n * **single-slot** (at most one extension may claim it — two claimers is a hard error).\n *\n * @remarks Semver 0.x — the shape may change until 1.0. Out-of-repo extensions should pin\n * a compatible `@dudousxd/nestjs-codegen` peer range.\n */\nexport interface CodegenExtension {\n /** Unique id. Used in conflict/collision errors and for deterministic ordering. */\n name: string;\n\n // ── multi hooks (every extension runs) ────────────────────────────────────\n\n /**\n * Mutate/augment the route IR before emit. Runs in registration order, chained\n * (each extension sees the previous one's output). Return the new array, or mutate\n * in place and return void. Example: the filter extension attaches `filterFields` to\n * matching routes here.\n */\n transformRoutes?(\n routes: RouteDescriptor[],\n ctx: ExtensionContext,\n ): RouteDescriptor[] | undefined | Promise<RouteDescriptor[] | undefined>;\n\n /**\n * Contribute extra output files (additive). Paths are relative to `outDir`; a path\n * claimed by two extensions is a hard error. Example: the Inertia extension does its\n * own page discovery via `ctx.project()` and emits `pages.d.ts` + `components.json`.\n */\n emitFiles?(ctx: ExtensionContext): EmittedFile[] | Promise<EmittedFile[]>;\n\n /**\n * Contribute top-level code to `api.ts` (imports + statements). Runs in registration\n * order; imports are deduped by the host. Example: the Inertia extension adds\n * `import { router } from '@inertiajs/react'` and the `navigate()` helper.\n */\n apiHeader?(ctx: ExtensionContext): ApiHeaderContribution | undefined;\n\n /**\n * Add named members to a **handle** leaf. Only runs when a client layer is active\n * (i.e. the leaf is a handle, not a bare callable). Member-name collisions across\n * extensions are a hard error. Example: the filter extension adds `filterQuery` to\n * leaves whose route carries `filterFields`.\n */\n apiMembers?(leaf: LeafModel, ctx: ExtensionContext): Record<string, string> | undefined;\n\n // ── single-slot hooks (at most one extension) ─────────────────────────────\n\n /**\n * Claims **what** a leaf returns and **how** it issues its request. At most one extension\n * may claim it. When unset, a leaf is a bare awaitable callable backed by the neutral\n * fetcher. Example: the TanStack extension wraps each leaf into a handle exposing\n * `{ fetch, queryKey, queryOptions | mutationOptions }`, composing with the fetcher\n * request the host passes in.\n */\n apiClientLayer?: ApiClientLayer;\n}\n\n/** Shared, read-only context handed to every extension hook. */\nexport interface ExtensionContext {\n cwd: string;\n outDir: string;\n routes: readonly RouteDescriptor[];\n config: ResolvedConfig;\n /** Lazily-created shared ts-morph Project for AST work (pages, custom decorators). */\n project(): Project;\n}\n\n/** A file contributed by an extension's `emitFiles` hook. */\nexport interface EmittedFile {\n /** Path relative to `outDir`. A collision across extensions throws. */\n path: string;\n contents: string;\n}\n\n/** Top-level `api.ts` contributions from an extension's `apiHeader` hook. */\nexport interface ApiHeaderContribution {\n /** Raw import lines (e.g. `import { router } from '@inertiajs/react';`), deduped by the host. */\n imports?: string[];\n /** Top-level statements appended after the api factory (e.g. the `navigate()` helper). */\n statements?: string[];\n}\n\n/**\n * The neutral, per-endpoint request model the host builds for each leaf before any\n * transport/layer runs. Extensions read this to render their output.\n */\nexport interface RequestModel {\n /** Dot-path route name, e.g. `users.show`. */\n routeName: string;\n method: 'get' | 'post' | 'put' | 'patch' | 'delete';\n isGet: boolean;\n /** True for reads: a GET, or a filter-search route (has `filterFields`) even when POST.\n * Client layers use this (not `isGet`) to decide query vs mutation helpers. */\n isQuery: boolean;\n hasParams: boolean;\n hasBody: boolean;\n /** Type of the leaf's `input` arg, e.g. `{ params: ...; query?: ... }` or `Record<string, never>`. */\n inputType: string;\n /** URL expression, e.g. `route('users.show', input?.params) || '/api/users/:id'`. */\n urlExpr: string;\n /** Request-options expression, e.g. `{ query: ... }` or `{ body: input?.body }`. */\n optsExpr: string;\n /** Response type access, e.g. `ApiRouter['users']['show']['response']`. */\n responseType: string;\n /** Stable query-key expression, e.g. `[\"users.show\", input] as const`. */\n queryKeyExpr: string;\n}\n\n/**\n * Per-leaf model passed through the api.ts pipeline: layer → member contributors → render.\n * `requestExpr` is the host's neutral fetcher request; `members`, when present, flips the\n * leaf from a bare callable to a handle.\n */\nexport interface LeafModel {\n route: RouteDescriptor;\n request: RequestModel;\n /** The expression that issues the request (the host's neutral fetcher call). */\n requestExpr: string;\n /** When present, the leaf renders as a handle exposing these members (ordered). */\n members?: Record<string, string>;\n}\n\n/**\n * Top-level `api.ts` imports a client layer depends on. A function of the context so it can\n * be route-aware (e.g. only import `mutationOptions` when a mutation exists). Imports are\n * deduped by the host across all extensions.\n */\nexport interface ApiModuleDeps {\n /** Raw import lines (e.g. `import { queryOptions as _q } from '@tanstack/react-query';`). */\n imports?(ctx: ExtensionContext): string[];\n}\n\n/** Single-slot: decides what a leaf returns (the handle members). */\nexport interface ApiClientLayer extends ApiModuleDeps {\n name: string;\n /**\n * Given the request expression (from the transport) and the leaf, return the handle's\n * members as an ordered `name → value` map (value is the expression after `name: `).\n * Returning members flips the leaf from a bare callable to a handle.\n */\n buildMembers(requestExpr: string, leaf: LeafModel, ctx: ExtensionContext): Record<string, string>;\n}\n\n/**\n * The four request-shape flags derived from a route's method + contract. Computed in ONE\n * place ({@link requestShape}) and read by both the host emitter and client-layer\n * extensions, so the \"filter-search POST counts as a read\" rule is encoded exactly once.\n */\nexport interface RequestShape {\n /** The route is a `GET`. */\n isGet: boolean;\n /** True for reads: a GET, or a filter-search route (carries `filterFields`) even when POST.\n * Client layers use this (not `isGet`) to decide query vs mutation helpers. */\n isQuery: boolean;\n /** The route carries a body contract (a mutation payload). */\n hasBody: boolean;\n /** The route can take a query string — always for GET; a mutation may too (query + body). */\n hasQuery: boolean;\n}\n\n/**\n * Compute the {@link RequestShape} flags for a route from its method and contract. This is\n * the SINGLE source of truth for these flags — `buildRequestModel`, the TanStack layer's\n * `imports()`, and any other reader must call this rather than re-deriving. The\n * \"filter-search POST counts as a read\" rule lives here and nowhere else.\n */\nexport function requestShape(route: RouteDescriptor): RequestShape {\n const cs = route.contract?.contractSource;\n const isGet = route.method.toUpperCase() === 'GET';\n const isQuery = isGet || !!cs?.filterFields?.length;\n const hasBody = !!cs?.bodyRef || (cs?.body != null && cs.body !== 'never');\n const hasQuery = isGet || !!cs?.queryRef || (cs?.query != null && cs.query !== 'never');\n return { isGet, isQuery, hasBody, hasQuery };\n}\n\n/** Identity helper for authoring extensions with full type inference. */\nexport function defineExtension(ext: CodegenExtension): CodegenExtension {\n return ext;\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, relative } from 'node:path';\nimport type { ValidationAdapter } from '../adapters/types.js';\nimport type { ResolvedFormsConfig } from '../config/types.js';\nimport type { RouteDescriptor, TypeRef } from '../discovery/types.js';\n\n/**\n * Emits `forms.ts` into `outDir`. Every validatable route is rendered through a\n * single {@link ValidationAdapter} path (IR → `adapter.renderModule`). The adapter\n * is required — `validation` is a mandatory config field.\n *\n * Two schema sources exist per route:\n * - Neutral IR (`bodySchema`/`querySchema`) synthesized from class-validator\n * DTOs — renderable through ANY adapter.\n * - Hand-written zod from `defineContract` (`bodyZodText`/`queryZodText` raw\n * source, or `bodyZodRef`/`queryZodRef` re-exports). This is genuine zod\n * source with no IR; it passes through verbatim only when the adapter sets\n * `acceptsRawZodSource` (the zod adapter), and is skipped with a warning\n * under any other adapter.\n *\n * Returns `true` when a `forms.ts` was written (drives the index export).\n */\nexport async function emitForms(\n routes: RouteDescriptor[],\n outDir: string,\n config: ResolvedFormsConfig | undefined,\n adapter: ValidationAdapter,\n): Promise<boolean> {\n if (config && config.enabled === false) return false;\n\n const content = buildFormsFileWithAdapter(routes, outDir, adapter, config);\n if (content === null) return false;\n await mkdir(outDir, { recursive: true });\n await writeFile(join(outDir, 'forms.ts'), content, 'utf8');\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** PascalCase from a single dot/identifier segment. */\nfunction pascal(segment: string): string {\n return segment\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('');\n}\n\n/**\n * PascalCase base name for a route. Uses the method segment (last dot-part);\n * the full dotted name is used to disambiguate collisions.\n */\nfunction deriveBaseName(routeName: string): { method: string; full: string } {\n const segments = routeName.split('.');\n const method = pascal(segments[segments.length - 1] ?? routeName);\n const full = segments.map(pascal).join('');\n return { method, full };\n}\n\n/** Relative import specifier from outDir to a source file (no extension). */\nfunction relImport(outDir: string, filePath: string): string {\n let relPath = relative(outDir, filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n return relPath;\n}\n\n/** The root identifier of a ref name like `loginContract.body` → `loginContract`. */\nfunction refRootIdentifier(refName: string): string {\n return refName.split('.')[0] ?? refName;\n}\n\n/**\n * A renderable form schema source. The IR is preferred (works through any\n * adapter); `zodText`/`zodRef` are the zod-only `defineContract` fallbacks.\n */\ninterface FormSource {\n /** Neutral IR — rendered via the active adapter. */\n schema?: import('../ir/schema-node.js').SchemaModule | null;\n /** Raw zod source text (defineContract inline / synthesized). */\n zodText?: string | null;\n /** Importable named const re-export (defineContract Path A). */\n zodRef?: TypeRef | null;\n}\n\nfunction hasSource(src: FormSource): boolean {\n return !!(src.schema || src.zodText || src.zodRef);\n}\n\n// ---------------------------------------------------------------------------\n// Nested-schema hoisting: dedup + collision disambiguation + recursion guard.\n// (Used for the zod-only `formNestedSchemas` text path.)\n// ---------------------------------------------------------------------------\n\ninterface FormEntry {\n routeName: string;\n baseName: string;\n body: FormSource | undefined;\n query: FormSource | undefined;\n /** zod-only nested schemas (name → zod text) for the text path. */\n nestedSchemas: Record<string, string> | null;\n warnings: string[];\n}\n\ninterface NestedSchemaPlan {\n globalSchemas: Map<string, string>;\n renamesByEntry: Map<FormEntry, Map<string, string>>;\n}\n\nfunction applyRenames(text: string, renames: Map<string, string> | null): string {\n if (!renames || renames.size === 0) return text;\n let out = text;\n for (const [from, to] of renames) {\n if (from === to) continue;\n out = out.replace(new RegExp(`\\\\b${escapeRegExp(from)}\\\\b`, 'g'), to);\n }\n return out;\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isSelfReferential(name: string, text: string): boolean {\n return new RegExp(`\\\\b${escapeRegExp(name)}\\\\b`).test(text);\n}\n\n/**\n * Build the global hoist registry + per-entry renames for zod-only nested\n * schema texts. See the original design notes: each unique (name, shape) is\n * declared once; same-name different-shape is suffixed; recursion is degraded.\n */\nfunction planNestedSchemas(entries: FormEntry[]): NestedSchemaPlan {\n const globalSchemas = new Map<string, string>();\n const renamesByEntry = new Map<FormEntry, Map<string, string>>();\n\n for (const entry of entries) {\n if (!entry.nestedSchemas) continue;\n const local = Object.entries(entry.nestedSchemas);\n if (local.length === 0) continue;\n\n const rename = new Map<string, string>();\n for (const [name] of local) rename.set(name, name);\n\n const textFor = (name: string): string => {\n const raw = entry.nestedSchemas?.[name] ?? '';\n return applyRenames(raw, rename);\n };\n\n let changed = true;\n let guard = 0;\n while (changed && guard < local.length + 2) {\n changed = false;\n guard += 1;\n for (const [name] of local) {\n const finalName = rename.get(name) ?? name;\n const text = textFor(name);\n const existing = globalSchemas.get(finalName);\n if (existing === undefined) continue;\n if (existing === text) continue;\n let i = 2;\n let candidate = `${name}_${i}`;\n while (\n (globalSchemas.has(candidate) && globalSchemas.get(candidate) !== textFor(name)) ||\n [...rename.values()].includes(candidate)\n ) {\n i += 1;\n candidate = `${name}_${i}`;\n }\n rename.set(name, candidate);\n changed = true;\n }\n }\n\n for (const [name] of local) {\n const finalName = rename.get(name) ?? name;\n let text = textFor(name);\n if (isSelfReferential(finalName, text)) {\n text = 'z.unknown() /* recursive type — not expanded */';\n }\n const existing = globalSchemas.get(finalName);\n if (existing === undefined) {\n globalSchemas.set(finalName, text);\n }\n }\n\n renamesByEntry.set(entry, rename);\n }\n\n return { globalSchemas, renamesByEntry };\n}\n\n// ---------------------------------------------------------------------------\n// Single adapter-driven forms builder\n// ---------------------------------------------------------------------------\n\n/**\n * Render `forms.ts` from the neutral validation IR via `adapter`, plus the\n * zod-only `defineContract` text/ref fallbacks (zod adapter only). Returns\n * `null` when nothing to emit.\n */\nfunction buildFormsFileWithAdapter(\n routes: RouteDescriptor[],\n outDir: string,\n adapter: ValidationAdapter,\n config?: ResolvedFormsConfig,\n): string | null {\n const acceptsRawZod = adapter.acceptsRawZodSource === true;\n const sorted = [...routes].filter((r) => r.contract).sort((a, b) => a.name.localeCompare(b.name));\n\n // Base-name collision pass (method-only name vs full dotted name).\n const methodNameCounts = new Map<string, number>();\n const candidates: FormEntry[] = [];\n for (const route of sorted) {\n const cs = route.contract!.contractSource;\n const body: FormSource = {\n schema: cs.bodySchema ?? null,\n zodText: cs.bodyZodText ?? null,\n zodRef: cs.bodyZodRef ?? null,\n };\n const query: FormSource = {\n schema: cs.querySchema ?? null,\n zodText: cs.queryZodText ?? null,\n zodRef: cs.queryZodRef ?? null,\n };\n if (!hasSource(body) && !hasSource(query)) continue;\n const { method, full } = deriveBaseName(route.name);\n methodNameCounts.set(method, (methodNameCounts.get(method) ?? 0) + 1);\n candidates.push({\n routeName: route.name,\n baseName: full, // resolved below\n body: hasSource(body) ? body : undefined,\n query: hasSource(query) ? query : undefined,\n nestedSchemas: cs.formNestedSchemas ?? null,\n warnings: cs.formWarnings ?? [],\n });\n }\n\n const entries: FormEntry[] = candidates.map((c) => {\n const { method, full } = deriveBaseName(c.routeName);\n const collision = (methodNameCounts.get(method) ?? 0) > 1;\n return { ...c, baseName: collision ? full : method };\n });\n\n if (entries.length === 0) return null;\n\n // Re-export imports (zod-only refs without inline text), grouped by file.\n const importsByFile = new Map<string, Set<string>>();\n const refAlias = new Map<string, string>();\n for (const entry of entries) {\n for (const src of [entry.body, entry.query]) {\n if (src?.zodRef && !src.zodText && !src.schema) {\n const root = refRootIdentifier(src.zodRef.name);\n const set = importsByFile.get(src.zodRef.filePath) ?? new Set<string>();\n set.add(root);\n importsByFile.set(src.zodRef.filePath, set);\n }\n }\n }\n\n const importLines: string[] = [];\n if (importsByFile.size > 0) {\n const emitted = new Set<string>();\n for (const [filePath, roots] of [...importsByFile.entries()].sort()) {\n const relPath = relImport(outDir, filePath);\n const specifiers: string[] = [];\n for (const root of [...roots].sort()) {\n if (emitted.has(root)) {\n const alias = `${root}_${emitted.size}`;\n specifiers.push(`${root} as ${alias}`);\n emitted.add(alias);\n refAlias.set(`${filePath}\\0${root}`, alias);\n } else {\n specifiers.push(root);\n emitted.add(root);\n refAlias.set(`${filePath}\\0${root}`, root);\n }\n }\n importLines.push(`import { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n }\n\n // Hoist zod-only nested schemas (text path) once, with collision handling.\n const { globalSchemas, renamesByEntry } = planNestedSchemas(entries);\n\n // Hoisted IR nested schemas (rendered via adapter, deduped by name).\n const irNamed = new Map<string, string>();\n // Recursive-schema extras (zod/valibot): hoisted TS type alias + const annotation.\n const irTypeAliases = new Map<string, string>();\n const irAnnotations = new Map<string, string>();\n const decls: string[] = [];\n const mapEntries: string[] = [];\n let used = false;\n\n const renderSource = (\n src: FormSource,\n rename: Map<string, string> | null,\n ): { text: string; warn?: string } | null => {\n // Prefer the neutral IR — works through any adapter.\n if (src.schema) {\n const r = adapter.renderModule(src.schema);\n for (const [n, t] of r.namedNestedSchemas) irNamed.set(n, t);\n if (r.namedTypeAliases) for (const [n, t] of r.namedTypeAliases) irTypeAliases.set(n, t);\n if (r.namedAnnotations) for (const [n, a] of r.namedAnnotations) irAnnotations.set(n, a);\n return { text: r.schemaText };\n }\n // zod-only defineContract fallbacks: text or re-export ref.\n if (src.zodText) {\n if (!acceptsRawZod) {\n return {\n text: '',\n warn: `is a defineContract (zod) schema; not translated to ${adapter.name} — use the zod adapter.`,\n };\n }\n return { text: applyRenames(src.zodText, rename) };\n }\n if (src.zodRef) {\n if (!acceptsRawZod) {\n return {\n text: '',\n warn: `is a defineContract (zod) schema; not translated to ${adapter.name} — use the zod adapter.`,\n };\n }\n const root = refRootIdentifier(src.zodRef.name);\n const alias = refAlias.get(`${src.zodRef.filePath}\\0${root}`) ?? root;\n const member = src.zodRef.name.slice(root.length);\n return { text: `${alias}${member}` };\n }\n return null;\n };\n\n for (const entry of entries) {\n const block: string[] = [];\n const rename = renamesByEntry.get(entry) ?? null;\n let bodyConst: string | undefined;\n\n if (entry.warnings && entry.warnings.length > 0) {\n for (const w of entry.warnings) block.push(`// warning: ${w}`);\n }\n\n if (entry.body) {\n const rendered = renderSource(entry.body, rename);\n if (rendered?.warn) {\n block.push(`// warning: ${entry.routeName} body ${rendered.warn}`);\n } else if (rendered) {\n used = true;\n bodyConst = `${entry.baseName}BodySchema`;\n block.push(`export const ${bodyConst} = ${rendered.text};`);\n block.push(`export type ${entry.baseName}Body = ${adapter.inferType(bodyConst)};`);\n }\n }\n if (entry.query) {\n const rendered = renderSource(entry.query, rename);\n if (rendered?.warn) {\n block.push(`// warning: ${entry.routeName} query ${rendered.warn}`);\n } else if (rendered) {\n used = true;\n const queryConst = `${entry.baseName}QuerySchema`;\n block.push(`export const ${queryConst} = ${rendered.text};`);\n block.push(`export type ${entry.baseName}Query = ${adapter.inferType(queryConst)};`);\n }\n }\n\n if (block.length === 0) continue;\n decls.push(`// ${entry.routeName}`, ...block, '');\n if (bodyConst) mapEntries.push(` ${JSON.stringify(entry.routeName)}: ${bodyConst},`);\n }\n\n if (!used) return null;\n\n const lines: string[] = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.'];\n if (acceptsRawZod) {\n const zodImport = config?.zodImport ?? 'zod';\n lines.push(`import { z } from '${zodImport}';`);\n } else {\n for (const imp of adapter.importStatements({ used: true })) lines.push(imp);\n }\n lines.push(...importLines);\n lines.push('');\n\n // Merge hoisted nested schemas: zod-only text path + IR-rendered nested.\n const allNested = new Map<string, string>();\n for (const [n, t] of globalSchemas) allNested.set(n, t);\n for (const [n, t] of irNamed) if (!allNested.has(n)) allNested.set(n, t);\n\n if (allNested.size > 0) {\n lines.push('// Hoisted nested schemas (shared across endpoints).');\n // Recursive schemas (zod/valibot) need their structural TS type hoisted so\n // the const can be annotated — this breaks the implicit-any self-reference\n // cycle that a bare `const X = ...lazy(() => X)...` would trigger.\n for (const [n, alias] of irTypeAliases) {\n if (allNested.has(n)) lines.push(`${alias};`);\n }\n for (const [n, t] of allNested) {\n const annotation = irAnnotations.get(n);\n lines.push(`const ${n}${annotation ? `: ${annotation}` : ''} = ${t};`);\n }\n lines.push('');\n }\n\n lines.push(...decls);\n lines.push('/** Route name → body schema map. */');\n lines.push('export const formSchemas = {');\n lines.push(...mapEntries);\n lines.push('} as const;');\n lines.push('');\n return lines.join('\\n');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function emitIndex(\n outDir: string,\n hasContracts = false,\n hasForms = false,\n): 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 if (hasForms) {\n exports.push(\"export * from './forms.js';\");\n }\n const content = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.', ...exports, ''].join(\n '\\n',\n );\n await writeFile(join(outDir, 'index.d.ts'), content, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\nimport type { SharedPropsResult } from '../discovery/shared-props.js';\n\nexport interface EmitPagesOptions {\n /** The export name to reference in import() type expressions (default: 'ComponentProps'). */\n propsExport?: string;\n /** When true, infer props from the default export's first parameter instead of a named export. */\n inferFromDefault?: boolean;\n /** When provided, emit an InertiaSharedProps augmentation alongside the pages. */\n sharedProps?: SharedPropsResult | null;\n}\n\nexport async function emitPages(\n pages: DiscoveredPage[],\n outDir: string,\n _options: EmitPagesOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const pageNameUnion =\n pages.length > 0 ? pages.map((p) => JSON.stringify(p.name)).join(' | ') : 'never';\n\n const augBody = pages\n .map((p) => {\n const key = needsQuotes(p.name) ? JSON.stringify(p.name) : p.name;\n const valueType = buildAugmentationType(p, outDir);\n return ` ${key}: ${valueType};`;\n })\n .join('\\n');\n\n const propsHelper =\n \"\\nexport type InertiaProps<K extends InertiaPageName> = import('@dudousxd/nestjs-inertia').InertiaPages[K];\\n\";\n\n const sharedPropsBlock = buildSharedPropsBlock(_options.sharedProps ?? null);\n\n const content = `// Generated by @dudousxd/nestjs-codegen. Do not edit.\\n\\nexport type InertiaPageName = ${pageNameUnion};\\n${propsHelper}\\ndeclare module '@dudousxd/nestjs-inertia' {\\n interface InertiaPages {\\n${augBody}\\n }\\n${sharedPropsBlock}}\\n`;\n\n await writeFile(join(outDir, 'pages.d.ts'), content, 'utf8');\n}\n\n/**\n * Build the `InertiaSharedProps` interface augmentation block.\n * Returns an empty string when sharedProps is null (graceful fallback).\n *\n * When `isImportRef` is true, the type is expressed as a mapped type from an import reference.\n * When `properties` are available, they are emitted as individual interface members.\n */\nfunction buildSharedPropsBlock(sharedProps: SharedPropsResult | null): string {\n if (!sharedProps) return '';\n\n // isImportRef case: emit a type alias that re-exports the external type\n if (sharedProps.isImportRef) {\n return `\\n // eslint-disable-next-line @typescript-eslint/no-empty-interface\\n interface InertiaSharedProps extends ${sharedProps.typeString} {}\\n`;\n }\n\n // Inline properties case\n if (!sharedProps.properties || sharedProps.properties.length === 0) return '';\n\n const propsBody = sharedProps.properties.map((p) => ` ${p.name}: ${p.type};`).join('\\n');\n\n return `\\n interface InertiaSharedProps {\\n${propsBody}\\n }\\n`;\n}\n\n/**\n * Build the type for a page in the module augmentation.\n * Uses `Parameters<typeof import('...').default>[0]` to infer props\n * directly from the default export — no named export needed.\n */\nfunction buildAugmentationType(page: DiscoveredPage, outDir: string): string {\n let importPath = relative(outDir, page.absolutePath).replace(/\\.(tsx?|vue|svelte)$/, '');\n if (!importPath.startsWith('.')) {\n importPath = `./${importPath}`;\n }\n return `Parameters<typeof import('${importPath}').default>[0]`;\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-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-codegen] 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-codegen 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-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 { 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 { 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-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(\n `[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`,\n );\n try {\n await generate(config);\n } catch {\n /* fallback: pages only */\n }\n }\n\n // ── Pages watcher (fast path — no route discovery) ──────────────────────────\n let pagesDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n // No `pages` config → watch a path that matches nothing (pages are Inertia-only).\n const pagesGlob = config.pages?.glob ?? '.nestjs-codegen-no-pages';\n const pagesWatcher = chokidar.watch(join(config.codegen.cwd, pagesGlob), {\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 (err) {\n console.error(\n '[nestjs-codegen] Pages generation failed:',\n err instanceof Error ? err.message : err,\n );\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 // Route through generate() so the incremental pass honors the SAME emit\n // options as the initial pass (query / mutationClient / queryImport / fetcher\n // importPath + the validation adapter). Emitting api.ts/forms.ts directly here\n // would silently drop those settings on every contract edit.\n await generate(config, routes);\n } catch (err) {\n console.error(\n '[nestjs-codegen] Contracts generation failed:',\n err instanceof Error ? err.message : err,\n );\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 // ── DTO watcher (forms.ts synthesis from class-validator DTOs) ───────────────\n // DTO classes live in *.dto.ts files (not matched by the controller glob), but\n // changes to them affect the synthesized form schemas. Re-run discovery (which\n // re-emits forms.ts) on any DTO change, reusing the contracts debounce.\n const formsWatcher = chokidar.watch(join(config.codegen.cwd, config.forms.watch), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n formsWatcher.on('add', scheduleContractsRegenerate);\n formsWatcher.on('change', scheduleContractsRegenerate);\n formsWatcher.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 formsWatcher.close();\n await lock.release();\n },\n };\n}\n","import { 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 MethodDeclaration,\n Node,\n Project,\n type SourceFile,\n} from 'ts-morph';\nimport { extractDtoContract } from './dto-type-resolver.js';\nimport { loadTsconfigPaths, setDiscoveryContext } from './type-ref-resolution.js';\nimport type { ContractSource, RouteDescriptor, TypeRef } from './types.js';\nimport { type ParsedContractDef, parseDefineContractCall } from './zod-ast-to-ts.js';\n\n// Re-export so existing test import paths (`../discovery/contracts-fast.js`)\n// keep resolving these symbols after the decomposition into sibling modules.\nexport { extractDtoContract } from './dto-type-resolver.js';\nexport { zodAstToTs } from './zod-ast-to-ts.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 // Bind the discovery context to this invocation's Project. Each call owns its\n // own Project, so concurrent callers never share or corrupt context.\n setDiscoveryContext(project, {\n projectRoot: cwd,\n tsconfigPaths: loadTsconfigPaths(tsconfigPath),\n });\n\n for (const sourceFile of project.getSourceFiles()) {\n routes.push(...extractFromSourceFile(sourceFile, project));\n }\n\n return routes;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\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 * 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// 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\n/** Resolved HTTP verb + handler sub-path read from a method's NestJS verb decorator. */\ninterface ResolvedVerb {\n httpMethod: string;\n handlerPath: string;\n}\n\n/**\n * Read the HTTP verb + sub-path from a method's NestJS verb decorator\n * (`@Get`/`@Post`/…). Returns null when the method carries no verb decorator.\n */\nfunction resolveVerb(method: MethodDeclaration): ResolvedVerb | null {\n for (const [decoratorName, verb] of Object.entries(HTTP_METHOD_DECORATORS)) {\n const httpDecorator = method.getDecorator(decoratorName);\n if (httpDecorator) {\n const httpArgs = httpDecorator.getArguments();\n const pathArg = httpArgs[0];\n return { httpMethod: verb, handlerPath: decoratorStringArg(pathArg) ?? '' };\n }\n }\n return null;\n}\n\n/**\n * Read an `@As(...)` decorator value off a node (class or method).\n * Throws when the decorator is present but its argument is empty — preserving\n * the @ApplyContract arm's strict policy, unified across both route arms.\n * Returns undefined when no `@As` decorator is present.\n */\nfunction readAsDecorator(\n node: ClassDeclaration | MethodDeclaration,\n label: string,\n): string | undefined {\n const asDecorator = node.getDecorator('As');\n if (!asDecorator) return undefined;\n const asName = decoratorStringArg(asDecorator.getArguments()[0]);\n if (!asName) {\n throw new Error(`@As decorator on ${label} must have a non-empty string argument.`);\n }\n return asName;\n}\n\n/**\n * Build a {@link RouteDescriptor} and register its name for collision detection.\n * Throws on a duplicate route name across the file's contracted/plain routes.\n */\nfunction buildRoute(args: {\n className: string;\n methodName: string;\n resolvedMethod: string;\n combinedPath: string;\n classAs: string | undefined;\n methodAs: string | undefined;\n sourceFile: SourceFile;\n seenNames: Map<string, string>;\n contractSource: ContractSource;\n}): RouteDescriptor {\n const {\n className,\n methodName,\n resolvedMethod,\n combinedPath,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource,\n } = args;\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // Collision detection across routes in the same file.\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 return {\n method: resolvedMethod,\n path: combinedPath,\n name: routeName,\n params: extractParams(combinedPath),\n controllerRef: { className, methodName, filePath: sourceFile.getFilePath() },\n contract: { contractSource },\n };\n}\n\n/**\n * Build a route from an `@ApplyContract` method. Returns null when the contract\n * cannot be resolved or the method lacks an HTTP verb decorator.\n */\nfunction extractContractRoute(args: {\n cls: ClassDeclaration;\n method: MethodDeclaration;\n applyContractDecorator: import('ts-morph').Decorator;\n verb: ResolvedVerb | null;\n prefix: string;\n className: string;\n sourceFile: SourceFile;\n seenNames: Map<string, string>;\n}): RouteDescriptor | null {\n const { cls, method, applyContractDecorator, verb, prefix, className, sourceFile, seenNames } =\n args;\n\n const firstDecoratorArg = applyContractDecorator.getArguments()[0];\n if (!firstDecoratorArg) return null;\n\n // Resolve contract definition from inline call or identifier.\n let contractDef: ParsedContractDef | null = null;\n // When the contract is a named const we can import, re-export its members\n // (`<const>.body` / `<const>.query`) for perfect parity.\n let bodyZodRef: TypeRef | null = null;\n let queryZodRef: TypeRef | 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-codegen/fast] Cannot resolve '${identName}' in ${sourceFile.getFilePath()} (cross-file imports are out-of-scope for v1) — skipping`,\n );\n return null;\n }\n\n const initializer = varDecl.getInitializer();\n if (!initializer) return null;\n\n contractDef = parseDefineContractCall(initializer);\n // Re-export the named contract's schema members (Path A). Only when the\n // const is exported so forms.ts can import it.\n if (contractDef && varDecl.isExported()) {\n const filePath = sourceFile.getFilePath();\n if (contractDef.body !== null) {\n bodyZodRef = { name: `${identName}.body`, filePath };\n }\n if (contractDef.query !== null) {\n queryZodRef = { name: `${identName}.query`, filePath };\n }\n }\n } else {\n console.warn(\n `[nestjs-codegen/fast] @ApplyContract arg is not an identifier or call expression in ${sourceFile.getFilePath()} — skipping`,\n );\n return null;\n }\n\n if (!contractDef) return null;\n\n // Method + path always come from NestJS decorators — skip if absent.\n if (!verb) return null;\n const resolvedPath = joinPaths(prefix, verb.handlerPath);\n const methodName = method.getName();\n\n const classAs = readAsDecorator(cls, `class ${className}`);\n const methodAs = readAsDecorator(method, `${className}.${methodName}`);\n\n return buildRoute({\n className,\n methodName,\n resolvedMethod: verb.httpMethod,\n combinedPath: resolvedPath,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource: {\n query: contractDef.query,\n body: contractDef.body,\n response: contractDef.response,\n // Path A: capture both the importable ref and the raw text. The emitter\n // prefers inlining the text (client-safe — re-exporting from a controller\n // would drag server-only deps into the client bundle).\n bodyZodRef,\n bodyZodText: contractDef.bodyZodText,\n queryZodRef,\n queryZodText: contractDef.queryZodText,\n },\n });\n}\n\n/**\n * Build a route from a plain HTTP-verb method (no `@ApplyContract`), extracting\n * any DTO-based contract info. Returns null when the method lacks a verb.\n */\nfunction extractDtoRoute(args: {\n cls: ClassDeclaration;\n method: MethodDeclaration;\n verb: ResolvedVerb | null;\n prefix: string;\n className: string;\n sourceFile: SourceFile;\n project: Project;\n seenNames: Map<string, string>;\n}): RouteDescriptor | null {\n const { cls, method, verb, prefix, className, sourceFile, project, seenNames } = args;\n\n if (!verb) return null;\n\n const combined = joinPaths(prefix, verb.handlerPath);\n const methodName = method.getName();\n\n const classAs = readAsDecorator(cls, `class ${className}`);\n const methodAs = readAsDecorator(method, `${className}.${methodName}`);\n\n const dtoContract = extractDtoContract(method, sourceFile, project);\n\n return buildRoute({\n className,\n methodName,\n resolvedMethod: verb.httpMethod,\n combinedPath: combined,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource: {\n query: dtoContract?.query ?? null,\n body: dtoContract?.body ?? null,\n response: dtoContract?.response ?? 'unknown',\n queryRef: dtoContract?.queryRef ?? null,\n bodyRef: dtoContract?.bodyRef ?? null,\n responseRef: dtoContract?.responseRef ?? null,\n filterFields: dtoContract?.filterFields ?? null,\n filterFieldTypes: dtoContract?.filterFieldTypes ?? null,\n filterSource: dtoContract?.filterSource ?? null,\n formWarnings: dtoContract?.formWarnings ?? [],\n bodySchema: dtoContract?.bodySchema ?? null,\n querySchema: dtoContract?.querySchema ?? null,\n },\n });\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 for (const cls of sourceFile.getClasses()) {\n // Find @Controller(...) decorator\n const controllerDecorator = cls.getDecorator('Controller');\n if (!controllerDecorator) continue;\n\n // Determine controller path prefix\n const firstArg = controllerDecorator.getArguments()[0];\n const prefix = decoratorStringArg(firstArg) ?? '';\n\n const className = cls.getName() ?? 'Unknown';\n\n for (const method of cls.getMethods()) {\n const verb = resolveVerb(method);\n const applyContractDecorator = method.getDecorator('ApplyContract');\n\n const route = applyContractDecorator\n ? extractContractRoute({\n cls,\n method,\n applyContractDecorator,\n verb,\n prefix,\n className,\n sourceFile,\n seenNames,\n })\n : extractDtoRoute({\n cls,\n method,\n verb,\n prefix,\n className,\n sourceFile,\n project,\n seenNames,\n });\n\n if (route) routes.push(route);\n }\n }\n\n return routes;\n}\n","import {\n type ClassDeclaration,\n type InterfaceDeclaration,\n type MethodDeclaration,\n Node,\n type Project,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport { extractSchemaFromDto } from './dto-to-ir.js';\nimport { extractApplyFilterInfo } from './filter-for.js';\nimport {\n type TypeDeclResult,\n dbg,\n findType,\n resolveImportedType,\n resolveTypeRef,\n} from './type-ref-resolution.js';\nimport type { FilterFieldType, TypeRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// DTO-based contract extraction (standard NestJS patterns — no defineContract)\n// ---------------------------------------------------------------------------\n\n/**\n * Wrapper type names whose wire shape reduces to their first type argument.\n * - `unwrap` → emit the type-arg as-is (e.g. Promise<T> → T)\n * - `arrayOf` → wrap the type-arg in `Array<>` (e.g. Collection<T> → Array<T>)\n */\nconst WRAPPER_TYPES: Record<string, 'unwrap' | 'arrayOf'> = {\n // MikroORM Ref/Reference/LoadedReference/IdentifiedReference are server-side\n // wrappers around related entities; the wire shape is just the referenced\n // entity. Unwrap to the type argument.\n Ref: 'unwrap',\n Reference: 'unwrap',\n LoadedReference: 'unwrap',\n IdentifiedReference: 'unwrap',\n // MikroORM Opt<T> is a marker, Loaded<T, ...> is a wrapper; both reduce to T.\n Opt: 'unwrap',\n Loaded: 'unwrap',\n // Promise<T> — unwrap\n Promise: 'unwrap',\n // MikroORM Collection<T> serializes as an array of T on the wire.\n Collection: 'arrayOf',\n // Array<T> generic form\n Array: 'arrayOf',\n};\n\n/** Well-known utility types — preserve full text with type args. */\nconst PASSTHROUGH_UTILITY = new Set([\n 'Record',\n 'Omit',\n 'Pick',\n 'Partial',\n 'Required',\n 'Readonly',\n 'Map',\n 'Set',\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 // Union: A | B | C — resolve each member so named refs get inlined\n if (Node.isUnionTypeNode(typeNode)) {\n return typeNode\n .getTypeNodes()\n .map((t) => resolveTypeNodeToString(t, sourceFile, project, depth))\n .join(' | ');\n }\n\n // Intersection: A & B — same treatment\n if (Node.isIntersectionTypeNode(typeNode)) {\n return typeNode\n .getTypeNodes()\n .map((t) => resolveTypeNodeToString(t, sourceFile, project, depth))\n .join(' & ');\n }\n\n // Parenthesized: ( ... ) — unwrap\n if (Node.isParenthesizedTypeNode(typeNode)) {\n return `(${resolveTypeNodeToString(typeNode.getTypeNode(), 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' || name === 'void') return 'unknown';\n // Server-only types that don't make sense on the client\n if (name === 'StreamableFile' || name === 'Observable' || name === 'ReadableStream')\n return 'unknown';\n\n // Known wrapper types — unwrap (or array-wrap) their first type argument.\n const wrapperMode = WRAPPER_TYPES[name];\n if (wrapperMode) {\n return unwrapFirstTypeArg(typeNode, sourceFile, project, depth, wrapperMode);\n }\n\n // Well-known utility types — preserve full text with type args\n if (PASSTHROUGH_UTILITY.has(name)) {\n return typeNode.getText();\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 // Unresolvable type — use unknown instead of bare name to avoid TS errors in generated code\n dbg('unresolvable type:', name, 'in', sourceFile.getFilePath());\n return 'unknown';\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 * Unwrap the first type argument of a wrapper TypeReference. In `unwrap` mode\n * the type-arg is emitted as-is; in `arrayOf` mode it is wrapped in `Array<>`.\n * Falls back to `'unknown'` / `'Array<unknown>'` when no type-arg is present.\n */\nfunction unwrapFirstTypeArg(\n typeNode: import('ts-morph').TypeReferenceNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n mode: 'unwrap' | 'arrayOf',\n): string {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n const inner = resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);\n return mode === 'arrayOf' ? `Array<${inner}>` : inner;\n }\n return mode === 'arrayOf' ? 'Array<unknown>' : 'unknown';\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 // Recursively resolve the alias body so that any named types it\n // references (e.g. `A | B | C`) are expanded inline rather than left\n // as bare identifiers, which would be undefined in the emitted code.\n if (result.typeNode) {\n return resolveTypeNodeToString(result.typeNode, result.file, project, depth);\n }\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(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): 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(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): 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(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): 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\n ? resolveTypeNodeToString(typeNode, sourceFile, project, 3)\n : '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(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): 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(\n node: Node,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): 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 * Resolve a `@Body()` / `@Query()` param or return-type `TypeNode` to a named\n * exported class/interface ref (unwrapping `Promise<T>` / `Array<T>` / `T[]`).\n * Thin wrapper over the shared {@link resolveTypeRef}.\n */\nfunction resolveBodyQueryResponseRef(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n): TypeRef | null {\n return resolveTypeRef(typeNode, sourceFile, project, {\n kinds: ['class', 'interface'],\n unwrapContainers: true,\n });\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): {\n query: string | null;\n body: string | null;\n response: string;\n params: string | null;\n queryRef?: TypeRef | null;\n bodyRef?: TypeRef | null;\n responseRef?: TypeRef | null;\n filterFields?: string[] | null;\n filterFieldTypes?: FilterFieldType[] | null;\n filterSource?: 'body' | 'query' | null;\n formWarnings?: string[];\n bodySchema?: import('../ir/schema-node.js').SchemaModule | null;\n querySchema?: import('../ir/schema-node.js').SchemaModule | null;\n} | null {\n let body = extractBodyType(method, sourceFile, project);\n const filterInfo = extractApplyFilterInfo(method, sourceFile, project);\n const query = extractQueryType(method, sourceFile, project);\n\n // Place filter type on the correct field based on @ApplyFilter source. The\n // body-source case still pre-renders a fixed `FilterQueryResult` here; the\n // query-source TypedFilterQuery TYPE is rendered in emit-api.ts (from\n // filterFields + filterFieldTypes) so it is byte-identical to the\n // `_filterQueryTyped<...>` factory args.\n if (filterInfo && filterInfo.source === 'body') {\n const bodyType = \"import('@dudousxd/nestjs-filter-client').FilterQueryResult\";\n body = body ?? bodyType;\n }\n\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. A query-source\n // `@ApplyFilter` route carries no pre-rendered `query` string anymore (the\n // TypedFilterQuery type is rendered in emit-api), so it must be kept alive via\n // `filterInfo` even when every other field is empty.\n if (\n body === null &&\n query === null &&\n paramsType === null &&\n response === 'unknown' &&\n filterInfo === null\n ) {\n return null;\n }\n\n // Capture type references for import generation\n let bodyRef: TypeRef | null = null;\n let queryRef: TypeRef | null = null;\n let responseRef: TypeRef | null = null;\n\n for (const param of method.getParameters()) {\n if (param.getDecorators().some((d) => d.getName() === 'Body') && param.getTypeNode()) {\n bodyRef = resolveBodyQueryResponseRef(param.getTypeNode()!, sourceFile, project);\n }\n if (param.getDecorators().some((d) => d.getName() === 'Query') && param.getTypeNode()) {\n queryRef = resolveBodyQueryResponseRef(param.getTypeNode()!, sourceFile, project);\n }\n }\n\n const returnTypeNode = method.getReturnTypeNode();\n if (returnTypeNode) {\n responseRef = resolveBodyQueryResponseRef(returnTypeNode, sourceFile, project);\n }\n // Also check @ApiResponse\n if (!responseRef) {\n const apiResp = method.getDecorator('ApiResponse');\n if (apiResp) {\n const args = apiResp.getArguments();\n const optsArg = args[0];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n for (const prop of optsArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'type') {\n const val = prop.getInitializer();\n if (val && Node.isIdentifier(val)) {\n const name = val.getText();\n const localDecl =\n sourceFile.getInterface(name) ||\n sourceFile.getClass(name) ||\n sourceFile.getTypeAlias(name);\n if (localDecl?.isExported()) {\n responseRef = { name, filePath: sourceFile.getFilePath() };\n } else {\n const resolved = resolveImportedType(name, sourceFile, project);\n if (\n resolved &&\n (resolved.kind === 'class' || resolved.kind === 'interface') &&\n resolved.decl.isExported()\n ) {\n responseRef = { name, filePath: resolved.file.getFilePath() };\n }\n }\n }\n }\n }\n }\n }\n }\n\n // ── Synthesize the neutral validation IR from class-validator DTOs (Path B) ─\n // Resolve the @Body()/@Query() param to a class declaration and translate its\n // decorators into the neutral IR, which emit-forms renders via any adapter\n // (zod included). A defineContract schema always wins, so this only runs on\n // the plain-verb path where no contract schema is present.\n let bodySchema: import('../ir/schema-node.js').SchemaModule | null = null;\n let querySchema: import('../ir/schema-node.js').SchemaModule | null = null;\n const formWarnings: string[] = [];\n\n const bodyClass = resolveParamClass(method, 'Body', sourceFile, project);\n if (bodyClass) {\n bodySchema = extractSchemaFromDto(bodyClass.decl, bodyClass.file, project);\n formWarnings.push(...bodySchema.warnings);\n }\n const queryClass = resolveParamClass(method, 'Query', sourceFile, project);\n if (queryClass) {\n querySchema = extractSchemaFromDto(queryClass.decl, queryClass.file, project);\n formWarnings.push(...querySchema.warnings);\n }\n\n return {\n query,\n body,\n response,\n params: paramsType,\n queryRef,\n bodyRef,\n responseRef,\n filterFields: filterInfo?.fieldNames ?? null,\n filterFieldTypes: filterInfo?.fieldTypes ?? null,\n filterSource: filterInfo?.source ?? null,\n formWarnings,\n bodySchema,\n querySchema,\n };\n}\n\n/**\n * Resolve a `@Body()` / `@Query()` parameter's TS type to a class declaration\n * (following imports). Returns null for interfaces / plain types / unresolved.\n */\nfunction resolveParamClass(\n method: MethodDeclaration,\n decoratorName: 'Body' | 'Query',\n sourceFile: SourceFile,\n project: Project,\n): { decl: ClassDeclaration; file: SourceFile } | null {\n for (const param of method.getParameters()) {\n if (!param.getDecorators().some((d) => d.getName() === decoratorName)) continue;\n const typeNode = param.getTypeNode();\n if (!typeNode) continue;\n // Strip array suffix — translate the element class.\n const text = typeNode.getText().replace(/\\[\\]$/, '');\n if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(text)) continue;\n const resolved = findType(text, sourceFile, project);\n if (resolved && resolved.kind === 'class') {\n return { decl: resolved.decl, file: resolved.file };\n }\n }\n return null;\n}\n","/**\n * Pure-AST translation of class-validator-decorated DTO classes into the neutral\n * {@link SchemaModule} IR. Reads decorator names + literal args via ts-morph — it\n * never imports class-validator at runtime. A `ValidationAdapter` renders the IR.\n *\n * This is the sole DTO translator: it emits neutral `SchemaNode` IR (replacing\n * the former `dto-to-zod.ts` text path). A `ValidationAdapter` renders the IR;\n * the bundled zod adapter reproduces the original zod-text output byte-for-byte.\n */\nimport {\n type ClassDeclaration,\n type Decorator,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport type { NumberCheck, SchemaModule, SchemaNode, StringCheck } from '../ir/schema-node.js';\nimport { findType } from './type-ref-resolution.js';\n\ninterface BuildContext {\n sourceFile: SourceFile;\n project: Project;\n named: Map<string, SchemaNode>;\n warnings: string[];\n warnedDecorators: Set<string>;\n emittedClasses: Map<string, string>;\n visiting: Set<string>;\n recursiveSchemas: Set<string>;\n depth: number;\n}\n\nconst KNOWN_DECORATORS = new Set([\n 'IsString',\n 'IsNumber',\n 'IsInt',\n 'IsBoolean',\n 'IsDate',\n 'IsEmail',\n 'IsUrl',\n 'IsUUID',\n 'MinLength',\n 'MaxLength',\n 'Length',\n 'Min',\n 'Max',\n 'IsPositive',\n 'IsNegative',\n 'Matches',\n 'IsEnum',\n 'IsIn',\n 'IsOptional',\n 'IsNotEmpty',\n 'IsArray',\n 'ValidateNested',\n 'Type',\n 'IsObject',\n 'Allow',\n 'IsDefined',\n]);\n\nexport function extractSchemaFromDto(\n classDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): SchemaModule {\n const ctx: BuildContext = {\n sourceFile,\n project,\n named: new Map(),\n warnings: [],\n warnedDecorators: new Set(),\n emittedClasses: new Map(),\n visiting: new Set(),\n recursiveSchemas: new Set(),\n depth: 0,\n };\n const root = buildObject(classDecl, sourceFile, ctx);\n // Recursive named schemas keep their real (self-referential) shape; the\n // recursion site carries a `lazyRef` back-edge. Each adapter breaks the\n // TypeScript inference cycle in its own way (annotated const + hoisted\n // structural type for zod/valibot, `this` for arktype). The set of genuinely\n // recursive names is surfaced so adapters know which consts need that.\n return { root, named: ctx.named, warnings: ctx.warnings, recursive: ctx.recursiveSchemas };\n}\n\n// ---------------------------------------------------------------------------\n// Object builder\n// ---------------------------------------------------------------------------\n\nfunction buildObject(\n classDecl: ClassDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n const props = classDecl.getProperties();\n if (props.length === 0) {\n return { kind: 'object', fields: [], passthrough: true };\n }\n const fields: Array<{ key: string; value: SchemaNode }> = [];\n for (const prop of props) {\n fields.push({ key: prop.getName(), value: buildProperty(prop, classFile, ctx) });\n }\n return { kind: 'object', fields, passthrough: false };\n}\n\n// ---------------------------------------------------------------------------\n// Property builder — the §2.2 mapping table lives here.\n// ---------------------------------------------------------------------------\n\nfunction buildProperty(\n prop: PropertyDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n const decorators = new Map<string, Decorator>();\n for (const d of prop.getDecorators()) decorators.set(d.getName(), d);\n const has = (n: string): boolean => decorators.has(n);\n const dec = (n: string): Decorator | undefined => decorators.get(n);\n\n const typeNode = prop.getTypeNode();\n const typeText = typeNode?.getText() ?? 'unknown';\n // Detect arrays from the AST, not the text: a union like `unknown | unknown[]`\n // ends in \"[]\" but is NOT an array type.\n const isArrayType = !!typeNode && Node.isArrayTypeNode(typeNode);\n\n // ── Nested / array-of-nested via @ValidateNested + @Type ────────────────\n const typeRefName = resolveTypeFactoryName(dec('Type'));\n if (has('ValidateNested') || typeRefName) {\n const childName = typeRefName ?? singularClassName(typeText);\n if (childName) {\n const childNode = buildNestedReference(childName, classFile, ctx);\n const wrapArray = has('IsArray') || isArrayType;\n const node: SchemaNode = wrapArray ? { kind: 'array', element: childNode } : childNode;\n return applyPresence(node, decorators);\n }\n }\n\n // ── Base type (TS property type), then decorator refinements ────────────\n let base = baseFromType(typeText, isArrayType);\n const stringChecks: StringCheck[] = [];\n const numberChecks: NumberCheck[] = [];\n\n // Type overrides\n if (has('IsString')) base = { kind: 'string', checks: stringChecks };\n if (has('IsBoolean')) base = { kind: 'boolean' };\n if (has('IsDate')) base = { kind: 'date' };\n if (has('IsNumber')) base = { kind: 'number', checks: numberChecks };\n if (has('IsInt')) {\n base = { kind: 'number', checks: numberChecks };\n numberChecks.push({ check: 'int' });\n }\n if (has('IsObject') && !has('ValidateNested')) {\n base = { kind: 'object', fields: [], passthrough: true };\n }\n if (has('Allow')) base = { kind: 'unknown' };\n\n const ensureString = (): void => {\n if (base.kind !== 'string') base = { kind: 'string', checks: stringChecks };\n };\n\n // String format refinements (these also imply string base).\n if (has('IsEmail')) {\n ensureString();\n const m = messageRaw(dec('IsEmail'));\n stringChecks.push(m === undefined ? { check: 'email' } : { check: 'email', messageRaw: m });\n }\n if (has('IsUrl')) {\n ensureString();\n const m = messageRaw(dec('IsUrl'));\n stringChecks.push(m === undefined ? { check: 'url' } : { check: 'url', messageRaw: m });\n }\n if (has('IsUUID')) {\n ensureString();\n const m = messageRaw(dec('IsUUID'));\n stringChecks.push(m === undefined ? { check: 'uuid' } : { check: 'uuid', messageRaw: m });\n }\n if (has('Matches')) {\n const re = firstArgText(dec('Matches'));\n if (re) {\n ensureString();\n stringChecks.push({ check: 'regex', pattern: re });\n }\n }\n\n // Length / size refinements\n if (has('MinLength')) {\n const n = numericArg(dec('MinLength'));\n if (n !== null) stringChecks.push({ check: 'min', value: n });\n }\n if (has('MaxLength')) {\n const n = numericArg(dec('MaxLength'));\n if (n !== null) stringChecks.push({ check: 'max', value: n });\n }\n if (has('Length')) {\n const [min, max] = numericArgs(dec('Length'));\n if (min !== null) stringChecks.push({ check: 'min', value: min });\n if (max !== null) stringChecks.push({ check: 'max', value: max });\n }\n if (has('Min')) {\n const n = numericArg(dec('Min'));\n if (n !== null) numberChecks.push({ check: 'min', value: n });\n }\n if (has('Max')) {\n const n = numericArg(dec('Max'));\n if (n !== null) numberChecks.push({ check: 'max', value: n });\n }\n if (has('IsPositive')) numberChecks.push({ check: 'positive' });\n if (has('IsNegative')) numberChecks.push({ check: 'negative' });\n if (has('IsNotEmpty') && base.kind === 'string') stringChecks.push({ check: 'min', value: '1' });\n\n // Enum / membership (replaces base).\n if (has('IsEnum')) {\n const enumNode = enumSchemaFromDecorator(dec('IsEnum'), classFile, ctx);\n if (enumNode) base = enumNode;\n }\n if (has('IsIn')) {\n const inNode = inSchemaFromDecorator(dec('IsIn'));\n if (inNode) base = inNode;\n }\n\n // ── Unmappable decorators → warn + comment, keep base ───────────────────\n const unmappable: string[] = [];\n for (const name of decorators.keys()) {\n if (!KNOWN_DECORATORS.has(name)) {\n unmappable.push(name);\n if (!ctx.warnedDecorators.has(name)) {\n ctx.warnedDecorators.add(name);\n const msg = `@${name} is not translatable to a client validation schema and was skipped (server-only validation).`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n }\n }\n\n // Attach the collected refinements to the base. `base` may have been created\n // by `baseFromType` (with its own empty checks array) or by an override, so\n // rebuild it here to guarantee the accumulated checks are the ones emitted.\n if (base.kind === 'string') base = { kind: 'string', checks: stringChecks };\n else if (base.kind === 'number') base = { kind: 'number', checks: numberChecks };\n\n let node: SchemaNode = base;\n\n // Array wrapping when the TS type is `T[]` and no nested handling occurred.\n if (isArrayType && node.kind !== 'array') {\n node = { kind: 'array', element: node };\n }\n\n node = applyPresence(node, decorators);\n\n if (unmappable.length > 0) {\n node = { kind: 'annotated', inner: node, unmappable };\n }\n return node;\n}\n\n/** `.optional()` / required handling from @IsOptional / @IsDefined. */\nfunction applyPresence(node: SchemaNode, decorators: Map<string, Decorator>): SchemaNode {\n if (decorators.has('IsDefined')) return node; // explicitly required\n if (decorators.has('IsOptional')) return { kind: 'optional', inner: node };\n return node;\n}\n\n// ---------------------------------------------------------------------------\n// Base type from the TS property type\n// ---------------------------------------------------------------------------\n\nfunction baseFromType(typeText: string, isArrayType: boolean): SchemaNode {\n const inner = isArrayType ? typeText.slice(0, -2).trim() : typeText;\n switch (inner) {\n case 'string':\n return { kind: 'string', checks: [] };\n case 'number':\n return { kind: 'number', checks: [] };\n case 'boolean':\n return { kind: 'boolean' };\n case 'Date':\n return { kind: 'date' };\n case 'File':\n case 'Express.Multer.File':\n return { kind: 'instanceof', ctor: 'File' };\n default:\n return { kind: 'unknown' };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nested DTO references (hoisted named consts)\n// ---------------------------------------------------------------------------\n\nfunction buildNestedReference(\n className: string,\n fromFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n // Genuine recursion guard FIRST: the class is already on the build stack, so\n // this is a self/mutual reference. Emit a `lazyRef` back-edge to the named\n // schema reserved by the outer frame and mark it recursive — adapters keep the\n // real shape and break the inference cycle themselves.\n if (ctx.visiting.has(className)) {\n const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);\n ctx.emittedClasses.set(className, reserved);\n ctx.recursiveSchemas.add(reserved);\n if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {\n ctx.warnedDecorators.add(`recursive:${reserved}`);\n const msg = `${className} is a recursive type; the generated schema validates it via a lazy self-reference.`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'lazyRef', name: reserved };\n }\n\n // Depth cap: not recursive, just nested deeper than we expand. Degrade this\n // branch to `unknown` inline (no named schema, not flagged as recursive).\n if (ctx.depth >= 8) {\n if (!ctx.warnedDecorators.has(`deep:${className}`)) {\n ctx.warnedDecorators.add(`deep:${className}`);\n const msg = `${className} nesting is too deep to expand; the generated schema uses unknown for it.`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'unknown', note: 'nesting too deep — not expanded' };\n }\n\n const existing = ctx.emittedClasses.get(className);\n if (existing) return { kind: 'ref', name: existing };\n\n const schemaName = aliasFor(className, ctx);\n const resolved = findType(className, fromFile, ctx.project);\n if (!resolved || resolved.kind !== 'class') {\n return { kind: 'object', fields: [], passthrough: true };\n }\n\n ctx.emittedClasses.set(className, schemaName);\n ctx.visiting.add(className);\n ctx.depth += 1;\n const childNode = buildObject(resolved.decl, resolved.file, ctx);\n ctx.depth -= 1;\n ctx.visiting.delete(className);\n\n ctx.named.set(schemaName, childNode);\n return { kind: 'ref', name: schemaName };\n}\n\nfunction aliasFor(className: string, ctx: BuildContext): string {\n const baseName = `${className}Schema`;\n let candidate = baseName;\n let i = 1;\n const used = new Set(ctx.named.keys());\n for (const v of ctx.emittedClasses.values()) used.add(v);\n while (used.has(candidate)) {\n candidate = `${baseName}_${i}`;\n i += 1;\n }\n return candidate;\n}\n\n// ---------------------------------------------------------------------------\n// Decorator argument readers (pure AST)\n// ---------------------------------------------------------------------------\n\nfunction firstArg(decorator: Decorator | undefined): Node | undefined {\n return decorator?.getArguments()[0];\n}\n\nfunction firstArgText(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n return arg ? arg.getText() : null;\n}\n\nfunction numericArg(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (arg && Node.isNumericLiteral(arg)) return arg.getText();\n return null;\n}\n\nfunction numericArgs(decorator: Decorator | undefined): [string | null, string | null] {\n const args = decorator?.getArguments() ?? [];\n const num = (n: Node | undefined): string | null =>\n n && Node.isNumericLiteral(n) ? n.getText() : null;\n return [num(args[0]), num(args[1])];\n}\n\n/** Reads a `{ message: '...' }` options object → the verbatim message literal text. */\nfunction messageRaw(decorator: Decorator | undefined): string | undefined {\n const args = decorator?.getArguments() ?? [];\n for (const arg of args) {\n if (Node.isObjectLiteralExpression(arg)) {\n for (const prop of arg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'message') {\n const init = prop.getInitializer();\n if (init && Node.isStringLiteral(init)) return init.getText();\n }\n }\n }\n }\n return undefined;\n}\n\n/** Resolve `@Type(() => Child)` → `'Child'`. */\nfunction resolveTypeFactoryName(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) return body.getText();\n }\n return null;\n}\n\n/** Drop array suffix from a type text → class name (`Child[]` → `Child`). */\nfunction singularClassName(typeText: string): string | null {\n const inner = typeText.endsWith('[]') ? typeText.slice(0, -2).trim() : typeText;\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(inner) ? inner : null;\n}\n\n/** `@IsEnum(E)` → enum node (or verbatim fallback when unresolvable). */\nfunction enumSchemaFromDecorator(\n decorator: Decorator | undefined,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isIdentifier(arg)) {\n const name = arg.getText();\n const resolved = findType(name, classFile, ctx.project);\n if (resolved && resolved.kind === 'enum') {\n return { kind: 'enum', literals: resolved.members };\n }\n const msg = `@IsEnum(${name}): enum could not be resolved to literal members and is not importable into the generated schema; falling back to unknown.`;\n if (!ctx.warnedDecorators.has(`IsEnum:${name}`)) {\n ctx.warnedDecorators.add(`IsEnum:${name}`);\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'unknown', note: `@IsEnum(${name}): enum not resolvable to literals` };\n }\n if (Node.isObjectLiteralExpression(arg)) {\n const values: string[] = [];\n for (const p of arg.getProperties()) {\n if (!Node.isPropertyAssignment(p)) continue;\n const init = p.getInitializer();\n if (init && Node.isStringLiteral(init)) values.push(init.getText());\n }\n if (values.length > 0) return { kind: 'enum', literals: values };\n }\n return null;\n}\n\n/** `@IsIn(['a','b'])` → enum node; non-string members → union of literals. */\nfunction inSchemaFromDecorator(decorator: Decorator | undefined): SchemaNode | null {\n const arg = firstArg(decorator);\n if (arg && Node.isArrayLiteralExpression(arg)) {\n const elements = arg.getElements();\n const allStrings = elements.every((e) => Node.isStringLiteral(e));\n if (allStrings && elements.length > 0) {\n return { kind: 'enum', literals: elements.map((e) => e.getText()) };\n }\n if (elements.length > 0) {\n return {\n kind: 'union',\n options: elements.map((e) => ({ kind: 'literal', raw: e.getText() })),\n };\n }\n }\n return null;\n}\n","import { readFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport {\n type ClassDeclaration,\n type InterfaceDeclaration,\n Node,\n type Project,\n type SourceFile,\n type TypeNode,\n} from 'ts-morph';\nimport type { TypeRef } from './types.js';\n\n/**\n * Type-reference resolution: the leaf module of the discovery DAG. Owns the\n * per-invocation discovery context (project root + tsconfig path aliases) and\n * the \"follow a name/TypeNode to its declaring file\" machinery shared by every\n * other discovery module.\n */\n\n// ---------------------------------------------------------------------------\n// Discovery context — scoped per `discoverContractsFast` invocation.\n// Keyed off the per-invocation ts-morph `Project` (every resolution entry point\n// already threads it), so concurrent invocations each get an isolated context\n// with no shared mutable global to corrupt.\n// ---------------------------------------------------------------------------\n\nexport interface DiscoveryContext {\n projectRoot: string;\n tsconfigPaths: Record<string, string[]> | null;\n}\n\nconst _EMPTY_CTX: DiscoveryContext = { projectRoot: '', tsconfigPaths: null };\n\n/** Per-`Project` discovery context. WeakMap so contexts die with their project. */\nconst _ctxByProject = new WeakMap<Project, DiscoveryContext>();\n\n/** Associate a discovery context with a `Project` for the duration of a run. */\nexport function setDiscoveryContext(project: Project, ctx: DiscoveryContext): void {\n _ctxByProject.set(project, ctx);\n}\n\nfunction _ctxFor(project: Project): DiscoveryContext {\n return _ctxByProject.get(project) ?? _EMPTY_CTX;\n}\n\nconst _debug = process.env.NESTJS_INERTIA_DEBUG === '1';\nexport function dbg(...args: unknown[]) {\n if (_debug) console.log('[codegen:debug]', ...args);\n}\n\nexport function loadTsconfigPaths(tsconfigPath: string): Record<string, string[]> | null {\n try {\n const raw = readFileSync(tsconfigPath, 'utf8');\n // Strip single-line comments (tsconfig allows them)\n const stripped = raw.replace(/\\/\\/.*$/gm, '');\n const parsed = JSON.parse(stripped) as {\n compilerOptions?: { paths?: Record<string, string[]> };\n };\n return parsed.compilerOptions?.paths ?? null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type-declaration lookup\n// ---------------------------------------------------------------------------\n\nexport type TypeDeclResult =\n | { kind: 'class'; decl: ClassDeclaration; file: SourceFile }\n | { kind: 'interface'; decl: InterfaceDeclaration; file: SourceFile }\n | { kind: 'typeAlias'; typeNode: TypeNode | undefined; file: SourceFile; 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 */\nexport function 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 {\n kind: 'typeAlias',\n typeNode,\n file,\n text: typeNode ? typeNode.getText() : 'unknown',\n };\n }\n\n const enumDecl = file.getEnum(name);\n if (enumDecl) {\n const members = enumDecl.getMembers().map((m) => {\n const val = m.getValue();\n // String value → quoted literal (\"active\"); numeric value → numeric\n // literal (1). Fall back to the member NAME only when the value can't be\n // resolved statically (e.g. a computed member).\n if (typeof val === 'string' || typeof val === 'number') return JSON.stringify(val);\n return 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 */\nexport function resolveModuleSpecifier(\n moduleSpecifier: string,\n sourceFile: SourceFile,\n project: Project,\n): string[] {\n if (moduleSpecifier.startsWith('.')) {\n const dir = dirname(sourceFile.getFilePath());\n // Strip an explicit ESM `.js`/`.ts` extension so `./x.dto.js` resolves to\n // `./x.dto.ts` (NodeNext import style).\n const noExt = moduleSpecifier.replace(/\\.(js|ts)$/, '');\n return [\n resolve(dir, `${noExt}.ts`),\n resolve(dir, `${moduleSpecifier}.ts`),\n resolve(dir, moduleSpecifier, 'index.ts'),\n ];\n }\n\n // Try to resolve path aliases via tsconfig paths (read directly from JSON)\n const ctx = _ctxFor(project);\n const baseUrl = ctx.projectRoot;\n const tsconfigPaths = ctx.tsconfigPaths;\n\n dbg(\n 'resolveModuleSpecifier',\n moduleSpecifier,\n 'paths:',\n JSON.stringify(tsconfigPaths),\n 'baseUrl:',\n baseUrl,\n );\n\n if (tsconfigPaths) {\n for (const [pattern, mappings] of Object.entries(tsconfigPaths)) {\n const prefix = pattern.replace('*', '');\n if (moduleSpecifier.startsWith(prefix)) {\n const rest = moduleSpecifier.slice(prefix.length);\n const candidates: string[] = [];\n for (const mapping of mappings) {\n const resolved = resolve(baseUrl, mapping.replace('*', rest));\n candidates.push(`${resolved}.ts`, resolve(resolved, 'index.ts'));\n }\n dbg(' resolved candidates:', candidates);\n return candidates;\n }\n }\n }\n\n return [];\n}\n\nexport function 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 const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);\n if (candidates.length === 0) continue;\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 // The target module may itself re-export the symbol from elsewhere\n // (`export { X } from './mod'` or `import { X } ...; export { X }`).\n const viaReExport = resolveReExportedType(name, importedFile, project, new Set());\n if (viaReExport) return viaReExport;\n }\n }\n // The current file may re-export the symbol from another module.\n return resolveReExportedType(name, sourceFile, project, new Set());\n}\n\n/**\n * Follow `export { X } from './mod'` / `export * from './mod'` re-exports, and\n * bare `export { X }` statements that re-publish a previously-imported symbol,\n * to find a type declaration in a sibling module. Guards against import cycles\n * via `seen`.\n */\nfunction resolveReExportedType(\n name: string,\n file: SourceFile,\n project: Project,\n seen: Set<string>,\n): TypeDeclResult | null {\n const filePath = file.getFilePath();\n if (seen.has(filePath)) return null;\n seen.add(filePath);\n\n for (const exportDecl of file.getExportDeclarations()) {\n const moduleSpecifier = exportDecl.getModuleSpecifierValue();\n const namedExports = exportDecl.getNamedExports();\n\n // `export { X } from './mod'` — only follow when X (or its alias source) matches.\n if (moduleSpecifier) {\n const hasStar = namedExports.length === 0; // `export * from './mod'`\n const reExportsName = namedExports.some(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!hasStar && !reExportsName) continue;\n // The source-side name (before any alias rename).\n const sourceName = hasStar\n ? name\n : (namedExports\n .find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)\n ?.getName() ?? name);\n const target = followModuleForType(sourceName, moduleSpecifier, file, project, seen);\n if (target) return target;\n continue;\n }\n\n // `export { X }` (no module specifier) — X was imported above into this file.\n const reExportsName = namedExports.some(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!reExportsName) continue;\n const sourceName =\n namedExports.find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)?.getName() ??\n name;\n const local = findTypeInFile(sourceName, file);\n if (local) return local;\n const imported = resolveImportedType(sourceName, file, project);\n if (imported) return imported;\n }\n return null;\n}\n\nfunction followModuleForType(\n name: string,\n moduleSpecifier: string,\n fromFile: SourceFile,\n project: Project,\n seen: Set<string>,\n): TypeDeclResult | null {\n const candidates = resolveModuleSpecifier(moduleSpecifier, fromFile, project);\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 const viaReExport = resolveReExportedType(name, importedFile, project, seen);\n if (viaReExport) return viaReExport;\n }\n return null;\n}\n\n/**\n * Per-`Project` memoization of {@link findType}. Within one discovery run the\n * `Project` is effectively immutable (`addSourceFileAtPath` is idempotent and\n * `getSourceFile` returns the existing instance), so the same `(file, name)`\n * pair always resolves to the same declaration. The same type/enum would\n * otherwise be fully re-resolved on every reference — O(routes × DTOs × imports).\n *\n * Keyed by `Project` via a WeakMap so the cache dies with its project and there\n * is no cross-run staleness: every `discoverContractsFast` call (and every watch\n * change) builds a fresh `Project`, hence a fresh cache. Null results are cached\n * too (use `.has` to distinguish \"cached null\" from \"not yet computed\").\n */\nconst _findTypeCache = new WeakMap<Project, Map<string, TypeDeclResult | null>>();\n\n/**\n * Find a type declaration by name: first in the current file, then by following imports.\n */\nexport function findType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n let byKey = _findTypeCache.get(project);\n if (byKey === undefined) {\n byKey = new Map();\n _findTypeCache.set(project, byKey);\n }\n const key = `${sourceFile.getFilePath()}\u0000${name}`;\n if (byKey.has(key)) return byKey.get(key) ?? null;\n const local = findTypeInFile(name, sourceFile);\n const result = local ?? resolveImportedType(name, sourceFile, project);\n byKey.set(key, result);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Importable named-ref resolution\n// ---------------------------------------------------------------------------\n\n/** The declaration kinds a `resolveTypeRef` call will accept as an importable ref. */\nexport type TypeRefKind = 'class' | 'interface' | 'typeAlias' | 'enum';\n\nexport interface ResolveTypeRefOptions {\n /**\n * Declaration kinds accepted as an importable named ref (applied identically\n * to local and imported declarations). The two call sites differ only here:\n * - body/query/response refs accept class + interface;\n * - `@FilterFor` param refs also accept enum + type alias.\n */\n kinds: TypeRefKind[];\n /**\n * Honour a bare (node_modules) import specifier — emit `{ name, filePath: spec }`\n * so the emitter imports straight from the package. tsconfig path aliases are\n * excluded (they resolve to files instead). Off for the body/query/response\n * path (which only ever points at project source files).\n */\n allowBareSpecifier?: boolean;\n /**\n * Unwrap `Promise<T>`, `Array<T>` and `T[]` to the inner named type (marking\n * array forms with `isArray`). Used for the body/query/response path which\n * receives a raw return/param `TypeNode`; the `@FilterFor` path passes a bare\n * symbol name and needs no unwrapping.\n */\n unwrapContainers?: boolean;\n}\n\n/** Skip-list of primitive / well-known names that never resolve to a named ref. */\nconst _NON_REF_NAMES = new Set(['string', 'number', 'boolean', 'void', 'unknown', 'any', 'Date']);\n\n/** Does an exported declaration found by `findTypeInFile` match the accepted kinds? */\nfunction _localDeclForKinds(name: string, file: SourceFile, kinds: TypeRefKind[]): boolean {\n if (kinds.includes('class') && file.getClass(name)?.isExported()) return true;\n if (kinds.includes('interface') && file.getInterface(name)?.isExported()) return true;\n if (kinds.includes('typeAlias') && file.getTypeAlias(name)?.isExported()) return true;\n if (kinds.includes('enum') && file.getEnum(name)?.isExported()) return true;\n return false;\n}\n\n/**\n * Resolve a type reference to an importable `TypeRef` — the symbol name plus the\n * absolute path of its declaring source file (for a relative import) OR the bare\n * module specifier (for a node_modules package). Accepts either a raw `TypeNode`\n * (with `unwrapContainers` to peel `Promise`/`Array`) or a bare symbol name.\n *\n * Walks: local exported decl → `{ name, thisFile }`; else the file's import\n * declarations to a matching exported decl → `{ name, importedFile }`. The\n * accepted declaration kinds (and bare-specifier / container-unwrap support) are\n * controlled by `opts`, letting both former resolvers share this one body.\n * Returns null when the symbol is not exported, not resolvable, or its import\n * path cannot be safely computed.\n */\nexport function resolveTypeRef(\n nodeOrName: TypeNode | string,\n sourceFile: SourceFile,\n project: Project,\n opts: ResolveTypeRefOptions,\n): TypeRef | null {\n // ── Resolve the bare symbol name (peeling containers for the TypeNode form) ──\n let name: string;\n if (typeof nodeOrName === 'string') {\n name = nodeOrName;\n } else {\n const typeNode = nodeOrName;\n\n if (opts.unwrapContainers && Node.isArrayTypeNode(typeNode)) {\n const inner = resolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project, opts);\n return inner ? { ...inner, isArray: true } : null;\n }\n\n if (!Node.isTypeReference(typeNode)) return null;\n const typeName = typeNode.getTypeName();\n const refName = Node.isIdentifier(typeName) ? typeName.getText() : null;\n if (!refName) return null;\n\n if (opts.unwrapContainers && refName === 'Promise') {\n const first = typeNode.getTypeArguments()[0];\n return first ? resolveTypeRef(first, sourceFile, project, opts) : null;\n }\n if (opts.unwrapContainers && refName === 'Array') {\n const first = typeNode.getTypeArguments()[0];\n if (!first) return null;\n const inner = resolveTypeRef(first, sourceFile, project, opts);\n return inner ? { ...inner, isArray: true } : null;\n }\n\n if (_NON_REF_NAMES.has(refName)) return null;\n name = refName;\n }\n\n // The bare-symbol resolution below is deterministic in (file, name, kinds,\n // allowBareSpecifier) within a run, so it is memoized per-Project.\n return _resolveNamedRef(name, sourceFile, project, opts);\n}\n\n/**\n * Per-`Project` memoization of the bare-symbol resolution arm of\n * {@link resolveTypeRef} (steps 1 & 2). Keyed by `(file, name, kinds,\n * allowBareSpecifier)` — the only inputs the import-following walk depends on.\n * `unwrapContainers` is excluded because container peeling happens in the caller\n * before this point. Same WeakMap-by-Project safety as {@link findType}: fresh\n * Project per run ⇒ fresh cache, no cross-run staleness. Null results cached too.\n *\n * Returns a fresh object copy on a cache hit so callers (which may spread\n * `{ ...ref, isArray: true }` or otherwise treat the ref as owned) never share a\n * mutable cached instance.\n */\nconst _resolveNamedRefCache = new WeakMap<Project, Map<string, TypeRef | null>>();\n\nfunction _resolveNamedRef(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n opts: ResolveTypeRefOptions,\n): TypeRef | null {\n let byKey = _resolveNamedRefCache.get(project);\n if (byKey === undefined) {\n byKey = new Map();\n _resolveNamedRefCache.set(project, byKey);\n }\n const kindsKey = [...opts.kinds].sort().join(',');\n const key = `${sourceFile.getFilePath()}\\0${name}\\0${kindsKey}\\0${opts.allowBareSpecifier ? 1 : 0}`;\n if (byKey.has(key)) {\n const cached = byKey.get(key) ?? null;\n return cached ? { ...cached } : null;\n }\n const computed = _computeNamedRef(name, sourceFile, project, opts);\n byKey.set(key, computed);\n return computed ? { ...computed } : null;\n}\n\nfunction _computeNamedRef(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n opts: ResolveTypeRefOptions,\n): TypeRef | null {\n // 1. Declared (and exported) in the current file → relative import to it.\n if (_localDeclForKinds(name, sourceFile, opts.kinds)) {\n return { name, filePath: sourceFile.getFilePath() };\n }\n\n // 2. Imported from another module — follow the import declaration.\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);\n if (!namedImport) continue;\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n\n // Bare specifier (node_modules package) → import directly by specifier.\n if (\n opts.allowBareSpecifier &&\n !moduleSpecifier.startsWith('.') &&\n !moduleSpecifier.startsWith('/')\n ) {\n // Only honour it if not a tsconfig path alias (those resolve to files).\n const tsconfigPaths = _ctxFor(project).tsconfigPaths;\n const isAlias =\n tsconfigPaths != null &&\n Object.keys(tsconfigPaths).some((p) => {\n const prefix = p.replace('*', '');\n return moduleSpecifier.startsWith(prefix);\n });\n if (!isAlias) {\n return { name, filePath: moduleSpecifier };\n }\n }\n\n // Local / aliased source file → resolve to its absolute path so the emitter\n // can compute a relative import from the generated output dir.\n const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);\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 if (_localDeclForKinds(name, importedFile, opts.kinds)) {\n return { name, filePath: importedFile.getFilePath() };\n }\n }\n }\n\n return null;\n}\n","import {\n type ClassDeclaration,\n type MethodDeclaration,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport {\n type ClassifyResult,\n classifyFieldType,\n classifyTypeNode,\n toFilterFieldType,\n} from './filter-field-types.js';\nimport { findType, resolveTypeRef } from './type-ref-resolution.js';\nimport type { FilterFieldType } from './types.js';\n\n/**\n * `@FilterFor` / `@ApplyFilter` discovery: resolve the virtual + entity-derived\n * filter fields (with their classified types) for a filter class referenced by\n * an `@ApplyFilter(FilterClass)` parameter.\n */\n\n/**\n * Map a single `@FilterFor` `type` hint token (read statically from the AST) to a\n * `ClassifyResult`. Supports the four primitive tokens plus a string-literal\n * array (enum) → literal string union. Returns null for anything unrecognised so\n * the caller falls back to the current permissive (`unknown`) behavior.\n */\nexport function classifyFilterForHint(typeInit: Node): ClassifyResult | null {\n // Primitive token: 'string' | 'number' | 'boolean' | 'Date'\n if (Node.isStringLiteral(typeInit)) {\n switch (typeInit.getLiteralValue()) {\n case 'string':\n return { kind: 'string' };\n case 'number':\n return { kind: 'number' };\n case 'boolean':\n return { kind: 'boolean' };\n case 'Date':\n return { kind: 'date' };\n default:\n return null;\n }\n }\n\n // Enum: a readonly array of string literals → literal string union.\n if (Node.isArrayLiteralExpression(typeInit)) {\n const values: string[] = [];\n for (const el of typeInit.getElements()) {\n if (!Node.isStringLiteral(el)) return null; // non-literal → bail to permissive\n values.push(el.getLiteralValue());\n }\n if (values.length === 0) return null;\n return { kind: 'string', enumValues: values };\n }\n\n return null;\n}\n\n/**\n * Classify the type of the FIRST parameter of a `@FilterFor` method (the new\n * primary inference mechanism). Precedence inside this function:\n * - primitive `number`/`string`/`boolean`/`Date` → emit directly.\n * - literal unions (`'a' | 'b'`, `1 | 2`) → emit the union text.\n * - named enum / type alias / interface → emit a `typeRef` (named import,\n * option B) when an import path is resolvable; otherwise fall back to\n * literal-union expansion for enums/unions, else skip.\n * - any/unknown/no-param/unresolvable → null (caller falls back).\n */\nexport function classifyFilterForParam(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult | null {\n const param = method.getParameters()[0];\n if (!param) return null;\n const typeNode = param.getTypeNode();\n if (!typeNode) return null;\n\n // Classify ONCE. `resolveRef` attaches an importable named ref (option B) when\n // the symbol resolves to an exported enum / type alias / interface / class with\n // a safe import path; the emitter prefers that `typeRef` over the `kind`. The\n // best-effort `kind` is still recorded so non-emit consumers (tests) see a\n // sensible classification.\n const wellKnown = ['string', 'number', 'boolean', 'Date', 'any', 'unknown'];\n const result = classifyTypeNode(typeNode, sourceFile, project, {\n resolveRef: (refName) => {\n if (wellKnown.includes(refName)) return null;\n // Only attempt a named import for symbols we can resolve to a declaration.\n if (!findType(refName, sourceFile, project)) return null;\n return resolveTypeRef(refName, sourceFile, project, {\n kinds: ['class', 'interface', 'typeAlias', 'enum'],\n allowBareSpecifier: true,\n });\n },\n });\n\n // A resolved `typeRef` is always usable (even with kind 'unknown' — the emitter\n // references the ref by name). Otherwise skip permissive `unknown` results.\n if (result.typeRef) return result;\n return result.kind === 'unknown' ? null : result;\n}\n\n/**\n * Discover virtual filter fields declared via `@FilterFor('key', { type })`\n * method decorators on the filter class. Field-type resolution precedence (high\n * wins): (1) explicit `{ type }` hint, (2) the method's first-parameter type\n * (named enums/aliases → real `import type` refs), (3+) fall back to existing\n * class-property / entity-column / `unknown` behavior (handled by the caller).\n *\n * Returns a map of inputKey → classified type for every `@FilterFor` that\n * carries a usable hint OR a usable first-parameter type. Keys with neither are\n * intentionally omitted here (they remain permissive / fall back).\n */\nexport function extractFilterForHints(\n classDecl: ClassDeclaration,\n project: Project,\n): Map<string, ClassifyResult> {\n const hints = new Map<string, ClassifyResult>();\n const sourceFile = classDecl.getSourceFile();\n for (const method of classDecl.getMethods()) {\n const filterForDec = method.getDecorators().find((d) => d.getName() === 'FilterFor');\n if (!filterForDec) continue;\n\n const args = filterForDec.getArguments();\n // inputKey: first string-literal arg, else the method name.\n const keyArg = args[0];\n const inputKey =\n keyArg && Node.isStringLiteral(keyArg) ? keyArg.getLiteralValue() : method.getName();\n\n // (1) Explicit `{ type }` hint — highest precedence, unchanged behavior.\n const optsArg = args[1];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n const typeProp = optsArg.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const typeInit = typeProp.getInitializer();\n if (typeInit) {\n const classified = classifyFilterForHint(typeInit);\n if (classified) {\n hints.set(inputKey, classified);\n continue;\n }\n }\n }\n }\n\n // (2) Method first-parameter type — the new primary inference mechanism.\n const fromParam = classifyFilterForParam(method, sourceFile, project);\n if (fromParam) hints.set(inputKey, fromParam);\n }\n return hints;\n}\n\n/**\n * Extract the filter field data from an `@ApplyFilter(FilterClass)` decorated\n * parameter. Resolves the filter class and reads its properties (excluding\n * inherited base class members). Returns the field names + classified types +\n * filter source, or null when no resolvable filter is present.\n */\nexport function extractApplyFilterInfo(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): {\n fieldNames: string[];\n fieldTypes: FilterFieldType[];\n source: 'body' | 'query';\n} | null {\n for (const param of method.getParameters()) {\n const filterDecorator = param.getDecorators().find((d) => d.getName() === 'ApplyFilter');\n if (!filterDecorator) continue;\n const args = filterDecorator.getArguments();\n if (args.length === 0) continue;\n const filterClassArg = args[0];\n if (!filterClassArg || !Node.isIdentifier(filterClassArg)) continue;\n\n // Read { source: \"body\" | \"query\" } from second argument\n let source: 'body' | 'query' = 'query';\n const optionsArg = args[1];\n if (optionsArg && Node.isObjectLiteralExpression(optionsArg)) {\n const sourceProp = optionsArg.getProperty('source');\n if (sourceProp && Node.isPropertyAssignment(sourceProp)) {\n const init = sourceProp.getInitializer();\n if (init && Node.isStringLiteral(init) && init.getLiteralValue() === 'body') {\n source = 'body';\n }\n }\n }\n\n const filterClassName = filterClassArg.getText();\n const resolved = findType(filterClassName, sourceFile, project);\n if (resolved && resolved.kind === 'class') {\n const classDecl = resolved.decl as ClassDeclaration;\n let fieldTypes = extractClassPropertyTypes(classDecl, project);\n\n // autoFields: if the filter class has no properties, resolve fields\n // from the entity referenced in @Filterable({ entity: X })\n if (fieldTypes.length === 0) {\n fieldTypes = extractFilterableEntityFields(classDecl, project);\n }\n\n // Merge in explicit @FilterFor('key', { type }) hints. An explicit hint\n // WINS over entity-column / class-property inference for the same key;\n // genuinely-virtual keys (no property, no column) are appended so they\n // appear in the Fields union and the type map M.\n const filterForHints = extractFilterForHints(classDecl, project);\n if (filterForHints.size > 0) {\n const byName = new Map(fieldTypes.map((f) => [f.name, f] as const));\n for (const [key, classified] of filterForHints) {\n byName.set(key, toFilterFieldType(key, classified));\n }\n fieldTypes = [...byName.values()];\n }\n\n if (fieldTypes.length === 0) return null;\n const fieldNames = fieldTypes.map((f) => f.name);\n return {\n fieldNames,\n fieldTypes,\n source,\n };\n }\n }\n return null;\n}\n\nconst RELATION_DECORATORS = new Set(['OneToMany', 'ManyToOne', 'ManyToMany', 'OneToOne']);\n\n/**\n * Recursively collect entity fields including dot-notation relation fields.\n * e.g. for PipelineRun with tasks: OneToMany<Task>, produces:\n * [\"id\", \"name\", \"status\", ..., \"tasks.id\", \"tasks.name\", ...]\n */\nfunction collectEntityFields(\n entityDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n prefix: string,\n visited: Set<string>,\n): FilterFieldType[] {\n const entityName = entityDecl.getName() ?? '';\n if (visited.has(entityName)) return [];\n visited.add(entityName);\n\n const fields: FilterFieldType[] = [];\n for (const prop of entityDecl.getProperties()) {\n const name = prop.getName();\n if (name.startsWith('$') || name.startsWith('_') || name.startsWith('[')) continue;\n if (prop.isStatic()) continue;\n\n const fullName = prefix ? `${prefix}.${name}` : name;\n const isRelation = prop.getDecorators().some((d) => RELATION_DECORATORS.has(d.getName()));\n\n if (isRelation) {\n const relEntity = resolveRelationEntity(prop, sourceFile, project);\n if (relEntity) {\n // Classify each relation leaf against the relation's own source file.\n fields.push(\n ...collectEntityFields(relEntity, relEntity.getSourceFile(), project, fullName, visited),\n );\n }\n } else {\n fields.push(toFilterFieldType(fullName, classifyFieldType(prop, sourceFile, project)));\n }\n }\n return fields;\n}\n\n/**\n * Given a relation property (e.g. `tasks = new Collection<Task>(this)`),\n * resolve the target entity class declaration.\n */\nfunction resolveRelationEntity(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassDeclaration | null {\n // Try from decorator argument: @OneToMany({ entity: () => Task, ... })\n for (const dec of prop.getDecorators()) {\n if (!RELATION_DECORATORS.has(dec.getName())) continue;\n const args = dec.getArguments();\n if (args.length === 0) continue;\n const arg = args[0];\n if (Node.isObjectLiteralExpression(arg)) {\n const entityProp = arg.getProperty('entity');\n if (entityProp && Node.isPropertyAssignment(entityProp)) {\n const init = entityProp.getInitializer();\n // () => Task\n if (init && Node.isArrowFunction(init)) {\n const body = init.getBody();\n if (Node.isIdentifier(body)) {\n const resolved = findType(body.getText(), prop.getSourceFile(), project);\n if (resolved?.kind === 'class') return resolved.decl as ClassDeclaration;\n }\n }\n }\n }\n // @ManyToOne(() => Task)\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) {\n const resolved = findType(body.getText(), prop.getSourceFile(), project);\n if (resolved?.kind === 'class') return resolved.decl as ClassDeclaration;\n }\n }\n }\n return null;\n}\n\n/** Classify each property of a filter DTO class into a FilterFieldType. */\nfunction extractClassPropertyTypes(\n classDecl: ClassDeclaration,\n project: Project,\n): FilterFieldType[] {\n const sourceFile = classDecl.getSourceFile();\n const fields: FilterFieldType[] = [];\n for (const prop of classDecl.getProperties()) {\n const name = prop.getName();\n if (name.startsWith('$') || name.startsWith('_')) continue;\n fields.push(toFilterFieldType(name, classifyFieldType(prop, sourceFile, project)));\n }\n return fields;\n}\n\n/**\n * When a filter class uses `@Filterable({ entity: X, autoFields: true })`,\n * resolve entity X and extract its property names (fields decorated with\n * `@Property`, `@PrimaryKey`, `@Enum`, etc. — skipping relations).\n */\nfunction extractFilterableEntityFields(\n filterClass: ClassDeclaration,\n project: Project,\n): FilterFieldType[] {\n const filterableDecorator = filterClass.getDecorators().find((d) => d.getName() === 'Filterable');\n if (!filterableDecorator) return [];\n const args = filterableDecorator.getArguments();\n if (args.length === 0) return [];\n\n const optionsArg = args[0];\n if (!Node.isObjectLiteralExpression(optionsArg)) return [];\n\n const entityProp = optionsArg.getProperty('entity');\n if (!entityProp || !Node.isPropertyAssignment(entityProp)) return [];\n\n const entityInit = entityProp.getInitializer();\n if (!entityInit || !Node.isIdentifier(entityInit)) return [];\n\n const entityName = entityInit.getText();\n const filterSourceFile = filterClass.getSourceFile();\n const resolvedEntity = findType(entityName, filterSourceFile, project);\n if (!resolvedEntity || resolvedEntity.kind !== 'class') return [];\n\n const entityDecl = resolvedEntity.decl as ClassDeclaration;\n const fields = collectEntityFields(\n entityDecl,\n entityDecl.getSourceFile(),\n project,\n '',\n new Set(),\n );\n\n // Also include keys declared via @Relations({ rel: { keys: [...] } }).\n // These string keys carry no resolvable type → kind: 'unknown'.\n const relationsDecorator = filterClass.getDecorators().find((d) => d.getName() === 'Relations');\n if (relationsDecorator) {\n const relArgs = relationsDecorator.getArguments();\n if (relArgs.length > 0 && Node.isObjectLiteralExpression(relArgs[0])) {\n for (const relProp of relArgs[0].getProperties()) {\n if (!Node.isPropertyAssignment(relProp)) continue;\n const relInit = relProp.getInitializer();\n if (!relInit || !Node.isObjectLiteralExpression(relInit)) continue;\n const keysProp = relInit.getProperty('keys');\n if (!keysProp || !Node.isPropertyAssignment(keysProp)) continue;\n const keysInit = keysProp.getInitializer();\n if (!keysInit || !Node.isArrayLiteralExpression(keysInit)) continue;\n for (const el of keysInit.getElements()) {\n if (Node.isStringLiteral(el)) {\n // Route through the single constructor (keeps the typeRef invariant\n // enforced in one place); these relation keys carry no type → unknown.\n fields.push(toFilterFieldType(el.getLiteralValue(), { kind: 'unknown' }));\n }\n }\n }\n }\n }\n\n return fields;\n}\n","import {\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport { resolveEnumValues } from './enum-resolution.js';\nimport type { FieldTypeKind, FilterFieldType, TypeRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Field-type classification (mirrors mapTypeOrmType / mapMikroOrmType so codegen\n// and the runtime adapters can never diverge). See nestjs-filter\n// packages/typeorm/src/typeorm.adapter.ts:190 (mapTypeOrmType).\n// ---------------------------------------------------------------------------\n\n/** Reference: typeorm.adapter.ts keyword tables (kept in sync intentionally). */\nconst STRING_TYPE_KEYWORDS = ['varchar', 'text', 'string', 'char', 'uuid', 'enum'];\nconst NUMBER_TYPE_KEYWORDS = ['int', 'float', 'double', 'decimal', 'number', 'numeric', 'real'];\nconst BOOLEAN_TYPE_KEYWORDS = ['bool', 'boolean', 'bit'];\nconst DATE_TYPE_KEYWORDS = ['date', 'time', 'timestamp', 'datetime'];\nconst JSON_TYPE_KEYWORDS = ['json', 'jsonb'];\n\n/** Classify a column/property type literal (e.g. 'varchar') the same way mapTypeOrmType does. */\nexport function classifyTypeKeyword(raw: string): FieldTypeKind | null {\n const t = raw.toLowerCase();\n if (STRING_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'string';\n if (NUMBER_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'number';\n if (BOOLEAN_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'boolean';\n if (DATE_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'date';\n if (JSON_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'json';\n return null;\n}\n\nexport interface ClassifyResult {\n kind: FieldTypeKind;\n enumValues?: string[];\n nullable?: boolean;\n numericEnum?: boolean;\n /** Importable reference to a named enum / type alias / interface (option B). */\n typeRef?: TypeRef;\n}\n\n/**\n * Return `r` with `nullable: true` set only when `nullable` is true.\n * Avoids assigning `undefined` to an optional prop under exactOptionalPropertyTypes.\n */\nexport function markNullable(r: ClassifyResult, nullable: boolean): ClassifyResult {\n return nullable ? { ...r, nullable: true } : r;\n}\n\n/**\n * Options for {@link classifyTypeNode}. When `resolveRef` is supplied and the\n * type node is a named reference (not a primitive / well-known name), it is\n * called with the symbol name; a non-null result is attached as `typeRef` on the\n * returned `ClassifyResult`. This lets `classifyFilterForParam` classify ONCE and\n * pick up the importable ref in the same pass.\n */\nexport interface ClassifyTypeNodeOptions {\n resolveRef?: (refName: string) => TypeRef | null;\n}\n\n/** Classify a TS type node into a field-type kind (+ enum members / nullable). */\nexport function classifyTypeNode(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n opts?: ClassifyTypeNodeOptions,\n): ClassifyResult {\n // Union: strip null/undefined, collect literal members, recurse otherwise.\n if (Node.isUnionTypeNode(typeNode)) {\n let nullable = false;\n const stringLits: string[] = [];\n const numberLits: string[] = [];\n const others: TypeNode[] = [];\n for (const member of typeNode.getTypeNodes()) {\n const kind = member.getKind();\n if (kind === SyntaxKind.NullKeyword || kind === SyntaxKind.UndefinedKeyword) {\n nullable = true;\n continue;\n }\n if (Node.isLiteralTypeNode(member)) {\n const lit = member.getLiteral();\n if (Node.isStringLiteral(lit)) {\n stringLits.push(lit.getLiteralValue());\n continue;\n }\n if (Node.isNumericLiteral(lit)) {\n numberLits.push(lit.getText());\n continue;\n }\n if (lit.getKind() === SyntaxKind.NullKeyword) {\n nullable = true;\n continue;\n }\n }\n others.push(member);\n }\n\n if (others.length === 0 && stringLits.length > 0 && numberLits.length === 0) {\n return markNullable({ kind: 'string', enumValues: stringLits }, nullable);\n }\n if (others.length === 0 && numberLits.length > 0 && stringLits.length === 0) {\n return markNullable({ kind: 'number', enumValues: numberLits, numericEnum: true }, nullable);\n }\n if (others.length === 1) {\n const inner = classifyTypeNode(others[0]!, sourceFile, project, opts);\n return markNullable(inner, nullable || inner.nullable === true);\n }\n return markNullable({ kind: 'unknown' }, nullable);\n }\n\n switch (typeNode.getKind()) {\n case SyntaxKind.StringKeyword:\n return { kind: 'string' };\n case SyntaxKind.NumberKeyword:\n return { kind: 'number' };\n case SyntaxKind.BooleanKeyword:\n return { kind: 'boolean' };\n case SyntaxKind.AnyKeyword:\n case SyntaxKind.UnknownKeyword:\n return { kind: 'unknown' };\n default:\n break;\n }\n\n if (Node.isTypeReference(typeNode)) {\n const refName = typeNode.getTypeName().getText();\n if (refName === 'Date') return { kind: 'date' };\n if (refName === 'Record' || refName === 'Object') return { kind: 'json' };\n // An importable named ref (enum / type alias / interface / class) wins for\n // emit when the caller supplied a resolver and a safe import path exists.\n const typeRef = opts?.resolveRef?.(refName) ?? null;\n // Possibly an enum type used as a property type.\n const en = resolveEnumValues(refName, sourceFile, project);\n if (en) {\n const base: ClassifyResult = en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n return typeRef ? { ...base, typeRef } : base;\n }\n if (typeRef) return { kind: 'unknown', typeRef };\n return { kind: 'unknown' };\n }\n\n if (Node.isTypeLiteral(typeNode)) return { kind: 'json' };\n\n return { kind: 'unknown' };\n}\n\n/** Resolve an enum from @Enum decorator args: `() => Status` or `{ items: () => Status }`. */\nexport function enumFromDecoratorArgs(\n args: Node[],\n sourceFile: SourceFile,\n project: Project,\n): { values: string[]; numeric: boolean } | null {\n for (const arg of args) {\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) {\n const en = resolveEnumValues(body.getText(), sourceFile, project);\n if (en) return en;\n }\n }\n if (Node.isObjectLiteralExpression(arg)) {\n const itemsProp = arg.getProperty('items');\n if (itemsProp && Node.isPropertyAssignment(itemsProp)) {\n const init = itemsProp.getInitializer();\n if (init && Node.isArrowFunction(init)) {\n const body = init.getBody();\n if (Node.isIdentifier(body)) {\n const en = resolveEnumValues(body.getText(), sourceFile, project);\n if (en) return en;\n }\n }\n }\n }\n }\n return null;\n}\n\n/** Classify a property from `@Column`/`@Property`/`@Enum` decorator options. */\nexport function classifyFromColumnDecorator(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult | null {\n for (const dec of prop.getDecorators()) {\n const decName = dec.getName();\n if (decName !== 'Column' && decName !== 'Property' && decName !== 'Enum') continue;\n const args = dec.getArguments();\n\n // @Enum({ items: () => Status }) or @Enum(() => Status)\n if (decName === 'Enum') {\n const en = enumFromDecoratorArgs(args, sourceFile, project);\n if (en) {\n return en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n }\n return { kind: 'string' };\n }\n\n for (const arg of args) {\n // @Column('varchar')\n if (Node.isStringLiteral(arg)) {\n const raw = arg.getLiteralValue();\n const kind = classifyTypeKeyword(raw);\n if (kind) {\n // @Column('enum', { enum: Status }) → resolve via the options object below\n if (kind === 'string' && raw.toLowerCase().includes('enum')) continue;\n return { kind };\n }\n }\n // @Column({ type: 'datetime' }) / @Property({ type: 'int' }) / { enum: Status }\n if (Node.isObjectLiteralExpression(arg)) {\n const enumProp = arg.getProperty('enum');\n if (enumProp && Node.isPropertyAssignment(enumProp)) {\n const init = enumProp.getInitializer();\n if (init && Node.isIdentifier(init)) {\n const en = resolveEnumValues(init.getText(), sourceFile, project);\n if (en) {\n return en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n }\n return { kind: 'string' };\n }\n }\n const typeProp = arg.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const init = typeProp.getInitializer();\n if (init && Node.isStringLiteral(init)) {\n const kind = classifyTypeKeyword(init.getLiteralValue());\n if (kind) return { kind };\n }\n }\n }\n }\n // Decorator present but no recognisable type info.\n return null;\n }\n return null;\n}\n\n/**\n * Classify a single entity/DTO property into a ClassifyResult (kind + enum + nullable),\n * mirroring the runtime ORM type mapping. Falls back to 'unknown' when unresolvable.\n */\nexport function classifyFieldType(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult {\n let nullable = prop.hasQuestionToken();\n const typeNode = prop.getTypeNode();\n\n if (typeNode) {\n const r = classifyTypeNode(typeNode, sourceFile, project);\n if (r.nullable) nullable = true;\n if (r.kind !== 'unknown') return markNullable(r, nullable);\n }\n\n const fromDecorator = classifyFromColumnDecorator(prop, sourceFile, project);\n if (fromDecorator) {\n return markNullable(fromDecorator, nullable || fromDecorator.nullable === true);\n }\n\n return markNullable({ kind: 'unknown' }, nullable);\n}\n\n/**\n * The single normalizing constructor for a {@link FilterFieldType} from a\n * classification. Concentrates the `typeRef` precedence invariant (see the\n * `FilterFieldType` doc): `kind`/`enumValues`/`numericEnum` are always recorded\n * best-effort, and `typeRef` (when present) is what the emitter actually uses.\n * Build `FilterFieldType` values through here — not inline — so the convention\n * has exactly one enforcement point.\n */\nexport function toFilterFieldType(name: string, r: ClassifyResult): FilterFieldType {\n const ft: FilterFieldType = { name, kind: r.kind };\n if (r.enumValues && r.enumValues.length > 0) ft.enumValues = r.enumValues;\n if (r.nullable) ft.nullable = true;\n if (r.numericEnum) ft.numericEnum = true;\n if (r.typeRef) ft.typeRef = r.typeRef;\n return ft;\n}\n","import type { Project, SourceFile } from 'ts-morph';\nimport { findType } from './type-ref-resolution.js';\n\n/**\n * Resolve an enum identifier to its raw member values + numeric flag.\n *\n * KNOWN LIMITATION — mixed enums with a computed member: `findType` serializes\n * each enum member with `JSON.stringify` of its static value, falling back to the\n * QUOTED member NAME for any member whose value can't be resolved statically\n * (e.g. a computed member). Here we re-derive `numeric` by `JSON.parse`-ing each\n * member: any string member (including that quoted-name fallback) flips `numeric`\n * to `false` for the WHOLE enum. So a primarily-numeric enum that contains a\n * single computed member is treated as a string enum, and its numeric members\n * are emitted as quoted string literals. This is a rare edge case; fixing it\n * would require threading per-member numeric-ness out of `findType` rather than\n * inferring it from the stringified members. Pure numeric and pure string enums\n * (the overwhelmingly common cases) are unaffected.\n */\ntype EnumResult = { values: string[]; numeric: boolean };\n\n/**\n * Per-`Project` memoization of {@link resolveEnumValues}. Same WeakMap-by-Project\n * safety as `findType`: each discovery run (and each watch change) builds a fresh\n * `Project`, so the cache dies with it and never goes stale. Null results are\n * cached too (via `.has`). Returns a copy on a cache hit so callers never share a\n * mutable `values` array.\n */\nconst _enumCache = new WeakMap<Project, Map<string, EnumResult | null>>();\n\nexport function resolveEnumValues(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): EnumResult | null {\n let byKey = _enumCache.get(project);\n if (byKey === undefined) {\n byKey = new Map();\n _enumCache.set(project, byKey);\n }\n const key = `${sourceFile.getFilePath()}\\0${name}`;\n if (byKey.has(key)) {\n const cached = byKey.get(key) ?? null;\n return cached ? { values: [...cached.values], numeric: cached.numeric } : null;\n }\n\n const resolved = findType(name, sourceFile, project);\n let result: EnumResult | null = null;\n if (resolved && resolved.kind === 'enum') {\n // members are JSON.stringify'd (\"A\" / \"0\"); strip quotes to raw values.\n let numeric = true;\n const values = resolved.members.map((m) => {\n const parsed = JSON.parse(m) as string | number;\n if (typeof parsed === 'string') numeric = false;\n return String(parsed);\n });\n if (values.length > 0) result = { values, numeric };\n }\n byKey.set(key, result);\n return result ? { values: [...result.values], numeric: result.numeric } : null;\n}\n","import { Node, SyntaxKind } from 'ts-morph';\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/** 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/**\n * Parse a defineContract({...}) call expression.\n * Returns { query, body, response } or null if unrecognised.\n */\nexport interface ParsedContractDef {\n query: string | null;\n body: string | null;\n response: string;\n /** Raw zod source text of the body initializer (for inline forms emit). */\n bodyZodText: string | null;\n /** Raw zod source text of the query initializer (for inline forms emit). */\n queryZodText: string | null;\n}\n\nexport function parseDefineContractCall(callExpr: Node): ParsedContractDef | 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 let bodyZodText: string | null = null;\n let queryZodText: string | null = null;\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 queryZodText = val.getText();\n } else if (propName === 'body') {\n body = zodAstToTs(val);\n bodyZodText = val.getText();\n } else if (propName === 'response') {\n response = zodAstToTs(val);\n }\n }\n\n return { query, body, response, bodyZodText, queryZodText };\n}\n","import { open } from 'node:fs/promises';\nimport { mkdir, readFile, unlink } 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 * Uses O_CREAT | O_EXCL (via 'wx' flag) for atomic file creation to prevent\n * TOCTOU race conditions between concurrent processes.\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 const lockData: LockData = { pid: process.pid, startedAt: new Date().toISOString() };\n\n // Try atomic creation first (O_WRONLY | O_CREAT | O_EXCL)\n try {\n const fd = await open(lockPath, 'wx');\n await fd.writeFile(`${JSON.stringify(lockData, null, 2)}\\n`, 'utf8');\n await fd.close();\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n // File exists — check if holder is alive\n try {\n const raw = await readFile(lockPath, 'utf8');\n const existing = JSON.parse(raw) as LockData;\n if (isProcessAlive(existing.pid)) return null;\n // Stale lock — remove and retry\n await unlink(lockPath);\n return acquireLock(outDir);\n } catch {\n return null;\n }\n }\n return null;\n }\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 = '0.4.1';\n\n// Codegen pipeline (migrated from nestjs-inertia)\nexport { defineConfig } from './config/define-config.js';\nexport { loadConfig, resolveConfig } 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\n// Validation IR + pluggable adapters\nexport type {\n SchemaModule,\n SchemaNode,\n StringCheck,\n NumberCheck,\n} from './ir/schema-node.js';\nexport { renderTsType } from './ir/render-ts-type.js';\nexport type { TsTypeContext } from './ir/render-ts-type.js';\nexport type {\n ValidationAdapter,\n AdapterUsage,\n RenderContext,\n RenderedModule,\n} from './adapters/types.js';\nexport { resolveAdapter } from './adapters/registry.js';\nexport type { ValidationOption } from './adapters/registry.js';\n\n// class-validator DTO → SchemaModule IR (consumed by the validation adapters)\nexport { extractSchemaFromDto } from './discovery/dto-to-ir.js';\n\n// Discovery + emit (programmatic API)\nexport type {\n RouteDescriptor,\n ContractDescriptor,\n ContractSource,\n ControllerRef,\n TypeRef,\n} from './discovery/types.js';\nexport { emitForms } from './emit/emit-forms.js';\nexport { emitApi } from './emit/emit-api.js';\nexport { emitRoutes } from './emit/emit-routes.js';\nexport { discoverContractsFast } from './discovery/contracts-fast.js';\nexport type { FastDiscoveryOptions } from './discovery/contracts-fast.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-codegen 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 { execFileSync } from 'node:child_process';\nimport { appendFileSync, existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { runCodegen } from './codegen.js';\nimport {\n INERTIA_TSCONFIG_TEMPLATE,\n TSCONFIG_INERTIA_TEMPLATE,\n patchNestCliJson,\n patchTsconfigExclude,\n runInit,\n} from './init.js';\n\ninterface Check {\n name: string;\n pass: boolean;\n fix?: string | undefined;\n autoFix?: (() => void | Promise<void>) | undefined;\n}\n\nfunction checkFileExists(cwd: string, file: string): boolean {\n return existsSync(join(cwd, file));\n}\n\nfunction readJson(path: string): Record<string, unknown> | null {\n try {\n const raw = readFileSync(path, 'utf8').replace(/\\/\\/.*$/gm, '');\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction writeJsonField(filePath: string, dotPath: string[], value: unknown): void {\n const raw = readFileSync(filePath, 'utf8');\n const stripped = raw.replace(/\\/\\/.*$/gm, '');\n const obj = JSON.parse(stripped) as Record<string, unknown>;\n let target = obj as Record<string, unknown>;\n for (let i = 0; i < dotPath.length - 1; i++) {\n const key = dotPath[i] as string;\n if (!target[key] || typeof target[key] !== 'object') {\n target[key] = {};\n }\n target = target[key] as Record<string, unknown>;\n }\n const lastKey = dotPath[dotPath.length - 1] as string;\n if (\n typeof value === 'object' &&\n value !== null &&\n typeof target[lastKey] === 'object' &&\n target[lastKey] !== null\n ) {\n target[lastKey] = {\n ...(target[lastKey] as Record<string, unknown>),\n ...(value as Record<string, unknown>),\n };\n } else {\n target[lastKey] = value;\n }\n writeFileSync(filePath, `${JSON.stringify(obj, null, 2)}\\n`, 'utf8');\n}\n\nfunction getPackageVersion(cwd: string, pkg: string): string | null {\n try {\n const pkgJson = readJson(join(cwd, 'node_modules', pkg, 'package.json'));\n return (pkgJson?.version as string) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction detectPkgManager(cwd: string): string {\n if (existsSync(join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';\n if (existsSync(join(cwd, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nexport async function runDoctor(opts: { cwd: string; fix?: boolean }): Promise<number> {\n const { cwd, fix = false } = opts;\n const checks: Check[] = [];\n const pm = detectPkgManager(cwd);\n\n // 1. Config file\n checks.push({\n name: 'nestjs-inertia.config.ts exists',\n pass: checkFileExists(cwd, 'nestjs-inertia.config.ts'),\n fix: 'Run: nestjs-inertia init',\n autoFix: () => runInit({ cwd }),\n });\n\n // 2. Shell template exists\n const shellExtensions = ['html', 'htm', 'hbs', 'ejs', 'pug', 'liquid'];\n const shellDirs = ['inertia', 'views'];\n let foundShellPath: string | null = null;\n let foundShellDir: string | null = null;\n for (const dir of shellDirs) {\n for (const ext of shellExtensions) {\n const candidates = [`${dir}/index.${ext}`, `${dir}/shell.${ext}`];\n for (const candidate of candidates) {\n if (checkFileExists(cwd, candidate)) {\n foundShellPath = candidate;\n foundShellDir = dir;\n break;\n }\n }\n if (foundShellPath) break;\n }\n if (foundShellPath) break;\n }\n checks.push({\n name: 'Shell template (rootView) exists',\n pass: !!foundShellPath,\n fix: 'Run: nestjs-inertia init (creates inertia/index.html)',\n autoFix: () => runInit({ cwd }),\n });\n\n // 3. nest-cli.json copies shell template to dist/\n if (foundShellDir) {\n const nestCliPath = join(cwd, 'nest-cli.json');\n const nestCli = readJson(nestCliPath);\n const compiler = (nestCli?.compilerOptions ?? {}) as Record<string, unknown>;\n const assets = (compiler.assets ?? []) as Array<string | Record<string, unknown>>;\n const hasCopy = assets.some((a) => {\n if (typeof a === 'string') return a.includes(foundShellDir!);\n return String(a.include ?? '').includes(foundShellDir!);\n });\n checks.push({\n name: `nest-cli.json copies ${foundShellDir}/ to dist/ (needed for Docker)`,\n pass: hasCopy,\n fix: `Add asset entry for ${foundShellDir}/ in nest-cli.json compilerOptions.assets`,\n autoFix: () => {\n patchNestCliJson(cwd, foundShellDir!);\n },\n });\n }\n\n // 4. Entry point exists at the correct path\n const entryExtensions = ['tsx', 'ts'];\n const correctEntryExists = entryExtensions.some((ext) =>\n checkFileExists(cwd, `inertia/app/client.${ext}`),\n );\n const legacyEntryExists = entryExtensions.some((ext) =>\n checkFileExists(cwd, `inertia/app.${ext}`),\n );\n checks.push({\n name: 'Entry point at inertia/app/client.tsx (matches Vite plugin default)',\n pass: correctEntryExists,\n fix: legacyEntryExists\n ? 'Move inertia/app.tsx → inertia/app/client.tsx (the Vite plugin resolves inertia/app/client.tsx by default)'\n : 'Run: nestjs-inertia init',\n autoFix: !correctEntryExists ? () => runInit({ cwd }) : undefined,\n });\n\n // 5. Codegen output\n const hasApi = checkFileExists(cwd, '.nestjs-inertia/api.ts');\n const hasRoutes = checkFileExists(cwd, '.nestjs-inertia/routes.ts');\n const hasPages = checkFileExists(cwd, '.nestjs-inertia/pages.d.ts');\n checks.push({\n name: '.nestjs-inertia/ codegen output exists',\n pass: hasApi && hasRoutes && hasPages,\n fix: 'Run: nestjs-codegen codegen',\n autoFix: () => runCodegen({ cwd }),\n });\n\n // 5. tsconfig paths\n const tsconfigPath = join(cwd, 'tsconfig.json');\n const tsconfig = readJson(tsconfigPath);\n const paths = (tsconfig?.compilerOptions as Record<string, unknown>)?.paths as\n | Record<string, string[]>\n | undefined;\n checks.push({\n name: 'tsconfig.json has @/* path alias',\n pass: !!paths?.['@/*'],\n fix: 'Add @/* path alias to tsconfig.json',\n autoFix: () =>\n writeJsonField(tsconfigPath, ['compilerOptions', 'paths'], { '@/*': ['./src/*'] }),\n });\n\n // 6. tsconfig.json and tsconfig.build.json exclude inertia/ from server build\n const inertiaDir = foundShellDir ?? 'inertia';\n for (const tsconfigFile of ['tsconfig.json', 'tsconfig.build.json']) {\n const tsc = readJson(join(cwd, tsconfigFile));\n if (!tsc) continue; // file doesn't exist, skip\n const excl = (tsc.exclude ?? []) as string[];\n const excludesIt = excl.includes(inertiaDir);\n checks.push({\n name: `${tsconfigFile} excludes ${inertiaDir}/ from server compilation`,\n pass: excludesIt,\n fix: `Add \"${inertiaDir}\" to ${tsconfigFile} exclude array (Vite-only APIs like import.meta.glob break nest build)`,\n autoFix: () => {\n patchTsconfigExclude(cwd, inertiaDir, tsconfigFile);\n },\n });\n }\n\n // 7. Root tsconfig.json excludes `dist` so the server typecheck doesn't\n // walk compiled artifacts under dist/inertia/* (would surface ~thousands\n // of phantom errors about unresolved aliases in the compiled tree).\n {\n const tsc = readJson(tsconfigPath);\n const excl = (tsc?.exclude ?? []) as string[];\n const excludesDist = excl.includes('dist');\n checks.push({\n name: 'tsconfig.json excludes dist/ (avoids phantom errors in compiled output)',\n pass: excludesDist,\n fix: 'Add \"dist\" to tsconfig.json exclude array',\n autoFix: () => {\n patchTsconfigExclude(cwd, 'dist', 'tsconfig.json');\n },\n });\n }\n\n // 8. Dedicated inertia tsconfig — required so the inertia/ tree + codegen\n // output can be typechecked without breaking the server tsconfig.\n const inertiaTsconfigPath = join(cwd, 'tsconfig.inertia.json');\n const inertiaTsconfig = readJson(inertiaTsconfigPath);\n checks.push({\n name: 'tsconfig.inertia.json exists',\n pass: !!inertiaTsconfig,\n fix: 'Create tsconfig.inertia.json (typechecks inertia/ + .nestjs-inertia/)',\n autoFix: () => {\n writeFileSync(inertiaTsconfigPath, TSCONFIG_INERTIA_TEMPLATE, 'utf8');\n },\n });\n\n if (inertiaTsconfig) {\n const inertiaOpts = (inertiaTsconfig.compilerOptions as Record<string, unknown>) ?? {};\n const inertiaPaths = (inertiaOpts.paths as Record<string, string[]> | undefined) ?? {};\n const at = inertiaPaths['@/*'] ?? [];\n const missingTilde = !inertiaPaths['~/*'];\n const missingCodegen = !inertiaPaths['~codegen/*'];\n const missingDualAt = !at.includes('./inertia/*') || !at.includes('./src/*');\n checks.push({\n name: 'tsconfig.inertia.json has ~/*, ~codegen/*, and @/* (inertia + src) aliases',\n pass: !missingTilde && !missingCodegen && !missingDualAt,\n fix: '@/* must include both ./inertia/* and ./src/* so codegen-resolved controllers + inertia user code both resolve',\n autoFix: () => {\n const additions: Record<string, string[]> = {};\n if (missingDualAt) additions['@/*'] = ['./inertia/*', './src/*'];\n if (missingTilde) additions['~/*'] = ['./inertia/*'];\n if (missingCodegen) additions['~codegen/*'] = ['./.nestjs-inertia/*'];\n writeJsonField(inertiaTsconfigPath, ['compilerOptions', 'paths'], additions);\n },\n });\n // experimentalDecorators is required: codegen api.ts imports controllers\n // (via Awaited<ReturnType<...>>) which TS has to parse for decorators.\n checks.push({\n name: 'tsconfig.inertia.json has experimentalDecorators: true',\n pass: inertiaOpts.experimentalDecorators === true,\n fix: 'Set compilerOptions.experimentalDecorators = true',\n autoFix: () => {\n writeJsonField(inertiaTsconfigPath, ['compilerOptions', 'experimentalDecorators'], true);\n },\n });\n // Without emitDecoratorMetadata: OFF, every src/ file pulled in\n // transitively complains with TS1272 unless it uses `import type`.\n checks.push({\n name: 'tsconfig.inertia.json has emitDecoratorMetadata: false',\n pass: inertiaOpts.emitDecoratorMetadata === false,\n fix: 'Set compilerOptions.emitDecoratorMetadata = false (avoids TS1272 spam from transitively-loaded src/ files)',\n autoFix: () => {\n writeJsonField(inertiaTsconfigPath, ['compilerOptions', 'emitDecoratorMetadata'], false);\n },\n });\n // Must include nestjs-inertia.d.ts so the InertiaRegistry augmentation\n // resolves Link route params, page names, and shared props.\n const include = (inertiaTsconfig.include as string[] | undefined) ?? [];\n checks.push({\n name: 'tsconfig.inertia.json includes nestjs-inertia.d.ts',\n pass: include.some((p) => p.includes('nestjs-inertia.d.ts')),\n fix: 'Add \"nestjs-inertia.d.ts\" to include array (resolves InertiaRegistry augmentation)',\n });\n }\n\n // 9. inertia/tsconfig.json — thin extends so VSCode/editors that walk up\n // to find the closest tsconfig pick up the inertia-aware aliases.\n const innerTsconfigPath = join(cwd, 'inertia', 'tsconfig.json');\n checks.push({\n name: 'inertia/tsconfig.json exists (VSCode picks up ~codegen alias)',\n pass: existsSync(innerTsconfigPath),\n fix: 'Create inertia/tsconfig.json that extends ../tsconfig.inertia.json',\n autoFix: () => {\n writeFileSync(innerTsconfigPath, INERTIA_TSCONFIG_TEMPLATE, 'utf8');\n },\n });\n\n // 7. Vite config\n if (checkFileExists(cwd, 'vite.config.ts')) {\n const viteContent = readFileSync(join(cwd, 'vite.config.ts'), 'utf8');\n checks.push({\n name: 'vite.config.ts has resolve.alias',\n pass: viteContent.includes('resolve') && viteContent.includes('alias'),\n fix: 'Add resolve.alias to vite.config.ts (manual — complex file)',\n });\n checks.push({\n name: 'vite.config.ts references nestjs-inertia',\n pass:\n viteContent.includes('nestInertia') ||\n viteContent.includes('nestjs-inertia') ||\n viteContent.includes('setupInertiaVite'),\n fix: \"Add: import nestInertia from '@dudousxd/nestjs-inertia-vite/plugin'\",\n });\n }\n\n // 8. Package versions\n const requiredPkgs = [\n '@dudousxd/nestjs-inertia',\n '@dudousxd/nestjs-codegen',\n '@dudousxd/nestjs-inertia-client',\n ];\n const missingRequired = requiredPkgs.filter((pkg) => !getPackageVersion(cwd, pkg));\n checks.push({\n name: 'Core packages installed (core + codegen + client)',\n pass: missingRequired.length === 0,\n fix: `Missing: ${missingRequired.join(', ')}`,\n autoFix:\n missingRequired.length > 0\n ? () => {\n const addCmd = pm === 'npm' ? 'install' : 'add';\n execFileSync(pm, [addCmd, ...missingRequired], { cwd, stdio: 'inherit' });\n }\n : undefined,\n });\n\n const libPackages = [\n '@dudousxd/nestjs-inertia',\n '@dudousxd/nestjs-codegen',\n '@dudousxd/nestjs-inertia-client',\n '@dudousxd/nestjs-inertia-vite',\n '@dudousxd/nestjs-inertia-testing',\n ];\n const versions = libPackages.map((pkg) => ({ pkg, version: getPackageVersion(cwd, pkg) }));\n const installed = versions.filter((v) => v.version !== null);\n const uniqueVersions = new Set(installed.map((v) => v.version));\n if (installed.length > 1) {\n checks.push({\n name: 'All packages on same version',\n pass: uniqueVersions.size === 1,\n fix: `Versions: ${installed.map((v) => `${v.pkg.replace('@dudousxd/', '')}@${v.version}`).join(', ')}`,\n });\n }\n\n // 9. Inertia.js version\n const inertiaReact = getPackageVersion(cwd, '@inertiajs/react');\n const inertiaVue = getPackageVersion(cwd, '@inertiajs/vue3');\n const inertiaSvelte = getPackageVersion(cwd, '@inertiajs/svelte');\n const inertiaVersion = inertiaReact ?? inertiaVue ?? inertiaSvelte;\n const inertiaFramework = inertiaReact\n ? 'react'\n : inertiaVue\n ? 'vue'\n : inertiaSvelte\n ? 'svelte'\n : null;\n\n if (inertiaVersion) {\n const majorVersion = Number.parseInt(inertiaVersion.split('.')[0] ?? '0', 10);\n checks.push({\n name: `@inertiajs/${inertiaFramework} is v3+`,\n pass: majorVersion >= 3,\n fix: `Current: v${inertiaVersion}`,\n autoFix:\n majorVersion < 3\n ? () => {\n const addCmd = pm === 'npm' ? 'install' : 'add';\n execFileSync(pm, [addCmd, `@inertiajs/${inertiaFramework}@^3.0.0`], {\n cwd,\n stdio: 'inherit',\n });\n }\n : undefined,\n });\n }\n\n // 10. .gitignore\n if (checkFileExists(cwd, '.gitignore')) {\n const gitignorePath = join(cwd, '.gitignore');\n const gitignore = readFileSync(gitignorePath, 'utf8');\n checks.push({\n name: '.gitignore includes .nestjs-inertia/',\n pass: gitignore.includes('.nestjs-inertia'),\n fix: 'Add .nestjs-inertia/ to .gitignore',\n autoFix: () => appendFileSync(gitignorePath, '\\n.nestjs-inertia/\\n'),\n });\n }\n\n // 11. Build scripts\n const pkgJsonPath = join(cwd, 'package.json');\n const pkgJson = readJson(pkgJsonPath);\n const scripts = (pkgJson?.scripts as Record<string, string>) ?? {};\n checks.push({\n name: 'package.json has build:client script',\n pass: !!scripts['build:client'],\n fix: 'Add build:client script',\n autoFix: () => writeJsonField(pkgJsonPath, ['scripts'], { 'build:client': 'vite build' }),\n });\n checks.push({\n name: 'package.json has typecheck:inertia script',\n pass: !!scripts['typecheck:inertia'],\n fix: 'Add: \"typecheck:inertia\": \"tsc --noEmit -p tsconfig.inertia.json\"',\n autoFix: () =>\n writeJsonField(pkgJsonPath, ['scripts'], {\n 'typecheck:inertia': 'tsc --noEmit -p tsconfig.inertia.json',\n }),\n });\n\n // Print results + auto-fix\n console.log('');\n console.log(`\\x1b[1mnestjs-inertia doctor${fix ? ' --fix' : ''}\\x1b[0m`);\n console.log('');\n\n let hasFailures = false;\n let fixed = 0;\n\n for (const check of checks) {\n if (check.pass) {\n console.log(` \\x1b[32m✓\\x1b[0m ${check.name}`);\n continue;\n }\n\n if (fix && check.autoFix) {\n try {\n check.autoFix();\n console.log(` \\x1b[34m⚡\\x1b[0m ${check.name} \\x1b[34m(fixed)\\x1b[0m`);\n fixed++;\n continue;\n } catch (err) {\n console.log(` \\x1b[31m✗\\x1b[0m ${check.name} \\x1b[31m(auto-fix failed)\\x1b[0m`);\n if (check.fix) console.log(` \\x1b[2m${check.fix}\\x1b[0m`);\n hasFailures = true;\n continue;\n }\n }\n\n console.log(` \\x1b[31m✗\\x1b[0m ${check.name}`);\n if (check.fix) {\n const hint = check.autoFix ? `${check.fix} (fixable with --fix)` : check.fix;\n console.log(` \\x1b[2m${hint}\\x1b[0m`);\n }\n hasFailures = true;\n }\n\n console.log('');\n const failCount = checks.filter((c) => !c.pass).length - fixed;\n if (fixed > 0) console.log(`\\x1b[34m${fixed} issue(s) auto-fixed\\x1b[0m`);\n if (failCount > 0) {\n console.log(`\\x1b[33m${failCount} issue(s) remaining\\x1b[0m`);\n } else if (!hasFailures) {\n console.log('\\x1b[32mAll checks passed!\\x1b[0m');\n }\n console.log('');\n\n return hasFailures ? 1 : 0;\n}\n","import { execFileSync } 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';\nimport { findAfterLastImport, insertImport, patchJsonFile } from './patch-utils.js';\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-codegen] 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 args: string[] = [];\n if (pkgManager === 'npm') {\n args.push('install');\n if (dev) args.push('--save-dev');\n } else {\n args.push('add');\n if (dev) args.push('-D');\n }\n args.push(...deps);\n\n logPatched(deps.join(', '), 'installed');\n try {\n execFileSync(pkgManager, args, { stdio: 'inherit' });\n } catch {\n logWarning(`Failed to install: ${deps.join(', ')}`);\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 * 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 content = insertImport(content, \"import { InertiaModule } from '@dudousxd/nestjs-inertia';\");\n\n // Ensure `resolve` from node:path is imported (needed for rootView).\n // Inserted unconditionally (even at offset 0, prepending) — matches the\n // original behaviour for files that have no other imports.\n if (!content.includes(\"from 'node:path'\") && !content.includes('from \"node:path\"')) {\n const insertAt2 = findAfterLastImport(content);\n content = `${content.slice(0, insertAt2)}import { resolve } from 'node:path';\\n${content.slice(insertAt2)}`;\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: resolve(__dirname, '../${rootView}'),\\n${indent}}),${content.slice(bracketPos)}`;\n changed = true;\n }\n }\n\n // --- HomeController ---\n if (!content.includes('HomeController')) {\n content = insertImport(content, \"import { HomeController } from './home.controller';\");\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 content = insertImport(\n content,\n \"import { setupInertiaVite } from '@dudousxd/nestjs-inertia-vite';\",\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-codegen';\n\nexport default defineConfig({\n pages: {\n glob: '${glob}',\n },\n});\n`;\n}\n\n/**\n * Standalone tsconfig that typechecks the inertia/ frontend + the codegen\n * output under .nestjs-inertia/. Lives at the project root and is invoked\n * via `pnpm typecheck:inertia` (or equivalent).\n *\n * Why a separate file:\n * - The server tsconfig excludes inertia/ (Vite-only APIs break nest build)\n * - The codegen emits imports like `import('../src/.../foo.controller')`,\n * so we need `experimentalDecorators` here to parse those controllers.\n * Decorator metadata is OFF so users don't get TS1272 leaks from src/.\n * - `@/*` resolves to BOTH `inertia/*` AND `src/*` because the codegen's\n * transitive imports use `@/` to mean `src/`, while inertia/ user code\n * uses `@/` to mean `inertia/`.\n */\nexport const TSCONFIG_INERTIA_TEMPLATE = `{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"module\": \"esnext\",\n \"moduleResolution\": \"bundler\",\n \"jsx\": \"react-jsx\",\n \"lib\": [\"DOM\", \"DOM.Iterable\", \"ESNext\"],\n \"types\": [\"vite/client\", \"node\"],\n \"allowImportingTsExtensions\": false,\n \"allowSyntheticDefaultImports\": true,\n \"esModuleInterop\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": false,\n \"resolveJsonModule\": true,\n \"isolatedModules\": true,\n \"noEmit\": true,\n \"incremental\": true,\n \"skipLibCheck\": true,\n \"strict\": false,\n \"strictNullChecks\": true,\n \"noUnusedLocals\": false,\n \"noUnusedParameters\": false,\n \"noFallthroughCasesInSwitch\": false,\n \"useUnknownInCatchVariables\": false,\n \"noImplicitAny\": false,\n \"ignoreDeprecations\": \"6.0\",\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./inertia/*\", \"./src/*\"],\n \"~/*\": [\"./inertia/*\"],\n \"~codegen/*\": [\"./.nestjs-inertia/*\"]\n }\n },\n \"include\": [\n \"inertia/**/*\",\n \".nestjs-inertia/**/*\",\n \"nestjs-inertia.d.ts\"\n ],\n \"exclude\": [\n \"node_modules\",\n \"dist\",\n \"inertia/**/*.test.ts\",\n \"inertia/**/*.test.tsx\",\n \"inertia/**/*.spec.ts\",\n \"inertia/**/*.spec.tsx\"\n ]\n}\n`;\n\n/**\n * Thin tsconfig inside inertia/ that just extends the root config. Lets\n * VSCode (and other editors that walk up to find a tsconfig) pick up the\n * inertia-aware aliases automatically when opening files in inertia/.\n */\nexport const INERTIA_TSCONFIG_TEMPLATE = `{\n \"extends\": \"../tsconfig.inertia.json\",\n \"include\": [\n \"**/*\",\n \"../.nestjs-inertia/**/*\",\n \"../nestjs-inertia.d.ts\"\n ],\n \"exclude\": [\n \"node_modules\",\n \"**/*.test.ts\",\n \"**/*.test.tsx\",\n \"**/*.spec.ts\",\n \"**/*.spec.tsx\"\n ]\n}\n`;\n\nconst DTS_TEMPLATE = `// Auto-generated by nestjs-codegen. Commit this file.\n// Re-run \\`nestjs-codegen 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('app/client.${ext}')\n</body>\n</html>\n`;\n}\n\nfunction viteConfigTemplate(framework: Framework): string {\n const pluginOption = `{ ${framework}: true }`;\n return `import { resolve } from 'node:path';\nimport { defineConfig } from 'vite';\nimport nestInertia from '@dudousxd/nestjs-inertia-vite/plugin';\n\nexport default defineConfig({\n plugins: [nestInertia(${pluginOption})],\n resolve: {\n alias: {\n '@': resolve(__dirname, 'src'),\n '~': resolve(__dirname, 'inertia'),\n '~codegen': resolve(__dirname, '.nestjs-inertia'),\n },\n },\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 * Patch `tsconfig.json` to exclude `inertia/` from the server-side TypeScript compilation.\n * Without this, `nest build` fails because `inertia/` files use Vite-only APIs like\n * `import.meta.glob` that are invalid in a Node.js/CommonJS context.\n */\nexport function patchTsconfigExclude(\n cwd: string,\n dir: string,\n filename = 'tsconfig.json',\n): 'patched' | 'already' | 'skipped' {\n const filePath = join(cwd, filename);\n return patchJsonFile(\n filePath,\n (json) => {\n const exclude = (json.exclude ?? []) as string[];\n if (exclude.includes(dir)) return false;\n exclude.push(dir);\n json.exclude = exclude;\n return true;\n },\n // Strip single-line comments before JSON.parse\n (raw) => raw.replace(/\\/\\/.*$/gm, ''),\n );\n}\n\n/**\n * Patch `nest-cli.json` so `nest build` copies the shell template into `dist/`.\n * Without this, Docker images that only ship `dist/` would be missing the rootView file.\n */\nexport function patchNestCliJson(cwd: string, shellDir: string): 'patched' | 'already' | 'skipped' {\n const filePath = join(cwd, 'nest-cli.json');\n return patchJsonFile(filePath, (json) => {\n const compiler = (json.compilerOptions ?? {}) as Record<string, unknown>;\n const assets = (compiler.assets ?? []) as Array<string | Record<string, unknown>>;\n\n const alreadyHas = assets.some((a) => {\n if (typeof a === 'string') return a.includes(shellDir);\n return String(a.include ?? '').includes(shellDir);\n });\n if (alreadyHas) return false;\n\n assets.push({\n include: `../${shellDir}/**/*`,\n outDir: `dist/${shellDir}`,\n watchAssets: true,\n });\n compiler.assets = assets;\n json.compilerOptions = compiler;\n return true;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Main entry — ordered init steps + runner\n// ---------------------------------------------------------------------------\n\n/**\n * Shared context threaded through every init step. Computed once up front so\n * the steps stay pure functions of detected framework/engine + derived paths.\n */\ninterface InitContext {\n opts: RunInitOptions;\n cwd: string;\n framework: Framework;\n engine: TemplateEngine;\n /** Shell file name inside inertia/ (e.g. `index.html`, `index.hbs`). */\n shellFileName: string;\n /** Entry-point extension (`tsx` for react, `ts` otherwise). */\n entryExt: string;\n /** Sample page extension (`tsx` | `vue` | `svelte`). */\n pageExt: string;\n /** Project-relative rootView path (e.g. `inertia/index.html`). */\n rootView: string;\n /** Top-level shell dir (e.g. `inertia`). */\n shellDir: string;\n}\n\ninterface InitStep {\n /** Human-readable label, logged by the runner before the step runs. */\n label: string;\n run: (ctx: InitContext) => void | Promise<void>;\n}\n\n/** Scaffold config, d.ts, tsconfigs, shell, vite config, entry, page, controller. */\nasync function scaffoldFiles(ctx: InitContext): Promise<void> {\n const { cwd, framework, engine, shellFileName, entryExt, pageExt } = ctx;\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 // Dedicated tsconfig for the inertia/ frontend + codegen output. The\n // server tsconfig.json can't typecheck inertia/ because Vite-only APIs\n // (import.meta.glob etc.) break nest build; this one fills that gap.\n await writeIfNotExists(\n join(cwd, 'tsconfig.inertia.json'),\n TSCONFIG_INERTIA_TEMPLATE,\n 'tsconfig.inertia.json',\n );\n\n // Thin tsconfig under inertia/ so VSCode/editors that walk up looking\n // for the closest tsconfig pick up the inertia-aware aliases (~codegen,\n // ~/*) when opening files in inertia/.\n await writeIfNotExists(\n join(cwd, 'inertia', 'tsconfig.json'),\n INERTIA_TSCONFIG_TEMPLATE,\n 'inertia/tsconfig.json',\n );\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', `client.${entryExt}`),\n entryPointTemplate(framework),\n `inertia/app/client.${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\n/** Patch src/app.module.ts (InertiaModule.forRoot + HomeController). */\nfunction patchServerAppModule(ctx: InitContext): void {\n const { cwd, rootView } = ctx;\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\n/** Patch src/main.ts (setupInertiaVite after NestFactory.create). */\nfunction patchServerMainTs(ctx: InitContext): void {\n const mainTsPath = join(ctx.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\n/** Patch nest-cli.json + both tsconfigs (exclude inertia/, then dist/). */\nfunction patchBuildConfigs(ctx: InitContext): void {\n const { cwd, shellDir } = ctx;\n\n // Patch nest-cli.json so `nest build` copies the shell template into dist/\n const nestCliResult = patchNestCliJson(cwd, shellDir);\n if (nestCliResult === 'patched') {\n logPatched('nest-cli.json', `added asset copy for ${shellDir}/ → dist/${shellDir}/`);\n } else if (nestCliResult === 'already') {\n console.log(\n ` ${cyan('→')} nest-cli.json ${dim(`(${shellDir}/ asset already configured, skipped)`)}`,\n );\n } else {\n logWarning('nest-cli.json not found — copy the shell template into dist/ manually');\n }\n\n // Patch tsconfig.json and tsconfig.build.json to exclude the inertia/ dir\n // from the server build. tsconfig.build.json's own `exclude` array overrides\n // the base tsconfig.json when present, so both must be patched.\n for (const tsconfigFile of ['tsconfig.json', 'tsconfig.build.json']) {\n const result = patchTsconfigExclude(cwd, shellDir, tsconfigFile);\n if (result === 'patched') {\n logPatched(tsconfigFile, `excluded ${shellDir}/ from server compilation`);\n } else if (result === 'already') {\n console.log(\n ` ${cyan('→')} ${tsconfigFile} ${dim(`(${shellDir}/ already excluded, skipped)`)}`,\n );\n }\n // 'skipped' = file doesn't exist, silently move on\n }\n}\n\n/** Patch .gitignore, then exclude dist/ from tsconfig.json. */\nasync function patchGitignoreAndDist(ctx: InitContext): Promise<void> {\n const { cwd } = ctx;\n\n await patchGitignore(join(cwd, '.gitignore'));\n\n // Patch tsconfig.json to also exclude `dist` so the server typecheck\n // doesn't walk compiled artifacts under dist/inertia/* and report\n // phantom errors about unresolved aliases in the compiled tree.\n const tsconfigDistResult = patchTsconfigExclude(cwd, 'dist', 'tsconfig.json');\n if (tsconfigDistResult === 'patched') {\n logPatched('tsconfig.json', 'excluded dist/ from server compilation');\n } else if (tsconfigDistResult === 'already') {\n console.log(` ${cyan('→')} tsconfig.json ${dim('(dist/ already excluded, skipped)')}`);\n }\n}\n\n/** Add build:client / build:ssr / typecheck:inertia scripts to package.json. */\nasync function scaffoldPackageScripts(ctx: InitContext): Promise<void> {\n await patchPackageJsonScripts(ctx.cwd, {\n 'build:client': 'vite build',\n 'build:ssr': 'VITE_SSR=1 vite build --ssr',\n 'typecheck:inertia': 'tsc --noEmit -p tsconfig.inertia.json',\n });\n}\n\n/** Install the missing common + framework deps (unless skipInstall). */\nasync function installMissingDeps(ctx: InitContext): Promise<void> {\n const { cwd, framework, opts } = ctx;\n\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\n/**\n * Ordered list of init steps. The first patch step prints the \"Patch existing\n * files\" section header so it appears exactly once, before the first patcher.\n */\nconst INIT_STEPS: InitStep[] = [\n { label: 'scaffold files', run: scaffoldFiles },\n {\n label: 'patch app.module.ts',\n run: (ctx) => {\n logSection('Patch existing files');\n patchServerAppModule(ctx);\n },\n },\n { label: 'patch main.ts', run: patchServerMainTs },\n { label: 'patch build configs', run: patchBuildConfigs },\n { label: 'patch .gitignore + dist exclude', run: patchGitignoreAndDist },\n { label: 'add package.json scripts', run: scaffoldPackageScripts },\n { label: 'install dependencies', run: installMissingDeps },\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. Derive the paths every step needs, build the shared context.\n const shellFileName =\n engine === 'html' ? 'index.html' : `index.${engine === 'handlebars' ? 'hbs' : engine}`;\n const rootView =\n engine === 'html'\n ? 'inertia/index.html'\n : `inertia/index.${engine === 'handlebars' ? 'hbs' : engine}`;\n const ctx: InitContext = {\n opts,\n cwd,\n framework,\n engine,\n shellFileName,\n entryExt: framework === 'react' ? 'tsx' : 'ts',\n pageExt: framework === 'react' ? 'tsx' : framework === 'vue' ? 'vue' : 'svelte',\n rootView,\n shellDir: rootView.split('/')[0]!, // e.g. \"inertia\" from \"inertia/index.html\"\n };\n\n // 4. Run the ordered steps. Each step's label is traced only when\n // NESTJS_CODEGEN_DEBUG is set, so default stdout stays byte-identical.\n for (const step of INIT_STEPS) {\n if (process.env.NESTJS_CODEGEN_DEBUG) {\n console.log(dim(` · ${step.label}`));\n }\n await step.run(ctx);\n }\n\n console.log(`\\n${green('✓')} Setup complete! Run: ${bold('nest start --watch')}\\n`);\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\n\n/**\n * Read a JSON file, run a mutator over the parsed object, and write it back\n * (2-space indent + trailing newline) only when the mutator reports a change.\n *\n * The mutator receives the parsed JSON object and returns:\n * - `true` → the object was changed, rewrite the file → 'patched'\n * - `false` → the object already had what we wanted, leave it → 'already'\n *\n * If the file is missing/unreadable, returns 'skipped' and never writes.\n *\n * `parse` lets a caller pre-process the raw text before JSON.parse (e.g. to\n * strip `//` comments from a tsconfig). Defaults to the identity transform.\n */\nexport function patchJsonFile(\n filePath: string,\n mutator: (json: Record<string, unknown>) => boolean,\n parse: (raw: string) => string = (raw) => raw,\n): 'patched' | 'already' | 'skipped' {\n let raw: string;\n try {\n raw = readFileSync(filePath, 'utf8');\n } catch {\n return 'skipped';\n }\n\n const json = JSON.parse(parse(raw)) as Record<string, unknown>;\n if (!mutator(json)) return 'already';\n\n writeFileSync(filePath, `${JSON.stringify(json, null, 2)}\\n`, 'utf8');\n return 'patched';\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 */\nexport function 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 * Splice an import statement into `content` just after the last existing\n * import. `stmt` must be the bare statement without a trailing newline; a\n * newline is appended. If there is no insertion point (offset 0, i.e. no\n * imports and content doesn't start with `import `), `content` is returned\n * unchanged — matching the original inline guard `if (insertAt > 0)`.\n */\nexport function insertImport(content: string, stmt: string): string {\n const insertAt = findAfterLastImport(content);\n if (insertAt <= 0) return content;\n return `${content.slice(0, insertAt)}${stmt}\\n${content.slice(insertAt)}`;\n}\n"],"mappings":"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","names":["import_promises","import_node_path","import_promises","import_node_path","fg","import_node_path","firstArg","import_promises","import_node_path","import_ts_morph","import_promises","import_node_path","import_promises","import_node_path","import_promises","import_node_path","exports","import_promises","import_node_path","import_promises","import_node_path","import_promises","import_node_path","import_node_path","import_fast_glob","import_ts_morph","import_ts_morph","import_ts_morph","import_node_path","import_ts_morph","reExportsName","sourceName","node","import_ts_morph","import_ts_morph","import_ts_morph","fg","firstArg","import_promises","import_node_path","chokidar","resolve","import_node_child_process","import_node_fs","import_node_path","import_node_fs","import_promises","import_node_path","import_node_fs","resolve","fileExists"]}