@dudousxd/nestjs-codegen 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/dist/cli/main.cjs +264 -91
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +248 -75
- package/dist/cli/main.js.map +1 -1
- package/dist/extension/index.d.cts +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/{index-CxkGbILp.d.cts → index-DvUzPXdh.d.cts} +7 -0
- package/dist/{index-CxkGbILp.d.ts → index-DvUzPXdh.d.ts} +7 -0
- package/dist/index.cjs +222 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -5
- package/dist/index.d.ts +31 -5
- package/dist/index.js +209 -36
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +267 -75
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +16 -5
- package/dist/nest/index.d.ts +16 -5
- package/dist/nest/index.js +267 -75
- package/dist/nest/index.js.map +1 -1
- package/package.json +1 -1
package/dist/nest/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/nest/index.ts","../../src/nest/module.ts","../../src/config/load-config.ts","../../src/exceptions.ts","../../src/adapters/registry.ts","../../src/watch/watcher.ts","../../src/discovery/contracts-fast.ts","../../src/discovery/dto-type-resolver.ts","../../src/discovery/dto-to-ir.ts","../../src/util/debug-log.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/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-mocks.ts","../../src/ir/schema-node-to-json-schema.ts","../../src/emit/mock-gen-runtime.ts","../../src/emit/emit-openapi.ts","../../src/emit/emit-pages.ts","../../src/emit/emit-routes.ts","../../src/watch/lock-file.ts"],"sourcesContent":["export {\n CODEGEN_MODULE_OPTIONS,\n NestjsCodegenModule,\n NestjsCodegenService,\n shouldRun,\n} from './module.js';\nexport type { CodegenModuleOptions } from './module.js';\n","import type { DynamicModule, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';\nimport { Inject, Injectable, Logger, Module } from '@nestjs/common';\nimport { resolveConfig } from '../config/load-config.js';\nimport type { UserConfig } from '../config/types.js';\nimport type { Watcher } from '../watch/watcher.js';\nimport { watch } from '../watch/watcher.js';\n\n/**\n * Options for {@link NestjsCodegenModule.forRoot}. These ARE the codegen config —\n * no `nestjs-codegen.config.ts` file is required. Import the module in your root\n * `AppModule` and the typed client regenerates as you edit your controllers:\n *\n * @example\n * ```ts\n * import { NestjsCodegenModule } from '@dudousxd/nestjs-codegen/nest';\n *\n * @Module({\n * imports: [\n * NestjsCodegenModule.forRoot({\n * contracts: { glob: 'src/**\\/*.controller.ts' },\n * codegen: { outDir: 'src/generated' },\n * extensions: [tanstackQuery()],\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\nexport interface CodegenModuleOptions extends Omit<UserConfig, 'validation'> {\n /**\n * Validation adapter for emitted `forms.ts` schemas. Required at runtime to emit\n * forms — pass `zodAdapter` from `@dudousxd/nestjs-codegen-zod` (or the valibot/\n * arktype adapter). Typed optional only so `forRoot()` stays terse; if omitted,\n * the watcher logs and skips rather than crashing app boot.\n */\n validation?: UserConfig['validation'];\n /**\n * Master switch for the boot-time watcher. When omitted, the watcher runs in every\n * environment EXCEPT production (`process.env.NODE_ENV === 'production'`) — codegen is a\n * dev/CI build step, not a production-runtime concern. Set `false` to disable entirely,\n * or `true` to force it on even in production.\n */\n enabled?: boolean;\n /** Project root used to resolve globs / `outDir`. Defaults to `process.cwd()`. */\n cwd?: string;\n}\n\n/** DI token holding the raw {@link CodegenModuleOptions} passed to `forRoot`. */\nexport const CODEGEN_MODULE_OPTIONS = Symbol('NESTJS_CODEGEN_MODULE_OPTIONS');\n\n/**\n * Decide whether the boot-time watcher should start, given the module options and the\n * current `NODE_ENV`. Explicit `enabled` always wins; otherwise default on unless prod.\n */\nexport function shouldRun(options: CodegenModuleOptions, env: string | undefined): boolean {\n if (options.enabled !== undefined) return options.enabled;\n return env !== 'production';\n}\n\n/**\n * Boots the codegen watcher on application start and tears it down on shutdown.\n * The watcher does an initial full generate, then regenerates `routes.ts`/`api.ts`/\n * `forms.ts` as controllers and DTOs change — mirroring `nestjs-codegen codegen --watch`,\n * but driven by the Nest lifecycle so no separate process is needed in dev.\n */\n@Injectable()\nexport class NestjsCodegenService implements OnApplicationBootstrap, OnModuleDestroy {\n private readonly logger = new Logger('NestjsCodegen');\n private watcher: Watcher | null = null;\n\n constructor(@Inject(CODEGEN_MODULE_OPTIONS) private readonly options: CodegenModuleOptions) {}\n\n async onApplicationBootstrap(): Promise<void> {\n if (!shouldRun(this.options, process.env.NODE_ENV)) return;\n\n const { enabled: _enabled, cwd, ...userConfig } = this.options;\n try {\n const config = resolveConfig(userConfig, cwd ?? process.cwd());\n this.watcher = await watch(config);\n this.logger.log(`Watching ${config.contracts.glob} → ${config.codegen.outDir}`);\n } catch (err) {\n // Never crash app boot because codegen failed to start — log and move on.\n this.logger.warn(\n `Codegen watcher failed to start: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n async onModuleDestroy(): Promise<void> {\n await this.watcher?.close();\n this.watcher = null;\n }\n}\n\n/**\n * NestJS module that auto-starts the codegen watcher on app boot — the recommended way\n * to wire `@dudousxd/nestjs-codegen` into a Nest app. For CI/pre-deploy, run the\n * one-shot CLI (`nestjs-codegen codegen`) instead.\n */\n@Module({})\nexport class NestjsCodegenModule {\n static forRoot(options: CodegenModuleOptions = {}): DynamicModule {\n return {\n module: NestjsCodegenModule,\n providers: [{ provide: CODEGEN_MODULE_OPTIONS, useValue: options }, NestjsCodegenService],\n };\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 const fileUrl = pathToFileURL(filePath).href;\n\n // Native-first: modern Node (>=22.18 / 23.6 / 24 / 25) strips TypeScript types\n // natively, so a plain dynamic import loads a `.ts` config with zero deps. This is\n // also the only path that works on Node 25, where tsx 4.22.4's resolver appends a\n // `?namespace=<ts>` query that Node 25's stricter finalizeResolution rejects with\n // ERR_MODULE_NOT_FOUND. We fall back to tsx only when native import fails (older\n // Node without type stripping, or configs using syntax that needs transformation\n // like enums/namespaces).\n try {\n return await import(fileUrl);\n } catch (nativeError) {\n // Native import failed — try the tsx ESM API as a fallback transformer.\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 // Both native import and tsx are unusable. Surface the actionable\n // \"install tsx\" guidance (the established behavior), chaining the native\n // error so the underlying load failure isn't lost.\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 { cause: nativeError },\n );\n }\n\n const parentURL = pathToFileURL(`${filePath}__parent__`).href;\n return tsImport(fileUrl, { parentURL });\n }\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 debug: userConfig.debug ?? false,\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 serialization: userConfig.serialization ?? 'json',\n forms: {\n enabled: userConfig.forms?.enabled ?? true,\n watch: userConfig.forms?.watch ?? 'src/**/*.dto.ts',\n zodImport: userConfig.forms?.zodImport ?? 'zod',\n },\n openapi: {\n enabled: userConfig.openapi?.enabled ?? false,\n fileName: userConfig.openapi?.fileName ?? 'openapi.json',\n title: userConfig.openapi?.title ?? 'NestJS API',\n version: userConfig.openapi?.version ?? '1.0.0',\n description: userConfig.openapi?.description ?? null,\n },\n mocks: {\n enabled: userConfig.mocks?.enabled ?? false,\n fileName: userConfig.mocks?.fileName ?? 'mocks.ts',\n seed: userConfig.mocks?.seed ?? 1,\n baseUrl: userConfig.mocks?.baseUrl ?? '',\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/**\n * A validation adapter instance. No adapter is bundled in core — import one from\n * its own package (`zodAdapter`/`valibotAdapter`/`arktypeAdapter`) or pass a custom\n * object. String shortcuts (`'zod'` etc.) are intentionally not part of this type:\n * they always threw at runtime, so the type guides you to an imported instance.\n */\nexport type ValidationOption = 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 * The parameter also accepts a `string` so the runtime guard still fires for JS\n * callers / untyped configs that pass a removed string shortcut (e.g. `'zod'`):\n * those throw a helpful error pointing at the adapter package. TypeScript users\n * are steered away from strings by the narrowed {@link ValidationOption} type.\n *\n * @example\n * import { zodAdapter } from '@dudousxd/nestjs-codegen-zod';\n * defineConfig({ validation: zodAdapter });\n */\nexport function resolveAdapter(option: ValidationOption | string): 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 { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport chokidar from 'chokidar';\nimport type { ResolvedConfig } from '../config/types.js';\nimport { PersistentDiscovery } 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 // Persistent ts-morph Project reused across every contract/DTO change. Built\n // once here; each change refreshes only the changed file(s) instead of\n // reconstructing the Project and re-parsing all controllers + DTOs. Lazily\n // (re)initialised so an initial-pass failure doesn't permanently disable it.\n let discovery: PersistentDiscovery | null = null;\n // Last successfully-discovered routes, reused by the pages watcher. The pages\n // fast path has no route discovery of its own; without this it would call\n // generate() with an empty route list, and any route-injecting extension (e.g.\n // notifications) would still emit — overwriting api.ts with an extension-only\n // stub and dropping every contract-derived route. Kept in sync with the initial\n // pass and every contracts rediscovery.\n //\n // Bounded-staleness tradeoff: if a page edit races a concurrent controller edit,\n // api.ts is stale by at most config.contracts.debounceMs until the contracts\n // watcher fires and overwrites — acceptable and self-correcting.\n let lastRoutes: RouteDescriptor[] = [];\n async function getDiscovery(): Promise<PersistentDiscovery> {\n if (discovery === null) {\n discovery = await PersistentDiscovery.create({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n return discovery;\n }\n return discovery;\n }\n\n // Run an initial full pass: pages + routes + contracts (same as a one-shot `codegen` run)\n try {\n const initialRoutes = (await getDiscovery()).discover();\n lastRoutes = initialRoutes;\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, lastRoutes);\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 // Reuse the last-known routes so a pages-only regen never drops the\n // contract-derived api.ts (see lastRoutes declaration).\n await generate(config, lastRoutes);\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 // Absolute paths changed since the last rediscovery, accumulated across the\n // debounce window so a burst of edits refreshes every touched file exactly once.\n const pendingChangedPaths = new Set<string>();\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(changedPath?: string): void {\n if (typeof changedPath === 'string') pendingChangedPaths.add(changedPath);\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n }\n contractsDebounceTimer = setTimeout(async () => {\n contractsDebounceTimer = undefined;\n const changed = [...pendingChangedPaths];\n pendingChangedPaths.clear();\n try {\n // Reuse the persistent Project: refresh only the changed file(s), re-glob\n // for added/removed controllers, then re-extract. Avoids reconstructing\n // the Project and re-parsing every controller + DTO on each change.\n const routes: RouteDescriptor[] = await (await getDiscovery()).rediscover(changed);\n lastRoutes = routes;\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', (p) => scheduleContractsRegenerate(p));\n contractsWatcher.on('change', (p) => scheduleContractsRegenerate(p));\n contractsWatcher.on('unlink', (p) => scheduleContractsRegenerate(p));\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', (p) => scheduleContractsRegenerate(p));\n formsWatcher.on('change', (p) => scheduleContractsRegenerate(p));\n formsWatcher.on('unlink', (p) => scheduleContractsRegenerate(p));\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 { clearEnumCache } from './enum-resolution.js';\nimport {\n clearTypeResolutionCaches,\n loadTsconfigPaths,\n resolveImportedVariable,\n setDiscoveryContext,\n} 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 = resolveTsconfigPath(cwd, tsconfig);\n const project = createDiscoveryProject(tsconfigPath);\n\n // Resolve controller file paths and add them to the project.\n const files = await fg(glob, { cwd, absolute: true, onlyFiles: true });\n for (const f of files) {\n project.addSourceFileAtPath(f);\n }\n\n bindDiscoveryContext(project, cwd, tsconfigPath);\n return extractAllRoutes(project);\n}\n\n// ---------------------------------------------------------------------------\n// Persistent-Project building blocks (used by the watcher to reuse ONE Project\n// across file changes — see watch/watcher.ts). The cold one-shot path above\n// keeps building a fresh Project per call, so its per-Project resolution caches\n// auto-invalidate; the watcher must evict them explicitly on each change.\n// ---------------------------------------------------------------------------\n\n/** Resolve the tsconfig path the same way the cold path does. */\nexport function resolveTsconfigPath(cwd: string, tsconfig?: string): string {\n return tsconfig ? resolve(tsconfig) : join(cwd, 'tsconfig.json');\n}\n\n/**\n * Construct a ts-morph `Project` configured exactly as the cold discovery path:\n * use the tsconfig when present, else fall back to bare compiler options.\n */\nexport function createDiscoveryProject(tsconfigPath: string): Project {\n try {\n return 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 return 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\n/** Bind the per-Project discovery context (project root + tsconfig path aliases). */\nexport function bindDiscoveryContext(project: Project, cwd: string, tsconfigPath: string): void {\n setDiscoveryContext(project, {\n projectRoot: cwd,\n tsconfigPaths: loadTsconfigPaths(tsconfigPath),\n });\n}\n\n/**\n * Run route extraction over every CONTROLLER source file currently in the\n * project. Only files matching the controller glob are extraction roots; DTO and\n * other imported files are pulled into the Project lazily during resolution but\n * are not themselves extraction roots. The cold path's loop visits all source\n * files, but at that point the Project contains ONLY the globbed controllers\n * (DTOs are added mid-extraction), so iterating `controllerPaths` is equivalent\n * — and necessary for the persistent Project, whose `getSourceFiles()` also\n * holds accumulated DTOs that must not be treated as controllers.\n */\nexport function extractRoutesFrom(\n project: Project,\n controllerPaths: Iterable<string>,\n): RouteDescriptor[] {\n const routes: RouteDescriptor[] = [];\n for (const path of controllerPaths) {\n const sourceFile = project.getSourceFile(path);\n if (sourceFile) routes.push(...extractFromSourceFile(sourceFile, project));\n }\n return routes;\n}\n\n/**\n * Run route extraction over every source file currently in the project.\n * Byte-identical to the cold path's extraction loop — used by both.\n */\nexport function extractAllRoutes(project: Project): RouteDescriptor[] {\n const routes: RouteDescriptor[] = [];\n for (const sourceFile of project.getSourceFiles()) {\n routes.push(...extractFromSourceFile(sourceFile, project));\n }\n return routes;\n}\n\n/**\n * A persistent-Project discovery session for watch mode. Holds ONE ts-morph\n * `Project` for the watcher's lifetime, re-globbing the controller set and\n * re-parsing only the file(s) that changed on each rediscovery — avoiding the\n * dominant cost of rebuilding the Project and re-parsing every controller + DTO\n * from scratch on every debounced change.\n *\n * Correctness: the per-Project resolution memoization (`_findTypeCache`,\n * `_resolveNamedRefCache`, `_enumCache`) no longer auto-invalidates because the\n * Project is reused, so {@link rediscover} clears those caches on every pass.\n * Output is byte-identical to {@link discoverContractsFast}: same Project config,\n * same context binding, same extraction over the globbed controller set.\n */\nexport class PersistentDiscovery {\n private readonly project: Project;\n private readonly cwd: string;\n private readonly glob: string;\n /** Absolute paths of the controllers currently loaded as extraction roots. */\n private controllerPaths = new Set<string>();\n\n private constructor(project: Project, cwd: string, glob: string) {\n this.project = project;\n this.cwd = cwd;\n this.glob = glob;\n }\n\n /**\n * Build the initial persistent Project: create it, glob + add all controllers,\n * bind the discovery context. Mirrors {@link discoverContractsFast}'s setup.\n */\n static async create(opts: FastDiscoveryOptions): Promise<PersistentDiscovery> {\n const { cwd, glob, tsconfig } = opts;\n const tsconfigPath = resolveTsconfigPath(cwd, tsconfig);\n const project = createDiscoveryProject(tsconfigPath);\n bindDiscoveryContext(project, cwd, tsconfigPath);\n\n const instance = new PersistentDiscovery(project, cwd, glob);\n const files = await fg(glob, { cwd, absolute: true, onlyFiles: true });\n for (const f of files) {\n project.addSourceFileAtPath(f);\n instance.controllerPaths.add(f);\n }\n return instance;\n }\n\n /** Run the initial extraction (equivalent to a first `discoverContractsFast`). */\n discover(): RouteDescriptor[] {\n return this.runExtraction();\n }\n\n /**\n * Re-discover after one or more files changed. Refreshes the changed file(s)\n * from disk (controllers AND any lazily-loaded DTO/imported files), re-globs\n * to pick up added/removed controllers, clears the per-Project caches, then\n * re-extracts. `changedPaths` is a hint; correctness does not depend on it\n * being exhaustive because re-globbing + refresh-on-presence covers the set.\n */\n async rediscover(changedPaths?: Iterable<string>): Promise<RouteDescriptor[]> {\n // 1. Refresh explicitly-changed files that are already in the Project. This\n // re-parses ONLY those files (the expensive ts-morph parse) — DTOs that\n // didn't change keep their already-parsed AST.\n if (changedPaths) {\n for (const p of changedPaths) {\n const abs = resolve(p);\n const sf = this.project.getSourceFile(abs);\n if (sf) {\n await sf.refreshFromFileSystem();\n }\n }\n }\n\n // 2. Re-glob to reconcile the controller set: add new controllers, drop\n // removed ones. Re-glob is cheap relative to parsing.\n const globbed = new Set(\n await fg(this.glob, { cwd: this.cwd, absolute: true, onlyFiles: true }),\n );\n for (const f of globbed) {\n if (!this.controllerPaths.has(f)) {\n try {\n this.project.addSourceFileAtPath(f);\n this.controllerPaths.add(f);\n } catch {\n /* file vanished between glob and add — ignore */\n }\n }\n }\n for (const f of this.controllerPaths) {\n if (!globbed.has(f)) {\n const sf = this.project.getSourceFile(f);\n if (sf) this.project.removeSourceFile(sf);\n this.controllerPaths.delete(f);\n }\n }\n\n return this.runExtraction();\n }\n\n /** Clear stale per-Project caches, then extract over the controller set. */\n private runExtraction(): RouteDescriptor[] {\n clearTypeResolutionCaches(this.project);\n clearEnumCache(this.project);\n return extractRoutesFrom(this.project, this.controllerPaths);\n }\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 // `@Sse('path')` is a server-sent-events endpoint — a GET on the wire.\n const sseDecorator = method.getDecorator('Sse');\n if (sseDecorator) {\n const pathArg = sseDecorator.getArguments()[0];\n return { httpMethod: 'GET', handlerPath: decoratorStringArg(pathArg) ?? '' };\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 project: Project;\n seenNames: Map<string, string>;\n}): RouteDescriptor | null {\n const {\n cls,\n method,\n applyContractDecorator,\n verb,\n prefix,\n className,\n sourceFile,\n project,\n 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 // Resolve the const — locally OR by following imports / barrel re-exports to\n // its declaring file (ts-morph walks the import to the declaration).\n const resolvedVar = resolveImportedVariable(identName, sourceFile, project);\n if (!resolvedVar) {\n console.warn(\n `[nestjs-codegen/fast] Cannot resolve contract identifier '${identName}' applied in ${sourceFile.getFilePath()} — the import could not be followed to a declaration; skipping`,\n );\n return null;\n }\n\n const { decl: varDecl, file: declFile } = resolvedVar;\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. The ref points at the const's\n // DECLARING file (which may differ from the controller for a cross-file ref),\n // and uses the LOCAL alias the controller imported it under for re-export.\n if (contractDef && varDecl.isExported()) {\n const filePath = declFile.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 error: contractDef.error,\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 error: dtoContract?.error ?? null,\n queryRef: dtoContract?.queryRef ?? null,\n bodyRef: dtoContract?.bodyRef ?? null,\n responseRef: dtoContract?.responseRef ?? null,\n errorRef: dtoContract?.errorRef ?? 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 stream: dtoContract?.stream ?? false,\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 project,\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 * `subst` maps generic type-parameter names to already-resolved type strings\n * (e.g. `{ T: '{ id: string }' }` while expanding `PaginatedDto<Item>`), so a\n * field typed `T`/`T[]` faithfully resolves instead of degrading to `unknown`.\n */\nfunction resolveTypeNodeToString(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n subst: Map<string, string> = new Map(),\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, subst)}>`;\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, subst))\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, subst))\n .join(' & ');\n }\n\n // Parenthesized: ( ... ) — unwrap\n if (Node.isParenthesizedTypeNode(typeNode)) {\n return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;\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 // A generic type-parameter binding in scope (e.g. `T` while expanding\n // `PaginatedDto<Item>`) → its concrete resolved type string.\n const bound = subst.get(name);\n if (bound !== undefined) return bound;\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, subst);\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 // Generic class/interface instantiation: bind its type parameters to the\n // supplied args (resolved in the CURRENT scope/subst) before expanding.\n const childSubst = buildSubst(resolved, typeNode, sourceFile, project, depth, subst);\n return expandTypeDecl(resolved, project, depth - 1, childSubst);\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 subst: Map<string, string> = new Map(),\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, subst);\n return mode === 'arrayOf' ? `Array<${inner}>` : inner;\n }\n return mode === 'arrayOf' ? 'Array<unknown>' : 'unknown';\n}\n\n/**\n * Build the type-parameter substitution map for a generic class/interface\n * instantiation: zip the declaration's type parameters (`<T, U>`) with the\n * reference's type arguments (`<Item, number>`), each resolved to a concrete\n * type string in the CURRENT scope. Returns an empty map for non-generic decls.\n */\nfunction buildSubst(\n result: TypeDeclResult,\n typeNode: import('ts-morph').TypeReferenceNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n parentSubst: Map<string, string>,\n): Map<string, string> {\n if (result.kind !== 'class' && result.kind !== 'interface') return new Map();\n const params = result.decl.getTypeParameters().map((p) => p.getName());\n if (params.length === 0) return new Map();\n const args = typeNode.getTypeArguments();\n const subst = new Map<string, string>();\n params.forEach((param, i) => {\n const arg = args[i];\n if (arg)\n subst.set(param, resolveTypeNodeToString(arg, sourceFile, project, depth, parentSubst));\n });\n return subst;\n}\n\n/**\n * Expand a TypeDeclResult into an inline TS type string.\n */\nfunction expandTypeDecl(\n result: TypeDeclResult,\n project: Project,\n depth: number,\n subst: Map<string, string> = new Map(),\n): string {\n if (depth < 0) return 'unknown';\n switch (result.kind) {\n case 'class':\n return resolvePropertied(result.decl, result.file, project, depth, subst);\n case 'interface':\n return resolvePropertied(result.decl, result.file, project, depth, subst);\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, subst);\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 subst: Map<string, string> = new Map(),\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, subst);\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 `@Query()`-decorated parameters.\n *\n * Two shapes are supported, in priority order:\n *\n * 1. Whole-object form — `@Query() dto: SomeQueryDto`. The parameter's declared\n * type is resolved and emitted as the entire `query` type. This is the\n * historical behavior and is preserved unchanged.\n *\n * 2. Named-param form — one or more `@Query('name')` decorators with a\n * string-literal name (e.g. `@Query('years') years?: number[]`). Each such\n * parameter contributes one property to a synthesized object type, keyed by\n * the string-literal name and typed by the parameter's annotation. This\n * mirrors {@link extractParamsType}'s handling of named `@Param('id')`.\n *\n * When BOTH shapes appear on the same handler (rare), the whole-object form\n * wins (it already describes the full query shape); the named params are\n * ignored to avoid emitting a conflicting partial type.\n *\n * Returns a TS type string or null when no usable `@Query` is present.\n */\nfunction extractQueryType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string | null {\n // 1. Whole-object form takes precedence.\n for (const param of method.getParameters()) {\n const queryDecorator = param.getDecorators().find((d) => d.getName() === 'Query');\n if (!queryDecorator) continue;\n if (queryDecorator.getArguments().length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n\n // 2. Named `@Query('name')` form — synthesize an object type, one property per\n // named query param. Mirrors extractParamsType's named-`@Param` handling.\n const entries: string[] = [];\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 const nameArg = queryArgs[0];\n if (!nameArg || !Node.isStringLiteral(nameArg)) continue;\n const queryName = nameArg.getLiteralValue();\n const typeNode = param.getTypeNode();\n // Pipes (ParseArrayPipe/ParseIntPipe/...) do not change the declared TS type,\n // so the annotation is read verbatim. A missing annotation falls back to\n // `string` (query-string values are always strings) — consistent with how\n // extractParamsType defaults a typeless `@Param`.\n const queryType = typeNode\n ? resolveTypeNodeToString(typeNode, sourceFile, project, 3)\n : 'string';\n entries.push(`${queryName}${isParamOptional(param) ? '?' : ''}: ${queryType}`);\n }\n return entries.length > 0 ? `{ ${entries.join('; ')} }` : null;\n}\n\n/**\n * Whether a handler parameter should be treated as an OPTIONAL query property.\n * True when the parameter has a `?` token, a default value, or a declared type\n * whose union includes `undefined` (e.g. `string | undefined`).\n */\nfunction isParamOptional(param: import('ts-morph').ParameterDeclaration): boolean {\n if (param.hasQuestionToken() || param.hasInitializer()) return true;\n const typeNode = param.getTypeNode();\n if (typeNode && Node.isUnionTypeNode(typeNode)) {\n return typeNode.getTypeNodes().some((t) => t.getKind() === SyntaxKind.UndefinedKeyword);\n }\n return false;\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 — but skip error-status (4xx/5xx) ones; those describe\n // the error body, not the success response.\n const apiResponseDecorator = method\n .getDecorators()\n .find((d) => d.getName() === 'ApiResponse' && (apiResponseStatus(d) ?? 0) < 400);\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 * The numeric `status` of an `@ApiResponse({ status, type })` decorator, or null\n * when absent / non-numeric.\n */\nfunction apiResponseStatus(decorator: import('ts-morph').Decorator): number | null {\n const optsArg = decorator.getArguments()[0];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n if (prop.getName() !== 'status') continue;\n const val = prop.getInitializer();\n if (val && Node.isNumericLiteral(val)) return Number(val.getLiteralValue());\n }\n return null;\n}\n\n/**\n * Read the `type:` initializer of an `@ApiResponse({ type })` decorator as an\n * expression node, or null. Handles both `type: X` and `type: [X]`.\n */\nfunction apiResponseTypeNode(\n decorator: import('ts-morph').Decorator,\n): { node: Node; isArray: boolean } | null {\n const optsArg = decorator.getArguments()[0];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\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) return null;\n if (Node.isArrayLiteralExpression(val)) {\n const first = val.getElements()[0];\n return first ? { node: first, isArray: true } : null;\n }\n return { node: val, isArray: false };\n }\n return null;\n}\n\n/**\n * Discover the route's error response body type from an `@ApiResponse({ status,\n * type })` decorator whose `status` is a 4xx/5xx code. This is the least-magic\n * signal available statically: it reuses the Swagger decorator NestJS apps\n * already write to document error responses. Returns the expanded TS type string\n * (and an importable ref when the type is an exported named class/interface), or\n * null when no error-status @ApiResponse is present.\n */\nfunction extractErrorType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): { type: string; ref: TypeRef | null } | null {\n for (const decorator of method.getDecorators()) {\n if (decorator.getName() !== 'ApiResponse') continue;\n const status = apiResponseStatus(decorator);\n if (status === null || status < 400) continue;\n const typeInfo = apiResponseTypeNode(decorator);\n if (!typeInfo) continue;\n const inner = resolveIdentifierToClassType(typeInfo.node, sourceFile, project, 3);\n const type = typeInfo.isArray ? `Array<${inner}>` : inner;\n\n let ref: TypeRef | null = null;\n if (Node.isIdentifier(typeInfo.node)) {\n const name = typeInfo.node.getText();\n const localDecl =\n sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);\n if (localDecl?.isExported()) {\n ref = { name, filePath: sourceFile.getFilePath(), isArray: typeInfo.isArray };\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 ref = { name, filePath: resolved.file.getFilePath(), isArray: typeInfo.isArray };\n }\n }\n }\n return { type, ref };\n }\n return null;\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// SSE / streaming detection\n// ---------------------------------------------------------------------------\n\n/**\n * Container types whose first type argument is the streamed ELEMENT. NestJS SSE\n * handlers return `Observable<T>` (often `Observable<MessageEvent<T>>`); a plain\n * async-generator handler returns `AsyncIterable<T>` / `AsyncGenerator<T>`.\n */\nconst STREAM_CONTAINERS = new Set(['Observable', 'AsyncIterable', 'AsyncIterableIterator']);\n// AsyncGenerator<T, ...> — T is the FIRST arg (yield type), same position.\nconst STREAM_CONTAINERS_GENERATOR = new Set(['AsyncGenerator']);\n\n/** NestJS SSE event-envelope whose `.data` (first type arg) is the real payload. */\nconst STREAM_ENVELOPES = new Set(['MessageEvent', 'MessageEventLike']);\n\n/**\n * The streamed element type-node of an SSE/streaming handler, or null when the\n * route is not a stream. The signal (least-magic, fully static): a `@Sse()`\n * decorator, OR a return type that is `Observable<T>` / `AsyncIterable<T>` /\n * `AsyncGenerator<T>`. The element is unwrapped through any `Promise<>` and any\n * NestJS `MessageEvent<>` envelope so the carried type is the real payload `T`.\n */\nfunction detectStreamElement(method: MethodDeclaration): TypeNode | null {\n const hasSse = method.getDecorators().some((d) => d.getName() === 'Sse');\n let node = method.getReturnTypeNode();\n\n // Peel a leading Promise<> (e.g. an async generator method annotated as such).\n node = unwrapNamedContainer(node, new Set(['Promise']));\n\n const containerEl = streamContainerElement(node);\n if (containerEl) {\n return unwrapNamedContainer(containerEl, STREAM_ENVELOPES) ?? containerEl;\n }\n\n // `@Sse()` present but no recognizable container (or no return annotation):\n // still a stream, element type unknown.\n if (hasSse) return node ?? null;\n return null;\n}\n\n/** If `node` is one of the stream container types, return its element type-node. */\nfunction streamContainerElement(node: TypeNode | undefined): TypeNode | null {\n if (!node || !Node.isTypeReference(node)) return null;\n const typeName = node.getTypeName();\n const name = Node.isIdentifier(typeName) ? typeName.getText() : '';\n if (STREAM_CONTAINERS.has(name) || STREAM_CONTAINERS_GENERATOR.has(name)) {\n return node.getTypeArguments()[0] ?? null;\n }\n return null;\n}\n\n/** Unwrap `node` once if it is one of `names` (a single-arg generic), else return as-is. */\nfunction unwrapNamedContainer(\n node: TypeNode | undefined,\n names: Set<string>,\n): TypeNode | undefined {\n if (!node || !Node.isTypeReference(node)) return node;\n const typeName = node.getTypeName();\n const name = Node.isIdentifier(typeName) ? typeName.getText() : '';\n if (names.has(name)) {\n return node.getTypeArguments()[0] ?? node;\n }\n return node;\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 error?: string | null;\n params: string | null;\n queryRef?: TypeRef | null;\n bodyRef?: TypeRef | null;\n responseRef?: TypeRef | null;\n errorRef?: 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 stream?: boolean;\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 // ── SSE / streaming: the streamed element type replaces `response` ──────────\n const streamElement = detectStreamElement(method);\n const isStream = streamElement !== null;\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 // For a stream, the wire shape is the ELEMENT type `T` (the client surfaces an\n // `AsyncIterable<T>`); otherwise resolve the normal response type.\n const response = isStream\n ? resolveTypeNodeToString(streamElement, sourceFile, project, 3)\n : extractResponseType(method, sourceFile, project);\n const errorInfo = extractErrorType(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 errorInfo === null &&\n filterInfo === null &&\n !isStream\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 // For a stream the importable ref (if any) is the streamed element type — not\n // the Observable/AsyncIterable container.\n const returnTypeNode = isStream ? streamElement : method.getReturnTypeNode();\n if (returnTypeNode) {\n responseRef = resolveBodyQueryResponseRef(returnTypeNode, sourceFile, project);\n }\n // Also check @ApiResponse (success-status only — error-status describes the error body)\n if (!responseRef && !isStream) {\n const apiResp = method\n .getDecorators()\n .find((d) => d.getName() === 'ApiResponse' && (apiResponseStatus(d) ?? 0) < 400);\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 error: errorInfo?.type ?? null,\n params: paramsType,\n queryRef,\n bodyRef,\n responseRef,\n errorRef: errorInfo?.ref ?? null,\n filterFields: filterInfo?.fieldNames ?? null,\n filterFieldTypes: filterInfo?.fieldTypes ?? null,\n filterSource: filterInfo?.source ?? null,\n formWarnings,\n bodySchema,\n querySchema,\n stream: isStream,\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 { debugWarn } from '../util/debug-log.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 /**\n * Maintained union of every schema name currently in use — the keys of\n * `named` plus the values of `emittedClasses`. Kept in sync at each insertion\n * site so {@link aliasFor} can probe membership in O(1) instead of rebuilding\n * the set on every call (former O(n²) over all nested references).\n */\n usedSchemaNames: Set<string>;\n visiting: Set<string>;\n recursiveSchemas: Set<string>;\n depth: number;\n /**\n * Active generic type-parameter bindings for the class currently being\n * expanded, e.g. `{ T: 'Item' }` while expanding `PaginatedDto<Item>`. A\n * property typed `T` / `T[]` resolves through this map to the concrete class,\n * giving wrapper DTOs a faithful schema instead of degrading to `unknown`.\n */\n typeBindings: Map<string, string>;\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 usedSchemaNames: new Set(),\n visiting: new Set(),\n recursiveSchemas: new Set(),\n depth: 0,\n typeBindings: new Map(),\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 // Finish a property whose value is a nested/union reference: wrap in an array\n // when the field is a collection (`@IsArray` or a `T[]` type), then apply\n // `@IsOptional`/`@IsDefined` presence. Shared by the three reference paths below.\n const asField = (child: SchemaNode): SchemaNode =>\n applyPresence(\n has('IsArray') || isArrayType ? { kind: 'array', element: child } : child,\n decorators,\n );\n\n // ── Discriminated union via @Type(() => Base, { discriminator: {...} }) ──\n // class-transformer's documented polymorphism convention. The `subTypes`\n // entries map a discriminator literal to a concrete class; we emit a union of\n // refs to those classes carrying the discriminator property name, which each\n // adapter renders as a tagged union (zod discriminatedUnion / valibot variant).\n const discriminator = resolveDiscriminator(dec('Type'));\n if (discriminator) {\n const options: SchemaNode[] = discriminator.subTypes.map((name) =>\n buildNestedReference(name, classFile, ctx),\n );\n return asField({ kind: 'union', options, discriminator: discriminator.property });\n }\n\n // ── Generic type-parameter property (T / T[]) resolved via active bindings ─\n // When expanding `Wrapper<Arg>`, a field typed `T`/`T[]` (where T is the\n // wrapper's type parameter) resolves to the concrete `Arg` class — giving the\n // wrapper a faithful schema instead of degrading to `unknown`. Takes priority\n // over `@Type` (whose factory can't name the still-generic `T`).\n const propTypeParam = singularClassName(typeText);\n if (propTypeParam && ctx.typeBindings.has(propTypeParam)) {\n const bound = ctx.typeBindings.get(propTypeParam) as string;\n return asField(buildNestedReference(bound, classFile, ctx));\n }\n\n // ── Nested / array-of-nested via @ValidateNested + @Type ────────────────\n const typeRefName = resolveTypeFactoryName(dec('Type'));\n if (has('ValidateNested') || typeRefName) {\n // A generic wrapper reference (`PaginatedDto<Item>`) carries its type args on\n // the property typeNode, not in `@Type`. Capture them so the wrapper's body\n // is expanded with `T → Item` bindings.\n const typeArgs = genericTypeArgNames(typeNode);\n const childName = typeRefName ?? singularClassName(typeText);\n if (childName) {\n return asField(buildNestedReference(childName, classFile, ctx, typeArgs));\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 debugWarn(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 typeArgs: string[] = [],\n): SchemaNode {\n // A generic instantiation (`PaginatedDto<Item>`) is keyed by class + args so\n // distinct instantiations don't collide in the emitted-class cache. A bare\n // (non-generic) reference keys by class name as before — byte-identical output.\n const cacheKey = typeArgs.length > 0 ? `${className}<${typeArgs.join(',')}>` : className;\n const schemaBase = typeArgs.length > 0 ? `${className}Of${typeArgs.join('')}` : className;\n\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(cacheKey)) {\n const reserved = ctx.emittedClasses.get(cacheKey) ?? aliasFor(schemaBase, ctx);\n ctx.emittedClasses.set(cacheKey, reserved);\n ctx.usedSchemaNames.add(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 debugWarn(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 debugWarn(msg);\n }\n return { kind: 'unknown', note: 'nesting too deep — not expanded' };\n }\n\n const existing = ctx.emittedClasses.get(cacheKey);\n if (existing) return { kind: 'ref', name: existing };\n\n const schemaName = aliasFor(schemaBase, 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 // Bind the class's type parameters to the supplied args for the duration of\n // this expansion (`class PaginatedDto<T>` + args [Item] → { T: 'Item' }).\n const params = resolved.decl.getTypeParameters().map((p) => p.getName());\n const newBindings: Array<[string, string]> = [];\n params.forEach((param, i) => {\n const arg = typeArgs[i];\n if (arg) newBindings.push([param, arg]);\n });\n for (const [k, v] of newBindings) ctx.typeBindings.set(k, v);\n\n ctx.emittedClasses.set(cacheKey, schemaName);\n ctx.usedSchemaNames.add(schemaName);\n ctx.visiting.add(cacheKey);\n ctx.depth += 1;\n const childNode = buildObject(resolved.decl, resolved.file, ctx);\n ctx.depth -= 1;\n ctx.visiting.delete(cacheKey);\n for (const [k] of newBindings) ctx.typeBindings.delete(k);\n\n ctx.named.set(schemaName, childNode);\n ctx.usedSchemaNames.add(schemaName);\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 // `usedSchemaNames` is the maintained union of `named` keys + `emittedClasses`\n // values, kept in sync at every insertion site — so this is an O(1) probe per\n // step instead of rebuilding the set on each call.\n while (ctx.usedSchemaNames.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/**\n * Resolve a class-transformer discriminator from the SECOND argument of\n * `@Type(() => Base, { discriminator: { property, subTypes } })`. Returns the\n * discriminator property name plus the ordered list of subtype class names, or\n * null when the decorator has no (valid) discriminator option.\n */\nfunction resolveDiscriminator(\n decorator: Decorator | undefined,\n): { property: string; subTypes: string[] } | null {\n const optsArg = decorator?.getArguments()[1];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\n\n let discProp: Node | undefined;\n for (const prop of optsArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'discriminator') {\n discProp = prop.getInitializer();\n }\n }\n if (!discProp || !Node.isObjectLiteralExpression(discProp)) return null;\n\n let property: string | null = null;\n const subTypes: string[] = [];\n for (const prop of discProp.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const name = prop.getName();\n const init = prop.getInitializer();\n if (!init) continue;\n if (name === 'property' && Node.isStringLiteral(init)) {\n property = init.getLiteralValue();\n } else if (name === 'subTypes' && Node.isArrayLiteralExpression(init)) {\n for (const el of init.getElements()) {\n if (!Node.isObjectLiteralExpression(el)) continue;\n for (const p of el.getProperties()) {\n if (!Node.isPropertyAssignment(p) || p.getName() !== 'name') continue;\n const nameInit = p.getInitializer();\n if (nameInit && Node.isIdentifier(nameInit)) subTypes.push(nameInit.getText());\n }\n }\n }\n }\n if (!property || subTypes.length === 0) return null;\n return { property, subTypes };\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/**\n * Read the simple identifier names of a type reference's type arguments, e.g.\n * `PaginatedDto<Item>` → `['Item']`. Returns `[]` when the node is not a generic\n * type reference or any argument is not a bare identifier (we only substitute\n * named class args; complex args are left to degrade as before).\n */\nfunction genericTypeArgNames(typeNode: import('ts-morph').TypeNode | undefined): string[] {\n if (!typeNode || !Node.isTypeReference(typeNode)) return [];\n const names: string[] = [];\n for (const arg of typeNode.getTypeArguments()) {\n if (!Node.isTypeReference(arg)) return [];\n const tn = arg.getTypeName();\n if (!Node.isIdentifier(tn)) return [];\n names.push(tn.getText());\n }\n return names;\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 debugWarn(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","/**\n * Opt-in terminal logging for schema-translation advisories.\n *\n * Messages like \"@X is not translatable to a client validation schema\" or\n * \"T is a recursive type\" are always recorded in the `SchemaModule.warnings`\n * array and re-emitted as `// warning:` comments in the generated output, so the\n * durable record never depends on this. The terminal copy is pure noise on a\n * normal run, so it is printed only when codegen runs with `debug: true`.\n *\n * The flag is process-wide and set once per pass by {@link generate}; codegen\n * runs as a single CLI invocation or one watcher tick, so a module-level switch\n * is sufficient (and matches the pre-existing direct `console.warn` it replaces).\n */\nlet debugEnabled = false;\n\n/** Set by `generate()` from the resolved `debug` config before each pass. */\nexport function setCodegenDebug(enabled: boolean): void {\n debugEnabled = enabled;\n}\n\n/** Emit a `[nestjs-codegen]` advisory to stderr only when debug is enabled. */\nexport function debugWarn(message: string): void {\n if (debugEnabled) console.warn(`[nestjs-codegen] ${message}`);\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 type VariableDeclaration,\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\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 // Bare node_modules specifier (e.g. `@scope/pkg`): our manual relative /\n // tsconfig-paths resolver yields no candidates. Fall back to the TS\n // compiler's own module resolution, which locates the package's `.d.ts`\n // declaration file. This is what lets a `@Filterable({ entity: X })` whose\n // entity lives in an external package still be resolved (and its columns\n // enumerated from the declaration file), rather than silently degrading the\n // route to a non-filter route.\n if (candidates.length === 0) {\n const viaCompiler = resolveBareSpecifierType(name, importDecl, project);\n if (viaCompiler) return viaCompiler;\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 * Resolve `name` against a bare (node_modules) import specifier using the TS\n * compiler's module resolution. `getModuleSpecifierSourceFile()` returns the\n * declaration (`.d.ts`) or source file the package resolves to; we then look up\n * the type there (and follow that file's own re-exports / barrels).\n */\nfunction resolveBareSpecifierType(\n name: string,\n importDecl: import('ts-morph').ImportDeclaration,\n project: Project,\n): TypeDeclResult | null {\n let target: SourceFile | undefined;\n try {\n target = importDecl.getModuleSpecifierSourceFile();\n } catch {\n return null;\n }\n if (!target) return null;\n const direct = findTypeInFile(name, target);\n if (direct) return direct;\n return resolveReExportedType(name, target, 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// Variable-declaration (const) lookup — for cross-file @ApplyContract refs\n// ---------------------------------------------------------------------------\n\n/** A resolved value-level `const`/variable declaration plus its declaring file. */\nexport interface VariableDeclResult {\n decl: VariableDeclaration;\n file: SourceFile;\n}\n\n/**\n * Resolve an identifier that names a value-level `const` (e.g. an imported\n * `defineContract(...)` result applied via `@ApplyContract(thatConst)`) to its\n * variable declaration and declaring file. Resolution order:\n * 1. local declaration in the current file;\n * 2. follow the file's import declarations to the declaring module;\n * 3. follow `export { X } from './mod'` / `export *` re-exports (barrels).\n *\n * Returns null when the identifier cannot be resolved to a variable declaration\n * (the caller then warns + skips, preserving the prior behavior).\n */\nexport function resolveImportedVariable(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): VariableDeclResult | null {\n const local = sourceFile.getVariableDeclaration(name);\n if (local) return { decl: local, file: sourceFile };\n return resolveVariableViaImports(name, sourceFile, project, new Set());\n}\n\n/** Follow the file's import declarations to a variable declaration in another module. */\nfunction resolveVariableViaImports(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n seen: Set<string>,\n): VariableDeclResult | null {\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl\n .getNamedImports()\n .find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name);\n if (!namedImport) continue;\n // The source-side (pre-alias) name to look up in the target module.\n const sourceName = namedImport.getName();\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n const found = followModuleForVariable(sourceName, moduleSpecifier, sourceFile, project, seen);\n if (found) return found;\n }\n return null;\n}\n\n/** Resolve `name` to a variable declaration inside the module at `moduleSpecifier`. */\nfunction followModuleForVariable(\n name: string,\n moduleSpecifier: string,\n fromFile: SourceFile,\n project: Project,\n seen: Set<string>,\n): VariableDeclResult | 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 found = resolveVariableInFile(name, importedFile, project, seen);\n if (found) return found;\n }\n return null;\n}\n\n/**\n * Find a variable declaration `name` in `file`: directly, then via re-exports\n * (`export { X } from './mod'`, `export *`, bare `export { X }`) and that file's\n * own imports. Guards against import/re-export cycles via `seen`.\n */\nfunction resolveVariableInFile(\n name: string,\n file: SourceFile,\n project: Project,\n seen: Set<string>,\n): VariableDeclResult | null {\n const filePath = file.getFilePath();\n if (seen.has(filePath)) return null;\n seen.add(filePath);\n\n const local = file.getVariableDeclaration(name);\n if (local) return { decl: local, file };\n\n for (const exportDecl of file.getExportDeclarations()) {\n const moduleSpecifier = exportDecl.getModuleSpecifierValue();\n const namedExports = exportDecl.getNamedExports();\n\n if (moduleSpecifier) {\n const hasStar = namedExports.length === 0; // `export * from './mod'`\n const reExport = namedExports.find(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!hasStar && !reExport) continue;\n const sourceName = hasStar ? name : (reExport?.getName() ?? name);\n const found = followModuleForVariable(sourceName, moduleSpecifier, file, project, seen);\n if (found) return found;\n continue;\n }\n\n // Bare `export { X }` — X was imported into this file above.\n const reExport = namedExports.find(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!reExport) continue;\n const sourceName = reExport.getName();\n const viaImports = resolveVariableViaImports(sourceName, file, project, seen);\n if (viaImports) return viaImports;\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 * Evict the per-`Project` resolution caches for a Project. Required by the watch\n * mode, which reuses ONE persistent `Project` across file changes: without a\n * fresh Project per run the WeakMap entries would otherwise never auto-invalidate,\n * so a changed file would resolve against stale, pre-change declarations. Clearing\n * the whole per-Project map on each change is the simple, always-correct choice\n * (the cold one-shot path keeps building a fresh Project and never calls this).\n */\nexport function clearTypeResolutionCaches(project: Project): void {\n _findTypeCache.delete(project);\n _resolveNamedRefCache.delete(project);\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 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\n/**\n * Evict the per-`Project` enum cache. Companion to\n * `clearTypeResolutionCaches` — the persistent watch-mode Project must drop this\n * on every change or a changed enum would resolve to stale members.\n */\nexport function clearEnumCache(project: Project): void {\n _enumCache.delete(project);\n}\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 /** Error response body type, from a `defineContract({ error })` zod schema. Null when absent. */\n error: string | null;\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 error: string | null = null;\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 } else if (propName === 'error') {\n error = zodAstToTs(val);\n }\n }\n\n return { query, body, response, error, bodyZodText, queryZodText };\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 { emitMocks } from './emit/emit-mocks.js';\nimport { emitOpenApi } from './emit/emit-openapi.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';\nimport { setCodegenDebug } from './util/debug-log.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 // Gate the schema-translation advisory chatter for this pass (off by default).\n setCodegenDebug(config.debug);\n\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 serialization: config.serialization,\n extensions,\n ctx,\n });\n }\n\n const hasForms = await emitForms(routes, config.codegen.outDir, config.forms, config.validation);\n\n // OpenAPI 3.1 spec export (opt-in). Lowers routes + validation IR into a spec.\n if (hasContracts && config.openapi.enabled) {\n await emitOpenApi(routes, config.codegen.outDir, {\n fileName: config.openapi.fileName,\n info: {\n title: config.openapi.title,\n version: config.openapi.version,\n ...(config.openapi.description ? { description: config.openapi.description } : {}),\n },\n });\n }\n\n // MSW + faker mock handlers (opt-in).\n if (hasContracts && config.mocks.enabled) {\n await emitMocks(routes, config.codegen.outDir, {\n fileName: config.mocks.fileName,\n seed: config.mocks.seed,\n baseUrl: config.mocks.baseUrl,\n });\n }\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 { SerializationMode } from '../config/types.js';\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 *\n * `serialization` controls how response types are emitted (default `'json'`):\n * in `'json'` mode each `response` type is wrapped in `Jsonify<...>` (so the\n * generated type reflects the JSON wire shape, e.g. `Date` → `string`); in\n * `'superjson'` mode the raw controller return type is emitted unchanged.\n */\nexport interface ApiEmitOptions {\n fetcherImportPath?: string | undefined;\n /** Registered extensions. Their api.ts hooks (transport/layer/members/header) are applied. */\n extensions?: CodegenExtension[] | undefined;\n /** Shared extension context (from `generate()`). When omitted, a minimal one is built from routes. */\n ctx?: ExtensionContext | undefined;\n /** How response payloads deserialize on the client. Default `'json'`. */\n serialization?: SerializationMode | undefined;\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 * The route `response` type expression for a leaf.\n *\n * In `'json'` mode the response crosses the wire as plain JSON, so wrap the raw\n * type in `Jsonify<...>` to reflect the serialized shape (Date → string, etc.).\n * In `'superjson'` mode the payload is revived on the client, so emit the raw\n * controller return type unchanged. Only the `response` field is wrapped — never\n * `error`, `body`, or `query`.\n */\nfunction buildResponseType(c: LeafEntry, outDir: string, serialization: SerializationMode): string {\n const raw = rawResponseType(c, outDir);\n return serialization === 'json' ? `Jsonify<${raw}>` : raw;\n}\n\n/** The un-wrapped response type expression for a leaf (stream / controllerRef / ref / inline). */\nfunction rawResponseType(c: LeafEntry, outDir: string): string {\n const respRef = c.contractSource.responseRef;\n // Streaming routes: `response` is the streamed ELEMENT type `T`. The method's\n // ReturnType is `Observable<...>` / `AsyncIterable<...>` (the container), so the\n // `ReturnType<...>` path would type the element as the container — use the\n // discovered element ref / inline element string instead.\n if (c.contractSource.stream) {\n if (respRef) return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;\n return c.contractSource.response;\n }\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 if (respRef) {\n return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;\n }\n return c.contractSource.response;\n}\n\n/**\n * The route's error response body type for the leaf `error` field. Prefers a\n * named `errorRef` (so it imports by name), then the inline `error` type string,\n * and finally `unknown` — an HTTP error always carries some body, so an undeclared\n * error type is `unknown` rather than `never`.\n */\nfunction buildErrorType(c: LeafEntry): string {\n const errRef = c.contractSource.errorRef;\n if (errRef) {\n return errRef.isArray ? `Array<${errRef.name}>` : errRef.name;\n }\n return c.contractSource.error ?? 'unknown';\n}\n\nfunction emitRouterTypeBlock(\n tree: Map<string, TreeNode>,\n indent: number,\n outDir: string,\n serialization: SerializationMode,\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, serialization);\n const error = buildErrorType(c);\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 // SSE/streaming routes carry `stream: true` so `Route.Stream<K>` and the\n // leaf's `stream()` surface can be derived purely from the ApiRouter type.\n const stream = c.contractSource.stream ? 'true' : 'false';\n lines.push(\n `${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; params: ${params}; query: ${query}; body: ${body}; response: ${response}; error: ${error}; filterFields: ${filterFields}; stream: ${stream} };`,\n );\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir, serialization));\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 // When no input is supplied the key omits the trailing element entirely\n // (`[name]` rather than `[name, undefined]`) so the bare `.queryKey()` is a\n // clean prefix that partial-matches every parametrized variant — making it\n // directly usable for `invalidateQueries`.\n queryKeyExpr: `(input === undefined ? [${flat}] as const : [${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 streamExpr: string | undefined,\n): string[] {\n const lines = [`${pad}${objKey}: (input?: ${req.inputType}) => ({`];\n lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);\n // SSE/streaming routes expose a typed `stream()` returning an AsyncIterable of\n // the streamed element type (alongside the awaitable base, which is rarely used\n // for a stream but kept for shape uniformity).\n if (streamExpr) {\n lines.push(`${pad} stream: () => ${streamExpr},`);\n }\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/**\n * The streaming consumption expression for an `@Sse()`/streaming leaf:\n * `fetcher.sse<T>(url, { query })`. The element type `T` is the route's\n * `response` (the codegen carried the streamed element through there).\n */\nfunction renderStreamExpr(req: RequestModel): string {\n return `fetcher.sse<${req.responseType}>(${req.urlExpr}, ${req.optsExpr})`;\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 const streamExpr = node.contractSource.stream ? renderStreamExpr(req) : undefined;\n\n lines.push(...renderLeaf(pad, objKey, req, leaf.requestExpr, members, streamExpr));\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 ' /** The streamed element type of an `@Sse()`/streaming route — the type yielded by its `stream()` AsyncIterable. */',\n ' export type Stream<K extends string> = ResolveByName<K, \"response\">;',\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 ' export type Stream<M extends string, U extends string> = ResolveByPath<M, U, \"response\">;',\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 Stream<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 ' export type Stream<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 serialization: SerializationMode = opts.serialization ?? 'json';\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 // EXCEPT for streams, whose response is the element ref (not the container ReturnType).\n // errorRef is always imported (the error type is never sourced from ReturnType).\n const refs =\n r.controllerRef && !cs.stream\n ? [cs.queryRef, cs.bodyRef, cs.errorRef]\n : [cs.queryRef, cs.bodyRef, cs.responseRef, cs.errorRef];\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 // In `'json'` mode every `response` type is wrapped in `Jsonify<...>` so the\n // generated type reflects the JSON wire shape; import the type helper (from the\n // same `runtimeImport`, so it tracks `fetcherImportPath`). Only when at least\n // one route is wrapped (the empty-routes branch wraps nothing).\n if (serialization === 'json' && contracted.length > 0) {\n lines.push(`import type { Jsonify } from '${runtimeImport}';`);\n }\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 ?? '', serialization));\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 escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Cache of word-boundary regexes keyed by token. Building `new RegExp` per\n * rename per call was O(renames) recompiles inside the fixed-point loop; tokens\n * recur heavily across entries, so a shared cache amortizes it. A `/g` regex is\n * safe to reuse with `String.prototype.replace` (replace does not read/advance\n * `lastIndex`), so one cached instance covers both `applyRenames` (global) and\n * `isSelfReferential` (test). For `.test()` we use a fresh non-global form to\n * avoid `lastIndex` statefulness.\n */\nconst wordBoundaryRegexCache = new Map<string, RegExp>();\n\nfunction wordBoundaryRegex(token: string): RegExp {\n let re = wordBoundaryRegexCache.get(token);\n if (re === undefined) {\n re = new RegExp(`\\\\b${escapeRegExp(token)}\\\\b`, 'g');\n wordBoundaryRegexCache.set(token, re);\n }\n return re;\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(wordBoundaryRegex(from), to);\n }\n return out;\n}\n\nfunction isSelfReferential(name: string, text: string): boolean {\n // Use a non-global probe: `RegExp.prototype.test` on a `/g` regex advances\n // `lastIndex`, which would make repeated calls for the same token stateful.\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 // Maintained mirror of `rename.values()` so the disambiguation loop can test\n // candidate membership in O(1) instead of rebuilding an array each probe.\n const renameValues = new Set<string>();\n const setRename = (key: string, value: string): void => {\n const prev = rename.get(key);\n rename.set(key, value);\n if (prev !== undefined && prev !== value) {\n // Drop the old value only if no other key still maps to it.\n let stillUsed = false;\n for (const v of rename.values()) {\n if (v === prev) {\n stillUsed = true;\n break;\n }\n }\n if (!stillUsed) renameValues.delete(prev);\n }\n renameValues.add(value);\n };\n for (const [name] of local) setRename(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 renameValues.has(candidate)\n ) {\n i += 1;\n candidate = `${name}_${i}`;\n }\n setRename(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","/**\n * MSW + (dependency-free) faker-style mock handler generation.\n *\n * Emits `mocks.ts`: an array of Mock Service Worker (`msw`) `http` handlers, one\n * per contracted route, each returning seeded mock data shaped to the route's\n * response JSON Schema (lowered from the same IR as the OpenAPI export). This is\n * Orval's headline feature; the key difference is we ship NO `@faker-js/faker`\n * dependency — a tiny `mulberry32`-seeded generator (`MOCK_GEN_RUNTIME` in\n * `emit/mock-gen-runtime.ts`) is embedded verbatim into the output, so the\n * generated module is self-contained and deterministic for a given seed.\n *\n * `msw` is a peer dependency the consumer installs; the generated file imports\n * `http`/`HttpResponse` from it. The generator runtime is embedded (not imported)\n * so the file has no dependency on this package at runtime.\n */\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport type { JsonSchema } from '../ir/schema-node-to-json-schema.js';\nimport { schemaModuleToJsonSchema } from '../ir/schema-node-to-json-schema.js';\nimport { MOCK_GEN_RUNTIME } from './mock-gen-runtime.js';\n\nexport interface MocksEmitOptions {\n /** Output file name within `outDir`. Default `'mocks.ts'`. */\n fileName?: string;\n /** Deterministic seed. Default `1`. */\n seed?: number;\n /** Base URL prepended to handler paths. Default `''`. */\n baseUrl?: string;\n}\n\nconst REF_PREFIX = '#/components/schemas/';\n\n/** MSW path syntax uses `:param`, which already matches NestJS paths. */\nfunction toMswPath(path: string, baseUrl: string): string {\n return `${baseUrl}${path}`;\n}\n\n/**\n * The response schema for a route, lowered from the response IR\n * (`responseSchema`) when present and hoisting its named schemas into the shared\n * `defs` map. Falls back to a permissive schema (the generator then yields a\n * neutral object, which still conforms) when no response IR exists.\n */\nfunction responseSchemaFor(route: RouteDescriptor, defs: Record<string, JsonSchema>): JsonSchema {\n const cs = route.contract!.contractSource;\n if (cs.responseSchema) {\n const { root, named } = schemaModuleToJsonSchema(cs.responseSchema, { refPrefix: REF_PREFIX });\n for (const [name, node] of Object.entries(named)) {\n if (!(name in defs)) defs[name] = node;\n }\n return root;\n }\n return {};\n}\n\n/** Build the `mocks.ts` source text. Pure (no I/O). */\nexport function buildMocksFile(routes: RouteDescriptor[], opts: MocksEmitOptions = {}): string {\n const seed = opts.seed ?? 1;\n const baseUrl = opts.baseUrl ?? '';\n const contracted = routes.filter((r) => r.contract);\n\n // Shared components map referenced by per-route response schemas.\n const defs: Record<string, JsonSchema> = {};\n const handlers: string[] = [];\n\n for (const r of contracted) {\n const schema = responseSchemaFor(r, defs);\n const method = r.method.toLowerCase();\n const mswMethod =\n method === 'get' ||\n method === 'post' ||\n method === 'put' ||\n method === 'patch' ||\n method === 'delete'\n ? method\n : 'all';\n const path = toMswPath(r.path, baseUrl);\n const cs = r.contract!.contractSource;\n const schemaLiteral = JSON.stringify(schema);\n const pathLit = JSON.stringify(path);\n if (cs.stream) {\n // SSE/streaming route: return a text/event-stream body with one event.\n handlers.push(\n [\n ` // ${r.name} (stream)`,\n ` http.${mswMethod}(${pathLit}, () => {`,\n ` const value = generateMock(${schemaLiteral}, makeRng(SEED), DEFS);`,\n ' const body = `data: ${JSON.stringify(value)}\\\\n\\\\n`;',\n \" return new HttpResponse(body, { headers: { 'Content-Type': 'text/event-stream' } });\",\n ' }),',\n ].join('\\n'),\n );\n } else {\n handlers.push(\n [\n ` // ${r.name}`,\n ` http.${mswMethod}(${pathLit}, () => {`,\n ` const value = generateMock(${schemaLiteral}, makeRng(SEED), DEFS);`,\n ' return HttpResponse.json(value);',\n ' }),',\n ].join('\\n'),\n );\n }\n }\n\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-codegen. Do not edit.',\n '// MSW handlers returning deterministic, schema-shaped mock data.',\n '/* eslint-disable */',\n '// @ts-nocheck',\n '',\n \"import { http, HttpResponse } from 'msw';\",\n '',\n `const SEED = ${seed};`,\n '',\n '// ---------------------------------------------------------------------------',\n '// Embedded mock-data runtime (mulberry32 PRNG + JSON-Schema value generator).',\n '// Dependency-free: no @faker-js/faker. Deterministic for a given SEED.',\n '// ---------------------------------------------------------------------------',\n MOCK_GEN_RUNTIME,\n '',\n '// Shared component schemas referenced by $ref.',\n `const DEFS = ${JSON.stringify(defs, null, 2)};`,\n '',\n '/** MSW request handlers, one per contracted route. */',\n 'export const handlers = [',\n ...handlers,\n '];',\n '',\n ];\n\n return lines.join('\\n');\n}\n\n/** Emit `mocks.ts` into `outDir`. */\nexport async function emitMocks(\n routes: RouteDescriptor[],\n outDir: string,\n opts: MocksEmitOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const content = buildMocksFile(routes, opts);\n const fileName = opts.fileName ?? 'mocks.ts';\n await writeFile(join(outDir, fileName), content, 'utf8');\n}\n\n// Re-export the lowering so callers/tests can build richer response schemas when\n// response IR becomes available.\nexport { schemaModuleToJsonSchema, REF_PREFIX };\n","/**\n * Converts the neutral {@link SchemaNode} / {@link SchemaModule} IR into a\n * JSON Schema object compatible with the OpenAPI 3.1 schema dialect (which *is*\n * JSON Schema 2020-12). This is the shared lowering used by both the OpenAPI 3.1\n * exporter (`emit/emit-openapi.ts`) and the MSW+faker mock generator\n * (`emit/emit-msw.ts`) — they consume the same JSON Schema so the spec and the\n * mocks can never disagree about a route's shape.\n *\n * Design notes:\n * - `enum` literals and `literal.raw` are verbatim TS source texts (quote style\n * preserved, produced by ts-morph `getText()`), e.g. `'active'`, `42`, `true`,\n * `null`. They are parsed back into real JSON values by {@link parseLiteral}.\n * - Named schemas (the `named` map of a `SchemaModule`) are lowered into\n * `components/schemas` and referenced via `$ref`, so recursion (`lazyRef`) and\n * sharing produce real `$ref` cycles rather than infinite inlining.\n * - `optional` only affects an *object field's* membership in `required`; a bare\n * optional widens the type with `null` (the closest JSON Schema analog).\n */\nimport type { SchemaModule, SchemaNode } from './schema-node.js';\n\n/** A minimal JSON Schema object (OpenAPI 3.1 dialect). Open-ended on purpose. */\nexport type JsonSchema = {\n type?: string | string[];\n format?: string;\n enum?: unknown[];\n const?: unknown;\n items?: JsonSchema;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n additionalProperties?: boolean | JsonSchema;\n oneOf?: JsonSchema[];\n anyOf?: JsonSchema[];\n discriminator?: { propertyName: string };\n $ref?: string;\n description?: string;\n nullable?: boolean; // not used in 3.1 (kept off by default); 3.1 uses type arrays\n [key: string]: unknown;\n};\n\nexport interface JsonSchemaContext {\n /** Prefix for `$ref` targets. Default `'#/components/schemas/'`. */\n refPrefix: string;\n}\n\nconst DEFAULT_CTX: JsonSchemaContext = { refPrefix: '#/components/schemas/' };\n\n/**\n * Parse a verbatim TS literal source text into a real JSON value.\n * Handles single/double-quoted strings, numbers, booleans and null. Anything\n * unrecognized falls back to the trimmed string form.\n */\nexport function parseLiteral(raw: string): unknown {\n const t = raw.trim();\n if (t === 'true') return true;\n if (t === 'false') return false;\n if (t === 'null') return null;\n // Quoted string (single, double, or backtick without interpolation).\n const q = t[0];\n if ((q === \"'\" || q === '\"' || q === '`') && t[t.length - 1] === q) {\n return t\n .slice(1, -1)\n .replace(/\\\\'/g, \"'\")\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\`/g, '`')\n .replace(/\\\\\\\\/g, '\\\\');\n }\n // Numeric literal.\n if (/^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(t)) {\n return Number(t);\n }\n return t;\n}\n\n/** Pick the narrowest JSON Schema `type` for a set of parsed literals. */\nfunction literalsType(values: unknown[]): string | undefined {\n const types = new Set(values.map((v) => (v === null ? 'null' : typeof v)));\n if (types.size === 1) {\n const only = [...types][0];\n if (only === 'string') return 'string';\n if (only === 'number') return 'number';\n if (only === 'boolean') return 'boolean';\n }\n return undefined;\n}\n\nfunction convert(node: SchemaNode, ctx: JsonSchemaContext): JsonSchema {\n switch (node.kind) {\n case 'string': {\n const out: JsonSchema = { type: 'string' };\n for (const c of node.checks) {\n if (c.check === 'email') out.format = 'email';\n else if (c.check === 'url') out.format = 'uri';\n else if (c.check === 'uuid') out.format = 'uuid';\n else if (c.check === 'min') out.minLength = Number(c.value);\n else if (c.check === 'max') out.maxLength = Number(c.value);\n else if (c.check === 'regex') {\n // Strip leading/trailing slashes and trailing flags from a regex literal.\n const m = /^\\/(.*)\\/[a-z]*$/.exec(c.pattern);\n out.pattern = m ? m[1] : c.pattern;\n }\n }\n return out;\n }\n case 'number': {\n const out: JsonSchema = { type: 'number' };\n for (const c of node.checks) {\n if (c.check === 'int') out.type = 'integer';\n else if (c.check === 'min') out.minimum = Number(c.value);\n else if (c.check === 'max') out.maximum = Number(c.value);\n else if (c.check === 'positive') out.exclusiveMinimum = 0;\n else if (c.check === 'negative') out.exclusiveMaximum = 0;\n }\n return out;\n }\n case 'boolean':\n return { type: 'boolean' };\n case 'date':\n // JSON has no date type; OpenAPI represents it as a date-time string.\n return { type: 'string', format: 'date-time' };\n case 'unknown':\n return node.note ? { description: node.note } : {};\n case 'instanceof':\n return { type: 'object', description: `instanceof ${node.ctor}` };\n case 'enum': {\n const values = node.literals.map(parseLiteral);\n const t = literalsType(values);\n const out: JsonSchema = { enum: values };\n if (t) out.type = t;\n return out;\n }\n case 'literal': {\n const value = parseLiteral(node.raw);\n const out: JsonSchema = { const: value };\n const t = literalsType([value]);\n if (t) out.type = t;\n return out;\n }\n case 'union': {\n const options = node.options.map((o) => convert(o, ctx));\n const out: JsonSchema = { oneOf: options };\n if (node.discriminator) {\n out.discriminator = { propertyName: node.discriminator };\n }\n return out;\n }\n case 'object': {\n const properties: Record<string, JsonSchema> = {};\n const required: string[] = [];\n for (const f of node.fields) {\n if (f.value.kind === 'optional') {\n properties[f.key] = convert(f.value.inner, ctx);\n } else {\n properties[f.key] = convert(f.value, ctx);\n required.push(f.key);\n }\n }\n const out: JsonSchema = { type: 'object', properties };\n if (required.length > 0) out.required = required;\n out.additionalProperties = node.passthrough;\n return out;\n }\n case 'array':\n return { type: 'array', items: convert(node.element, ctx) };\n case 'optional':\n // A bare optional (not on an object key) — widen with null.\n return widenNullable(convert(node.inner, ctx));\n case 'ref':\n case 'lazyRef':\n return { $ref: `${ctx.refPrefix}${node.name}` };\n case 'annotated':\n return convert(node.inner, ctx);\n }\n}\n\n/** Add `null` to a schema's type (OpenAPI 3.1 style: a type-array). */\nfunction widenNullable(schema: JsonSchema): JsonSchema {\n if (schema.$ref) {\n // Can't add null to a bare $ref in 3.1 without anyOf — wrap it.\n return { anyOf: [schema, { type: 'null' }] };\n }\n if (typeof schema.type === 'string') {\n return { ...schema, type: [schema.type, 'null'] };\n }\n if (Array.isArray(schema.type)) {\n return schema.type.includes('null') ? schema : { ...schema, type: [...schema.type, 'null'] };\n }\n return { anyOf: [schema, { type: 'null' }] };\n}\n\n/** Convert a single {@link SchemaNode} to a JSON Schema object. */\nexport function schemaNodeToJsonSchema(\n node: SchemaNode,\n ctx: JsonSchemaContext = DEFAULT_CTX,\n): JsonSchema {\n return convert(node, ctx);\n}\n\n/**\n * Lower an entire {@link SchemaModule} to a `{ root, named }` pair of JSON\n * Schemas. The `named` map becomes `components/schemas` entries; `root` is the\n * route-level schema that references them via `$ref`.\n */\nexport function schemaModuleToJsonSchema(\n mod: SchemaModule,\n ctx: JsonSchemaContext = DEFAULT_CTX,\n): { root: JsonSchema; named: Record<string, JsonSchema> } {\n const named: Record<string, JsonSchema> = {};\n for (const [name, node] of mod.named) {\n named[name] = convert(node, ctx);\n }\n return { root: convert(mod.root, ctx), named };\n}\n","/**\n * The dependency-free mock-data generator runtime, as an embeddable source-text\n * constant.\n *\n * This is the SINGLE SOURCE OF TRUTH for the generator: the emitter inlines this\n * exact text into the generated `mocks.ts` (so the output is self-contained, with\n * no runtime dependency on this package), and `mock-gen.ts` evaluates this same\n * text to expose typed `makeRng`/`generateMock` to the unit tests. One string,\n * two consumers — the tested behavior and the emitted behavior can never drift.\n *\n * Why a string (vs a normal module read at runtime): the package is bundled by\n * tsup into a single `dist/index.js` and only `dist` is published, so reading a\n * sibling `.ts` source at runtime would fail once installed. A string constant is\n * bundled with the code and works everywhere.\n *\n * Design choice (vs Orval): Orval shells out to `@faker-js/faker`; we ship a tiny\n * `mulberry32`-seeded generator so there is NO faker dependency and output is\n * fully deterministic for a given seed (the tests rely on this). The generator\n * consumes the same JSON Schema that drives the OpenAPI export, so spec and mocks\n * can never disagree about a route's shape.\n */\nexport const MOCK_GEN_RUNTIME = `\n/** mulberry32 — a tiny, fast, seedable PRNG. \\`next()\\` returns a float in [0, 1). */\nfunction makeRng(seed) {\n let a = seed >>> 0;\n return {\n next() {\n a |= 0;\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n },\n };\n}\n\nfunction __pick(rng, items) {\n return items[Math.floor(rng.next() * items.length)];\n}\n\nfunction __intBetween(rng, min, max) {\n return Math.floor(rng.next() * (max - min + 1)) + min;\n}\n\nconst __WORDS = ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', 'sed', 'tempor'];\nconst __FIRST_NAMES = ['Ada', 'Alan', 'Grace', 'Linus', 'Margaret', 'Dennis'];\nconst __LAST_NAMES = ['Lovelace', 'Turing', 'Hopper', 'Torvalds', 'Hamilton', 'Ritchie'];\n\nfunction __fakeWords(rng, count) {\n let out = [];\n for (let i = 0; i < count; i++) out.push(__pick(rng, __WORDS));\n return out.join(' ');\n}\n\nfunction __hex(rng, len) {\n let s = '';\n for (let i = 0; i < len; i++) s += Math.floor(rng.next() * 16).toString(16);\n return s;\n}\n\nfunction __fakeUuid(rng) {\n return __hex(rng, 8) + '-' + __hex(rng, 4) + '-4' + __hex(rng, 3) + '-' + __pick(rng, ['8', '9', 'a', 'b']) + __hex(rng, 3) + '-' + __hex(rng, 12);\n}\n\nfunction __fakeString(rng, schema) {\n switch (schema.format) {\n case 'email':\n return __pick(rng, __FIRST_NAMES).toLowerCase() + '.' + __pick(rng, __LAST_NAMES).toLowerCase() + '@example.com';\n case 'uri':\n case 'url':\n return 'https://example.com/' + __pick(rng, __WORDS);\n case 'uuid':\n return __fakeUuid(rng);\n case 'date-time':\n return new Date(Date.UTC(2020, __intBetween(rng, 0, 11), __intBetween(rng, 1, 28))).toISOString();\n default:\n return __fakeWords(rng, __intBetween(rng, 1, 3));\n }\n}\n\n/** Generate a mock value for a JSON Schema node (depth-capped recursion via $ref). */\nfunction generateMock(schema, rng, defs, depth) {\n defs = defs || {};\n depth = depth || 0;\n if (schema.$ref) {\n const name = schema.$ref.replace('#/components/schemas/', '');\n const target = defs[name];\n if (!target || depth > 4) return null;\n return generateMock(target, rng, defs, depth + 1);\n }\n if ('const' in schema) return schema.const;\n if (schema.enum && schema.enum.length > 0) return __pick(rng, schema.enum);\n if (schema.oneOf && schema.oneOf.length > 0) return generateMock(__pick(rng, schema.oneOf), rng, defs, depth);\n if (schema.anyOf && schema.anyOf.length > 0) return generateMock(__pick(rng, schema.anyOf), rng, defs, depth);\n let type = Array.isArray(schema.type)\n ? (schema.type.filter((t) => t !== 'null')[0] || 'null')\n : schema.type;\n switch (type) {\n case 'string':\n return __fakeString(rng, schema);\n case 'integer':\n return __intBetween(rng, typeof schema.minimum === 'number' ? schema.minimum : 0, typeof schema.maximum === 'number' ? schema.maximum : 1000);\n case 'number':\n return __intBetween(rng, typeof schema.minimum === 'number' ? schema.minimum : 0, typeof schema.maximum === 'number' ? schema.maximum : 1000) + Math.round(rng.next() * 100) / 100;\n case 'boolean':\n return rng.next() < 0.5;\n case 'null':\n return null;\n case 'array': {\n const count = depth > 2 ? 0 : __intBetween(rng, 1, 2);\n const items = schema.items || {};\n let arr = [];\n for (let i = 0; i < count; i++) arr.push(generateMock(items, rng, defs, depth + 1));\n return arr;\n }\n case 'object': {\n const out = {};\n const props = schema.properties || {};\n for (const key of Object.keys(props)) out[key] = generateMock(props[key], rng, defs, depth + 1);\n return out;\n }\n default:\n return {};\n }\n}\n`.trim();\n","/**\n * OpenAPI 3.1 exporter. Lowers the discovered {@link RouteDescriptor} set + the\n * neutral validation IR (`SchemaModule`) into a valid `openapi.json` (OpenAPI\n * 3.1, whose schema dialect *is* JSON Schema 2020-12).\n *\n * Why 3.1 (vs 3.0): 3.1 aligns its schema object with JSON Schema 2020-12, so\n * our IR lowering ({@link schemaModuleToJsonSchema}) maps cleanly — `type` arrays\n * for nullability, `const`, `$ref` recursion, and `oneOf` + `discriminator` for\n * discriminated unions all work without the 3.0 `nullable`/`x-` workarounds. This\n * mirrors what openapi-typescript / Hey API consume and what Orval/Kubb publish.\n *\n * Coverage:\n * - paths: one entry per route, NestJS `:param` → OpenAPI `{param}`, method,\n * path/query parameters, request body (non-GET), and responses.\n * - responses: the success response, plus the typed error response now carried\n * in the IR (`error`/`errorRef`) emitted under a 4xx code (`default` is also\n * populated so any error status resolves).\n * - streaming routes (`stream: true`): success response content type is\n * `text/event-stream`.\n * - components/schemas: every named schema reachable from a route's body/query\n * IR (`SchemaModule.named`) — including discriminated unions, arrays, enums and\n * recursion via `$ref`. TS-type-only positions (no IR) degrade to a permissive\n * schema annotated with the original TS type string, so the spec stays valid.\n *\n * The exporter never boots Nest; it reads only the static IR + descriptors.\n */\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ContractSource, RouteDescriptor } from '../discovery/types.js';\nimport { type JsonSchema, schemaModuleToJsonSchema } from '../ir/schema-node-to-json-schema.js';\nimport type { SchemaModule } from '../ir/schema-node.js';\n\nexport interface OpenApiInfo {\n title?: string;\n version?: string;\n description?: string;\n}\n\nexport interface OpenApiEmitOptions {\n info?: OpenApiInfo;\n /** Output file name within `outDir`. Default `'openapi.json'`. */\n fileName?: string;\n}\n\nexport interface OpenApiDocument {\n openapi: '3.1.0';\n info: { title: string; version: string; description?: string };\n paths: Record<string, Record<string, unknown>>;\n components: { schemas: Record<string, JsonSchema> };\n}\n\nconst REF_PREFIX = '#/components/schemas/';\n\n/** NestJS path `/users/:id` → OpenAPI path `/users/{id}`. */\nfunction toOpenApiPath(path: string): string {\n return path.replace(/:([^/]+)/g, '{$1}');\n}\n\n/**\n * Lower a route position (body/query/response/error) to a JSON Schema, hoisting\n * any named IR schemas into the shared `components` map. Falls back to a\n * permissive schema annotated with the TS type string when no IR is available.\n */\nfunction positionSchema(\n schema: SchemaModule | null | undefined,\n tsType: string | null | undefined,\n components: Record<string, JsonSchema>,\n): JsonSchema {\n if (schema) {\n const { root, named } = schemaModuleToJsonSchema(schema, { refPrefix: REF_PREFIX });\n for (const [name, node] of Object.entries(named)) {\n // First writer wins; later identical names are assumed structurally equal\n // (they reference the same DTO class across routes).\n if (!(name in components)) components[name] = node;\n }\n return root;\n }\n // No rich IR — emit a permissive schema carrying the TS type as documentation.\n return tsType ? { description: tsType } : {};\n}\n\nfunction buildParameters(route: RouteDescriptor): unknown[] {\n const params: unknown[] = [];\n for (const p of route.params) {\n if (p.source === 'path') {\n params.push({\n name: p.name,\n in: 'path',\n required: true,\n schema: { type: 'string' },\n });\n } else if (p.source === 'query') {\n params.push({\n name: p.name,\n in: 'query',\n required: false,\n schema: { type: 'string' },\n });\n } else if (p.source === 'header') {\n params.push({\n name: p.name,\n in: 'header',\n required: false,\n schema: { type: 'string' },\n });\n }\n }\n return params;\n}\n\nfunction buildResponses(\n cs: ContractSource,\n components: Record<string, JsonSchema>,\n): Record<string, unknown> {\n const responses: Record<string, unknown> = {};\n\n const successSchema = positionSchema(\n // Prefer rich response IR when present; otherwise fall back to the TS type.\n cs.responseSchema ?? null,\n cs.response,\n components,\n );\n const successContentType = cs.stream ? 'text/event-stream' : 'application/json';\n responses['200'] = {\n description: cs.stream ? 'Server-sent event stream' : 'Successful response',\n content: { [successContentType]: { schema: successSchema } },\n };\n\n // Typed error response now carried in the IR. We don't know the exact status\n // code statically, so publish it under `default` (and a representative 4xx).\n const errorSchema = positionSchema(null, cs.error ?? null, components);\n const errorBody = {\n description: 'Error response',\n content: { 'application/json': { schema: errorSchema } },\n };\n if (cs.error || cs.errorRef) {\n responses['400'] = errorBody;\n responses.default = errorBody;\n } else {\n responses.default = {\n description: 'Error response',\n content: { 'application/json': { schema: {} } },\n };\n }\n\n return responses;\n}\n\nfunction buildOperation(\n route: RouteDescriptor,\n components: Record<string, JsonSchema>,\n): Record<string, unknown> {\n const cs = route.contract!.contractSource;\n const op: Record<string, unknown> = {\n operationId: route.name,\n parameters: buildParameters(route),\n responses: buildResponses(cs, components),\n };\n\n const method = route.method.toUpperCase();\n const hasBody = method !== 'GET' && method !== 'HEAD' && method !== 'DELETE';\n if (hasBody && (cs.bodySchema || cs.body)) {\n const bodySchema = positionSchema(cs.bodySchema, cs.body, components);\n op.requestBody = {\n required: true,\n content: { 'application/json': { schema: bodySchema } },\n };\n }\n\n return op;\n}\n\n/** Build the OpenAPI 3.1 document object from the route set. Pure (no I/O). */\nexport function buildOpenApiSpec(\n routes: RouteDescriptor[],\n opts: OpenApiEmitOptions = {},\n): OpenApiDocument {\n const components: Record<string, JsonSchema> = {};\n const paths: Record<string, Record<string, unknown>> = {};\n\n for (const route of routes) {\n if (!route.contract) continue;\n const oaPath = toOpenApiPath(route.path);\n const method = route.method.toLowerCase();\n let pathItem = paths[oaPath];\n if (!pathItem) {\n pathItem = {};\n paths[oaPath] = pathItem;\n }\n pathItem[method] = buildOperation(route, components);\n }\n\n const info = opts.info ?? {};\n const doc: OpenApiDocument = {\n openapi: '3.1.0',\n info: {\n title: info.title ?? 'NestJS API',\n version: info.version ?? '1.0.0',\n ...(info.description ? { description: info.description } : {}),\n },\n paths,\n components: { schemas: components },\n };\n return doc;\n}\n\n/** Emit `openapi.json` into `outDir` for all contracted routes. */\nexport async function emitOpenApi(\n routes: RouteDescriptor[],\n outDir: string,\n opts: OpenApiEmitOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const doc = buildOpenApiSpec(routes, opts);\n const fileName = opts.fileName ?? 'openapi.json';\n await writeFile(join(outDir, fileName), `${JSON.stringify(doc, null, 2)}\\n`, '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 { 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"],"mappings":"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","names":["import_promises","import_node_path","import_node_path","import_ts_morph","import_ts_morph","import_ts_morph","import_node_path","reExportsName","sourceName","reExport","import_ts_morph","import_ts_morph","import_ts_morph","fg","firstArg","import_promises","import_node_path","import_promises","import_node_path","import_fast_glob","fg","import_node_path","import_ts_morph","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","REF_PREFIX","import_promises","import_node_path","import_promises","import_node_path","import_promises","import_node_path","chokidar"]}
|
|
1
|
+
{"version":3,"sources":["../../src/nest/index.ts","../../src/nest/module.ts","../../src/config/load-config.ts","../../src/exceptions.ts","../../src/adapters/registry.ts","../../src/watch/watcher.ts","../../src/discovery/contracts-fast.ts","../../src/discovery/dto-type-resolver.ts","../../src/discovery/dto-to-ir.ts","../../src/util/debug-log.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/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-mocks.ts","../../src/ir/schema-node-to-json-schema.ts","../../src/emit/mock-gen-runtime.ts","../../src/emit/emit-openapi.ts","../../src/emit/emit-pages.ts","../../src/emit/emit-routes.ts","../../src/generate-manifest.ts","../../src/watch/lock-file.ts","../../src/index.ts"],"sourcesContent":["export {\n CODEGEN_MODULE_OPTIONS,\n NestjsCodegenModule,\n NestjsCodegenService,\n shouldRun,\n} from './module.js';\nexport type { CodegenModuleOptions } from './module.js';\n","import type { DynamicModule, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';\nimport { Inject, Injectable, Logger, Module } from '@nestjs/common';\nimport { resolveConfig } from '../config/load-config.js';\nimport type { UserConfig } from '../config/types.js';\nimport type { Watcher } from '../watch/watcher.js';\nimport { watch } from '../watch/watcher.js';\n\n/**\n * Options for {@link NestjsCodegenModule.forRoot}. These ARE the codegen config —\n * no `nestjs-codegen.config.ts` file is required. Import the module in your root\n * `AppModule` and the typed client regenerates as you edit your controllers:\n *\n * @example\n * ```ts\n * import { NestjsCodegenModule } from '@dudousxd/nestjs-codegen/nest';\n *\n * @Module({\n * imports: [\n * NestjsCodegenModule.forRoot({\n * contracts: { glob: 'src/**\\/*.controller.ts' },\n * codegen: { outDir: 'src/generated' },\n * extensions: [tanstackQuery()],\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\nexport interface CodegenModuleOptions extends Omit<UserConfig, 'validation'> {\n /**\n * Validation adapter for emitted `forms.ts` schemas. Required at runtime to emit\n * forms — pass `zodAdapter` from `@dudousxd/nestjs-codegen-zod` (or the valibot/\n * arktype adapter). Typed optional only so `forRoot()` stays terse; if omitted,\n * the watcher logs and skips rather than crashing app boot.\n */\n validation?: UserConfig['validation'];\n /**\n * Master switch for the boot-time watcher. When omitted, the watcher runs in every\n * environment EXCEPT production — codegen is a dev/CI build step, not a\n * production-runtime concern. Set `false` to disable entirely, or `true` to force it\n * on even in production (overrides {@link runInProduction}).\n */\n enabled?: boolean;\n /**\n * Run the boot-time watcher even when `NODE_ENV` is `production`. Codegen is a\n * dev-time concern — in production the artifacts are already built by the CLI in the\n * build pipeline — so this defaults to `false` (skip in production). Set `true` only\n * if you genuinely need to regenerate at production runtime. Ignored when `enabled`\n * is set explicitly.\n *\n * @default false\n */\n runInProduction?: boolean;\n /** Project root used to resolve globs / `outDir`. Defaults to `process.cwd()`. */\n cwd?: string;\n}\n\n/** DI token holding the raw {@link CodegenModuleOptions} passed to `forRoot`. */\nexport const CODEGEN_MODULE_OPTIONS = Symbol('NESTJS_CODEGEN_MODULE_OPTIONS');\n\n/** True when `NODE_ENV` (trimmed, lowercased) is exactly `production`. */\nexport function isProductionEnv(env: string | undefined): boolean {\n return (env ?? '').trim().toLowerCase() === 'production';\n}\n\n/**\n * Decide whether the boot-time watcher should start, given the module options and the\n * current `NODE_ENV`. Explicit `enabled` always wins; otherwise default on everywhere\n * except production, where it stays off unless `runInProduction` is set.\n */\nexport function shouldRun(options: CodegenModuleOptions, env: string | undefined): boolean {\n if (options.enabled !== undefined) return options.enabled;\n if (isProductionEnv(env)) return options.runInProduction === true;\n return true;\n}\n\n/**\n * Boots the codegen watcher on application start and tears it down on shutdown.\n * The watcher does an initial full generate, then regenerates `routes.ts`/`api.ts`/\n * `forms.ts` as controllers and DTOs change — mirroring `nestjs-codegen codegen --watch`,\n * but driven by the Nest lifecycle so no separate process is needed in dev.\n */\n@Injectable()\nexport class NestjsCodegenService implements OnApplicationBootstrap, OnModuleDestroy {\n private readonly logger = new Logger('NestjsCodegen');\n private watcher: Watcher | null = null;\n\n constructor(@Inject(CODEGEN_MODULE_OPTIONS) private readonly options: CodegenModuleOptions) {}\n\n async onApplicationBootstrap(): Promise<void> {\n if (!shouldRun(this.options, process.env.NODE_ENV)) {\n if (this.options.enabled === undefined && isProductionEnv(process.env.NODE_ENV)) {\n this.logger.log('Skipped in production (set runInProduction: true to override).');\n }\n return;\n }\n\n const {\n enabled: _enabled,\n runInProduction: _runInProduction,\n cwd,\n ...userConfig\n } = this.options;\n try {\n const config = resolveConfig(userConfig, cwd ?? process.cwd());\n // Fire-and-forget the initial generate so codegen never blocks time-to-ready;\n // the watcher (and its lock) are still set up synchronously.\n this.watcher = await watch(config, undefined, { deferInitialGenerate: true });\n this.logger.log(`Watching ${config.contracts.glob} → ${config.codegen.outDir}`);\n } catch (err) {\n // Never crash app boot because codegen failed to start — log and move on.\n this.logger.warn(\n `Codegen watcher failed to start: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n async onModuleDestroy(): Promise<void> {\n await this.watcher?.close();\n this.watcher = null;\n }\n}\n\n/**\n * NestJS module that auto-starts the codegen watcher on app boot — the recommended way\n * to wire `@dudousxd/nestjs-codegen` into a Nest app. For CI/pre-deploy, run the\n * one-shot CLI (`nestjs-codegen codegen`) instead.\n */\n@Module({})\nexport class NestjsCodegenModule {\n static forRoot(options: CodegenModuleOptions = {}): DynamicModule {\n return {\n module: NestjsCodegenModule,\n providers: [{ provide: CODEGEN_MODULE_OPTIONS, useValue: options }, NestjsCodegenService],\n };\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 const fileUrl = pathToFileURL(filePath).href;\n\n // Native-first: modern Node (>=22.18 / 23.6 / 24 / 25) strips TypeScript types\n // natively, so a plain dynamic import loads a `.ts` config with zero deps. This is\n // also the only path that works on Node 25, where tsx 4.22.4's resolver appends a\n // `?namespace=<ts>` query that Node 25's stricter finalizeResolution rejects with\n // ERR_MODULE_NOT_FOUND. We fall back to tsx only when native import fails (older\n // Node without type stripping, or configs using syntax that needs transformation\n // like enums/namespaces).\n try {\n return await import(fileUrl);\n } catch (nativeError) {\n // Native import failed — try the tsx ESM API as a fallback transformer.\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 // Both native import and tsx are unusable. Surface the actionable\n // \"install tsx\" guidance (the established behavior), chaining the native\n // error so the underlying load failure isn't lost.\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 { cause: nativeError },\n );\n }\n\n const parentURL = pathToFileURL(`${filePath}__parent__`).href;\n return tsImport(fileUrl, { parentURL });\n }\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 debug: userConfig.debug ?? false,\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 serialization: userConfig.serialization ?? 'json',\n forms: {\n enabled: userConfig.forms?.enabled ?? true,\n watch: userConfig.forms?.watch ?? 'src/**/*.dto.ts',\n zodImport: userConfig.forms?.zodImport ?? 'zod',\n },\n openapi: {\n enabled: userConfig.openapi?.enabled ?? false,\n fileName: userConfig.openapi?.fileName ?? 'openapi.json',\n title: userConfig.openapi?.title ?? 'NestJS API',\n version: userConfig.openapi?.version ?? '1.0.0',\n description: userConfig.openapi?.description ?? null,\n },\n mocks: {\n enabled: userConfig.mocks?.enabled ?? false,\n fileName: userConfig.mocks?.fileName ?? 'mocks.ts',\n seed: userConfig.mocks?.seed ?? 1,\n baseUrl: userConfig.mocks?.baseUrl ?? '',\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/**\n * A validation adapter instance. No adapter is bundled in core — import one from\n * its own package (`zodAdapter`/`valibotAdapter`/`arktypeAdapter`) or pass a custom\n * object. String shortcuts (`'zod'` etc.) are intentionally not part of this type:\n * they always threw at runtime, so the type guides you to an imported instance.\n */\nexport type ValidationOption = 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 * The parameter also accepts a `string` so the runtime guard still fires for JS\n * callers / untyped configs that pass a removed string shortcut (e.g. `'zod'`):\n * those throw a helpful error pointing at the adapter package. TypeScript users\n * are steered away from strings by the narrowed {@link ValidationOption} type.\n *\n * @example\n * import { zodAdapter } from '@dudousxd/nestjs-codegen-zod';\n * defineConfig({ validation: zodAdapter });\n */\nexport function resolveAdapter(option: ValidationOption | string): 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 { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport chokidar from 'chokidar';\nimport type { ResolvedConfig } from '../config/types.js';\nimport { PersistentDiscovery } 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\nexport interface WatchOptions {\n /**\n * Run the initial discover + generate as fire-and-forget instead of awaiting it\n * before returning. The lock is still acquired and the chokidar watchers are\n * still set up synchronously; only the initial generate is backgrounded. Used by\n * the Nest `onApplicationBootstrap` hook so codegen never blocks time-to-ready.\n * The one-shot CLI leaves this `false` so the build step stays synchronous.\n *\n * @default false\n */\n deferInitialGenerate?: boolean;\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(\n config: ResolvedConfig,\n onChange?: () => void,\n options: WatchOptions = {},\n): 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 // Persistent ts-morph Project reused across every contract/DTO change. Built\n // once here; each change refreshes only the changed file(s) instead of\n // reconstructing the Project and re-parsing all controllers + DTOs. Lazily\n // (re)initialised so an initial-pass failure doesn't permanently disable it.\n let discovery: PersistentDiscovery | null = null;\n // Last successfully-discovered routes, reused by the pages watcher. The pages\n // fast path has no route discovery of its own; without this it would call\n // generate() with an empty route list, and any route-injecting extension (e.g.\n // notifications) would still emit — overwriting api.ts with an extension-only\n // stub and dropping every contract-derived route. Kept in sync with the initial\n // pass and every contracts rediscovery.\n //\n // Bounded-staleness tradeoff: if a page edit races a concurrent controller edit,\n // api.ts is stale by at most config.contracts.debounceMs until the contracts\n // watcher fires and overwrites — acceptable and self-correcting.\n let lastRoutes: RouteDescriptor[] = [];\n async function getDiscovery(): Promise<PersistentDiscovery> {\n if (discovery === null) {\n discovery = await PersistentDiscovery.create({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n return discovery;\n }\n return discovery;\n }\n\n // Initial full pass: pages + routes + contracts (same as a one-shot `codegen` run).\n async function runInitialPass(): Promise<void> {\n try {\n const initialRoutes = (await getDiscovery()).discover();\n lastRoutes = initialRoutes;\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, lastRoutes);\n } catch {\n /* fallback: pages only */\n }\n }\n }\n\n if (options.deferInitialGenerate) {\n // Fire-and-forget: return immediately so the caller (Nest boot) isn't blocked\n // on codegen. runInitialPass swallows its own errors, but guard the promise\n // too so a rejection can never surface as an unhandled rejection.\n void runInitialPass().catch((err: unknown) => {\n console.warn(\n `[nestjs-codegen] Background initial generate failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n } else {\n await runInitialPass();\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 // Reuse the last-known routes so a pages-only regen never drops the\n // contract-derived api.ts (see lastRoutes declaration).\n await generate(config, lastRoutes);\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 // Absolute paths changed since the last rediscovery, accumulated across the\n // debounce window so a burst of edits refreshes every touched file exactly once.\n const pendingChangedPaths = new Set<string>();\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(changedPath?: string): void {\n if (typeof changedPath === 'string') pendingChangedPaths.add(changedPath);\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n }\n contractsDebounceTimer = setTimeout(async () => {\n contractsDebounceTimer = undefined;\n const changed = [...pendingChangedPaths];\n pendingChangedPaths.clear();\n try {\n // Reuse the persistent Project: refresh only the changed file(s), re-glob\n // for added/removed controllers, then re-extract. Avoids reconstructing\n // the Project and re-parsing every controller + DTO on each change.\n const routes: RouteDescriptor[] = await (await getDiscovery()).rediscover(changed);\n lastRoutes = routes;\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', (p) => scheduleContractsRegenerate(p));\n contractsWatcher.on('change', (p) => scheduleContractsRegenerate(p));\n contractsWatcher.on('unlink', (p) => scheduleContractsRegenerate(p));\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', (p) => scheduleContractsRegenerate(p));\n formsWatcher.on('change', (p) => scheduleContractsRegenerate(p));\n formsWatcher.on('unlink', (p) => scheduleContractsRegenerate(p));\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 { clearEnumCache } from './enum-resolution.js';\nimport {\n clearTypeResolutionCaches,\n loadTsconfigPaths,\n resolveImportedVariable,\n setDiscoveryContext,\n} 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 = resolveTsconfigPath(cwd, tsconfig);\n const project = createDiscoveryProject(tsconfigPath);\n\n // Resolve controller file paths and add them to the project.\n const files = await fg(glob, { cwd, absolute: true, onlyFiles: true });\n for (const f of files) {\n project.addSourceFileAtPath(f);\n }\n\n bindDiscoveryContext(project, cwd, tsconfigPath);\n return extractAllRoutes(project);\n}\n\n// ---------------------------------------------------------------------------\n// Persistent-Project building blocks (used by the watcher to reuse ONE Project\n// across file changes — see watch/watcher.ts). The cold one-shot path above\n// keeps building a fresh Project per call, so its per-Project resolution caches\n// auto-invalidate; the watcher must evict them explicitly on each change.\n// ---------------------------------------------------------------------------\n\n/** Resolve the tsconfig path the same way the cold path does. */\nexport function resolveTsconfigPath(cwd: string, tsconfig?: string): string {\n return tsconfig ? resolve(tsconfig) : join(cwd, 'tsconfig.json');\n}\n\n/**\n * Construct a ts-morph `Project` configured exactly as the cold discovery path:\n * use the tsconfig when present, else fall back to bare compiler options.\n */\nexport function createDiscoveryProject(tsconfigPath: string): Project {\n try {\n return 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 return 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\n/** Bind the per-Project discovery context (project root + tsconfig path aliases). */\nexport function bindDiscoveryContext(project: Project, cwd: string, tsconfigPath: string): void {\n setDiscoveryContext(project, {\n projectRoot: cwd,\n tsconfigPaths: loadTsconfigPaths(tsconfigPath),\n });\n}\n\n/**\n * Run route extraction over every CONTROLLER source file currently in the\n * project. Only files matching the controller glob are extraction roots; DTO and\n * other imported files are pulled into the Project lazily during resolution but\n * are not themselves extraction roots. The cold path's loop visits all source\n * files, but at that point the Project contains ONLY the globbed controllers\n * (DTOs are added mid-extraction), so iterating `controllerPaths` is equivalent\n * — and necessary for the persistent Project, whose `getSourceFiles()` also\n * holds accumulated DTOs that must not be treated as controllers.\n */\nexport function extractRoutesFrom(\n project: Project,\n controllerPaths: Iterable<string>,\n): RouteDescriptor[] {\n const routes: RouteDescriptor[] = [];\n for (const path of controllerPaths) {\n const sourceFile = project.getSourceFile(path);\n if (sourceFile) routes.push(...extractFromSourceFile(sourceFile, project));\n }\n return routes;\n}\n\n/**\n * Run route extraction over every source file currently in the project.\n * Byte-identical to the cold path's extraction loop — used by both.\n */\nexport function extractAllRoutes(project: Project): RouteDescriptor[] {\n const routes: RouteDescriptor[] = [];\n for (const sourceFile of project.getSourceFiles()) {\n routes.push(...extractFromSourceFile(sourceFile, project));\n }\n return routes;\n}\n\n/**\n * A persistent-Project discovery session for watch mode. Holds ONE ts-morph\n * `Project` for the watcher's lifetime, re-globbing the controller set and\n * re-parsing only the file(s) that changed on each rediscovery — avoiding the\n * dominant cost of rebuilding the Project and re-parsing every controller + DTO\n * from scratch on every debounced change.\n *\n * Correctness: the per-Project resolution memoization (`_findTypeCache`,\n * `_resolveNamedRefCache`, `_enumCache`) no longer auto-invalidates because the\n * Project is reused, so {@link rediscover} clears those caches on every pass.\n * Output is byte-identical to {@link discoverContractsFast}: same Project config,\n * same context binding, same extraction over the globbed controller set.\n */\nexport class PersistentDiscovery {\n private readonly project: Project;\n private readonly cwd: string;\n private readonly glob: string;\n /** Absolute paths of the controllers currently loaded as extraction roots. */\n private controllerPaths = new Set<string>();\n\n private constructor(project: Project, cwd: string, glob: string) {\n this.project = project;\n this.cwd = cwd;\n this.glob = glob;\n }\n\n /**\n * Build the initial persistent Project: create it, glob + add all controllers,\n * bind the discovery context. Mirrors {@link discoverContractsFast}'s setup.\n */\n static async create(opts: FastDiscoveryOptions): Promise<PersistentDiscovery> {\n const { cwd, glob, tsconfig } = opts;\n const tsconfigPath = resolveTsconfigPath(cwd, tsconfig);\n const project = createDiscoveryProject(tsconfigPath);\n bindDiscoveryContext(project, cwd, tsconfigPath);\n\n const instance = new PersistentDiscovery(project, cwd, glob);\n const files = await fg(glob, { cwd, absolute: true, onlyFiles: true });\n for (const f of files) {\n project.addSourceFileAtPath(f);\n instance.controllerPaths.add(f);\n }\n return instance;\n }\n\n /** Run the initial extraction (equivalent to a first `discoverContractsFast`). */\n discover(): RouteDescriptor[] {\n return this.runExtraction();\n }\n\n /**\n * Re-discover after one or more files changed. Refreshes the changed file(s)\n * from disk (controllers AND any lazily-loaded DTO/imported files), re-globs\n * to pick up added/removed controllers, clears the per-Project caches, then\n * re-extracts. `changedPaths` is a hint; correctness does not depend on it\n * being exhaustive because re-globbing + refresh-on-presence covers the set.\n */\n async rediscover(changedPaths?: Iterable<string>): Promise<RouteDescriptor[]> {\n // 1. Refresh explicitly-changed files that are already in the Project. This\n // re-parses ONLY those files (the expensive ts-morph parse) — DTOs that\n // didn't change keep their already-parsed AST.\n if (changedPaths) {\n for (const p of changedPaths) {\n const abs = resolve(p);\n const sf = this.project.getSourceFile(abs);\n if (sf) {\n await sf.refreshFromFileSystem();\n }\n }\n }\n\n // 2. Re-glob to reconcile the controller set: add new controllers, drop\n // removed ones. Re-glob is cheap relative to parsing.\n const globbed = new Set(\n await fg(this.glob, { cwd: this.cwd, absolute: true, onlyFiles: true }),\n );\n for (const f of globbed) {\n if (!this.controllerPaths.has(f)) {\n try {\n this.project.addSourceFileAtPath(f);\n this.controllerPaths.add(f);\n } catch {\n /* file vanished between glob and add — ignore */\n }\n }\n }\n for (const f of this.controllerPaths) {\n if (!globbed.has(f)) {\n const sf = this.project.getSourceFile(f);\n if (sf) this.project.removeSourceFile(sf);\n this.controllerPaths.delete(f);\n }\n }\n\n return this.runExtraction();\n }\n\n /** Clear stale per-Project caches, then extract over the controller set. */\n private runExtraction(): RouteDescriptor[] {\n clearTypeResolutionCaches(this.project);\n clearEnumCache(this.project);\n return extractRoutesFrom(this.project, this.controllerPaths);\n }\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 // `@Sse('path')` is a server-sent-events endpoint — a GET on the wire.\n const sseDecorator = method.getDecorator('Sse');\n if (sseDecorator) {\n const pathArg = sseDecorator.getArguments()[0];\n return { httpMethod: 'GET', handlerPath: decoratorStringArg(pathArg) ?? '' };\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 project: Project;\n seenNames: Map<string, string>;\n}): RouteDescriptor | null {\n const {\n cls,\n method,\n applyContractDecorator,\n verb,\n prefix,\n className,\n sourceFile,\n project,\n 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 // Resolve the const — locally OR by following imports / barrel re-exports to\n // its declaring file (ts-morph walks the import to the declaration).\n const resolvedVar = resolveImportedVariable(identName, sourceFile, project);\n if (!resolvedVar) {\n console.warn(\n `[nestjs-codegen/fast] Cannot resolve contract identifier '${identName}' applied in ${sourceFile.getFilePath()} — the import could not be followed to a declaration; skipping`,\n );\n return null;\n }\n\n const { decl: varDecl, file: declFile } = resolvedVar;\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. The ref points at the const's\n // DECLARING file (which may differ from the controller for a cross-file ref),\n // and uses the LOCAL alias the controller imported it under for re-export.\n if (contractDef && varDecl.isExported()) {\n const filePath = declFile.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 error: contractDef.error,\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 error: dtoContract?.error ?? null,\n queryRef: dtoContract?.queryRef ?? null,\n bodyRef: dtoContract?.bodyRef ?? null,\n responseRef: dtoContract?.responseRef ?? null,\n errorRef: dtoContract?.errorRef ?? 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 stream: dtoContract?.stream ?? false,\n multipart: dtoContract?.multipart ?? false,\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 project,\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 * `subst` maps generic type-parameter names to already-resolved type strings\n * (e.g. `{ T: '{ id: string }' }` while expanding `PaginatedDto<Item>`), so a\n * field typed `T`/`T[]` faithfully resolves instead of degrading to `unknown`.\n */\nfunction resolveTypeNodeToString(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n subst: Map<string, string> = new Map(),\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, subst)}>`;\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, subst))\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, subst))\n .join(' & ');\n }\n\n // Parenthesized: ( ... ) — unwrap\n if (Node.isParenthesizedTypeNode(typeNode)) {\n return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;\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 // A generic type-parameter binding in scope (e.g. `T` while expanding\n // `PaginatedDto<Item>`) → its concrete resolved type string.\n const bound = subst.get(name);\n if (bound !== undefined) return bound;\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, subst);\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 // Generic class/interface instantiation: bind its type parameters to the\n // supplied args (resolved in the CURRENT scope/subst) before expanding.\n const childSubst = buildSubst(resolved, typeNode, sourceFile, project, depth, subst);\n return expandTypeDecl(resolved, project, depth - 1, childSubst);\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 subst: Map<string, string> = new Map(),\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, subst);\n return mode === 'arrayOf' ? `Array<${inner}>` : inner;\n }\n return mode === 'arrayOf' ? 'Array<unknown>' : 'unknown';\n}\n\n/**\n * Build the type-parameter substitution map for a generic class/interface\n * instantiation: zip the declaration's type parameters (`<T, U>`) with the\n * reference's type arguments (`<Item, number>`), each resolved to a concrete\n * type string in the CURRENT scope. Returns an empty map for non-generic decls.\n */\nfunction buildSubst(\n result: TypeDeclResult,\n typeNode: import('ts-morph').TypeReferenceNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n parentSubst: Map<string, string>,\n): Map<string, string> {\n if (result.kind !== 'class' && result.kind !== 'interface') return new Map();\n const params = result.decl.getTypeParameters().map((p) => p.getName());\n if (params.length === 0) return new Map();\n const args = typeNode.getTypeArguments();\n const subst = new Map<string, string>();\n params.forEach((param, i) => {\n const arg = args[i];\n if (arg)\n subst.set(param, resolveTypeNodeToString(arg, sourceFile, project, depth, parentSubst));\n });\n return subst;\n}\n\n/**\n * Expand a TypeDeclResult into an inline TS type string.\n */\nfunction expandTypeDecl(\n result: TypeDeclResult,\n project: Project,\n depth: number,\n subst: Map<string, string> = new Map(),\n): string {\n if (depth < 0) return 'unknown';\n switch (result.kind) {\n case 'class':\n return resolvePropertied(result.decl, result.file, project, depth, subst);\n case 'interface':\n return resolvePropertied(result.decl, result.file, project, depth, subst);\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, subst);\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 subst: Map<string, string> = new Map(),\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, subst);\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 `@Query()`-decorated parameters.\n *\n * Two shapes are supported, in priority order:\n *\n * 1. Whole-object form — `@Query() dto: SomeQueryDto`. The parameter's declared\n * type is resolved and emitted as the entire `query` type. This is the\n * historical behavior and is preserved unchanged.\n *\n * 2. Named-param form — one or more `@Query('name')` decorators with a\n * string-literal name (e.g. `@Query('years') years?: number[]`). Each such\n * parameter contributes one property to a synthesized object type, keyed by\n * the string-literal name and typed by the parameter's annotation. This\n * mirrors {@link extractParamsType}'s handling of named `@Param('id')`.\n *\n * When BOTH shapes appear on the same handler (rare), the whole-object form\n * wins (it already describes the full query shape); the named params are\n * ignored to avoid emitting a conflicting partial type.\n *\n * Returns a TS type string or null when no usable `@Query` is present.\n */\nfunction extractQueryType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string | null {\n // 1. Whole-object form takes precedence.\n for (const param of method.getParameters()) {\n const queryDecorator = param.getDecorators().find((d) => d.getName() === 'Query');\n if (!queryDecorator) continue;\n if (queryDecorator.getArguments().length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n\n // 2. Named `@Query('name')` form — synthesize an object type, one property per\n // named query param. Mirrors extractParamsType's named-`@Param` handling.\n const entries: string[] = [];\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 const nameArg = queryArgs[0];\n if (!nameArg || !Node.isStringLiteral(nameArg)) continue;\n const queryName = nameArg.getLiteralValue();\n const typeNode = param.getTypeNode();\n // Pipes (ParseArrayPipe/ParseIntPipe/...) do not change the declared TS type,\n // so the annotation is read verbatim. A missing annotation falls back to\n // `string` (query-string values are always strings) — consistent with how\n // extractParamsType defaults a typeless `@Param`.\n const queryType = typeNode\n ? resolveTypeNodeToString(typeNode, sourceFile, project, 3)\n : 'string';\n entries.push(`${queryName}${isParamOptional(param) ? '?' : ''}: ${queryType}`);\n }\n return entries.length > 0 ? `{ ${entries.join('; ')} }` : null;\n}\n\n/**\n * Whether a handler parameter should be treated as an OPTIONAL query property.\n * True when the parameter has a `?` token, a default value, or a declared type\n * whose union includes `undefined` (e.g. `string | undefined`).\n */\nfunction isParamOptional(param: import('ts-morph').ParameterDeclaration): boolean {\n if (param.hasQuestionToken() || param.hasInitializer()) return true;\n const typeNode = param.getTypeNode();\n if (typeNode && Node.isUnionTypeNode(typeNode)) {\n return typeNode.getTypeNodes().some((t) => t.getKind() === SyntaxKind.UndefinedKeyword);\n }\n return false;\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 * Detect Multer file uploads on a handler and synthesize the browser-facing\n * file fields for the request body.\n *\n * The HTTP field name(s) live in the `@UseInterceptors(FileInterceptor('x'))`\n * call — the `@UploadedFile()` / `@UploadedFiles()` param decorators are usually\n * arg-less — so the interceptor argument is the authoritative source of field\n * names and arity. Server-side a file is `Express.Multer.File`, but the client\n * sends a browser `File | Blob`, so that is what we emit (never the Multer type).\n *\n * Returns the file-field entries (e.g. `file: File | Blob`) and whether the\n * route is multipart. `fields` is null for a multipart route whose field names\n * aren't statically known (e.g. `AnyFilesInterceptor`).\n */\nfunction extractUploadedFiles(method: MethodDeclaration): {\n fields: string | null;\n multipart: boolean;\n} {\n const FILE = 'File | Blob';\n const entries: string[] = [];\n let multipart = false;\n\n const hasUploadedFileParam = method.getParameters().some((p) =>\n p.getDecorators().some((d) => {\n const name = d.getName();\n return name === 'UploadedFile' || name === 'UploadedFiles';\n }),\n );\n\n for (const decorator of method.getDecorators()) {\n if (decorator.getName() !== 'UseInterceptors') continue;\n for (const arg of decorator.getArguments()) {\n if (!Node.isCallExpression(arg)) continue;\n const interceptor = arg.getExpression().getText();\n const callArgs = arg.getArguments();\n const firstArg = callArgs[0];\n\n if (interceptor === 'FileInterceptor') {\n if (firstArg && Node.isStringLiteral(firstArg)) {\n entries.push(`${firstArg.getLiteralValue()}: ${FILE}`);\n multipart = true;\n }\n } else if (interceptor === 'FilesInterceptor') {\n if (firstArg && Node.isStringLiteral(firstArg)) {\n entries.push(`${firstArg.getLiteralValue()}: Array<${FILE}>`);\n multipart = true;\n }\n } else if (interceptor === 'FileFieldsInterceptor') {\n if (firstArg && Node.isArrayLiteralExpression(firstArg)) {\n for (const el of firstArg.getElements()) {\n if (!Node.isObjectLiteralExpression(el)) continue;\n const nameProp = el.getProperty('name');\n if (nameProp && Node.isPropertyAssignment(nameProp)) {\n const init = nameProp.getInitializer();\n if (init && Node.isStringLiteral(init)) {\n // FileFieldsInterceptor delivers each named field as an array.\n entries.push(`${init.getLiteralValue()}: Array<${FILE}>`);\n }\n }\n }\n multipart = true;\n }\n } else if (interceptor === 'AnyFilesInterceptor') {\n multipart = true;\n }\n }\n }\n\n // A bare @UploadedFile()/@UploadedFiles() with no recognized interceptor still\n // marks the route multipart even though we can't name the field statically.\n if (hasUploadedFileParam) multipart = true;\n\n return { fields: entries.length > 0 ? entries.join('; ') : null, multipart };\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 — but skip error-status (4xx/5xx) ones; those describe\n // the error body, not the success response.\n const apiResponseDecorator = method\n .getDecorators()\n .find((d) => d.getName() === 'ApiResponse' && (apiResponseStatus(d) ?? 0) < 400);\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 * The numeric `status` of an `@ApiResponse({ status, type })` decorator, or null\n * when absent / non-numeric.\n */\nfunction apiResponseStatus(decorator: import('ts-morph').Decorator): number | null {\n const optsArg = decorator.getArguments()[0];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n if (prop.getName() !== 'status') continue;\n const val = prop.getInitializer();\n if (val && Node.isNumericLiteral(val)) return Number(val.getLiteralValue());\n }\n return null;\n}\n\n/**\n * Read the `type:` initializer of an `@ApiResponse({ type })` decorator as an\n * expression node, or null. Handles both `type: X` and `type: [X]`.\n */\nfunction apiResponseTypeNode(\n decorator: import('ts-morph').Decorator,\n): { node: Node; isArray: boolean } | null {\n const optsArg = decorator.getArguments()[0];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\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) return null;\n if (Node.isArrayLiteralExpression(val)) {\n const first = val.getElements()[0];\n return first ? { node: first, isArray: true } : null;\n }\n return { node: val, isArray: false };\n }\n return null;\n}\n\n/**\n * Discover the route's error response body type from an `@ApiResponse({ status,\n * type })` decorator whose `status` is a 4xx/5xx code. This is the least-magic\n * signal available statically: it reuses the Swagger decorator NestJS apps\n * already write to document error responses. Returns the expanded TS type string\n * (and an importable ref when the type is an exported named class/interface), or\n * null when no error-status @ApiResponse is present.\n */\nfunction extractErrorType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): { type: string; ref: TypeRef | null } | null {\n for (const decorator of method.getDecorators()) {\n if (decorator.getName() !== 'ApiResponse') continue;\n const status = apiResponseStatus(decorator);\n if (status === null || status < 400) continue;\n const typeInfo = apiResponseTypeNode(decorator);\n if (!typeInfo) continue;\n const inner = resolveIdentifierToClassType(typeInfo.node, sourceFile, project, 3);\n const type = typeInfo.isArray ? `Array<${inner}>` : inner;\n\n let ref: TypeRef | null = null;\n if (Node.isIdentifier(typeInfo.node)) {\n const name = typeInfo.node.getText();\n const localDecl =\n sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);\n if (localDecl?.isExported()) {\n ref = { name, filePath: sourceFile.getFilePath(), isArray: typeInfo.isArray };\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 ref = { name, filePath: resolved.file.getFilePath(), isArray: typeInfo.isArray };\n }\n }\n }\n return { type, ref };\n }\n return null;\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// SSE / streaming detection\n// ---------------------------------------------------------------------------\n\n/**\n * Container types whose first type argument is the streamed ELEMENT. NestJS SSE\n * handlers return `Observable<T>` (often `Observable<MessageEvent<T>>`); a plain\n * async-generator handler returns `AsyncIterable<T>` / `AsyncGenerator<T>`.\n */\nconst STREAM_CONTAINERS = new Set(['Observable', 'AsyncIterable', 'AsyncIterableIterator']);\n// AsyncGenerator<T, ...> — T is the FIRST arg (yield type), same position.\nconst STREAM_CONTAINERS_GENERATOR = new Set(['AsyncGenerator']);\n\n/** NestJS SSE event-envelope whose `.data` (first type arg) is the real payload. */\nconst STREAM_ENVELOPES = new Set(['MessageEvent', 'MessageEventLike']);\n\n/**\n * The streamed element type-node of an SSE/streaming handler, or null when the\n * route is not a stream. The signal (least-magic, fully static): a `@Sse()`\n * decorator, OR a return type that is `Observable<T>` / `AsyncIterable<T>` /\n * `AsyncGenerator<T>`. The element is unwrapped through any `Promise<>` and any\n * NestJS `MessageEvent<>` envelope so the carried type is the real payload `T`.\n */\nfunction detectStreamElement(method: MethodDeclaration): TypeNode | null {\n const hasSse = method.getDecorators().some((d) => d.getName() === 'Sse');\n let node = method.getReturnTypeNode();\n\n // Peel a leading Promise<> (e.g. an async generator method annotated as such).\n node = unwrapNamedContainer(node, new Set(['Promise']));\n\n const containerEl = streamContainerElement(node);\n if (containerEl) {\n return unwrapNamedContainer(containerEl, STREAM_ENVELOPES) ?? containerEl;\n }\n\n // `@Sse()` present but no recognizable container (or no return annotation):\n // still a stream, element type unknown.\n if (hasSse) return node ?? null;\n return null;\n}\n\n/** If `node` is one of the stream container types, return its element type-node. */\nfunction streamContainerElement(node: TypeNode | undefined): TypeNode | null {\n if (!node || !Node.isTypeReference(node)) return null;\n const typeName = node.getTypeName();\n const name = Node.isIdentifier(typeName) ? typeName.getText() : '';\n if (STREAM_CONTAINERS.has(name) || STREAM_CONTAINERS_GENERATOR.has(name)) {\n return node.getTypeArguments()[0] ?? null;\n }\n return null;\n}\n\n/** Unwrap `node` once if it is one of `names` (a single-arg generic), else return as-is. */\nfunction unwrapNamedContainer(\n node: TypeNode | undefined,\n names: Set<string>,\n): TypeNode | undefined {\n if (!node || !Node.isTypeReference(node)) return node;\n const typeName = node.getTypeName();\n const name = Node.isIdentifier(typeName) ? typeName.getText() : '';\n if (names.has(name)) {\n return node.getTypeArguments()[0] ?? node;\n }\n return node;\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 error?: string | null;\n params: string | null;\n queryRef?: TypeRef | null;\n bodyRef?: TypeRef | null;\n responseRef?: TypeRef | null;\n errorRef?: 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 stream?: boolean;\n multipart?: boolean;\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 // ── Multipart uploads: merge the uploaded-file field(s) into the body so the\n // client gets `@Body DTO & { file: File | Blob }` and can build a FormData. ──\n const uploads = extractUploadedFiles(method);\n if (uploads.fields) {\n const fileObject = `{ ${uploads.fields} }`;\n // Parenthesize the existing body so the intersection binds to the WHOLE\n // type even when it is a union (`(A | B) & { file }`, not `A | B & { file }`).\n body = body ? `(${body}) & ${fileObject}` : fileObject;\n }\n\n // ── SSE / streaming: the streamed element type replaces `response` ──────────\n const streamElement = detectStreamElement(method);\n const isStream = streamElement !== null;\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 // For a stream, the wire shape is the ELEMENT type `T` (the client surfaces an\n // `AsyncIterable<T>`); otherwise resolve the normal response type.\n const response = isStream\n ? resolveTypeNodeToString(streamElement, sourceFile, project, 3)\n : extractResponseType(method, sourceFile, project);\n const errorInfo = extractErrorType(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 errorInfo === null &&\n filterInfo === null &&\n !isStream &&\n !uploads.multipart\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 // For a stream the importable ref (if any) is the streamed element type — not\n // the Observable/AsyncIterable container.\n const returnTypeNode = isStream ? streamElement : method.getReturnTypeNode();\n if (returnTypeNode) {\n responseRef = resolveBodyQueryResponseRef(returnTypeNode, sourceFile, project);\n }\n // Also check @ApiResponse (success-status only — error-status describes the error body)\n if (!responseRef && !isStream) {\n const apiResp = method\n .getDecorators()\n .find((d) => d.getName() === 'ApiResponse' && (apiResponseStatus(d) ?? 0) < 400);\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 error: errorInfo?.type ?? null,\n params: paramsType,\n queryRef,\n bodyRef,\n responseRef,\n errorRef: errorInfo?.ref ?? null,\n filterFields: filterInfo?.fieldNames ?? null,\n filterFieldTypes: filterInfo?.fieldTypes ?? null,\n filterSource: filterInfo?.source ?? null,\n formWarnings,\n bodySchema,\n querySchema,\n stream: isStream,\n multipart: uploads.multipart,\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 { debugWarn } from '../util/debug-log.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 /**\n * Maintained union of every schema name currently in use — the keys of\n * `named` plus the values of `emittedClasses`. Kept in sync at each insertion\n * site so {@link aliasFor} can probe membership in O(1) instead of rebuilding\n * the set on every call (former O(n²) over all nested references).\n */\n usedSchemaNames: Set<string>;\n visiting: Set<string>;\n recursiveSchemas: Set<string>;\n depth: number;\n /**\n * Active generic type-parameter bindings for the class currently being\n * expanded, e.g. `{ T: 'Item' }` while expanding `PaginatedDto<Item>`. A\n * property typed `T` / `T[]` resolves through this map to the concrete class,\n * giving wrapper DTOs a faithful schema instead of degrading to `unknown`.\n */\n typeBindings: Map<string, string>;\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 usedSchemaNames: new Set(),\n visiting: new Set(),\n recursiveSchemas: new Set(),\n depth: 0,\n typeBindings: new Map(),\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 // Finish a property whose value is a nested/union reference: wrap in an array\n // when the field is a collection (`@IsArray` or a `T[]` type), then apply\n // `@IsOptional`/`@IsDefined` presence. Shared by the three reference paths below.\n const asField = (child: SchemaNode): SchemaNode =>\n applyPresence(\n has('IsArray') || isArrayType ? { kind: 'array', element: child } : child,\n decorators,\n );\n\n // ── Discriminated union via @Type(() => Base, { discriminator: {...} }) ──\n // class-transformer's documented polymorphism convention. The `subTypes`\n // entries map a discriminator literal to a concrete class; we emit a union of\n // refs to those classes carrying the discriminator property name, which each\n // adapter renders as a tagged union (zod discriminatedUnion / valibot variant).\n const discriminator = resolveDiscriminator(dec('Type'));\n if (discriminator) {\n const options: SchemaNode[] = discriminator.subTypes.map((name) =>\n buildNestedReference(name, classFile, ctx),\n );\n return asField({ kind: 'union', options, discriminator: discriminator.property });\n }\n\n // ── Generic type-parameter property (T / T[]) resolved via active bindings ─\n // When expanding `Wrapper<Arg>`, a field typed `T`/`T[]` (where T is the\n // wrapper's type parameter) resolves to the concrete `Arg` class — giving the\n // wrapper a faithful schema instead of degrading to `unknown`. Takes priority\n // over `@Type` (whose factory can't name the still-generic `T`).\n const propTypeParam = singularClassName(typeText);\n if (propTypeParam && ctx.typeBindings.has(propTypeParam)) {\n const bound = ctx.typeBindings.get(propTypeParam) as string;\n return asField(buildNestedReference(bound, classFile, ctx));\n }\n\n // ── Nested / array-of-nested via @ValidateNested + @Type ────────────────\n const typeRefName = resolveTypeFactoryName(dec('Type'));\n if (has('ValidateNested') || typeRefName) {\n // A generic wrapper reference (`PaginatedDto<Item>`) carries its type args on\n // the property typeNode, not in `@Type`. Capture them so the wrapper's body\n // is expanded with `T → Item` bindings.\n const typeArgs = genericTypeArgNames(typeNode);\n const childName = typeRefName ?? singularClassName(typeText);\n if (childName) {\n return asField(buildNestedReference(childName, classFile, ctx, typeArgs));\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 debugWarn(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 typeArgs: string[] = [],\n): SchemaNode {\n // A generic instantiation (`PaginatedDto<Item>`) is keyed by class + args so\n // distinct instantiations don't collide in the emitted-class cache. A bare\n // (non-generic) reference keys by class name as before — byte-identical output.\n const cacheKey = typeArgs.length > 0 ? `${className}<${typeArgs.join(',')}>` : className;\n const schemaBase = typeArgs.length > 0 ? `${className}Of${typeArgs.join('')}` : className;\n\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(cacheKey)) {\n const reserved = ctx.emittedClasses.get(cacheKey) ?? aliasFor(schemaBase, ctx);\n ctx.emittedClasses.set(cacheKey, reserved);\n ctx.usedSchemaNames.add(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 debugWarn(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 debugWarn(msg);\n }\n return { kind: 'unknown', note: 'nesting too deep — not expanded' };\n }\n\n const existing = ctx.emittedClasses.get(cacheKey);\n if (existing) return { kind: 'ref', name: existing };\n\n const schemaName = aliasFor(schemaBase, 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 // Bind the class's type parameters to the supplied args for the duration of\n // this expansion (`class PaginatedDto<T>` + args [Item] → { T: 'Item' }).\n const params = resolved.decl.getTypeParameters().map((p) => p.getName());\n const newBindings: Array<[string, string]> = [];\n params.forEach((param, i) => {\n const arg = typeArgs[i];\n if (arg) newBindings.push([param, arg]);\n });\n for (const [k, v] of newBindings) ctx.typeBindings.set(k, v);\n\n ctx.emittedClasses.set(cacheKey, schemaName);\n ctx.usedSchemaNames.add(schemaName);\n ctx.visiting.add(cacheKey);\n ctx.depth += 1;\n const childNode = buildObject(resolved.decl, resolved.file, ctx);\n ctx.depth -= 1;\n ctx.visiting.delete(cacheKey);\n for (const [k] of newBindings) ctx.typeBindings.delete(k);\n\n ctx.named.set(schemaName, childNode);\n ctx.usedSchemaNames.add(schemaName);\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 // `usedSchemaNames` is the maintained union of `named` keys + `emittedClasses`\n // values, kept in sync at every insertion site — so this is an O(1) probe per\n // step instead of rebuilding the set on each call.\n while (ctx.usedSchemaNames.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/**\n * Resolve a class-transformer discriminator from the SECOND argument of\n * `@Type(() => Base, { discriminator: { property, subTypes } })`. Returns the\n * discriminator property name plus the ordered list of subtype class names, or\n * null when the decorator has no (valid) discriminator option.\n */\nfunction resolveDiscriminator(\n decorator: Decorator | undefined,\n): { property: string; subTypes: string[] } | null {\n const optsArg = decorator?.getArguments()[1];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\n\n let discProp: Node | undefined;\n for (const prop of optsArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'discriminator') {\n discProp = prop.getInitializer();\n }\n }\n if (!discProp || !Node.isObjectLiteralExpression(discProp)) return null;\n\n let property: string | null = null;\n const subTypes: string[] = [];\n for (const prop of discProp.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const name = prop.getName();\n const init = prop.getInitializer();\n if (!init) continue;\n if (name === 'property' && Node.isStringLiteral(init)) {\n property = init.getLiteralValue();\n } else if (name === 'subTypes' && Node.isArrayLiteralExpression(init)) {\n for (const el of init.getElements()) {\n if (!Node.isObjectLiteralExpression(el)) continue;\n for (const p of el.getProperties()) {\n if (!Node.isPropertyAssignment(p) || p.getName() !== 'name') continue;\n const nameInit = p.getInitializer();\n if (nameInit && Node.isIdentifier(nameInit)) subTypes.push(nameInit.getText());\n }\n }\n }\n }\n if (!property || subTypes.length === 0) return null;\n return { property, subTypes };\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/**\n * Read the simple identifier names of a type reference's type arguments, e.g.\n * `PaginatedDto<Item>` → `['Item']`. Returns `[]` when the node is not a generic\n * type reference or any argument is not a bare identifier (we only substitute\n * named class args; complex args are left to degrade as before).\n */\nfunction genericTypeArgNames(typeNode: import('ts-morph').TypeNode | undefined): string[] {\n if (!typeNode || !Node.isTypeReference(typeNode)) return [];\n const names: string[] = [];\n for (const arg of typeNode.getTypeArguments()) {\n if (!Node.isTypeReference(arg)) return [];\n const tn = arg.getTypeName();\n if (!Node.isIdentifier(tn)) return [];\n names.push(tn.getText());\n }\n return names;\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 debugWarn(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","/**\n * Opt-in terminal logging for schema-translation advisories.\n *\n * Messages like \"@X is not translatable to a client validation schema\" or\n * \"T is a recursive type\" are always recorded in the `SchemaModule.warnings`\n * array and re-emitted as `// warning:` comments in the generated output, so the\n * durable record never depends on this. The terminal copy is pure noise on a\n * normal run, so it is printed only when codegen runs with `debug: true`.\n *\n * The flag is process-wide and set once per pass by {@link generate}; codegen\n * runs as a single CLI invocation or one watcher tick, so a module-level switch\n * is sufficient (and matches the pre-existing direct `console.warn` it replaces).\n */\nlet debugEnabled = false;\n\n/** Set by `generate()` from the resolved `debug` config before each pass. */\nexport function setCodegenDebug(enabled: boolean): void {\n debugEnabled = enabled;\n}\n\n/** Emit a `[nestjs-codegen]` advisory to stderr only when debug is enabled. */\nexport function debugWarn(message: string): void {\n if (debugEnabled) console.warn(`[nestjs-codegen] ${message}`);\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 type VariableDeclaration,\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\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 // Bare node_modules specifier (e.g. `@scope/pkg`): our manual relative /\n // tsconfig-paths resolver yields no candidates. Fall back to the TS\n // compiler's own module resolution, which locates the package's `.d.ts`\n // declaration file. This is what lets a `@Filterable({ entity: X })` whose\n // entity lives in an external package still be resolved (and its columns\n // enumerated from the declaration file), rather than silently degrading the\n // route to a non-filter route.\n if (candidates.length === 0) {\n const viaCompiler = resolveBareSpecifierType(name, importDecl, project);\n if (viaCompiler) return viaCompiler;\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 * Resolve `name` against a bare (node_modules) import specifier using the TS\n * compiler's module resolution. `getModuleSpecifierSourceFile()` returns the\n * declaration (`.d.ts`) or source file the package resolves to; we then look up\n * the type there (and follow that file's own re-exports / barrels).\n */\nfunction resolveBareSpecifierType(\n name: string,\n importDecl: import('ts-morph').ImportDeclaration,\n project: Project,\n): TypeDeclResult | null {\n let target: SourceFile | undefined;\n try {\n target = importDecl.getModuleSpecifierSourceFile();\n } catch {\n return null;\n }\n if (!target) return null;\n const direct = findTypeInFile(name, target);\n if (direct) return direct;\n return resolveReExportedType(name, target, 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// Variable-declaration (const) lookup — for cross-file @ApplyContract refs\n// ---------------------------------------------------------------------------\n\n/** A resolved value-level `const`/variable declaration plus its declaring file. */\nexport interface VariableDeclResult {\n decl: VariableDeclaration;\n file: SourceFile;\n}\n\n/**\n * Resolve an identifier that names a value-level `const` (e.g. an imported\n * `defineContract(...)` result applied via `@ApplyContract(thatConst)`) to its\n * variable declaration and declaring file. Resolution order:\n * 1. local declaration in the current file;\n * 2. follow the file's import declarations to the declaring module;\n * 3. follow `export { X } from './mod'` / `export *` re-exports (barrels).\n *\n * Returns null when the identifier cannot be resolved to a variable declaration\n * (the caller then warns + skips, preserving the prior behavior).\n */\nexport function resolveImportedVariable(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): VariableDeclResult | null {\n const local = sourceFile.getVariableDeclaration(name);\n if (local) return { decl: local, file: sourceFile };\n return resolveVariableViaImports(name, sourceFile, project, new Set());\n}\n\n/** Follow the file's import declarations to a variable declaration in another module. */\nfunction resolveVariableViaImports(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n seen: Set<string>,\n): VariableDeclResult | null {\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl\n .getNamedImports()\n .find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name);\n if (!namedImport) continue;\n // The source-side (pre-alias) name to look up in the target module.\n const sourceName = namedImport.getName();\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n const found = followModuleForVariable(sourceName, moduleSpecifier, sourceFile, project, seen);\n if (found) return found;\n }\n return null;\n}\n\n/** Resolve `name` to a variable declaration inside the module at `moduleSpecifier`. */\nfunction followModuleForVariable(\n name: string,\n moduleSpecifier: string,\n fromFile: SourceFile,\n project: Project,\n seen: Set<string>,\n): VariableDeclResult | 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 found = resolveVariableInFile(name, importedFile, project, seen);\n if (found) return found;\n }\n return null;\n}\n\n/**\n * Find a variable declaration `name` in `file`: directly, then via re-exports\n * (`export { X } from './mod'`, `export *`, bare `export { X }`) and that file's\n * own imports. Guards against import/re-export cycles via `seen`.\n */\nfunction resolveVariableInFile(\n name: string,\n file: SourceFile,\n project: Project,\n seen: Set<string>,\n): VariableDeclResult | null {\n const filePath = file.getFilePath();\n if (seen.has(filePath)) return null;\n seen.add(filePath);\n\n const local = file.getVariableDeclaration(name);\n if (local) return { decl: local, file };\n\n for (const exportDecl of file.getExportDeclarations()) {\n const moduleSpecifier = exportDecl.getModuleSpecifierValue();\n const namedExports = exportDecl.getNamedExports();\n\n if (moduleSpecifier) {\n const hasStar = namedExports.length === 0; // `export * from './mod'`\n const reExport = namedExports.find(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!hasStar && !reExport) continue;\n const sourceName = hasStar ? name : (reExport?.getName() ?? name);\n const found = followModuleForVariable(sourceName, moduleSpecifier, file, project, seen);\n if (found) return found;\n continue;\n }\n\n // Bare `export { X }` — X was imported into this file above.\n const reExport = namedExports.find(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!reExport) continue;\n const sourceName = reExport.getName();\n const viaImports = resolveVariableViaImports(sourceName, file, project, seen);\n if (viaImports) return viaImports;\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 * Evict the per-`Project` resolution caches for a Project. Required by the watch\n * mode, which reuses ONE persistent `Project` across file changes: without a\n * fresh Project per run the WeakMap entries would otherwise never auto-invalidate,\n * so a changed file would resolve against stale, pre-change declarations. Clearing\n * the whole per-Project map on each change is the simple, always-correct choice\n * (the cold one-shot path keeps building a fresh Project and never calls this).\n */\nexport function clearTypeResolutionCaches(project: Project): void {\n _findTypeCache.delete(project);\n _resolveNamedRefCache.delete(project);\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 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\n/**\n * Evict the per-`Project` enum cache. Companion to\n * `clearTypeResolutionCaches` — the persistent watch-mode Project must drop this\n * on every change or a changed enum would resolve to stale members.\n */\nexport function clearEnumCache(project: Project): void {\n _enumCache.delete(project);\n}\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 /** Error response body type, from a `defineContract({ error })` zod schema. Null when absent. */\n error: string | null;\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 error: string | null = null;\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 } else if (propName === 'error') {\n error = zodAstToTs(val);\n }\n }\n\n return { query, body, response, error, bodyZodText, queryZodText };\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 { emitMocks } from './emit/emit-mocks.js';\nimport { emitOpenApi } from './emit/emit-openapi.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';\nimport {\n computeInputsHash,\n isManifestFresh,\n listOutputFiles,\n readManifest,\n writeManifest,\n} from './generate-manifest.js';\nimport { VERSION } from './index.js';\nimport { setCodegenDebug } from './util/debug-log.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 // Gate the schema-translation advisory chatter for this pass (off by default).\n setCodegenDebug(config.debug);\n\n // Skip-when-unchanged: if the inputs (source files + resolved config + lib\n // version) hash-match the last run AND every recorded output still exists, this\n // pass is a no-op. This stops watch/HMR from rewriting api.ts when nothing\n // changed, which would otherwise churn downstream tsbuildinfo. Computed per\n // call so an actual file change still regenerates.\n const inputsHash = await computeInputsHash(config);\n const manifest = await readManifest(config.codegen.outDir);\n if (await isManifestFresh(config.codegen.outDir, manifest, inputsHash)) {\n console.log(`[nestjs-codegen] ${config.codegen.outDir} up to date, skipped`);\n return;\n }\n\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 serialization: config.serialization,\n extensions,\n ctx,\n });\n }\n\n const hasForms = await emitForms(routes, config.codegen.outDir, config.forms, config.validation);\n\n // OpenAPI 3.1 spec export (opt-in). Lowers routes + validation IR into a spec.\n if (hasContracts && config.openapi.enabled) {\n await emitOpenApi(routes, config.codegen.outDir, {\n fileName: config.openapi.fileName,\n info: {\n title: config.openapi.title,\n version: config.openapi.version,\n ...(config.openapi.description ? { description: config.openapi.description } : {}),\n },\n });\n }\n\n // MSW + faker mock handlers (opt-in).\n if (hasContracts && config.mocks.enabled) {\n await emitMocks(routes, config.codegen.outDir, {\n fileName: config.mocks.fileName,\n seed: config.mocks.seed,\n baseUrl: config.mocks.baseUrl,\n });\n }\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 // Record the inputs hash + the output file set, so the next call can skip when\n // nothing changed. Recorded after a successful pass; a throw above leaves the\n // old manifest (or none) in place, so the next run regenerates.\n const outputFiles = await listOutputFiles(config.codegen.outDir);\n await writeManifest(config.codegen.outDir, {\n version: VERSION,\n hash: inputsHash,\n files: outputFiles,\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 { SerializationMode } from '../config/types.js';\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 *\n * `serialization` controls how response types are emitted (default `'json'`):\n * in `'json'` mode each `response` type is wrapped in `Jsonify<...>` (so the\n * generated type reflects the JSON wire shape, e.g. `Date` → `string`); in\n * `'superjson'` mode the raw controller return type is emitted unchanged.\n */\nexport interface ApiEmitOptions {\n fetcherImportPath?: string | undefined;\n /** Registered extensions. Their api.ts hooks (transport/layer/members/header) are applied. */\n extensions?: CodegenExtension[] | undefined;\n /** Shared extension context (from `generate()`). When omitted, a minimal one is built from routes. */\n ctx?: ExtensionContext | undefined;\n /** How response payloads deserialize on the client. Default `'json'`. */\n serialization?: SerializationMode | undefined;\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 * The route `response` type expression for a leaf.\n *\n * In `'json'` mode the response crosses the wire as plain JSON, so wrap the raw\n * type in `Jsonify<...>` to reflect the serialized shape (Date → string, etc.).\n * In `'superjson'` mode the payload is revived on the client, so emit the raw\n * controller return type unchanged. Only the `response` field is wrapped — never\n * `error`, `body`, or `query`.\n */\nfunction buildResponseType(c: LeafEntry, outDir: string, serialization: SerializationMode): string {\n const raw = rawResponseType(c, outDir);\n return serialization === 'json' ? `Jsonify<${raw}>` : raw;\n}\n\n/** The un-wrapped response type expression for a leaf (stream / controllerRef / ref / inline). */\nfunction rawResponseType(c: LeafEntry, outDir: string): string {\n const respRef = c.contractSource.responseRef;\n // Streaming routes: `response` is the streamed ELEMENT type `T`. The method's\n // ReturnType is `Observable<...>` / `AsyncIterable<...>` (the container), so the\n // `ReturnType<...>` path would type the element as the container — use the\n // discovered element ref / inline element string instead.\n if (c.contractSource.stream) {\n if (respRef) return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;\n return c.contractSource.response;\n }\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 if (respRef) {\n return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;\n }\n return c.contractSource.response;\n}\n\n/**\n * The route's error response body type for the leaf `error` field. Prefers a\n * named `errorRef` (so it imports by name), then the inline `error` type string,\n * and finally `unknown` — an HTTP error always carries some body, so an undeclared\n * error type is `unknown` rather than `never`.\n */\nfunction buildErrorType(c: LeafEntry): string {\n const errRef = c.contractSource.errorRef;\n if (errRef) {\n return errRef.isArray ? `Array<${errRef.name}>` : errRef.name;\n }\n return c.contractSource.error ?? 'unknown';\n}\n\nfunction emitRouterTypeBlock(\n tree: Map<string, TreeNode>,\n indent: number,\n outDir: string,\n serialization: SerializationMode,\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, serialization);\n const error = buildErrorType(c);\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 // SSE/streaming routes carry `stream: true` so `Route.Stream<K>` and the\n // leaf's `stream()` surface can be derived purely from the ApiRouter type.\n const stream = c.contractSource.stream ? 'true' : 'false';\n lines.push(\n `${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; params: ${params}; query: ${query}; body: ${body}; response: ${response}; error: ${error}; filterFields: ${filterFields}; stream: ${stream} };`,\n );\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir, serialization));\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 // Multipart routes (an `@UploadedFile()` handler) signal the fetcher to\n // serialize the body object to a `FormData` instead of JSON.\n if (hasBody && c.contractSource.multipart) optsParts.push('multipart: true');\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 // When no input is supplied the key omits the trailing element entirely\n // (`[name]` rather than `[name, undefined]`) so the bare `.queryKey()` is a\n // clean prefix that partial-matches every parametrized variant — making it\n // directly usable for `invalidateQueries`.\n queryKeyExpr: `(input === undefined ? [${flat}] as const : [${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 streamExpr: string | undefined,\n): string[] {\n const lines = [`${pad}${objKey}: (input?: ${req.inputType}) => ({`];\n lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);\n // SSE/streaming routes expose a typed `stream()` returning an AsyncIterable of\n // the streamed element type (alongside the awaitable base, which is rarely used\n // for a stream but kept for shape uniformity).\n if (streamExpr) {\n lines.push(`${pad} stream: () => ${streamExpr},`);\n }\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/**\n * The streaming consumption expression for an `@Sse()`/streaming leaf:\n * `fetcher.sse<T>(url, { query })`. The element type `T` is the route's\n * `response` (the codegen carried the streamed element through there).\n */\nfunction renderStreamExpr(req: RequestModel): string {\n return `fetcher.sse<${req.responseType}>(${req.urlExpr}, ${req.optsExpr})`;\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 const streamExpr = node.contractSource.stream ? renderStreamExpr(req) : undefined;\n\n lines.push(...renderLeaf(pad, objKey, req, leaf.requestExpr, members, streamExpr));\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 ' /** The streamed element type of an `@Sse()`/streaming route — the type yielded by its `stream()` AsyncIterable. */',\n ' export type Stream<K extends string> = ResolveByName<K, \"response\">;',\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 ' export type Stream<M extends string, U extends string> = ResolveByPath<M, U, \"response\">;',\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 Stream<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 ' export type Stream<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 serialization: SerializationMode = opts.serialization ?? 'json';\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 // EXCEPT for streams, whose response is the element ref (not the container ReturnType).\n // errorRef is always imported (the error type is never sourced from ReturnType).\n const refs =\n r.controllerRef && !cs.stream\n ? [cs.queryRef, cs.bodyRef, cs.errorRef]\n : [cs.queryRef, cs.bodyRef, cs.responseRef, cs.errorRef];\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 // In `'json'` mode every `response` type is wrapped in `Jsonify<...>` so the\n // generated type reflects the JSON wire shape; import the type helper (from the\n // same `runtimeImport`, so it tracks `fetcherImportPath`). Only when at least\n // one route is wrapped (the empty-routes branch wraps nothing).\n if (serialization === 'json' && contracted.length > 0) {\n lines.push(`import type { Jsonify } from '${runtimeImport}';`);\n }\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 ?? '', serialization));\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 escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Cache of word-boundary regexes keyed by token. Building `new RegExp` per\n * rename per call was O(renames) recompiles inside the fixed-point loop; tokens\n * recur heavily across entries, so a shared cache amortizes it. A `/g` regex is\n * safe to reuse with `String.prototype.replace` (replace does not read/advance\n * `lastIndex`), so one cached instance covers both `applyRenames` (global) and\n * `isSelfReferential` (test). For `.test()` we use a fresh non-global form to\n * avoid `lastIndex` statefulness.\n */\nconst wordBoundaryRegexCache = new Map<string, RegExp>();\n\nfunction wordBoundaryRegex(token: string): RegExp {\n let re = wordBoundaryRegexCache.get(token);\n if (re === undefined) {\n re = new RegExp(`\\\\b${escapeRegExp(token)}\\\\b`, 'g');\n wordBoundaryRegexCache.set(token, re);\n }\n return re;\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(wordBoundaryRegex(from), to);\n }\n return out;\n}\n\nfunction isSelfReferential(name: string, text: string): boolean {\n // Use a non-global probe: `RegExp.prototype.test` on a `/g` regex advances\n // `lastIndex`, which would make repeated calls for the same token stateful.\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 // Maintained mirror of `rename.values()` so the disambiguation loop can test\n // candidate membership in O(1) instead of rebuilding an array each probe.\n const renameValues = new Set<string>();\n const setRename = (key: string, value: string): void => {\n const prev = rename.get(key);\n rename.set(key, value);\n if (prev !== undefined && prev !== value) {\n // Drop the old value only if no other key still maps to it.\n let stillUsed = false;\n for (const v of rename.values()) {\n if (v === prev) {\n stillUsed = true;\n break;\n }\n }\n if (!stillUsed) renameValues.delete(prev);\n }\n renameValues.add(value);\n };\n for (const [name] of local) setRename(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 renameValues.has(candidate)\n ) {\n i += 1;\n candidate = `${name}_${i}`;\n }\n setRename(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","/**\n * MSW + (dependency-free) faker-style mock handler generation.\n *\n * Emits `mocks.ts`: an array of Mock Service Worker (`msw`) `http` handlers, one\n * per contracted route, each returning seeded mock data shaped to the route's\n * response JSON Schema (lowered from the same IR as the OpenAPI export). This is\n * Orval's headline feature; the key difference is we ship NO `@faker-js/faker`\n * dependency — a tiny `mulberry32`-seeded generator (`MOCK_GEN_RUNTIME` in\n * `emit/mock-gen-runtime.ts`) is embedded verbatim into the output, so the\n * generated module is self-contained and deterministic for a given seed.\n *\n * `msw` is a peer dependency the consumer installs; the generated file imports\n * `http`/`HttpResponse` from it. The generator runtime is embedded (not imported)\n * so the file has no dependency on this package at runtime.\n */\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport type { JsonSchema } from '../ir/schema-node-to-json-schema.js';\nimport { schemaModuleToJsonSchema } from '../ir/schema-node-to-json-schema.js';\nimport { MOCK_GEN_RUNTIME } from './mock-gen-runtime.js';\n\nexport interface MocksEmitOptions {\n /** Output file name within `outDir`. Default `'mocks.ts'`. */\n fileName?: string;\n /** Deterministic seed. Default `1`. */\n seed?: number;\n /** Base URL prepended to handler paths. Default `''`. */\n baseUrl?: string;\n}\n\nconst REF_PREFIX = '#/components/schemas/';\n\n/** MSW path syntax uses `:param`, which already matches NestJS paths. */\nfunction toMswPath(path: string, baseUrl: string): string {\n return `${baseUrl}${path}`;\n}\n\n/**\n * The response schema for a route, lowered from the response IR\n * (`responseSchema`) when present and hoisting its named schemas into the shared\n * `defs` map. Falls back to a permissive schema (the generator then yields a\n * neutral object, which still conforms) when no response IR exists.\n */\nfunction responseSchemaFor(route: RouteDescriptor, defs: Record<string, JsonSchema>): JsonSchema {\n const cs = route.contract!.contractSource;\n if (cs.responseSchema) {\n const { root, named } = schemaModuleToJsonSchema(cs.responseSchema, { refPrefix: REF_PREFIX });\n for (const [name, node] of Object.entries(named)) {\n if (!(name in defs)) defs[name] = node;\n }\n return root;\n }\n return {};\n}\n\n/** Build the `mocks.ts` source text. Pure (no I/O). */\nexport function buildMocksFile(routes: RouteDescriptor[], opts: MocksEmitOptions = {}): string {\n const seed = opts.seed ?? 1;\n const baseUrl = opts.baseUrl ?? '';\n const contracted = routes.filter((r) => r.contract);\n\n // Shared components map referenced by per-route response schemas.\n const defs: Record<string, JsonSchema> = {};\n const handlers: string[] = [];\n\n for (const r of contracted) {\n const schema = responseSchemaFor(r, defs);\n const method = r.method.toLowerCase();\n const mswMethod =\n method === 'get' ||\n method === 'post' ||\n method === 'put' ||\n method === 'patch' ||\n method === 'delete'\n ? method\n : 'all';\n const path = toMswPath(r.path, baseUrl);\n const cs = r.contract!.contractSource;\n const schemaLiteral = JSON.stringify(schema);\n const pathLit = JSON.stringify(path);\n if (cs.stream) {\n // SSE/streaming route: return a text/event-stream body with one event.\n handlers.push(\n [\n ` // ${r.name} (stream)`,\n ` http.${mswMethod}(${pathLit}, () => {`,\n ` const value = generateMock(${schemaLiteral}, makeRng(SEED), DEFS);`,\n ' const body = `data: ${JSON.stringify(value)}\\\\n\\\\n`;',\n \" return new HttpResponse(body, { headers: { 'Content-Type': 'text/event-stream' } });\",\n ' }),',\n ].join('\\n'),\n );\n } else {\n handlers.push(\n [\n ` // ${r.name}`,\n ` http.${mswMethod}(${pathLit}, () => {`,\n ` const value = generateMock(${schemaLiteral}, makeRng(SEED), DEFS);`,\n ' return HttpResponse.json(value);',\n ' }),',\n ].join('\\n'),\n );\n }\n }\n\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-codegen. Do not edit.',\n '// MSW handlers returning deterministic, schema-shaped mock data.',\n '/* eslint-disable */',\n '// @ts-nocheck',\n '',\n \"import { http, HttpResponse } from 'msw';\",\n '',\n `const SEED = ${seed};`,\n '',\n '// ---------------------------------------------------------------------------',\n '// Embedded mock-data runtime (mulberry32 PRNG + JSON-Schema value generator).',\n '// Dependency-free: no @faker-js/faker. Deterministic for a given SEED.',\n '// ---------------------------------------------------------------------------',\n MOCK_GEN_RUNTIME,\n '',\n '// Shared component schemas referenced by $ref.',\n `const DEFS = ${JSON.stringify(defs, null, 2)};`,\n '',\n '/** MSW request handlers, one per contracted route. */',\n 'export const handlers = [',\n ...handlers,\n '];',\n '',\n ];\n\n return lines.join('\\n');\n}\n\n/** Emit `mocks.ts` into `outDir`. */\nexport async function emitMocks(\n routes: RouteDescriptor[],\n outDir: string,\n opts: MocksEmitOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const content = buildMocksFile(routes, opts);\n const fileName = opts.fileName ?? 'mocks.ts';\n await writeFile(join(outDir, fileName), content, 'utf8');\n}\n\n// Re-export the lowering so callers/tests can build richer response schemas when\n// response IR becomes available.\nexport { schemaModuleToJsonSchema, REF_PREFIX };\n","/**\n * Converts the neutral {@link SchemaNode} / {@link SchemaModule} IR into a\n * JSON Schema object compatible with the OpenAPI 3.1 schema dialect (which *is*\n * JSON Schema 2020-12). This is the shared lowering used by both the OpenAPI 3.1\n * exporter (`emit/emit-openapi.ts`) and the MSW+faker mock generator\n * (`emit/emit-msw.ts`) — they consume the same JSON Schema so the spec and the\n * mocks can never disagree about a route's shape.\n *\n * Design notes:\n * - `enum` literals and `literal.raw` are verbatim TS source texts (quote style\n * preserved, produced by ts-morph `getText()`), e.g. `'active'`, `42`, `true`,\n * `null`. They are parsed back into real JSON values by {@link parseLiteral}.\n * - Named schemas (the `named` map of a `SchemaModule`) are lowered into\n * `components/schemas` and referenced via `$ref`, so recursion (`lazyRef`) and\n * sharing produce real `$ref` cycles rather than infinite inlining.\n * - `optional` only affects an *object field's* membership in `required`; a bare\n * optional widens the type with `null` (the closest JSON Schema analog).\n */\nimport type { SchemaModule, SchemaNode } from './schema-node.js';\n\n/** A minimal JSON Schema object (OpenAPI 3.1 dialect). Open-ended on purpose. */\nexport type JsonSchema = {\n type?: string | string[];\n format?: string;\n enum?: unknown[];\n const?: unknown;\n items?: JsonSchema;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n additionalProperties?: boolean | JsonSchema;\n oneOf?: JsonSchema[];\n anyOf?: JsonSchema[];\n discriminator?: { propertyName: string };\n $ref?: string;\n description?: string;\n nullable?: boolean; // not used in 3.1 (kept off by default); 3.1 uses type arrays\n [key: string]: unknown;\n};\n\nexport interface JsonSchemaContext {\n /** Prefix for `$ref` targets. Default `'#/components/schemas/'`. */\n refPrefix: string;\n}\n\nconst DEFAULT_CTX: JsonSchemaContext = { refPrefix: '#/components/schemas/' };\n\n/**\n * Parse a verbatim TS literal source text into a real JSON value.\n * Handles single/double-quoted strings, numbers, booleans and null. Anything\n * unrecognized falls back to the trimmed string form.\n */\nexport function parseLiteral(raw: string): unknown {\n const t = raw.trim();\n if (t === 'true') return true;\n if (t === 'false') return false;\n if (t === 'null') return null;\n // Quoted string (single, double, or backtick without interpolation).\n const q = t[0];\n if ((q === \"'\" || q === '\"' || q === '`') && t[t.length - 1] === q) {\n return t\n .slice(1, -1)\n .replace(/\\\\'/g, \"'\")\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\`/g, '`')\n .replace(/\\\\\\\\/g, '\\\\');\n }\n // Numeric literal.\n if (/^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(t)) {\n return Number(t);\n }\n return t;\n}\n\n/** Pick the narrowest JSON Schema `type` for a set of parsed literals. */\nfunction literalsType(values: unknown[]): string | undefined {\n const types = new Set(values.map((v) => (v === null ? 'null' : typeof v)));\n if (types.size === 1) {\n const only = [...types][0];\n if (only === 'string') return 'string';\n if (only === 'number') return 'number';\n if (only === 'boolean') return 'boolean';\n }\n return undefined;\n}\n\nfunction convert(node: SchemaNode, ctx: JsonSchemaContext): JsonSchema {\n switch (node.kind) {\n case 'string': {\n const out: JsonSchema = { type: 'string' };\n for (const c of node.checks) {\n if (c.check === 'email') out.format = 'email';\n else if (c.check === 'url') out.format = 'uri';\n else if (c.check === 'uuid') out.format = 'uuid';\n else if (c.check === 'min') out.minLength = Number(c.value);\n else if (c.check === 'max') out.maxLength = Number(c.value);\n else if (c.check === 'regex') {\n // Strip leading/trailing slashes and trailing flags from a regex literal.\n const m = /^\\/(.*)\\/[a-z]*$/.exec(c.pattern);\n out.pattern = m ? m[1] : c.pattern;\n }\n }\n return out;\n }\n case 'number': {\n const out: JsonSchema = { type: 'number' };\n for (const c of node.checks) {\n if (c.check === 'int') out.type = 'integer';\n else if (c.check === 'min') out.minimum = Number(c.value);\n else if (c.check === 'max') out.maximum = Number(c.value);\n else if (c.check === 'positive') out.exclusiveMinimum = 0;\n else if (c.check === 'negative') out.exclusiveMaximum = 0;\n }\n return out;\n }\n case 'boolean':\n return { type: 'boolean' };\n case 'date':\n // JSON has no date type; OpenAPI represents it as a date-time string.\n return { type: 'string', format: 'date-time' };\n case 'unknown':\n return node.note ? { description: node.note } : {};\n case 'instanceof':\n return { type: 'object', description: `instanceof ${node.ctor}` };\n case 'enum': {\n const values = node.literals.map(parseLiteral);\n const t = literalsType(values);\n const out: JsonSchema = { enum: values };\n if (t) out.type = t;\n return out;\n }\n case 'literal': {\n const value = parseLiteral(node.raw);\n const out: JsonSchema = { const: value };\n const t = literalsType([value]);\n if (t) out.type = t;\n return out;\n }\n case 'union': {\n const options = node.options.map((o) => convert(o, ctx));\n const out: JsonSchema = { oneOf: options };\n if (node.discriminator) {\n out.discriminator = { propertyName: node.discriminator };\n }\n return out;\n }\n case 'object': {\n const properties: Record<string, JsonSchema> = {};\n const required: string[] = [];\n for (const f of node.fields) {\n if (f.value.kind === 'optional') {\n properties[f.key] = convert(f.value.inner, ctx);\n } else {\n properties[f.key] = convert(f.value, ctx);\n required.push(f.key);\n }\n }\n const out: JsonSchema = { type: 'object', properties };\n if (required.length > 0) out.required = required;\n out.additionalProperties = node.passthrough;\n return out;\n }\n case 'array':\n return { type: 'array', items: convert(node.element, ctx) };\n case 'optional':\n // A bare optional (not on an object key) — widen with null.\n return widenNullable(convert(node.inner, ctx));\n case 'ref':\n case 'lazyRef':\n return { $ref: `${ctx.refPrefix}${node.name}` };\n case 'annotated':\n return convert(node.inner, ctx);\n }\n}\n\n/** Add `null` to a schema's type (OpenAPI 3.1 style: a type-array). */\nfunction widenNullable(schema: JsonSchema): JsonSchema {\n if (schema.$ref) {\n // Can't add null to a bare $ref in 3.1 without anyOf — wrap it.\n return { anyOf: [schema, { type: 'null' }] };\n }\n if (typeof schema.type === 'string') {\n return { ...schema, type: [schema.type, 'null'] };\n }\n if (Array.isArray(schema.type)) {\n return schema.type.includes('null') ? schema : { ...schema, type: [...schema.type, 'null'] };\n }\n return { anyOf: [schema, { type: 'null' }] };\n}\n\n/** Convert a single {@link SchemaNode} to a JSON Schema object. */\nexport function schemaNodeToJsonSchema(\n node: SchemaNode,\n ctx: JsonSchemaContext = DEFAULT_CTX,\n): JsonSchema {\n return convert(node, ctx);\n}\n\n/**\n * Lower an entire {@link SchemaModule} to a `{ root, named }` pair of JSON\n * Schemas. The `named` map becomes `components/schemas` entries; `root` is the\n * route-level schema that references them via `$ref`.\n */\nexport function schemaModuleToJsonSchema(\n mod: SchemaModule,\n ctx: JsonSchemaContext = DEFAULT_CTX,\n): { root: JsonSchema; named: Record<string, JsonSchema> } {\n const named: Record<string, JsonSchema> = {};\n for (const [name, node] of mod.named) {\n named[name] = convert(node, ctx);\n }\n return { root: convert(mod.root, ctx), named };\n}\n","/**\n * The dependency-free mock-data generator runtime, as an embeddable source-text\n * constant.\n *\n * This is the SINGLE SOURCE OF TRUTH for the generator: the emitter inlines this\n * exact text into the generated `mocks.ts` (so the output is self-contained, with\n * no runtime dependency on this package), and `mock-gen.ts` evaluates this same\n * text to expose typed `makeRng`/`generateMock` to the unit tests. One string,\n * two consumers — the tested behavior and the emitted behavior can never drift.\n *\n * Why a string (vs a normal module read at runtime): the package is bundled by\n * tsup into a single `dist/index.js` and only `dist` is published, so reading a\n * sibling `.ts` source at runtime would fail once installed. A string constant is\n * bundled with the code and works everywhere.\n *\n * Design choice (vs Orval): Orval shells out to `@faker-js/faker`; we ship a tiny\n * `mulberry32`-seeded generator so there is NO faker dependency and output is\n * fully deterministic for a given seed (the tests rely on this). The generator\n * consumes the same JSON Schema that drives the OpenAPI export, so spec and mocks\n * can never disagree about a route's shape.\n */\nexport const MOCK_GEN_RUNTIME = `\n/** mulberry32 — a tiny, fast, seedable PRNG. \\`next()\\` returns a float in [0, 1). */\nfunction makeRng(seed) {\n let a = seed >>> 0;\n return {\n next() {\n a |= 0;\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n },\n };\n}\n\nfunction __pick(rng, items) {\n return items[Math.floor(rng.next() * items.length)];\n}\n\nfunction __intBetween(rng, min, max) {\n return Math.floor(rng.next() * (max - min + 1)) + min;\n}\n\nconst __WORDS = ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', 'sed', 'tempor'];\nconst __FIRST_NAMES = ['Ada', 'Alan', 'Grace', 'Linus', 'Margaret', 'Dennis'];\nconst __LAST_NAMES = ['Lovelace', 'Turing', 'Hopper', 'Torvalds', 'Hamilton', 'Ritchie'];\n\nfunction __fakeWords(rng, count) {\n let out = [];\n for (let i = 0; i < count; i++) out.push(__pick(rng, __WORDS));\n return out.join(' ');\n}\n\nfunction __hex(rng, len) {\n let s = '';\n for (let i = 0; i < len; i++) s += Math.floor(rng.next() * 16).toString(16);\n return s;\n}\n\nfunction __fakeUuid(rng) {\n return __hex(rng, 8) + '-' + __hex(rng, 4) + '-4' + __hex(rng, 3) + '-' + __pick(rng, ['8', '9', 'a', 'b']) + __hex(rng, 3) + '-' + __hex(rng, 12);\n}\n\nfunction __fakeString(rng, schema) {\n switch (schema.format) {\n case 'email':\n return __pick(rng, __FIRST_NAMES).toLowerCase() + '.' + __pick(rng, __LAST_NAMES).toLowerCase() + '@example.com';\n case 'uri':\n case 'url':\n return 'https://example.com/' + __pick(rng, __WORDS);\n case 'uuid':\n return __fakeUuid(rng);\n case 'date-time':\n return new Date(Date.UTC(2020, __intBetween(rng, 0, 11), __intBetween(rng, 1, 28))).toISOString();\n default:\n return __fakeWords(rng, __intBetween(rng, 1, 3));\n }\n}\n\n/** Generate a mock value for a JSON Schema node (depth-capped recursion via $ref). */\nfunction generateMock(schema, rng, defs, depth) {\n defs = defs || {};\n depth = depth || 0;\n if (schema.$ref) {\n const name = schema.$ref.replace('#/components/schemas/', '');\n const target = defs[name];\n if (!target || depth > 4) return null;\n return generateMock(target, rng, defs, depth + 1);\n }\n if ('const' in schema) return schema.const;\n if (schema.enum && schema.enum.length > 0) return __pick(rng, schema.enum);\n if (schema.oneOf && schema.oneOf.length > 0) return generateMock(__pick(rng, schema.oneOf), rng, defs, depth);\n if (schema.anyOf && schema.anyOf.length > 0) return generateMock(__pick(rng, schema.anyOf), rng, defs, depth);\n let type = Array.isArray(schema.type)\n ? (schema.type.filter((t) => t !== 'null')[0] || 'null')\n : schema.type;\n switch (type) {\n case 'string':\n return __fakeString(rng, schema);\n case 'integer':\n return __intBetween(rng, typeof schema.minimum === 'number' ? schema.minimum : 0, typeof schema.maximum === 'number' ? schema.maximum : 1000);\n case 'number':\n return __intBetween(rng, typeof schema.minimum === 'number' ? schema.minimum : 0, typeof schema.maximum === 'number' ? schema.maximum : 1000) + Math.round(rng.next() * 100) / 100;\n case 'boolean':\n return rng.next() < 0.5;\n case 'null':\n return null;\n case 'array': {\n const count = depth > 2 ? 0 : __intBetween(rng, 1, 2);\n const items = schema.items || {};\n let arr = [];\n for (let i = 0; i < count; i++) arr.push(generateMock(items, rng, defs, depth + 1));\n return arr;\n }\n case 'object': {\n const out = {};\n const props = schema.properties || {};\n for (const key of Object.keys(props)) out[key] = generateMock(props[key], rng, defs, depth + 1);\n return out;\n }\n default:\n return {};\n }\n}\n`.trim();\n","/**\n * OpenAPI 3.1 exporter. Lowers the discovered {@link RouteDescriptor} set + the\n * neutral validation IR (`SchemaModule`) into a valid `openapi.json` (OpenAPI\n * 3.1, whose schema dialect *is* JSON Schema 2020-12).\n *\n * Why 3.1 (vs 3.0): 3.1 aligns its schema object with JSON Schema 2020-12, so\n * our IR lowering ({@link schemaModuleToJsonSchema}) maps cleanly — `type` arrays\n * for nullability, `const`, `$ref` recursion, and `oneOf` + `discriminator` for\n * discriminated unions all work without the 3.0 `nullable`/`x-` workarounds. This\n * mirrors what openapi-typescript / Hey API consume and what Orval/Kubb publish.\n *\n * Coverage:\n * - paths: one entry per route, NestJS `:param` → OpenAPI `{param}`, method,\n * path/query parameters, request body (non-GET), and responses.\n * - responses: the success response, plus the typed error response now carried\n * in the IR (`error`/`errorRef`) emitted under a 4xx code (`default` is also\n * populated so any error status resolves).\n * - streaming routes (`stream: true`): success response content type is\n * `text/event-stream`.\n * - components/schemas: every named schema reachable from a route's body/query\n * IR (`SchemaModule.named`) — including discriminated unions, arrays, enums and\n * recursion via `$ref`. TS-type-only positions (no IR) degrade to a permissive\n * schema annotated with the original TS type string, so the spec stays valid.\n *\n * The exporter never boots Nest; it reads only the static IR + descriptors.\n */\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ContractSource, RouteDescriptor } from '../discovery/types.js';\nimport { type JsonSchema, schemaModuleToJsonSchema } from '../ir/schema-node-to-json-schema.js';\nimport type { SchemaModule } from '../ir/schema-node.js';\n\nexport interface OpenApiInfo {\n title?: string;\n version?: string;\n description?: string;\n}\n\nexport interface OpenApiEmitOptions {\n info?: OpenApiInfo;\n /** Output file name within `outDir`. Default `'openapi.json'`. */\n fileName?: string;\n}\n\nexport interface OpenApiDocument {\n openapi: '3.1.0';\n info: { title: string; version: string; description?: string };\n paths: Record<string, Record<string, unknown>>;\n components: { schemas: Record<string, JsonSchema> };\n}\n\nconst REF_PREFIX = '#/components/schemas/';\n\n/** NestJS path `/users/:id` → OpenAPI path `/users/{id}`. */\nfunction toOpenApiPath(path: string): string {\n return path.replace(/:([^/]+)/g, '{$1}');\n}\n\n/**\n * Lower a route position (body/query/response/error) to a JSON Schema, hoisting\n * any named IR schemas into the shared `components` map. Falls back to a\n * permissive schema annotated with the TS type string when no IR is available.\n */\nfunction positionSchema(\n schema: SchemaModule | null | undefined,\n tsType: string | null | undefined,\n components: Record<string, JsonSchema>,\n): JsonSchema {\n if (schema) {\n const { root, named } = schemaModuleToJsonSchema(schema, { refPrefix: REF_PREFIX });\n for (const [name, node] of Object.entries(named)) {\n // First writer wins; later identical names are assumed structurally equal\n // (they reference the same DTO class across routes).\n if (!(name in components)) components[name] = node;\n }\n return root;\n }\n // No rich IR — emit a permissive schema carrying the TS type as documentation.\n return tsType ? { description: tsType } : {};\n}\n\nfunction buildParameters(route: RouteDescriptor): unknown[] {\n const params: unknown[] = [];\n for (const p of route.params) {\n if (p.source === 'path') {\n params.push({\n name: p.name,\n in: 'path',\n required: true,\n schema: { type: 'string' },\n });\n } else if (p.source === 'query') {\n params.push({\n name: p.name,\n in: 'query',\n required: false,\n schema: { type: 'string' },\n });\n } else if (p.source === 'header') {\n params.push({\n name: p.name,\n in: 'header',\n required: false,\n schema: { type: 'string' },\n });\n }\n }\n return params;\n}\n\nfunction buildResponses(\n cs: ContractSource,\n components: Record<string, JsonSchema>,\n): Record<string, unknown> {\n const responses: Record<string, unknown> = {};\n\n const successSchema = positionSchema(\n // Prefer rich response IR when present; otherwise fall back to the TS type.\n cs.responseSchema ?? null,\n cs.response,\n components,\n );\n const successContentType = cs.stream ? 'text/event-stream' : 'application/json';\n responses['200'] = {\n description: cs.stream ? 'Server-sent event stream' : 'Successful response',\n content: { [successContentType]: { schema: successSchema } },\n };\n\n // Typed error response now carried in the IR. We don't know the exact status\n // code statically, so publish it under `default` (and a representative 4xx).\n const errorSchema = positionSchema(null, cs.error ?? null, components);\n const errorBody = {\n description: 'Error response',\n content: { 'application/json': { schema: errorSchema } },\n };\n if (cs.error || cs.errorRef) {\n responses['400'] = errorBody;\n responses.default = errorBody;\n } else {\n responses.default = {\n description: 'Error response',\n content: { 'application/json': { schema: {} } },\n };\n }\n\n return responses;\n}\n\nfunction buildOperation(\n route: RouteDescriptor,\n components: Record<string, JsonSchema>,\n): Record<string, unknown> {\n const cs = route.contract!.contractSource;\n const op: Record<string, unknown> = {\n operationId: route.name,\n parameters: buildParameters(route),\n responses: buildResponses(cs, components),\n };\n\n const method = route.method.toUpperCase();\n const hasBody = method !== 'GET' && method !== 'HEAD' && method !== 'DELETE';\n if (hasBody && (cs.bodySchema || cs.body)) {\n const bodySchema = positionSchema(cs.bodySchema, cs.body, components);\n op.requestBody = {\n required: true,\n content: { 'application/json': { schema: bodySchema } },\n };\n }\n\n return op;\n}\n\n/** Build the OpenAPI 3.1 document object from the route set. Pure (no I/O). */\nexport function buildOpenApiSpec(\n routes: RouteDescriptor[],\n opts: OpenApiEmitOptions = {},\n): OpenApiDocument {\n const components: Record<string, JsonSchema> = {};\n const paths: Record<string, Record<string, unknown>> = {};\n\n for (const route of routes) {\n if (!route.contract) continue;\n const oaPath = toOpenApiPath(route.path);\n const method = route.method.toLowerCase();\n let pathItem = paths[oaPath];\n if (!pathItem) {\n pathItem = {};\n paths[oaPath] = pathItem;\n }\n pathItem[method] = buildOperation(route, components);\n }\n\n const info = opts.info ?? {};\n const doc: OpenApiDocument = {\n openapi: '3.1.0',\n info: {\n title: info.title ?? 'NestJS API',\n version: info.version ?? '1.0.0',\n ...(info.description ? { description: info.description } : {}),\n },\n paths,\n components: { schemas: components },\n };\n return doc;\n}\n\n/** Emit `openapi.json` into `outDir` for all contracted routes. */\nexport async function emitOpenApi(\n routes: RouteDescriptor[],\n outDir: string,\n opts: OpenApiEmitOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const doc = buildOpenApiSpec(routes, opts);\n const fileName = opts.fileName ?? 'openapi.json';\n await writeFile(join(outDir, fileName), `${JSON.stringify(doc, null, 2)}\\n`, '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 { createHash } from 'node:crypto';\nimport { readFile, readdir, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport fg from 'fast-glob';\nimport type { ResolvedConfig } from './config/types.js';\nimport { VERSION } from './index.js';\n\n/** File name of the manifest persisted alongside generated output in `outDir`. */\nexport const MANIFEST_FILE = '.codegen-manifest.json';\n\n/** Lock file name, excluded from the recorded output set (it is not generated output). */\nconst LOCK_FILE = '.watcher.lock';\n\n/**\n * Persisted record of the last successful generate, written to\n * `<outDir>/.codegen-manifest.json`. Used to skip regeneration when nothing\n * relevant changed (see {@link isManifestFresh}).\n */\nexport interface CodegenManifest {\n /** Lib version that produced the output. A lib upgrade invalidates the manifest. */\n version: string;\n /** Content hash over all generate inputs (source files + resolved config + version). */\n hash: string;\n /** Generated output files, relative to `outDir`, recorded after the last run. */\n files: string[];\n}\n\ninterface ManifestShape {\n version: string;\n hash: string;\n files: string[];\n}\n\nfunction isManifestShape(value: unknown): value is ManifestShape {\n if (typeof value !== 'object' || value === null) return false;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.version !== 'string') return false;\n if (typeof candidate.hash !== 'string') return false;\n if (!Array.isArray(candidate.files)) return false;\n return candidate.files.every((entry) => typeof entry === 'string');\n}\n\n/**\n * Stable JSON serialization of the resolved config for hashing. Functions\n * (extensions, validation adapter methods, component-name strategies) are folded\n * in via `toString()` so a change to their source invalidates the hash; anything\n * non-serializable degrades to a marker rather than throwing.\n */\nfunction serializeConfig(config: ResolvedConfig): string {\n try {\n return JSON.stringify(config, (_key, value) => {\n if (typeof value === 'function') return `[fn:${value.name}]${value.toString()}`;\n return value;\n });\n } catch {\n // Non-serializable config (e.g. a cyclic extension) — fall back to a coarse\n // marker so the hash still varies by a few stable fields. Worst case the\n // skip never triggers and we always regenerate, which is safe.\n return `unserializable:${config.codegen.outDir}:${config.contracts.glob}`;\n }\n}\n\n/**\n * Globs the input source files that determine generate output: controllers\n * (`contracts.glob`), DTOs (`forms.watch`), and — when configured — Inertia pages\n * (`pages.glob`). All resolved relative to `config.codegen.cwd`.\n */\nasync function discoverInputFiles(config: ResolvedConfig): Promise<string[]> {\n const globs = [config.contracts.glob, config.forms.watch];\n if (config.pages) globs.push(config.pages.glob);\n\n const cwd = config.codegen.cwd;\n const matched = await fg(globs, { cwd, absolute: true, onlyFiles: true });\n // Sort for a deterministic hash regardless of glob/FS ordering.\n return [...new Set(matched)].sort();\n}\n\n/**\n * Compute a content hash over everything that determines generate output: the\n * contents of all discovered input source files, the serialized resolved config,\n * and the lib version. A change to any input — a controller edit, a config tweak,\n * or a lib upgrade — produces a different hash.\n */\nexport async function computeInputsHash(config: ResolvedConfig): Promise<string> {\n const hash = createHash('sha256');\n hash.update(`version:${VERSION}\\n`);\n hash.update(`config:${serializeConfig(config)}\\n`);\n\n const inputFiles = await discoverInputFiles(config);\n const cwd = config.codegen.cwd;\n for (const file of inputFiles) {\n const contents = await readFile(file, 'utf8');\n // Hash the relative path too, so a rename (same contents) still invalidates.\n hash.update(`file:${relative(cwd, file)}\\n`);\n hash.update(contents);\n hash.update('\\n');\n }\n\n return hash.digest('hex');\n}\n\n/** Read and validate the manifest in `outDir`, or `null` if absent/unreadable/malformed. */\nexport async function readManifest(outDir: string): Promise<CodegenManifest | null> {\n try {\n const raw = await readFile(join(outDir, MANIFEST_FILE), 'utf8');\n const parsed: unknown = JSON.parse(raw);\n if (!isManifestShape(parsed)) return null;\n return { version: parsed.version, hash: parsed.hash, files: parsed.files };\n } catch {\n return null;\n }\n}\n\n/** Write the manifest to `outDir`. */\nexport async function writeManifest(outDir: string, manifest: CodegenManifest): Promise<void> {\n await writeFile(join(outDir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\n}\n\n/**\n * List the generated output files currently in `outDir` (recursively), relative to\n * `outDir`. The manifest and the watcher lock are excluded — they are bookkeeping,\n * not generated output.\n */\nexport async function listOutputFiles(outDir: string): Promise<string[]> {\n const found: string[] = [];\n\n async function walk(dir: string): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);\n for (const entry of entries) {\n const abs = join(dir, entry.name);\n if (entry.isDirectory()) {\n await walk(abs);\n } else if (entry.isFile()) {\n const rel = relative(outDir, abs);\n if (rel === MANIFEST_FILE || rel === LOCK_FILE) continue;\n found.push(rel);\n }\n }\n }\n\n await walk(outDir);\n return found.sort();\n}\n\n/** True when every path (relative to `outDir`) still exists on disk. */\nasync function allOutputsExist(outDir: string, files: string[]): Promise<boolean> {\n const present = new Set(await listOutputFiles(outDir));\n return files.every((file) => present.has(file));\n}\n\n/**\n * Decide whether the persisted manifest still matches the current inputs: same lib\n * version, same content hash, and every recorded output file still on disk. When\n * true, the caller may skip the generate entirely.\n */\nexport async function isManifestFresh(\n outDir: string,\n manifest: CodegenManifest | null,\n inputsHash: string,\n): Promise<boolean> {\n if (manifest === null) return false;\n if (manifest.version !== VERSION) return false;\n if (manifest.hash !== inputsHash) return false;\n if (manifest.files.length === 0) return false;\n return allOutputsExist(outDir, manifest.files);\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.13.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, WatchOptions } from './watch/watcher.js';\nexport { acquireLock } from './watch/lock-file.js';\nexport type { CodegenManifest } from './generate-manifest.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';\nexport {\n createChainModuleRenderer,\n typeNameFor,\n toObjectKey,\n} from './adapters/chain-module.js';\nexport type { ChainModuleRendererOptions } from './adapters/chain-module.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 { emitOpenApi, buildOpenApiSpec } from './emit/emit-openapi.js';\nexport type {\n OpenApiDocument,\n OpenApiEmitOptions,\n OpenApiInfo,\n} from './emit/emit-openapi.js';\nexport { emitMocks, buildMocksFile } from './emit/emit-mocks.js';\nexport type { MocksEmitOptions } from './emit/emit-mocks.js';\nexport {\n schemaNodeToJsonSchema,\n schemaModuleToJsonSchema,\n} from './ir/schema-node-to-json-schema.js';\nexport type { JsonSchema } from './ir/schema-node-to-json-schema.js';\nexport { discoverContractsFast } from './discovery/contracts-fast.js';\nexport type { FastDiscoveryOptions } from './discovery/contracts-fast.js';\n"],"mappings":"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","names":["import_promises","import_node_path","import_node_path","import_ts_morph","import_ts_morph","import_ts_morph","import_node_path","reExportsName","sourceName","reExport","import_ts_morph","import_ts_morph","firstArg","import_ts_morph","fg","firstArg","import_promises","import_node_path","import_promises","import_node_path","import_fast_glob","fg","import_node_path","import_ts_morph","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","REF_PREFIX","import_promises","import_node_path","import_promises","import_node_path","import_promises","import_node_path","import_fast_glob","import_promises","import_node_path","LOCK_FILE","fg","chokidar"]}
|