@dudousxd/nestjs-codegen 0.2.1 → 0.3.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 +30 -0
- package/dist/cli/main.cjs +1214 -1613
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +1188 -1587
- package/dist/cli/main.js.map +1 -1
- package/dist/extension/index.cjs +12 -2
- package/dist/extension/index.cjs.map +1 -1
- package/dist/extension/index.d.cts +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/extension/index.js +10 -1
- package/dist/extension/index.js.map +1 -1
- package/dist/{index-BwIRjOQA.d.cts → index-oH5t7x4G.d.cts} +56 -41
- package/dist/{index-BwIRjOQA.d.ts → index-oH5t7x4G.d.ts} +56 -41
- package/dist/index.cjs +1003 -1457
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -16
- package/dist/index.d.ts +32 -16
- package/dist/index.js +977 -1430
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +908 -1355
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +9 -2
- package/dist/nest/index.d.ts +9 -2
- package/dist/nest/index.js +893 -1340
- package/dist/nest/index.js.map +1 -1
- package/package.json +3 -2
package/dist/nest/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/nest/module.ts","../../src/config/load-config.ts","../../src/exceptions.ts","../../src/adapters/zod.ts","../../src/adapters/registry.ts","../../src/watch/watcher.ts","../../src/discovery/contracts-fast.ts","../../src/discovery/dto-to-ir.ts","../../src/discovery/type-ref-resolution.ts","../../src/discovery/dto-to-zod.ts","../../src/discovery/filter-for.ts","../../src/discovery/filter-field-types.ts","../../src/discovery/enum-resolution.ts","../../src/generate.ts","../../src/discovery/pages.ts","../../src/discovery/shared-props.ts","../../src/emit/emit-api.ts","../../src/extension/registry.ts","../../src/emit/emit-cache.ts","../../src/emit/emit-forms.ts","../../src/emit/emit-index.ts","../../src/emit/emit-pages.ts","../../src/emit/emit-routes.ts","../../src/watch/lock-file.ts"],"sourcesContent":["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 UserConfig {\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 // Use tsx ESM API to load TypeScript config files at runtime\n let tsImport:\n | ((specifier: string, options: string | { parentURL: string }) => Promise<unknown>)\n | undefined;\n try {\n const tsxEsm = await import('tsx/esm/api');\n tsImport = tsxEsm.tsImport;\n } catch {\n throw new ConfigError(\n 'Failed to load config: `tsx` is required for loading TypeScript config files. ' +\n 'Install it as a dev dependency: pnpm add -D tsx',\n );\n }\n\n const parentURL = pathToFileURL(`${filePath}__parent__`).href;\n const fileUrl = pathToFileURL(filePath).href;\n return tsImport(fileUrl, { parentURL });\n}\n\nfunction resolveAbsolute(cwd: string, p: string): string {\n if (isAbsolute(p)) return p;\n return resolve(cwd, p);\n}\n\n/**\n * Validates that `resolvedPath` is contained inside `cwd`.\n * Throws `ConfigError` if the path escapes the project root (e.g. via `..`\n * traversal or an absolute path outside cwd).\n */\nfunction assertInsideCwd(cwd: string, resolvedPath: string, fieldName: string): void {\n const rel = relative(cwd, resolvedPath);\n // relative() returns a path starting with '..' when the target is outside cwd,\n // and isAbsolute() catches platform edge-cases (e.g. Windows drive letters).\n if (rel.startsWith(`..${sep}`) || rel === '..' || isAbsolute(rel)) {\n throw new ConfigError(\n `\\`${fieldName}\\` must be inside the project cwd.\\n Resolved to: ${resolvedPath}\\n Project cwd: ${cwd}\\nIf this is intentional, move the file inside your project directory.`,\n );\n }\n}\n\n/**\n * Resolve a {@link UserConfig} (e.g. `NestjsCodegenModule.forRoot()` options) into a\n * fully-defaulted {@link ResolvedConfig} — without reading a config file. Used by the\n * Nest module and any programmatic caller that already holds the config in memory.\n *\n * @param userConfig the raw user config (forRoot options minus module-only fields)\n * @param cwd project root used to resolve globs / outDir. Defaults to `process.cwd()`.\n */\nexport function resolveConfig(userConfig: UserConfig, cwd?: string): ResolvedConfig {\n return applyDefaults(userConfig, cwd ?? process.cwd());\n}\n\nfunction applyDefaults(userConfig: UserConfig, cwd: string): ResolvedConfig {\n const outDir = userConfig.codegen?.outDir\n ? resolveAbsolute(cwd, userConfig.codegen.outDir)\n : join(cwd, '.nestjs-inertia');\n\n const resolvedCwd = userConfig.codegen?.cwd ? resolveAbsolute(cwd, userConfig.codegen.cwd) : cwd;\n\n let app: ResolvedConfig['app'] = null;\n if (userConfig.app) {\n const resolvedEntry = resolveAbsolute(cwd, userConfig.app.moduleEntry);\n assertInsideCwd(cwd, resolvedEntry, 'app.moduleEntry');\n\n let resolvedTsconfig: string | null = null;\n if (userConfig.app.tsconfig) {\n resolvedTsconfig = resolveAbsolute(cwd, userConfig.app.tsconfig);\n assertInsideCwd(cwd, resolvedTsconfig, 'app.tsconfig');\n }\n\n app = {\n moduleEntry: resolvedEntry,\n tsconfig: resolvedTsconfig,\n };\n }\n\n return {\n extensions: userConfig.extensions ?? [],\n validation: resolveAdapter(userConfig.validation ?? 'zod'),\n pages: userConfig.pages\n ? {\n glob: userConfig.pages.glob,\n propsExport: userConfig.pages.propsExport ?? 'ComponentProps',\n componentNameStrategy: userConfig.pages.componentNameStrategy ?? 'relative-no-ext',\n }\n : null,\n contracts: {\n glob: userConfig.contracts?.glob ?? 'src/**/*.controller.ts',\n debounceMs: userConfig.contracts?.debounceMs ?? 500,\n },\n scopes: userConfig.scopes ?? {},\n codegen: {\n outDir,\n cwd: resolvedCwd,\n },\n app,\n fetcher: userConfig.fetcher ?? null,\n forms: {\n enabled: userConfig.forms?.enabled ?? true,\n watch: userConfig.forms?.watch ?? 'src/**/*.dto.ts',\n zodImport: userConfig.forms?.zodImport ?? 'zod',\n },\n };\n}\n\nexport async function loadConfig(cwd?: string): Promise<ResolvedConfig> {\n const resolvedCwd = cwd ?? process.cwd();\n\n let configPath: string | undefined;\n for (const name of CONFIG_FILES) {\n const candidate = join(resolvedCwd, name);\n if (await fileExists(candidate)) {\n configPath = candidate;\n break;\n }\n }\n\n if (!configPath) {\n throw new ConfigError(\n `Config file not found in ${resolvedCwd} (looked for ${CONFIG_FILES.join(', ')})\\nRun \\`nestjs-codegen init\\` to create a starter config.`,\n );\n }\n\n let mod: unknown;\n try {\n mod = await importTs(configPath);\n } catch (err) {\n if (err instanceof ConfigError) throw err;\n throw new ConfigError(`Failed to load config from ${configPath}`, { cause: err });\n }\n\n // tsImport returns a namespace module where `mod.default` is the module namespace object.\n // The actual `export default` value lives at `mod.default.default` (or `mod.default` for CJS interop).\n const modNs = (mod as Record<string, unknown>).default;\n const userConfig =\n modNs != null && typeof modNs === 'object' && 'default' in (modNs as object)\n ? ((modNs as Record<string, unknown>).default as UserConfig)\n : (modNs as UserConfig | undefined);\n\n if (!userConfig || typeof userConfig !== 'object') {\n throw new ConfigError(\n `Config file must have a default export. Did you forget \\`export default defineConfig({...})\\`? (${configPath})`,\n );\n }\n\n // `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 (${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 type { SchemaNode, StringCheck } from '../ir/schema-node.js';\nimport type { SchemaModule } from '../ir/schema-node.js';\nimport type { AdapterUsage, RenderContext, RenderedModule, ValidationAdapter } from './types.js';\n\n/** Valid JS identifier → bare key, else quoted. */\nfunction toObjectKey(name: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);\n}\n\nfunction messageSuffix(messageRaw: string | undefined): string {\n return messageRaw ? `{ message: ${messageRaw} }` : '';\n}\n\nfunction renderStringChecks(checks: StringCheck[]): string {\n let out = '';\n for (const c of checks) {\n switch (c.check) {\n case 'email':\n out += `.email(${messageSuffix(c.messageRaw)})`;\n break;\n case 'url':\n out += `.url(${messageSuffix(c.messageRaw)})`;\n break;\n case 'uuid':\n out += `.uuid(${messageSuffix(c.messageRaw)})`;\n break;\n case 'regex':\n out += `.regex(${c.pattern})`;\n break;\n case 'min':\n out += `.min(${c.value})`;\n break;\n case 'max':\n out += `.max(${c.value})`;\n break;\n }\n }\n return out;\n}\n\nfunction render(node: SchemaNode, ctx: RenderContext): string {\n switch (node.kind) {\n case 'string':\n return `z.string()${renderStringChecks(node.checks)}`;\n case 'number': {\n let out = 'z.number()';\n for (const c of node.checks) {\n if (c.check === 'int') out += '.int()';\n else if (c.check === 'positive') out += '.positive()';\n else if (c.check === 'negative') out += '.negative()';\n else if (c.check === 'min') out += `.min(${c.value})`;\n else if (c.check === 'max') out += `.max(${c.value})`;\n }\n return out;\n }\n case 'boolean':\n return 'z.boolean()';\n case 'date':\n return 'z.coerce.date()';\n case 'unknown':\n return node.note ? `z.unknown() /* ${node.note} */` : 'z.unknown()';\n case 'instanceof':\n return `z.instanceof(${node.ctor})`;\n case 'enum':\n return `z.enum([${node.literals.join(', ')}])`;\n case 'literal':\n return `z.literal(${node.raw})`;\n case 'union':\n return `z.union([${node.options.map((o) => render(o, ctx)).join(', ')}])`;\n case 'object': {\n if (node.fields.length === 0) {\n return node.passthrough ? 'z.object({}).passthrough()' : 'z.object({})';\n }\n const inner = node.fields\n .map((f) => `${toObjectKey(f.key)}: ${render(f.value, ctx)}`)\n .join(', ');\n return `z.object({ ${inner} })${node.passthrough ? '.passthrough()' : ''}`;\n }\n case 'array':\n return `z.array(${render(node.element, ctx)})`;\n case 'optional':\n return `${render(node.inner, ctx)}.optional()`;\n case 'ref':\n return node.name;\n case 'lazyRef':\n return `z.lazy(() => ${node.name})`;\n case 'annotated': {\n const comments = node.unmappable\n .map((n) => `/* @${n}: not translatable to zod (server-only) */`)\n .join(' ');\n return `${render(node.inner, ctx)} ${comments}`;\n }\n }\n}\n\nexport const zodAdapter: ValidationAdapter = {\n name: 'zod',\n importStatements(usage: AdapterUsage): string[] {\n return usage.used ? [\"import { z } from 'zod';\"] : [];\n },\n render,\n inferType(schemaConst: string): string {\n return `z.infer<typeof ${schemaConst}>`;\n },\n renderModule(mod: SchemaModule): RenderedModule {\n const ctx: RenderContext = { named: mod.named };\n const namedNestedSchemas = new Map<string, string>();\n for (const [name, node] of mod.named) {\n namedNestedSchemas.set(name, render(node, ctx));\n }\n return { schemaText: render(mod.root, ctx), namedNestedSchemas, warnings: mod.warnings };\n },\n};\n","import { ConfigError } from '../exceptions.js';\nimport type { ValidationAdapter } from './types.js';\nimport { zodAdapter } from './zod.js';\n\n/** A built-in adapter name or a custom adapter instance. */\nexport type ValidationOption = 'zod' | 'valibot' | 'arktype' | ValidationAdapter;\n\n/**\n * Resolve a `validation` config value to a {@link ValidationAdapter}. `'zod'` is\n * bundled in core; the valibot/arktype adapters ship as their own packages — import\n * the adapter instance and pass it directly (it passes through here). A custom\n * adapter object also passes through.\n *\n * @example\n * import { valibotAdapter } from '@dudousxd/nestjs-codegen-valibot';\n * defineConfig({ validation: valibotAdapter });\n */\nexport function resolveAdapter(option: ValidationOption): ValidationAdapter {\n if (typeof option !== 'string') return option;\n if (option === 'zod') return zodAdapter;\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 { discoverContractsFast } from '../discovery/contracts-fast.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport { generate } from '../generate.js';\nimport { acquireLock } from './lock-file.js';\n\nconst PAGES_DEBOUNCE_MS = 150;\n\nexport interface Watcher {\n close(): Promise<void>;\n}\n\n/** No-op watcher returned when the lock is already held. */\nconst NO_OP_WATCHER: Watcher = { close: async () => {} };\n\n/**\n * Start two chokidar watchers:\n *\n * 1. **Pages watcher** (`config.pages.glob`, 150 ms debounce) — runs `generate(config)` on\n * any page file change, regenerating `pages.d.ts` and the cache manifest.\n *\n * 2. **Contracts watcher** (`config.contracts.glob`, configurable debounce — default 500 ms) —\n * re-runs static AST route discovery via ts-morph, then re-emits `routes.ts` and (when\n * contracts are present) `api.ts` + `index.d.ts`.\n *\n * Both watchers share a single lock file in `config.codegen.outDir`. If another live process\n * already holds the lock, logs a warning and returns a no-op watcher.\n */\nexport async function watch(config: ResolvedConfig, onChange?: () => void): Promise<Watcher> {\n const lock = await acquireLock(config.codegen.outDir);\n\n if (lock === null) {\n // Read the lock file to include the PID in the warning message\n let holderPid = 'unknown';\n try {\n const raw = await readFile(join(config.codegen.outDir, '.watcher.lock'), 'utf8');\n const data = JSON.parse(raw) as { pid?: number };\n if (data.pid !== undefined) holderPid = String(data.pid);\n } catch {\n // Lock file unreadable — fall back to generic warning\n }\n console.warn(\n `[nestjs-codegen] auto-watch skipped — another process (PID ${holderPid}) is already running the watcher in ${config.codegen.outDir}. Files will continue to regenerate from that process. To take over, stop the other watcher.`,\n );\n return NO_OP_WATCHER;\n }\n\n // Run an initial full pass: pages + routes + contracts (same as a one-shot `codegen` run)\n try {\n const initialRoutes = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n await generate(config, initialRoutes);\n } catch (err) {\n // Best-effort; don't crash the watcher on initial generation failure\n console.warn(\n `[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`,\n );\n try {\n await generate(config);\n } catch {\n /* fallback: pages only */\n }\n }\n\n // ── Pages watcher (fast path — no route discovery) ──────────────────────────\n let pagesDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n // No `pages` config → watch a path that matches nothing (pages are Inertia-only).\n const pagesGlob = config.pages?.glob ?? '.nestjs-codegen-no-pages';\n const pagesWatcher = chokidar.watch(join(config.codegen.cwd, pagesGlob), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n function schedulePagesRegenerate(): void {\n if (pagesDebounceTimer !== undefined) {\n clearTimeout(pagesDebounceTimer);\n }\n pagesDebounceTimer = setTimeout(async () => {\n pagesDebounceTimer = undefined;\n try {\n await generate(config);\n } catch (err) {\n console.error(\n '[nestjs-codegen] Pages generation failed:',\n err instanceof Error ? err.message : err,\n );\n }\n onChange?.();\n }, PAGES_DEBOUNCE_MS);\n }\n\n pagesWatcher.on('add', schedulePagesRegenerate);\n pagesWatcher.on('change', schedulePagesRegenerate);\n pagesWatcher.on('unlink', schedulePagesRegenerate);\n\n // ── Contracts watcher (static AST discovery via ts-morph) ────────────────────\n let contractsDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n const contractsWatcher = chokidar.watch(join(config.codegen.cwd, config.contracts.glob), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n function scheduleContractsRegenerate(): void {\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n }\n contractsDebounceTimer = setTimeout(async () => {\n contractsDebounceTimer = undefined;\n try {\n const routes: RouteDescriptor[] = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n\n // Route through generate() so the incremental pass honors the SAME emit\n // options as the initial pass (query / mutationClient / queryImport / fetcher\n // importPath + the validation adapter). Emitting api.ts/forms.ts directly here\n // would silently drop those settings on every contract edit.\n await generate(config, routes);\n } catch (err) {\n console.error(\n '[nestjs-codegen] Contracts generation failed:',\n err instanceof Error ? err.message : err,\n );\n }\n onChange?.();\n }, config.contracts.debounceMs);\n }\n\n contractsWatcher.on('add', scheduleContractsRegenerate);\n contractsWatcher.on('change', scheduleContractsRegenerate);\n contractsWatcher.on('unlink', scheduleContractsRegenerate);\n\n // ── DTO watcher (forms.ts synthesis from class-validator DTOs) ───────────────\n // DTO classes live in *.dto.ts files (not matched by the controller glob), but\n // changes to them affect the synthesized form schemas. Re-run discovery (which\n // re-emits forms.ts) on any DTO change, reusing the contracts debounce.\n const formsWatcher = chokidar.watch(join(config.codegen.cwd, config.forms.watch), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n formsWatcher.on('add', scheduleContractsRegenerate);\n formsWatcher.on('change', scheduleContractsRegenerate);\n formsWatcher.on('unlink', scheduleContractsRegenerate);\n\n return {\n close: async () => {\n if (pagesDebounceTimer !== undefined) {\n clearTimeout(pagesDebounceTimer);\n pagesDebounceTimer = undefined;\n }\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n contractsDebounceTimer = undefined;\n }\n await pagesWatcher.close();\n await contractsWatcher.close();\n await formsWatcher.close();\n await lock.release();\n },\n };\n}\n","import { join, resolve } from 'node:path';\nimport fg from 'fast-glob';\n/**\n * Static AST-based contract discovery using ts-morph.\n * Cold start ~100-500 ms.\n */\nimport {\n type ClassDeclaration,\n type InterfaceDeclaration,\n type MethodDeclaration,\n Node,\n Project,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport { extractSchemaFromDto } from './dto-to-ir.js';\nimport { extractZodFromDto } from './dto-to-zod.js';\nimport { extractApplyFilterInfo } from './filter-for.js';\nimport {\n type TypeDeclResult,\n dbg,\n findType,\n loadTsconfigPaths,\n resolveImportedType,\n resolveTypeRef,\n restoreDiscoveryContext,\n setDiscoveryContext,\n} from './type-ref-resolution.js';\nimport type { FilterFieldType, RouteDescriptor, TypeRef } from './types.js';\n\nexport interface FastDiscoveryOptions {\n /** Absolute path to the project root. */\n cwd: string;\n /** Controllers glob, e.g. 'src/**\\/*.controller.ts' */\n glob: string;\n /** Optional tsconfig.json path; default 'tsconfig.json' in cwd */\n tsconfig?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport async function discoverContractsFast(\n opts: FastDiscoveryOptions,\n): Promise<RouteDescriptor[]> {\n const { cwd, glob, tsconfig } = opts;\n\n const tsconfigPath = tsconfig ? resolve(tsconfig) : join(cwd, 'tsconfig.json');\n\n // Try to use tsconfig if it exists; fall back to bare compiler options\n let project: Project;\n try {\n project = new Project({\n tsConfigFilePath: tsconfigPath,\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n });\n } catch {\n // tsconfig not found — create a minimal project without it\n project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: {\n allowJs: true,\n resolveJsonModule: false,\n strict: false,\n },\n });\n }\n\n // Resolve controller file paths\n const files = await fg(glob, { cwd, absolute: true, onlyFiles: true });\n\n for (const f of files) {\n project.addSourceFileAtPath(f);\n }\n\n const routes: RouteDescriptor[] = [];\n\n // Save previous context and set current (prevents cross-call corruption)\n const prevCtx = setDiscoveryContext({\n projectRoot: cwd,\n tsconfigPaths: loadTsconfigPaths(tsconfigPath),\n });\n\n try {\n for (const sourceFile of project.getSourceFiles()) {\n routes.push(...extractFromSourceFile(sourceFile, project));\n }\n } finally {\n // Restore previous context so concurrent callers are not affected\n restoreDiscoveryContext(prevCtx);\n }\n\n return routes;\n}\n\n// ---------------------------------------------------------------------------\n// AST walker — exported so unit tests can import it directly\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a ts-morph Node (expression) representing a Zod schema call to a\n * TypeScript type-source string. Falls back to `'unknown'` for anything\n * unrecognised.\n */\nexport function zodAstToTs(node: Node): string {\n // We only handle call expressions (e.g. z.string(), z.object({…}).optional())\n if (!Node.isCallExpression(node)) return 'unknown';\n\n const expr = node.getExpression();\n\n // ── Chained calls: z.xxx().optional() / .nullable() ──────────────────────\n if (Node.isPropertyAccessExpression(expr)) {\n const methodName = expr.getName();\n const receiver = expr.getExpression();\n\n if (methodName === 'optional') {\n return `${zodAstToTs(receiver)} | undefined`;\n }\n if (methodName === 'nullable') {\n return `${zodAstToTs(receiver)} | null`;\n }\n\n // ── z.<method>(…) top-level calls ────────────────────────────────────────\n const args = node.getArguments();\n\n switch (methodName) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'unknown':\n return 'unknown';\n case 'any':\n return 'unknown';\n\n case 'literal': {\n const lit = args[0];\n if (!lit) return 'unknown';\n if (Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());\n if (Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();\n if (lit.getKind() === SyntaxKind.TrueKeyword) return 'true';\n if (lit.getKind() === SyntaxKind.FalseKeyword) return 'false';\n return 'unknown';\n }\n\n case 'enum': {\n // z.enum([\"a\",\"b\",\"c\"])\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n const members = arrArg\n .getElements()\n .map((el) =>\n Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : 'unknown',\n );\n return members.join(' | ');\n }\n\n case 'array': {\n const inner = args[0];\n if (!inner) return 'unknown';\n return `Array<${zodAstToTs(inner)}>`;\n }\n\n case 'object': {\n const objArg = args[0];\n if (!objArg || !Node.isObjectLiteralExpression(objArg)) return 'unknown';\n const lines: string[] = [];\n for (const prop of objArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const key = prop.getName();\n const valNode = prop.getInitializer();\n if (!valNode) continue;\n const tsType = zodAstToTs(valNode);\n // Mark optional if the value is .optional()\n const isOpt = isOptionalChain(valNode);\n lines.push(`${key}${isOpt ? '?' : ''}: ${tsType}`);\n }\n return `{ ${lines.join('; ')} }`;\n }\n\n case 'union': {\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n return arrArg.getElements().map(zodAstToTs).join(' | ');\n }\n\n case 'record': {\n // z.record(V) or z.record(K, V) — always emit Record<string, V>\n const valArg = args.length === 1 ? args[0] : args[1];\n if (!valArg) return 'unknown';\n return `Record<string, ${zodAstToTs(valArg)}>`;\n }\n\n case 'tuple': {\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n return `[${arrArg.getElements().map(zodAstToTs).join(', ')}]`;\n }\n\n default:\n return 'unknown';\n }\n }\n\n return 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Return true when `node` is a CallExpression ending in `.optional()`. */\nfunction isOptionalChain(node: Node): boolean {\n if (!Node.isCallExpression(node)) return false;\n const expr = node.getExpression();\n return Node.isPropertyAccessExpression(expr) && expr.getName() === 'optional';\n}\n\n/** Extract the string value from a decorator argument that is a string literal. */\nfunction decoratorStringArg(decoratorExpr: Node | undefined): string | undefined {\n if (!decoratorExpr) return undefined;\n if (Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();\n if (Node.isArrayLiteralExpression(decoratorExpr)) {\n const first = decoratorExpr.getElements()[0];\n if (first && Node.isStringLiteral(first)) return first.getLiteralValue();\n }\n return undefined;\n}\n\n/**\n * Parse a defineContract({...}) call expression.\n * Returns { query, body, response } or null if unrecognised.\n */\ninterface ParsedContractDef {\n query: string | null;\n body: string | null;\n response: string;\n /** Raw zod source text of the body initializer (for inline forms emit). */\n bodyZodText: string | null;\n /** Raw zod source text of the query initializer (for inline forms emit). */\n queryZodText: string | null;\n}\n\nfunction parseDefineContractCall(callExpr: Node): ParsedContractDef | null {\n if (!Node.isCallExpression(callExpr)) return null;\n\n const callee = callExpr.getExpression();\n // Accept both `defineContract(...)` and any identifier named defineContract\n const calleeName = Node.isIdentifier(callee)\n ? callee.getText()\n : Node.isPropertyAccessExpression(callee)\n ? callee.getName()\n : '';\n\n if (calleeName !== 'defineContract') return null;\n\n const args = callExpr.getArguments();\n const optsArg = args[0];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\n\n let query: string | null = null;\n let body: string | null = null;\n let response = 'unknown';\n let bodyZodText: string | null = null;\n let queryZodText: string | null = null;\n\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const propName = prop.getName();\n const val = prop.getInitializer();\n if (!val) continue;\n\n if (propName === 'query') {\n query = zodAstToTs(val);\n queryZodText = val.getText();\n } else if (propName === 'body') {\n body = zodAstToTs(val);\n bodyZodText = val.getText();\n } else if (propName === 'response') {\n response = zodAstToTs(val);\n }\n }\n\n return { query, body, response, bodyZodText, queryZodText };\n}\n\n/**\n * Derive the route name from a controller class name and method name.\n * Strips the `Controller` suffix from the class name and lowercases the first letter.\n * e.g. `UsersController.list` → `users.list`\n */\nexport function deriveRouteName(className: string, methodName: string): string {\n const noSuffix = className.replace(/Controller$/, '');\n if (!noSuffix) {\n throw new Error(\n `Controller class name \"${className}\" derives empty route segment after stripping \"Controller\". Add an @As(...) override.`,\n );\n }\n const segment = noSuffix.charAt(0).toLowerCase() + noSuffix.slice(1);\n return `${segment}.${methodName}`;\n}\n\n/**\n * Derive just the class segment (no method) from a controller class name.\n * Strips the `Controller` suffix and lowercases the first letter.\n */\nexport function deriveClassSegment(className: string): string {\n const noSuffix = className.replace(/Controller$/, '');\n if (!noSuffix) {\n throw new Error(\n `Controller class name \"${className}\" derives empty route segment after stripping \"Controller\". Add an @As(...) override at the class level.`,\n );\n }\n return noSuffix.charAt(0).toLowerCase() + noSuffix.slice(1);\n}\n\n/**\n * Compose the final route name from class-level and method-level @As decorators.\n * Rule:\n * classPortion = class @As value ?? deriveClassSegment(className)\n * methodPortion = method @As value ?? methodName\n * result = `${classPortion}.${methodPortion}`\n */\nexport function resolveRouteName(\n className: string,\n methodName: string,\n classAs: string | undefined,\n methodAs: string | undefined,\n): string {\n const classPortion = classAs ?? deriveClassSegment(className);\n const methodPortion = methodAs ?? methodName;\n return `${classPortion}.${methodPortion}`;\n}\n\n/** Join two URL path segments, normalising duplicate slashes. */\nexport function joinPaths(prefix: string, suffix: string): string {\n if (!prefix && !suffix) return '/';\n if (!prefix) return suffix.startsWith('/') ? suffix : `/${suffix}`;\n if (!suffix) return prefix.startsWith('/') ? prefix : `/${prefix}`;\n\n const p = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const s = suffix.startsWith('/') ? suffix : `/${suffix}`;\n const combined = p + s;\n return combined === '' ? '/' : combined;\n}\n\n/** Extract path params from a URL pattern string, e.g. `/users/:id` → [{name:'id',source:'path'}] */\nfunction extractParams(\n path: string,\n): Array<{ name: string; source: 'path' | 'query' | 'body' | 'header' }> {\n const matches = path.matchAll(/:(\\w+)/g);\n return Array.from(matches).map((m) => ({ name: m[1] as string, source: 'path' as const }));\n}\n\n// ---------------------------------------------------------------------------\n// DTO-based contract extraction (standard NestJS patterns — no defineContract)\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a TypeNode to a TypeScript type-source string.\n * Follows imports across files via the ts-morph Project.\n * `depth` limits recursive expansion (guards against circular references).\n */\nfunction resolveTypeNodeToString(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (depth <= 0) return 'unknown';\n\n // Array<T> or T[] — unwrap and wrap\n if (Node.isArrayTypeNode(typeNode)) {\n const elementType = typeNode.getElementTypeNode();\n return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth)}>`;\n }\n\n // Union: A | B | C — resolve each member so named refs get inlined\n if (Node.isUnionTypeNode(typeNode)) {\n return typeNode\n .getTypeNodes()\n .map((t) => resolveTypeNodeToString(t, sourceFile, project, depth))\n .join(' | ');\n }\n\n // Intersection: A & B — same treatment\n if (Node.isIntersectionTypeNode(typeNode)) {\n return typeNode\n .getTypeNodes()\n .map((t) => resolveTypeNodeToString(t, sourceFile, project, depth))\n .join(' & ');\n }\n\n // Parenthesized: ( ... ) — unwrap\n if (Node.isParenthesizedTypeNode(typeNode)) {\n return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth)})`;\n }\n\n // TypeReference: Foo, Foo[], Array<Foo>, Promise<Foo>, etc.\n if (Node.isTypeReference(typeNode)) {\n const typeName = typeNode.getTypeName();\n const name = Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();\n\n // Well-known pass-through primitives and types\n if (name === 'string' || name === 'number' || name === 'boolean') return name;\n if (name === 'Date') return 'string';\n if (name === 'unknown' || name === 'any' || name === 'void') return 'unknown';\n // Server-only types that don't make sense on the client\n if (name === 'StreamableFile' || name === 'Observable' || name === 'ReadableStream')\n return 'unknown';\n\n // MikroORM Ref/Reference/LoadedReference are server-side wrappers around\n // related entities. The wire shape is just the referenced entity (or a\n // shallow `{ id }` projection when not populated). Unwrap to the type\n // argument so client code sees the plain entity shape.\n if (\n name === 'Ref' ||\n name === 'Reference' ||\n name === 'LoadedReference' ||\n name === 'IdentifiedReference'\n ) {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);\n }\n return 'unknown';\n }\n // MikroORM Collection<T> serializes as an array of T on the wire.\n if (name === 'Collection') {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return `Array<${resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth)}>`;\n }\n return 'Array<unknown>';\n }\n // MikroORM Opt<T> / Loaded<T, ...> — Opt is a marker, Loaded is a wrapper.\n // Both reduce to T at the JSON wire level.\n if (name === 'Opt' || name === 'Loaded') {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);\n }\n return 'unknown';\n }\n\n // Array<T> generic form\n if (name === 'Array') {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return `Array<${resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth)}>`;\n }\n return 'Array<unknown>';\n }\n\n // Well-known utility types — preserve full text with type args\n if (\n ['Record', 'Omit', 'Pick', 'Partial', 'Required', 'Readonly', 'Map', 'Set'].includes(name)\n ) {\n return typeNode.getText();\n }\n\n // Promise<T> — unwrap\n if (name === 'Promise') {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n return resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);\n }\n return 'unknown';\n }\n\n // Try same file first, then follow imports (class, interface, type alias, enum)\n const resolved = findType(name, sourceFile, project);\n if (resolved) {\n return expandTypeDecl(resolved, project, depth - 1);\n }\n\n // 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 * Expand a TypeDeclResult into an inline TS type string.\n */\nfunction expandTypeDecl(result: TypeDeclResult, project: Project, depth: number): string {\n if (depth < 0) return 'unknown';\n switch (result.kind) {\n case 'class':\n return resolvePropertied(result.decl, result.file, project, depth);\n case 'interface':\n return resolvePropertied(result.decl, result.file, project, depth);\n case 'typeAlias':\n // Recursively resolve the alias body so that any named types it\n // references (e.g. `A | B | C`) are expanded inline rather than left\n // as bare identifiers, which would be undefined in the emitted code.\n if (result.typeNode) {\n return resolveTypeNodeToString(result.typeNode, result.file, project, depth);\n }\n return result.text;\n case 'enum':\n return result.members.join(' | ');\n }\n}\n\n/**\n * Turn a class or interface declaration's properties into a TS object type string like\n * `{ id: string; title: string; page?: number }`.\n */\nfunction resolvePropertied(\n decl: ClassDeclaration | InterfaceDeclaration,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (depth < 0) return 'unknown';\n\n const lines: string[] = [];\n for (const prop of decl.getProperties()) {\n const propName = prop.getName();\n const isOptional = prop.hasQuestionToken();\n const propTypeNode = prop.getTypeNode();\n let propType = 'unknown';\n if (propTypeNode) {\n propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth);\n }\n lines.push(`${propName}${isOptional ? '?' : ''}: ${propType}`);\n }\n return `{ ${lines.join('; ')} }`;\n}\n\n/**\n * Extract the body type from a `@Body()` (no-arg) decorated parameter.\n * Returns a TS type string or null.\n */\nfunction extractBodyType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string | null {\n for (const param of method.getParameters()) {\n const bodyDecorator = param.getDecorators().find((d) => d.getName() === 'Body');\n if (!bodyDecorator) continue;\n const bodyArgs = bodyDecorator.getArguments();\n if (bodyArgs.length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n return null;\n}\n\n/**\n * Extract the query type from a `@Query()` (no-arg) decorated parameter.\n * Returns a TS type string or null.\n */\nfunction extractQueryType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string | null {\n for (const param of method.getParameters()) {\n const queryDecorator = param.getDecorators().find((d) => d.getName() === 'Query');\n if (!queryDecorator) continue;\n const queryArgs = queryDecorator.getArguments();\n if (queryArgs.length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n return null;\n}\n\n/**\n * Collect `@Param('name')` decorated parameters into a `{ name: type; ... }` string.\n * Returns a TS type string or null when no @Param decorators are present.\n */\nfunction extractParamsType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string | null {\n const entries: string[] = [];\n for (const param of method.getParameters()) {\n const paramDecorator = param.getDecorators().find((d) => d.getName() === 'Param');\n if (!paramDecorator) continue;\n const paramArgs = paramDecorator.getArguments();\n if (paramArgs.length === 0) continue;\n const nameArg = paramArgs[0];\n if (!Node.isStringLiteral(nameArg)) continue;\n const paramName = nameArg.getLiteralValue();\n const typeNode = param.getTypeNode();\n const paramType = typeNode\n ? resolveTypeNodeToString(typeNode, sourceFile, project, 3)\n : 'string';\n entries.push(`${paramName}: ${paramType}`);\n }\n return entries.length > 0 ? `{ ${entries.join('; ')} }` : null;\n}\n\n/**\n * Extract the response type from `@ApiResponse({ type: X })` or `@ApiResponse({ type: [X] })`.\n * Falls back to the method return type annotation (unwrapping `Promise<>`).\n * Returns a TS type string (never null — falls back to 'unknown').\n */\nfunction extractResponseType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string {\n // 1. Try @ApiResponse\n const apiResponseDecorator = method.getDecorator('ApiResponse');\n if (apiResponseDecorator) {\n const args = apiResponseDecorator.getArguments();\n const optsArg = args[0];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n if (prop.getName() !== 'type') continue;\n const val = prop.getInitializer();\n if (!val) continue;\n\n // type: [PostDto] — array syntax\n if (Node.isArrayLiteralExpression(val)) {\n const elements = val.getElements();\n const firstEl = elements[0];\n if (elements.length > 0 && firstEl !== undefined) {\n const innerType = resolveIdentifierToClassType(firstEl, sourceFile, project, 3);\n return `Array<${innerType}>`;\n }\n return 'Array<unknown>';\n }\n\n // type: PostDto — single class reference\n return resolveIdentifierToClassType(val, sourceFile, project, 3);\n }\n }\n }\n\n // 2. Fall back to return type annotation\n const returnTypeNode = method.getReturnTypeNode();\n if (returnTypeNode) {\n return resolveTypeNodeToString(returnTypeNode, sourceFile, project, 3);\n }\n\n return 'unknown';\n}\n\n/**\n * Resolve an expression (expected to be a class identifier) to its expanded type string.\n * E.g. the `PostDto` identifier in `@ApiResponse({ type: PostDto })`.\n */\nfunction resolveIdentifierToClassType(\n node: Node,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (!Node.isIdentifier(node)) return 'unknown';\n const name = node.getText();\n const resolved = findType(name, sourceFile, project);\n if (resolved) {\n return expandTypeDecl(resolved, project, depth - 1);\n }\n return name;\n}\n\n/**\n * Resolve a `@Body()` / `@Query()` param or return-type `TypeNode` to a named\n * exported class/interface ref (unwrapping `Promise<T>` / `Array<T>` / `T[]`).\n * Thin wrapper over the shared {@link resolveTypeRef}.\n */\nfunction resolveBodyQueryResponseRef(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n): TypeRef | null {\n return resolveTypeRef(typeNode, sourceFile, project, {\n kinds: ['class', 'interface'],\n unwrapContainers: true,\n });\n}\n\n/**\n * Determine whether a method has any DTO-based contract info worth emitting\n * (body, query, params, or non-unknown response).\n * Returns a ContractSource-shaped object or null.\n */\nexport function extractDtoContract(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): {\n query: string | null;\n body: string | null;\n response: string;\n params: string | null;\n queryRef?: TypeRef | null;\n bodyRef?: TypeRef | null;\n responseRef?: TypeRef | null;\n filterFields?: string[] | null;\n filterFieldTypes?: FilterFieldType[] | null;\n filterSource?: 'body' | 'query' | null;\n bodyZodText?: string | null;\n queryZodText?: string | null;\n formNestedSchemas?: Record<string, string> | null;\n formWarnings?: string[];\n bodySchema?: import('../ir/schema-node.js').SchemaModule | null;\n querySchema?: import('../ir/schema-node.js').SchemaModule | null;\n} | null {\n let body = extractBodyType(method, sourceFile, project);\n const filterInfo = extractApplyFilterInfo(method, sourceFile, project);\n const query = extractQueryType(method, sourceFile, project);\n\n // Place filter type on the correct field based on @ApplyFilter source. The\n // body-source case still pre-renders a fixed `FilterQueryResult` here; the\n // query-source TypedFilterQuery TYPE is rendered in emit-api.ts (from\n // filterFields + filterFieldTypes) so it is byte-identical to the\n // `_filterQueryTyped<...>` factory args.\n if (filterInfo && filterInfo.source === 'body') {\n const bodyType = \"import('@dudousxd/nestjs-filter-client').FilterQueryResult\";\n body = body ?? bodyType;\n }\n\n const paramsType = extractParamsType(method, sourceFile, project);\n const response = extractResponseType(method, sourceFile, project);\n\n // Only emit a contract if there is at least something useful. A query-source\n // `@ApplyFilter` route carries no pre-rendered `query` string anymore (the\n // TypedFilterQuery type is rendered in emit-api), so it must be kept alive via\n // `filterInfo` even when every other field is empty.\n if (\n body === null &&\n query === null &&\n paramsType === null &&\n response === 'unknown' &&\n filterInfo === null\n ) {\n return null;\n }\n\n // Capture type references for import generation\n let bodyRef: TypeRef | null = null;\n let queryRef: TypeRef | null = null;\n let responseRef: TypeRef | null = null;\n\n for (const param of method.getParameters()) {\n if (param.getDecorators().some((d) => d.getName() === 'Body') && param.getTypeNode()) {\n bodyRef = resolveBodyQueryResponseRef(param.getTypeNode()!, sourceFile, project);\n }\n if (param.getDecorators().some((d) => d.getName() === 'Query') && param.getTypeNode()) {\n queryRef = resolveBodyQueryResponseRef(param.getTypeNode()!, sourceFile, project);\n }\n }\n\n const returnTypeNode = method.getReturnTypeNode();\n if (returnTypeNode) {\n responseRef = resolveBodyQueryResponseRef(returnTypeNode, sourceFile, project);\n }\n // Also check @ApiResponse\n if (!responseRef) {\n const apiResp = method.getDecorator('ApiResponse');\n if (apiResp) {\n const args = apiResp.getArguments();\n const optsArg = args[0];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n for (const prop of optsArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'type') {\n const val = prop.getInitializer();\n if (val && Node.isIdentifier(val)) {\n const name = val.getText();\n const localDecl =\n sourceFile.getInterface(name) ||\n sourceFile.getClass(name) ||\n sourceFile.getTypeAlias(name);\n if (localDecl?.isExported()) {\n responseRef = { name, filePath: sourceFile.getFilePath() };\n } else {\n const resolved = resolveImportedType(name, sourceFile, project);\n if (\n resolved &&\n (resolved.kind === 'class' || resolved.kind === 'interface') &&\n resolved.decl.isExported()\n ) {\n responseRef = { name, filePath: resolved.file.getFilePath() };\n }\n }\n }\n }\n }\n }\n }\n }\n\n // ── Synthesize form zod schemas from class-validator DTOs (Path B) ────────\n // Resolve the @Body()/@Query() param to a class declaration and translate its\n // decorators. A defineContract schema always wins, so this only runs on the\n // plain-verb path where no contract schema is present.\n let bodyZodText: string | null = null;\n let queryZodText: string | null = null;\n // Neutral IR for class-validator DTOs, so emit-forms can render via any adapter.\n let bodySchema: import('../ir/schema-node.js').SchemaModule | null = null;\n let querySchema: import('../ir/schema-node.js').SchemaModule | null = null;\n const formNested: Record<string, string> = {};\n const formWarnings: string[] = [];\n\n const bodyClass = resolveParamClass(method, 'Body', sourceFile, project);\n if (bodyClass) {\n const result = extractZodFromDto(bodyClass.decl, bodyClass.file, project);\n bodyZodText = result.schemaText;\n for (const [k, v] of result.namedNestedSchemas) formNested[k] = v;\n formWarnings.push(...result.warnings);\n bodySchema = extractSchemaFromDto(bodyClass.decl, bodyClass.file, project);\n }\n const queryClass = resolveParamClass(method, 'Query', sourceFile, project);\n if (queryClass) {\n const result = extractZodFromDto(queryClass.decl, queryClass.file, project);\n queryZodText = result.schemaText;\n for (const [k, v] of result.namedNestedSchemas) formNested[k] = v;\n formWarnings.push(...result.warnings);\n querySchema = extractSchemaFromDto(queryClass.decl, queryClass.file, project);\n }\n\n return {\n query,\n body,\n response,\n params: paramsType,\n queryRef,\n bodyRef,\n responseRef,\n filterFields: filterInfo?.fieldNames ?? null,\n filterFieldTypes: filterInfo?.fieldTypes ?? null,\n filterSource: filterInfo?.source ?? null,\n bodyZodText,\n queryZodText,\n formNestedSchemas: Object.keys(formNested).length > 0 ? formNested : null,\n formWarnings,\n bodySchema,\n querySchema,\n };\n}\n\n/**\n * Resolve a `@Body()` / `@Query()` parameter's TS type to a class declaration\n * (following imports). Returns null for interfaces / plain types / unresolved.\n */\nfunction resolveParamClass(\n method: MethodDeclaration,\n decoratorName: 'Body' | 'Query',\n sourceFile: SourceFile,\n project: Project,\n): { decl: ClassDeclaration; file: SourceFile } | null {\n for (const param of method.getParameters()) {\n if (!param.getDecorators().some((d) => d.getName() === decoratorName)) continue;\n const typeNode = param.getTypeNode();\n if (!typeNode) continue;\n // Strip array suffix — translate the element class.\n const text = typeNode.getText().replace(/\\[\\]$/, '');\n if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(text)) continue;\n const resolved = findType(text, sourceFile, project);\n if (resolved && resolved.kind === 'class') {\n return { decl: resolved.decl, file: resolved.file };\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// HTTP method decorator names recognised by the fast path\n// ---------------------------------------------------------------------------\n\nconst HTTP_METHOD_DECORATORS: Record<string, string> = {\n Get: 'GET',\n Post: 'POST',\n Put: 'PUT',\n Patch: 'PATCH',\n Delete: 'DELETE',\n Options: 'OPTIONS',\n Head: 'HEAD',\n All: 'ALL',\n};\n\n// ---------------------------------------------------------------------------\n// Per-file extraction\n// ---------------------------------------------------------------------------\n\nfunction extractFromSourceFile(sourceFile: SourceFile, project: Project): RouteDescriptor[] {\n const routes: RouteDescriptor[] = [];\n // Track derived/assigned names to detect collisions: name → fully-qualified method ref\n const seenNames = new Map<string, string>();\n\n const classes = sourceFile.getClasses();\n\n for (const cls of classes) {\n // Find @Controller(...) decorator\n const controllerDecorator = cls.getDecorator('Controller');\n if (!controllerDecorator) continue;\n\n // Determine controller path prefix\n const controllerArgs = controllerDecorator.getArguments();\n const firstArg = controllerArgs[0];\n const prefix = decoratorStringArg(firstArg) ?? '';\n\n const className = cls.getName() ?? 'Unknown';\n\n // Walk all methods\n for (const method of cls.getMethods()) {\n // ── Determine HTTP method + sub-path from NestJS verb decorators ──────\n let httpMethod: string | undefined;\n let handlerPath = '';\n\n for (const [decoratorName, verb] of Object.entries(HTTP_METHOD_DECORATORS)) {\n const httpDecorator = method.getDecorator(decoratorName);\n if (httpDecorator) {\n httpMethod = verb;\n const httpArgs = httpDecorator.getArguments();\n const pathArg = httpArgs[0];\n handlerPath = decoratorStringArg(pathArg) ?? '';\n break;\n }\n }\n\n // ── Check for @ApplyContract ──────────────────────────────────────────\n const applyContractDecorator = method.getDecorator('ApplyContract');\n\n if (applyContractDecorator) {\n const decoratorArgs = applyContractDecorator.getArguments();\n const firstDecoratorArg = decoratorArgs[0];\n if (!firstDecoratorArg) continue;\n\n // Resolve contract definition from inline call or identifier\n let contractDef: ParsedContractDef | null = null;\n // When the contract is a named const we can import, re-export its\n // members (`<const>.body` / `<const>.query`) for perfect parity.\n let bodyZodRef: TypeRef | null = null;\n let queryZodRef: TypeRef | null = null;\n\n if (Node.isCallExpression(firstDecoratorArg)) {\n contractDef = parseDefineContractCall(firstDecoratorArg);\n } else if (Node.isIdentifier(firstDecoratorArg)) {\n const identName = firstDecoratorArg.getText();\n const varDecl = sourceFile.getVariableDeclaration(identName);\n if (!varDecl) {\n console.warn(\n `[nestjs-codegen/fast] Cannot resolve '${identName}' in ${sourceFile.getFilePath()} (cross-file imports are out-of-scope for v1) — skipping`,\n );\n continue;\n }\n\n const initializer = varDecl.getInitializer();\n if (!initializer) continue;\n\n contractDef = parseDefineContractCall(initializer);\n // Re-export the named contract's schema members (Path A). Only when the\n // const is exported so forms.ts can import it.\n if (contractDef && varDecl.isExported()) {\n const filePath = sourceFile.getFilePath();\n if (contractDef.body !== null) {\n bodyZodRef = { name: `${identName}.body`, filePath };\n }\n if (contractDef.query !== null) {\n queryZodRef = { name: `${identName}.query`, filePath };\n }\n }\n } else {\n console.warn(\n `[nestjs-codegen/fast] @ApplyContract arg is not an identifier or call expression in ${sourceFile.getFilePath()} — skipping`,\n );\n continue;\n }\n\n if (!contractDef) continue;\n\n // Method + path always come from NestJS decorators — skip if absent\n if (!httpMethod) continue;\n const resolvedMethod = httpMethod;\n const resolvedPath = joinPaths(prefix, handlerPath);\n\n const combined = resolvedPath;\n const params = extractParams(combined);\n\n // Determine route name: compose class-level @As + method-level @As\n const methodName = method.getName();\n\n // Read class-level @As\n const classAsDecorator = cls.getDecorator('As');\n let classAs: string | undefined;\n if (classAsDecorator) {\n const classAsArgs = classAsDecorator.getArguments();\n const classAsName = decoratorStringArg(classAsArgs[0]);\n if (!classAsName) {\n throw new Error(\n `@As decorator on class ${className} must have a non-empty string argument.`,\n );\n }\n classAs = classAsName;\n }\n\n // Read method-level @As\n const methodAsDecorator = method.getDecorator('As');\n let methodAs: string | undefined;\n if (methodAsDecorator) {\n const methodAsArgs = methodAsDecorator.getArguments();\n const methodAsName = decoratorStringArg(methodAsArgs[0]);\n if (!methodAsName) {\n throw new Error(\n `@As decorator on ${className}.${methodName} must have a non-empty string argument.`,\n );\n }\n methodAs = methodAsName;\n }\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // Collision detection across contracted routes\n const qualifiedRef = `${className}.${methodName}`;\n const existing = seenNames.get(routeName);\n if (existing !== undefined) {\n throw new Error(\n `Route name collision: \"${routeName}\" is used by both \"${existing}\" and \"${qualifiedRef}\". Use @As(...) to give one of them a unique name.`,\n );\n }\n seenNames.set(routeName, qualifiedRef);\n\n routes.push({\n method: resolvedMethod,\n path: combined,\n name: routeName,\n params,\n controllerRef: { className, methodName, filePath: sourceFile.getFilePath() },\n contract: {\n contractSource: {\n query: contractDef.query,\n body: contractDef.body,\n response: contractDef.response,\n // Path A: capture both the importable ref and the raw text. The\n // emitter prefers inlining the text (client-safe — re-exporting from\n // a controller 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 } else {\n // ── Plain HTTP verb decorator (no @ApplyContract) ──────────────────\n if (!httpMethod) continue;\n\n const combined = joinPaths(prefix, handlerPath);\n const params = extractParams(combined);\n\n const methodName = method.getName();\n\n // Read class-level @As\n const classAsDecorator = cls.getDecorator('As');\n let classAs: string | undefined;\n if (classAsDecorator) {\n const classAsArgs = classAsDecorator.getArguments();\n const classAsName = decoratorStringArg(classAsArgs[0]);\n if (classAsName) classAs = classAsName;\n }\n\n // Read method-level @As\n const methodAsDecorator = method.getDecorator('As');\n let methodAs: string | undefined;\n if (methodAsDecorator) {\n const methodAsArgs = methodAsDecorator.getArguments();\n const methodAsName = decoratorStringArg(methodAsArgs[0]);\n if (methodAsName) methodAs = methodAsName;\n }\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // ── DTO-based contract extraction ──────────────────────────────────\n const dtoContract = extractDtoContract(method, sourceFile, project);\n\n routes.push({\n method: httpMethod,\n path: combined,\n name: routeName,\n params,\n controllerRef: { className, methodName, filePath: sourceFile.getFilePath() },\n contract: {\n contractSource: {\n query: dtoContract?.query ?? null,\n body: dtoContract?.body ?? null,\n response: dtoContract?.response ?? 'unknown',\n queryRef: dtoContract?.queryRef ?? null,\n bodyRef: dtoContract?.bodyRef ?? null,\n responseRef: dtoContract?.responseRef ?? null,\n filterFields: dtoContract?.filterFields ?? null,\n filterFieldTypes: dtoContract?.filterFieldTypes ?? null,\n filterSource: dtoContract?.filterSource ?? null,\n bodyZodText: dtoContract?.bodyZodText ?? null,\n queryZodText: dtoContract?.queryZodText ?? null,\n formNestedSchemas: dtoContract?.formNestedSchemas ?? null,\n formWarnings: dtoContract?.formWarnings ?? [],\n bodySchema: dtoContract?.bodySchema ?? null,\n querySchema: dtoContract?.querySchema ?? null,\n },\n },\n });\n }\n }\n }\n\n return routes;\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 structural successor of `dto-to-zod.ts`: same control flow,\n * recursion guard, and warnings, but it emits `SchemaNode` values instead of zod\n * text. The zod adapter reproduces the previous output byte-for-byte.\n */\nimport {\n type ClassDeclaration,\n type Decorator,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport type { NumberCheck, SchemaModule, SchemaNode, StringCheck } from '../ir/schema-node.js';\nimport { findType } from './type-ref-resolution.js';\n\ninterface BuildContext {\n sourceFile: SourceFile;\n project: Project;\n named: Map<string, SchemaNode>;\n warnings: string[];\n warnedDecorators: Set<string>;\n emittedClasses: Map<string, string>;\n visiting: Set<string>;\n recursiveSchemas: Set<string>;\n depth: number;\n}\n\nconst KNOWN_DECORATORS = new Set([\n 'IsString',\n 'IsNumber',\n 'IsInt',\n 'IsBoolean',\n 'IsDate',\n 'IsEmail',\n 'IsUrl',\n 'IsUUID',\n 'MinLength',\n 'MaxLength',\n 'Length',\n 'Min',\n 'Max',\n 'IsPositive',\n 'IsNegative',\n 'Matches',\n 'IsEnum',\n 'IsIn',\n 'IsOptional',\n 'IsNotEmpty',\n 'IsArray',\n 'ValidateNested',\n 'Type',\n 'IsObject',\n 'Allow',\n 'IsDefined',\n]);\n\nexport function extractSchemaFromDto(\n classDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): SchemaModule {\n const ctx: BuildContext = {\n sourceFile,\n project,\n named: new Map(),\n warnings: [],\n warnedDecorators: new Set(),\n emittedClasses: new Map(),\n visiting: new Set(),\n recursiveSchemas: new Set(),\n depth: 0,\n };\n const root = buildObject(classDecl, sourceFile, ctx);\n // Recursive schemas cannot be hoisted as a plain `const X = (... X ...)` without\n // a type annotation. Degrade any self-referential nested schema to a neutral\n // `unknown` placeholder; each adapter renders its own lib's `unknown` + comment.\n for (const schemaName of ctx.recursiveSchemas) {\n ctx.named.set(schemaName, { kind: 'unknown', note: 'recursive type — not expanded' });\n }\n return { root, named: ctx.named, warnings: ctx.warnings };\n}\n\n// ---------------------------------------------------------------------------\n// Object builder\n// ---------------------------------------------------------------------------\n\nfunction buildObject(\n classDecl: ClassDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n const props = classDecl.getProperties();\n if (props.length === 0) {\n return { kind: 'object', fields: [], passthrough: true };\n }\n const fields: Array<{ key: string; value: SchemaNode }> = [];\n for (const prop of props) {\n fields.push({ key: prop.getName(), value: buildProperty(prop, classFile, ctx) });\n }\n return { kind: 'object', fields, passthrough: false };\n}\n\n// ---------------------------------------------------------------------------\n// Property builder — the §2.2 mapping table lives here.\n// ---------------------------------------------------------------------------\n\nfunction buildProperty(\n prop: PropertyDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n const decorators = new Map<string, Decorator>();\n for (const d of prop.getDecorators()) decorators.set(d.getName(), d);\n const has = (n: string): boolean => decorators.has(n);\n const dec = (n: string): Decorator | undefined => decorators.get(n);\n\n const typeNode = prop.getTypeNode();\n const typeText = typeNode?.getText() ?? 'unknown';\n const isArrayType = !!typeNode && typeNode.getText().endsWith('[]');\n\n // ── Nested / array-of-nested via @ValidateNested + @Type ────────────────\n const typeRefName = resolveTypeFactoryName(dec('Type'));\n if (has('ValidateNested') || typeRefName) {\n const childName = typeRefName ?? singularClassName(typeText);\n if (childName) {\n const childNode = buildNestedReference(childName, classFile, ctx);\n const wrapArray = has('IsArray') || isArrayType;\n const node: SchemaNode = wrapArray ? { kind: 'array', element: childNode } : childNode;\n return applyPresence(node, decorators);\n }\n }\n\n // ── Base type (TS property type), then decorator refinements ────────────\n let base = baseFromType(typeText, isArrayType);\n const stringChecks: StringCheck[] = [];\n const numberChecks: NumberCheck[] = [];\n\n // Type overrides\n if (has('IsString')) base = { kind: 'string', checks: stringChecks };\n if (has('IsBoolean')) base = { kind: 'boolean' };\n if (has('IsDate')) base = { kind: 'date' };\n if (has('IsNumber')) base = { kind: 'number', checks: numberChecks };\n if (has('IsInt')) {\n base = { kind: 'number', checks: numberChecks };\n numberChecks.push({ check: 'int' });\n }\n if (has('IsObject') && !has('ValidateNested')) {\n base = { kind: 'object', fields: [], passthrough: true };\n }\n if (has('Allow')) base = { kind: 'unknown' };\n\n const ensureString = (): void => {\n if (base.kind !== 'string') base = { kind: 'string', checks: stringChecks };\n };\n\n // String format refinements (these also imply string base).\n if (has('IsEmail')) {\n ensureString();\n const m = messageRaw(dec('IsEmail'));\n stringChecks.push(m === undefined ? { check: 'email' } : { check: 'email', messageRaw: m });\n }\n if (has('IsUrl')) {\n ensureString();\n const m = messageRaw(dec('IsUrl'));\n stringChecks.push(m === undefined ? { check: 'url' } : { check: 'url', messageRaw: m });\n }\n if (has('IsUUID')) {\n ensureString();\n const m = messageRaw(dec('IsUUID'));\n stringChecks.push(m === undefined ? { check: 'uuid' } : { check: 'uuid', messageRaw: m });\n }\n if (has('Matches')) {\n const re = firstArgText(dec('Matches'));\n if (re) {\n ensureString();\n stringChecks.push({ check: 'regex', pattern: re });\n }\n }\n\n // Length / size refinements\n if (has('MinLength')) {\n const n = numericArg(dec('MinLength'));\n if (n !== null) stringChecks.push({ check: 'min', value: n });\n }\n if (has('MaxLength')) {\n const n = numericArg(dec('MaxLength'));\n if (n !== null) stringChecks.push({ check: 'max', value: n });\n }\n if (has('Length')) {\n const [min, max] = numericArgs(dec('Length'));\n if (min !== null) stringChecks.push({ check: 'min', value: min });\n if (max !== null) stringChecks.push({ check: 'max', value: max });\n }\n if (has('Min')) {\n const n = numericArg(dec('Min'));\n if (n !== null) numberChecks.push({ check: 'min', value: n });\n }\n if (has('Max')) {\n const n = numericArg(dec('Max'));\n if (n !== null) numberChecks.push({ check: 'max', value: n });\n }\n if (has('IsPositive')) numberChecks.push({ check: 'positive' });\n if (has('IsNegative')) numberChecks.push({ check: 'negative' });\n if (has('IsNotEmpty') && base.kind === 'string') stringChecks.push({ check: 'min', value: '1' });\n\n // Enum / membership (replaces base).\n if (has('IsEnum')) {\n const enumNode = enumSchemaFromDecorator(dec('IsEnum'), classFile, ctx);\n if (enumNode) base = enumNode;\n }\n if (has('IsIn')) {\n const inNode = inSchemaFromDecorator(dec('IsIn'));\n if (inNode) base = inNode;\n }\n\n // ── Unmappable decorators → warn + comment, keep base ───────────────────\n const unmappable: string[] = [];\n for (const name of decorators.keys()) {\n if (!KNOWN_DECORATORS.has(name)) {\n unmappable.push(name);\n if (!ctx.warnedDecorators.has(name)) {\n ctx.warnedDecorators.add(name);\n const msg = `@${name} is not translatable to a client validation schema and was skipped (server-only validation).`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n }\n }\n\n // Attach the collected refinements to the base. `base` may have been created\n // by `baseFromType` (with its own empty checks array) or by an override, so\n // rebuild it here to guarantee the accumulated checks are the ones emitted.\n if (base.kind === 'string') base = { kind: 'string', checks: stringChecks };\n else if (base.kind === 'number') base = { kind: 'number', checks: numberChecks };\n\n let node: SchemaNode = base;\n\n // Array wrapping when the TS type is `T[]` and no nested handling occurred.\n if (isArrayType && node.kind !== 'array') {\n node = { kind: 'array', element: node };\n }\n\n node = applyPresence(node, decorators);\n\n if (unmappable.length > 0) {\n node = { kind: 'annotated', inner: node, unmappable };\n }\n return node;\n}\n\n/** `.optional()` / required handling from @IsOptional / @IsDefined. */\nfunction applyPresence(node: SchemaNode, decorators: Map<string, Decorator>): SchemaNode {\n if (decorators.has('IsDefined')) return node; // explicitly required\n if (decorators.has('IsOptional')) return { kind: 'optional', inner: node };\n return node;\n}\n\n// ---------------------------------------------------------------------------\n// Base type from the TS property type\n// ---------------------------------------------------------------------------\n\nfunction baseFromType(typeText: string, isArrayType: boolean): SchemaNode {\n const inner = isArrayType ? typeText.slice(0, -2).trim() : typeText;\n switch (inner) {\n case 'string':\n return { kind: 'string', checks: [] };\n case 'number':\n return { kind: 'number', checks: [] };\n case 'boolean':\n return { kind: 'boolean' };\n case 'Date':\n return { kind: 'date' };\n case 'File':\n case 'Express.Multer.File':\n return { kind: 'instanceof', ctor: 'File' };\n default:\n return { kind: 'unknown' };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nested DTO references (hoisted named consts)\n// ---------------------------------------------------------------------------\n\nfunction buildNestedReference(\n className: string,\n fromFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n // Recursion guard FIRST.\n if (ctx.visiting.has(className) || ctx.depth >= 8) {\n const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);\n ctx.emittedClasses.set(className, reserved);\n ctx.recursiveSchemas.add(reserved);\n if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {\n ctx.warnedDecorators.add(`recursive:${reserved}`);\n const msg = `${className} is a recursive type and was not expanded; the generated schema uses unknown for it.`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'lazyRef', name: reserved };\n }\n\n const existing = ctx.emittedClasses.get(className);\n if (existing) return { kind: 'ref', name: existing };\n\n const schemaName = aliasFor(className, ctx);\n const resolved = findType(className, fromFile, ctx.project);\n if (!resolved || resolved.kind !== 'class') {\n return { kind: 'object', fields: [], passthrough: true };\n }\n\n ctx.emittedClasses.set(className, schemaName);\n ctx.visiting.add(className);\n ctx.depth += 1;\n const childNode = buildObject(resolved.decl, resolved.file, ctx);\n ctx.depth -= 1;\n ctx.visiting.delete(className);\n\n ctx.named.set(schemaName, childNode);\n return { kind: 'ref', name: schemaName };\n}\n\nfunction aliasFor(className: string, ctx: BuildContext): string {\n const baseName = `${className}Schema`;\n let candidate = baseName;\n let i = 1;\n const used = new Set(ctx.named.keys());\n for (const v of ctx.emittedClasses.values()) used.add(v);\n while (used.has(candidate)) {\n candidate = `${baseName}_${i}`;\n i += 1;\n }\n return candidate;\n}\n\n// ---------------------------------------------------------------------------\n// Decorator argument readers (pure AST)\n// ---------------------------------------------------------------------------\n\nfunction firstArg(decorator: Decorator | undefined): Node | undefined {\n return decorator?.getArguments()[0];\n}\n\nfunction firstArgText(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n return arg ? arg.getText() : null;\n}\n\nfunction numericArg(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (arg && Node.isNumericLiteral(arg)) return arg.getText();\n return null;\n}\n\nfunction numericArgs(decorator: Decorator | undefined): [string | null, string | null] {\n const args = decorator?.getArguments() ?? [];\n const num = (n: Node | undefined): string | null =>\n n && Node.isNumericLiteral(n) ? n.getText() : null;\n return [num(args[0]), num(args[1])];\n}\n\n/** Reads a `{ message: '...' }` options object → the verbatim message literal text. */\nfunction messageRaw(decorator: Decorator | undefined): string | undefined {\n const args = decorator?.getArguments() ?? [];\n for (const arg of args) {\n if (Node.isObjectLiteralExpression(arg)) {\n for (const prop of arg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'message') {\n const init = prop.getInitializer();\n if (init && Node.isStringLiteral(init)) return init.getText();\n }\n }\n }\n }\n return undefined;\n}\n\n/** Resolve `@Type(() => Child)` → `'Child'`. */\nfunction resolveTypeFactoryName(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) return body.getText();\n }\n return null;\n}\n\n/** Drop array suffix from a type text → class name (`Child[]` → `Child`). */\nfunction singularClassName(typeText: string): string | null {\n const inner = typeText.endsWith('[]') ? typeText.slice(0, -2).trim() : typeText;\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(inner) ? inner : null;\n}\n\n/** `@IsEnum(E)` → enum node (or verbatim fallback when unresolvable). */\nfunction enumSchemaFromDecorator(\n decorator: Decorator | undefined,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isIdentifier(arg)) {\n const name = arg.getText();\n const resolved = findType(name, classFile, ctx.project);\n if (resolved && resolved.kind === 'enum') {\n return { kind: 'enum', literals: resolved.members };\n }\n const msg = `@IsEnum(${name}): enum could not be resolved to literal members and is not importable into the generated schema; falling back to unknown.`;\n if (!ctx.warnedDecorators.has(`IsEnum:${name}`)) {\n ctx.warnedDecorators.add(`IsEnum:${name}`);\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'unknown', note: `@IsEnum(${name}): enum not resolvable to literals` };\n }\n if (Node.isObjectLiteralExpression(arg)) {\n const values: string[] = [];\n for (const p of arg.getProperties()) {\n if (!Node.isPropertyAssignment(p)) continue;\n const init = p.getInitializer();\n if (init && Node.isStringLiteral(init)) values.push(init.getText());\n }\n if (values.length > 0) return { kind: 'enum', literals: values };\n }\n return null;\n}\n\n/** `@IsIn(['a','b'])` → enum node; non-string members → union of literals. */\nfunction inSchemaFromDecorator(decorator: Decorator | undefined): SchemaNode | null {\n const arg = firstArg(decorator);\n if (arg && Node.isArrayLiteralExpression(arg)) {\n const elements = arg.getElements();\n const allStrings = elements.every((e) => Node.isStringLiteral(e));\n if (allStrings && elements.length > 0) {\n return { kind: 'enum', literals: elements.map((e) => e.getText()) };\n }\n if (elements.length > 0) {\n return {\n kind: 'union',\n options: elements.map((e) => ({ kind: 'literal', raw: e.getText() })),\n };\n }\n }\n return null;\n}\n","import { readFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport {\n type ClassDeclaration,\n type InterfaceDeclaration,\n Node,\n type Project,\n type SourceFile,\n type TypeNode,\n} from 'ts-morph';\nimport type { TypeRef } from './types.js';\n\n/**\n * Type-reference resolution: the leaf module of the discovery DAG. Owns the\n * per-invocation discovery context (project root + tsconfig path aliases) and\n * the \"follow a name/TypeNode to its declaring file\" machinery shared by every\n * other discovery module.\n */\n\n// ---------------------------------------------------------------------------\n// Discovery context — scoped per `discoverContractsFast` invocation.\n// Saved/restored around each call to prevent cross-call corruption when\n// concurrent invocations occur (e.g. in tests or overlapping watcher triggers).\n// ---------------------------------------------------------------------------\n\nexport interface DiscoveryContext {\n projectRoot: string;\n tsconfigPaths: Record<string, string[]> | null;\n}\n\nlet _ctx: DiscoveryContext = { projectRoot: '', tsconfigPaths: null };\n\n/** Set the active discovery context, returning the previous one for restoration. */\nexport function setDiscoveryContext(ctx: DiscoveryContext): DiscoveryContext {\n const prev = _ctx;\n _ctx = ctx;\n return prev;\n}\n\n/** Restore a previously-saved discovery context. */\nexport function restoreDiscoveryContext(ctx: DiscoveryContext): void {\n _ctx = ctx;\n}\n\n// Backwards-compatible accessors for internal functions\nfunction _projectRoot(): string {\n return _ctx.projectRoot;\n}\nfunction _tsconfigPaths(): Record<string, string[]> | null {\n return _ctx.tsconfigPaths;\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 baseUrl = _projectRoot();\n const tsconfigPaths = _tsconfigPaths();\n\n dbg(\n 'resolveModuleSpecifier',\n moduleSpecifier,\n 'paths:',\n JSON.stringify(tsconfigPaths),\n 'baseUrl:',\n baseUrl,\n );\n\n if (tsconfigPaths) {\n for (const [pattern, mappings] of Object.entries(tsconfigPaths)) {\n const prefix = pattern.replace('*', '');\n if (moduleSpecifier.startsWith(prefix)) {\n const rest = moduleSpecifier.slice(prefix.length);\n const candidates: string[] = [];\n for (const mapping of mappings) {\n const resolved = resolve(baseUrl, mapping.replace('*', rest));\n candidates.push(`${resolved}.ts`, resolve(resolved, 'index.ts'));\n }\n dbg(' resolved candidates:', candidates);\n return candidates;\n }\n }\n }\n\n return [];\n}\n\nexport function resolveImportedType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);\n if (!namedImport) continue;\n\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);\n if (candidates.length === 0) continue;\n\n for (const candidate of candidates) {\n let importedFile = project.getSourceFile(candidate);\n if (!importedFile) {\n try {\n importedFile = project.addSourceFileAtPath(candidate);\n } catch {\n continue;\n }\n }\n const result = findTypeInFile(name, importedFile);\n if (result) return result;\n // The target module may itself re-export the symbol from elsewhere\n // (`export { X } from './mod'` or `import { X } ...; export { X }`).\n const viaReExport = resolveReExportedType(name, importedFile, project, new Set());\n if (viaReExport) return viaReExport;\n }\n }\n // The current file may re-export the symbol from another module.\n return resolveReExportedType(name, sourceFile, project, new Set());\n}\n\n/**\n * Follow `export { X } from './mod'` / `export * from './mod'` re-exports, and\n * bare `export { X }` statements that re-publish a previously-imported symbol,\n * to find a type declaration in a sibling module. Guards against import cycles\n * via `seen`.\n */\nfunction resolveReExportedType(\n name: string,\n file: SourceFile,\n project: Project,\n seen: Set<string>,\n): TypeDeclResult | null {\n const filePath = file.getFilePath();\n if (seen.has(filePath)) return null;\n seen.add(filePath);\n\n for (const exportDecl of file.getExportDeclarations()) {\n const moduleSpecifier = exportDecl.getModuleSpecifierValue();\n const namedExports = exportDecl.getNamedExports();\n\n // `export { X } from './mod'` — only follow when X (or its alias source) matches.\n if (moduleSpecifier) {\n const hasStar = namedExports.length === 0; // `export * from './mod'`\n const reExportsName = namedExports.some(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!hasStar && !reExportsName) continue;\n // The source-side name (before any alias rename).\n const sourceName = hasStar\n ? name\n : (namedExports\n .find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)\n ?.getName() ?? name);\n const target = followModuleForType(sourceName, moduleSpecifier, file, project, seen);\n if (target) return target;\n continue;\n }\n\n // `export { X }` (no module specifier) — X was imported above into this file.\n const reExportsName = namedExports.some(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!reExportsName) continue;\n const sourceName =\n namedExports.find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)?.getName() ??\n name;\n const local = findTypeInFile(sourceName, file);\n if (local) return local;\n const imported = resolveImportedType(sourceName, file, project);\n if (imported) return imported;\n }\n return null;\n}\n\nfunction followModuleForType(\n name: string,\n moduleSpecifier: string,\n fromFile: SourceFile,\n project: Project,\n seen: Set<string>,\n): TypeDeclResult | null {\n const candidates = resolveModuleSpecifier(moduleSpecifier, fromFile, project);\n for (const candidate of candidates) {\n let importedFile = project.getSourceFile(candidate);\n if (!importedFile) {\n try {\n importedFile = project.addSourceFileAtPath(candidate);\n } catch {\n continue;\n }\n }\n const result = findTypeInFile(name, importedFile);\n if (result) return result;\n const viaReExport = resolveReExportedType(name, importedFile, project, seen);\n if (viaReExport) return viaReExport;\n }\n return null;\n}\n\n/**\n * Find a type declaration by name: first in the current file, then by following imports.\n */\nexport function findType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n const local = findTypeInFile(name, sourceFile);\n if (local) return local;\n return resolveImportedType(name, sourceFile, project);\n}\n\n// ---------------------------------------------------------------------------\n// Importable named-ref resolution\n// ---------------------------------------------------------------------------\n\n/** The declaration kinds a `resolveTypeRef` call will accept as an importable ref. */\nexport type TypeRefKind = 'class' | 'interface' | 'typeAlias' | 'enum';\n\nexport interface ResolveTypeRefOptions {\n /**\n * Declaration kinds accepted as an importable named ref (applied identically\n * to local and imported declarations). The two call sites differ only here:\n * - body/query/response refs accept class + interface;\n * - `@FilterFor` param refs also accept enum + type alias.\n */\n kinds: TypeRefKind[];\n /**\n * Honour a bare (node_modules) import specifier — emit `{ name, filePath: spec }`\n * so the emitter imports straight from the package. tsconfig path aliases are\n * excluded (they resolve to files instead). Off for the body/query/response\n * path (which only ever points at project source files).\n */\n allowBareSpecifier?: boolean;\n /**\n * Unwrap `Promise<T>`, `Array<T>` and `T[]` to the inner named type (marking\n * array forms with `isArray`). Used for the body/query/response path which\n * receives a raw return/param `TypeNode`; the `@FilterFor` path passes a bare\n * symbol name and needs no unwrapping.\n */\n unwrapContainers?: boolean;\n}\n\n/** Skip-list of primitive / well-known names that never resolve to a named ref. */\nconst _NON_REF_NAMES = new Set(['string', 'number', 'boolean', 'void', 'unknown', 'any', 'Date']);\n\n/** Does an exported declaration found by `findTypeInFile` match the accepted kinds? */\nfunction _localDeclForKinds(name: string, file: SourceFile, kinds: TypeRefKind[]): boolean {\n if (kinds.includes('class') && file.getClass(name)?.isExported()) return true;\n if (kinds.includes('interface') && file.getInterface(name)?.isExported()) return true;\n if (kinds.includes('typeAlias') && file.getTypeAlias(name)?.isExported()) return true;\n if (kinds.includes('enum') && file.getEnum(name)?.isExported()) return true;\n return false;\n}\n\n/**\n * Resolve a type reference to an importable `TypeRef` — the symbol name plus the\n * absolute path of its declaring source file (for a relative import) OR the bare\n * module specifier (for a node_modules package). Accepts either a raw `TypeNode`\n * (with `unwrapContainers` to peel `Promise`/`Array`) or a bare symbol name.\n *\n * Walks: local exported decl → `{ name, thisFile }`; else the file's import\n * declarations to a matching exported decl → `{ name, importedFile }`. The\n * accepted declaration kinds (and bare-specifier / container-unwrap support) are\n * controlled by `opts`, letting both former resolvers share this one body.\n * Returns null when the symbol is not exported, not resolvable, or its import\n * path cannot be safely computed.\n */\nexport function resolveTypeRef(\n nodeOrName: TypeNode | string,\n sourceFile: SourceFile,\n project: Project,\n opts: ResolveTypeRefOptions,\n): TypeRef | null {\n // ── Resolve the bare symbol name (peeling containers for the TypeNode form) ──\n let name: string;\n if (typeof nodeOrName === 'string') {\n name = nodeOrName;\n } else {\n const typeNode = nodeOrName;\n\n if (opts.unwrapContainers && Node.isArrayTypeNode(typeNode)) {\n const inner = resolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project, opts);\n return inner ? { ...inner, isArray: true } : null;\n }\n\n if (!Node.isTypeReference(typeNode)) return null;\n const typeName = typeNode.getTypeName();\n const refName = Node.isIdentifier(typeName) ? typeName.getText() : null;\n if (!refName) return null;\n\n if (opts.unwrapContainers && refName === 'Promise') {\n const first = typeNode.getTypeArguments()[0];\n return first ? resolveTypeRef(first, sourceFile, project, opts) : null;\n }\n if (opts.unwrapContainers && refName === 'Array') {\n const first = typeNode.getTypeArguments()[0];\n if (!first) return null;\n const inner = resolveTypeRef(first, sourceFile, project, opts);\n return inner ? { ...inner, isArray: true } : null;\n }\n\n if (_NON_REF_NAMES.has(refName)) return null;\n name = refName;\n }\n\n // 1. Declared (and exported) in the current file → relative import to it.\n if (_localDeclForKinds(name, sourceFile, opts.kinds)) {\n return { name, filePath: sourceFile.getFilePath() };\n }\n\n // 2. Imported from another module — follow the import declaration.\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);\n if (!namedImport) continue;\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n\n // Bare specifier (node_modules package) → import directly by specifier.\n if (\n opts.allowBareSpecifier &&\n !moduleSpecifier.startsWith('.') &&\n !moduleSpecifier.startsWith('/')\n ) {\n // Only honour it if not a tsconfig path alias (those resolve to files).\n const tsconfigPaths = _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","/**\n * Pure-AST translation of class-validator-decorated DTO classes into zod schema\n * source text. Reads decorator names + literal args via ts-morph — it never\n * imports class-validator at runtime.\n *\n * Precedence (handled by the caller): a `defineContract` body/query always wins;\n * this translator runs only when no contract schema is present.\n */\nimport {\n type ClassDeclaration,\n type Decorator,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport { findType } from './type-ref-resolution.js';\n\nexport interface DtoZodResult {\n /** e.g. `\"z.object({ email: z.string().email() })\"`. */\n schemaText: string;\n /** name → `\"z.object({...})\"` hoisted above the parent. */\n namedNestedSchemas: Map<string, string>;\n warnings: string[];\n}\n\ninterface BuildContext {\n sourceFile: SourceFile;\n project: Project;\n namedNestedSchemas: Map<string, string>;\n warnings: string[];\n warnedDecorators: Set<string>;\n /** class name → emitted schema name (dedupe + alias). */\n emittedClasses: Map<string, string>;\n /** Class names currently being built (recursion guard). */\n visiting: Set<string>;\n /** Emitted schema names that turned out to be recursive (self-referential). */\n recursiveSchemas: Set<string>;\n depth: number;\n}\n\n/** Decorators we recognise as type/refinement overrides. */\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 extractZodFromDto(\n classDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): DtoZodResult {\n const ctx: BuildContext = {\n sourceFile,\n project,\n namedNestedSchemas: new Map(),\n warnings: [],\n warnedDecorators: new Set(),\n emittedClasses: new Map(),\n visiting: new Set(),\n recursiveSchemas: new Set(),\n depth: 0,\n };\n const schemaText = buildObjectSchema(classDecl, sourceFile, ctx);\n // Recursive schemas cannot be hoisted as a plain `const X = z.object({... X ...})`\n // without an explicit type annotation (TS7022/TS7024: implicit any). Per the\n // generator's \"never emit invalid TypeScript\" policy, degrade any\n // self-referential nested schema to a valid `z.unknown()` placeholder.\n for (const schemaName of ctx.recursiveSchemas) {\n ctx.namedNestedSchemas.set(schemaName, 'z.unknown() /* recursive type — not expanded */');\n }\n return {\n schemaText,\n namedNestedSchemas: ctx.namedNestedSchemas,\n warnings: ctx.warnings,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Object builder\n// ---------------------------------------------------------------------------\n\nfunction buildObjectSchema(\n classDecl: ClassDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): string {\n const props = classDecl.getProperties();\n if (props.length === 0) {\n return 'z.object({}).passthrough()';\n }\n const fields: string[] = [];\n for (const prop of props) {\n const name = prop.getName();\n const expr = buildPropertySchema(prop, classFile, ctx);\n fields.push(`${toObjectKey(name)}: ${expr}`);\n }\n return `z.object({ ${fields.join(', ')} })`;\n}\n\nfunction toObjectKey(name: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);\n}\n\n// ---------------------------------------------------------------------------\n// Property builder — the §2.2 mapping table lives here.\n// ---------------------------------------------------------------------------\n\nfunction buildPropertySchema(\n prop: PropertyDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): string {\n const decorators = new Map<string, Decorator>();\n for (const d of prop.getDecorators()) decorators.set(d.getName(), d);\n\n const has = (n: string): boolean => decorators.has(n);\n const dec = (n: string): Decorator | undefined => decorators.get(n);\n\n const typeNode = prop.getTypeNode();\n const typeText = typeNode?.getText() ?? 'unknown';\n const isArrayType = !!typeNode && typeNode.getText().endsWith('[]');\n\n // Track unmappable comments to append.\n const comments: string[] = [];\n\n // ── Nested / array-of-nested via @ValidateNested + @Type ────────────────\n const typeRefName = resolveTypeFactoryName(dec('Type'));\n if (has('ValidateNested') || typeRefName) {\n const childName = typeRefName ?? singularClassName(typeText);\n if (childName) {\n const childExpr = buildNestedReference(childName, classFile, ctx);\n const wrapArray = has('IsArray') || isArrayType;\n let expr = wrapArray ? `z.array(${childExpr})` : childExpr;\n expr = applyPresence(expr, decorators);\n return expr;\n }\n }\n\n // ── Base type (TS property type), then decorator refinements ────────────\n let base = baseFromType(typeText, isArrayType, ctx, classFile);\n const refinements: string[] = [];\n\n // Type overrides\n if (has('IsString')) base = 'z.string()';\n if (has('IsBoolean')) base = 'z.boolean()';\n if (has('IsDate')) base = 'z.coerce.date()';\n if (has('IsNumber')) base = 'z.number()';\n if (has('IsInt')) base = 'z.number().int()';\n if (has('IsObject') && !has('ValidateNested')) base = 'z.object({}).passthrough()';\n if (has('Allow')) base = 'z.unknown()';\n\n // String format refinements (these also imply string base).\n if (has('IsEmail')) {\n base = ensureStringBase(base);\n refinements.push(`.email(${messageArg(dec('IsEmail'))})`);\n }\n if (has('IsUrl')) {\n base = ensureStringBase(base);\n refinements.push(`.url(${messageArg(dec('IsUrl'))})`);\n }\n if (has('IsUUID')) {\n base = ensureStringBase(base);\n refinements.push(`.uuid(${messageArg(dec('IsUUID'))})`);\n }\n if (has('Matches')) {\n const re = firstArgText(dec('Matches'));\n if (re) {\n base = ensureStringBase(base);\n refinements.push(`.regex(${re})`);\n }\n }\n\n // Length / size refinements\n if (has('MinLength')) {\n const n = numericArg(dec('MinLength'));\n if (n !== null) refinements.push(`.min(${n})`);\n }\n if (has('MaxLength')) {\n const n = numericArg(dec('MaxLength'));\n if (n !== null) refinements.push(`.max(${n})`);\n }\n if (has('Length')) {\n const [min, max] = numericArgs(dec('Length'));\n if (min !== null) refinements.push(`.min(${min})`);\n if (max !== null) refinements.push(`.max(${max})`);\n }\n if (has('Min')) {\n const n = numericArg(dec('Min'));\n if (n !== null) refinements.push(`.min(${n})`);\n }\n if (has('Max')) {\n const n = numericArg(dec('Max'));\n if (n !== null) refinements.push(`.max(${n})`);\n }\n if (has('IsPositive')) refinements.push('.positive()');\n if (has('IsNegative')) refinements.push('.negative()');\n if (has('IsNotEmpty') && isStringBase(base)) refinements.push('.min(1)');\n\n // Enum / membership\n if (has('IsEnum')) {\n const enumExpr = enumSchemaFromDecorator(dec('IsEnum'), classFile, ctx);\n if (enumExpr) base = enumExpr;\n }\n if (has('IsIn')) {\n const inExpr = inSchemaFromDecorator(dec('IsIn'));\n if (inExpr) base = inExpr;\n }\n\n // ── Unmappable decorators → warn + comment, keep base ───────────────────\n for (const name of decorators.keys()) {\n if (!KNOWN_DECORATORS.has(name)) {\n // Block comment, not `//` — the schema is emitted on a single line, so a\n // line comment would swallow the rest of the object literal (the closing\n // `})` and any following fields), producing invalid TypeScript.\n comments.push(`/* @${name}: not translatable to zod (server-only) */`);\n if (!ctx.warnedDecorators.has(name)) {\n ctx.warnedDecorators.add(name);\n const msg = `@${name} is not translatable to zod and was skipped (server-only validation).`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen/forms] ${msg}`);\n }\n }\n }\n\n let expr = base + refinements.join('');\n\n // Array wrapping when the TS type is `T[]` and no nested handling occurred.\n if (isArrayType && !expr.startsWith('z.array(')) {\n expr = `z.array(${expr})`;\n }\n\n expr = applyPresence(expr, decorators);\n\n if (comments.length > 0) {\n expr = `${expr} ${comments.join(' ')}`;\n }\n return expr;\n}\n\n/** `.optional()` / required handling from @IsOptional / @IsDefined. */\nfunction applyPresence(expr: string, decorators: Map<string, Decorator>): string {\n if (decorators.has('IsDefined')) return expr; // explicitly required\n if (decorators.has('IsOptional')) return `${expr}.optional()`;\n return expr;\n}\n\n// ---------------------------------------------------------------------------\n// Base type from the TS property type\n// ---------------------------------------------------------------------------\n\nfunction baseFromType(\n typeText: string,\n isArrayType: boolean,\n ctx: BuildContext,\n classFile: SourceFile,\n): string {\n const inner = isArrayType ? typeText.slice(0, -2).trim() : typeText;\n switch (inner) {\n case 'string':\n return 'z.string()';\n case 'number':\n return 'z.number()';\n case 'boolean':\n return 'z.boolean()';\n case 'Date':\n return 'z.coerce.date()';\n case 'File':\n case 'Express.Multer.File':\n return 'z.instanceof(File)';\n default:\n return 'z.unknown()';\n }\n}\n\nfunction ensureStringBase(base: string): string {\n return isStringBase(base) ? base : 'z.string()';\n}\n\nfunction isStringBase(base: string): boolean {\n return base.startsWith('z.string(');\n}\n\n// ---------------------------------------------------------------------------\n// Nested DTO references (hoisted named consts)\n// ---------------------------------------------------------------------------\n\nfunction buildNestedReference(className: string, fromFile: SourceFile, ctx: BuildContext): string {\n // Recursion guard FIRST: a class currently being built (cycle) or excessive\n // depth → emit a lazy reference to the (already-reserved) schema name.\n if (ctx.visiting.has(className) || ctx.depth >= 8) {\n const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);\n ctx.emittedClasses.set(className, reserved);\n // This schema references itself (directly or transitively). Record it so the\n // hoisted declaration is degraded to a valid annotation-free placeholder\n // instead of an implicit-any `const X = z.lazy(() => ... X ...)`.\n ctx.recursiveSchemas.add(reserved);\n if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {\n ctx.warnedDecorators.add(`recursive:${reserved}`);\n const msg = `${className} is a recursive type and was not expanded; the generated form schema uses z.unknown() for it.`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen/forms] ${msg}`);\n }\n return `z.lazy(() => ${reserved})`;\n }\n\n const existing = ctx.emittedClasses.get(className);\n if (existing) return existing;\n\n const schemaName = aliasFor(className, ctx);\n const resolved = findType(className, fromFile, ctx.project);\n if (!resolved || resolved.kind !== 'class') {\n // Unknown nested type — passthrough object.\n return 'z.object({}).passthrough()';\n }\n\n ctx.emittedClasses.set(className, schemaName);\n ctx.visiting.add(className);\n ctx.depth += 1;\n const childText = buildObjectSchema(resolved.decl, resolved.file, ctx);\n ctx.depth -= 1;\n ctx.visiting.delete(className);\n\n ctx.namedNestedSchemas.set(schemaName, childText);\n return schemaName;\n}\n\nfunction aliasFor(className: string, ctx: BuildContext): string {\n const baseName = `${className}Schema`;\n let candidate = baseName;\n let i = 1;\n const used = new Set(ctx.namedNestedSchemas.keys());\n for (const v of ctx.emittedClasses.values()) used.add(v);\n while (used.has(candidate)) {\n candidate = `${baseName}_${i}`;\n i += 1;\n }\n return candidate;\n}\n\n// ---------------------------------------------------------------------------\n// Decorator argument readers (pure AST)\n// ---------------------------------------------------------------------------\n\nfunction firstArg(decorator: Decorator | undefined): Node | undefined {\n return decorator?.getArguments()[0];\n}\n\nfunction firstArgText(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n return arg ? arg.getText() : null;\n}\n\nfunction numericArg(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (arg && Node.isNumericLiteral(arg)) return arg.getText();\n return null;\n}\n\nfunction numericArgs(decorator: Decorator | undefined): [string | null, string | null] {\n const args = decorator?.getArguments() ?? [];\n const num = (n: Node | undefined): string | null =>\n n && Node.isNumericLiteral(n) ? n.getText() : null;\n return [num(args[0]), num(args[1])];\n}\n\n/** Reads a `{ message: '...' }` options object → `{ message: '...' }` (or empty). */\nfunction messageArg(decorator: Decorator | undefined): string {\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)) {\n return `{ message: ${init.getText()} }`;\n }\n }\n }\n }\n }\n return '';\n}\n\n/** Resolve `@Type(() => Child)` → `'Child'`. */\nfunction resolveTypeFactoryName(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) return body.getText();\n }\n return null;\n}\n\n/** Drop array suffix from a type text → class name (`Child[]` → `Child`). */\nfunction singularClassName(typeText: string): string | null {\n const inner = typeText.endsWith('[]') ? typeText.slice(0, -2).trim() : typeText;\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(inner) ? inner : null;\n}\n\n/** `@IsEnum(E)` → `z.nativeEnum(E)` (or `z.enum([...])` from resolved members). */\nfunction enumSchemaFromDecorator(\n decorator: Decorator | undefined,\n classFile: SourceFile,\n ctx: BuildContext,\n): string | 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 // resolved.members are already JSON-stringified literals.\n return `z.enum([${resolved.members.join(', ')}])`;\n }\n // The enum could not be resolved to literal members. Emitting\n // `z.nativeEnum(${name})` would reference an identifier that is NOT imported\n // into the generated forms file → a `Cannot find name` compile error. Fall\n // back to a valid degraded schema instead (same policy as untranslatable\n // decorators): a passing schema beats invalid output.\n const msg = `@IsEnum(${name}): enum could not be resolved to literal members and is not importable into the generated form schema; falling back to z.unknown().`;\n if (!ctx.warnedDecorators.has(`IsEnum:${name}`)) {\n ctx.warnedDecorators.add(`IsEnum:${name}`);\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen/forms] ${msg}`);\n }\n return `z.unknown() /* @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 `z.enum([${values.join(', ')}])`;\n }\n return null;\n}\n\n/** `@IsIn(['a','b'])` → `z.enum(['a','b'])`. */\nfunction inSchemaFromDecorator(decorator: Decorator | undefined): string | 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 `z.enum([${elements.map((e) => e.getText()).join(', ')}])`;\n }\n if (elements.length > 0) {\n return `z.union([${elements.map((e) => `z.literal(${e.getText()})`).join(', ')}])`;\n }\n }\n return null;\n}\n","import {\n type ClassDeclaration,\n type MethodDeclaration,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport {\n type ClassifyResult,\n classifyFieldType,\n classifyTypeNode,\n toFilterFieldType,\n} from './filter-field-types.js';\nimport { findType, resolveTypeRef } from './type-ref-resolution.js';\nimport type { FilterFieldType } from './types.js';\n\n/**\n * `@FilterFor` / `@ApplyFilter` discovery: resolve the virtual + entity-derived\n * filter fields (with their classified types) for a filter class referenced by\n * an `@ApplyFilter(FilterClass)` parameter.\n */\n\n/**\n * Map a single `@FilterFor` `type` hint token (read statically from the AST) to a\n * `ClassifyResult`. Supports the four primitive tokens plus a string-literal\n * array (enum) → literal string union. Returns null for anything unrecognised so\n * the caller falls back to the current permissive (`unknown`) behavior.\n */\nexport function classifyFilterForHint(typeInit: Node): ClassifyResult | null {\n // Primitive token: 'string' | 'number' | 'boolean' | 'Date'\n if (Node.isStringLiteral(typeInit)) {\n switch (typeInit.getLiteralValue()) {\n case 'string':\n return { kind: 'string' };\n case 'number':\n return { kind: 'number' };\n case 'boolean':\n return { kind: 'boolean' };\n case 'Date':\n return { kind: 'date' };\n default:\n return null;\n }\n }\n\n // Enum: a readonly array of string literals → literal string union.\n if (Node.isArrayLiteralExpression(typeInit)) {\n const values: string[] = [];\n for (const el of typeInit.getElements()) {\n if (!Node.isStringLiteral(el)) return null; // non-literal → bail to permissive\n values.push(el.getLiteralValue());\n }\n if (values.length === 0) return null;\n return { kind: 'string', enumValues: values };\n }\n\n return null;\n}\n\n/**\n * Classify the type of the FIRST parameter of a `@FilterFor` method (the new\n * primary inference mechanism). Precedence inside this function:\n * - primitive `number`/`string`/`boolean`/`Date` → emit directly.\n * - literal unions (`'a' | 'b'`, `1 | 2`) → emit the union text.\n * - named enum / type alias / interface → emit a `typeRef` (named import,\n * option B) when an import path is resolvable; otherwise fall back to\n * literal-union expansion for enums/unions, else skip.\n * - any/unknown/no-param/unresolvable → null (caller falls back).\n */\nexport function classifyFilterForParam(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult | null {\n const param = method.getParameters()[0];\n if (!param) return null;\n const typeNode = param.getTypeNode();\n if (!typeNode) return null;\n\n // Classify ONCE. `resolveRef` attaches an importable named ref (option B) when\n // the symbol resolves to an exported enum / type alias / interface / class with\n // a safe import path; the emitter prefers that `typeRef` over the `kind`. The\n // best-effort `kind` is still recorded so non-emit consumers (tests) see a\n // sensible classification.\n const wellKnown = ['string', 'number', 'boolean', 'Date', 'any', 'unknown'];\n const result = classifyTypeNode(typeNode, sourceFile, project, {\n resolveRef: (refName) => {\n if (wellKnown.includes(refName)) return null;\n // Only attempt a named import for symbols we can resolve to a declaration.\n if (!findType(refName, sourceFile, project)) return null;\n return resolveTypeRef(refName, sourceFile, project, {\n kinds: ['class', 'interface', 'typeAlias', 'enum'],\n allowBareSpecifier: true,\n });\n },\n });\n\n // A resolved `typeRef` is always usable (even with kind 'unknown' — the emitter\n // references the ref by name). Otherwise skip permissive `unknown` results.\n if (result.typeRef) return result;\n return result.kind === 'unknown' ? null : result;\n}\n\n/**\n * Discover virtual filter fields declared via `@FilterFor('key', { type })`\n * method decorators on the filter class. Field-type resolution precedence (high\n * wins): (1) explicit `{ type }` hint, (2) the method's first-parameter type\n * (named enums/aliases → real `import type` refs), (3+) fall back to existing\n * class-property / entity-column / `unknown` behavior (handled by the caller).\n *\n * Returns a map of inputKey → classified type for every `@FilterFor` that\n * carries a usable hint OR a usable first-parameter type. Keys with neither are\n * intentionally omitted here (they remain permissive / fall back).\n */\nexport function extractFilterForHints(\n classDecl: ClassDeclaration,\n project: Project,\n): Map<string, ClassifyResult> {\n const hints = new Map<string, ClassifyResult>();\n const sourceFile = classDecl.getSourceFile();\n for (const method of classDecl.getMethods()) {\n const filterForDec = method.getDecorators().find((d) => d.getName() === 'FilterFor');\n if (!filterForDec) continue;\n\n const args = filterForDec.getArguments();\n // inputKey: first string-literal arg, else the method name.\n const keyArg = args[0];\n const inputKey =\n keyArg && Node.isStringLiteral(keyArg) ? keyArg.getLiteralValue() : method.getName();\n\n // (1) Explicit `{ type }` hint — highest precedence, unchanged behavior.\n const optsArg = args[1];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n const typeProp = optsArg.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const typeInit = typeProp.getInitializer();\n if (typeInit) {\n const classified = classifyFilterForHint(typeInit);\n if (classified) {\n hints.set(inputKey, classified);\n continue;\n }\n }\n }\n }\n\n // (2) Method first-parameter type — the new primary inference mechanism.\n const fromParam = classifyFilterForParam(method, sourceFile, project);\n if (fromParam) hints.set(inputKey, fromParam);\n }\n return hints;\n}\n\n/**\n * Extract the filter field data from an `@ApplyFilter(FilterClass)` decorated\n * parameter. Resolves the filter class and reads its properties (excluding\n * inherited base class members). Returns the field names + classified types +\n * filter source, or null when no resolvable filter is present.\n */\nexport function extractApplyFilterInfo(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): {\n fieldNames: string[];\n fieldTypes: FilterFieldType[];\n source: 'body' | 'query';\n} | null {\n for (const param of method.getParameters()) {\n const filterDecorator = param.getDecorators().find((d) => d.getName() === 'ApplyFilter');\n if (!filterDecorator) continue;\n const args = filterDecorator.getArguments();\n if (args.length === 0) continue;\n const filterClassArg = args[0];\n if (!filterClassArg || !Node.isIdentifier(filterClassArg)) continue;\n\n // Read { source: \"body\" | \"query\" } from second argument\n let source: 'body' | 'query' = 'query';\n const optionsArg = args[1];\n if (optionsArg && Node.isObjectLiteralExpression(optionsArg)) {\n const sourceProp = optionsArg.getProperty('source');\n if (sourceProp && Node.isPropertyAssignment(sourceProp)) {\n const init = sourceProp.getInitializer();\n if (init && Node.isStringLiteral(init) && init.getLiteralValue() === 'body') {\n source = 'body';\n }\n }\n }\n\n const filterClassName = filterClassArg.getText();\n const resolved = findType(filterClassName, sourceFile, project);\n if (resolved && resolved.kind === 'class') {\n const classDecl = resolved.decl as ClassDeclaration;\n let fieldTypes = extractClassPropertyTypes(classDecl, project);\n\n // autoFields: if the filter class has no properties, resolve fields\n // from the entity referenced in @Filterable({ entity: X })\n if (fieldTypes.length === 0) {\n fieldTypes = extractFilterableEntityFields(classDecl, project);\n }\n\n // Merge in explicit @FilterFor('key', { type }) hints. An explicit hint\n // WINS over entity-column / class-property inference for the same key;\n // genuinely-virtual keys (no property, no column) are appended so they\n // appear in the Fields union and the type map M.\n const filterForHints = extractFilterForHints(classDecl, project);\n if (filterForHints.size > 0) {\n const byName = new Map(fieldTypes.map((f) => [f.name, f] as const));\n for (const [key, classified] of filterForHints) {\n byName.set(key, toFilterFieldType(key, classified));\n }\n fieldTypes = [...byName.values()];\n }\n\n if (fieldTypes.length === 0) return null;\n const fieldNames = fieldTypes.map((f) => f.name);\n return {\n fieldNames,\n fieldTypes,\n source,\n };\n }\n }\n return null;\n}\n\nconst RELATION_DECORATORS = new Set(['OneToMany', 'ManyToOne', 'ManyToMany', 'OneToOne']);\n\n/**\n * Recursively collect entity fields including dot-notation relation fields.\n * e.g. for PipelineRun with tasks: OneToMany<Task>, produces:\n * [\"id\", \"name\", \"status\", ..., \"tasks.id\", \"tasks.name\", ...]\n */\nfunction collectEntityFields(\n entityDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n prefix: string,\n visited: Set<string>,\n): FilterFieldType[] {\n const entityName = entityDecl.getName() ?? '';\n if (visited.has(entityName)) return [];\n visited.add(entityName);\n\n const fields: FilterFieldType[] = [];\n for (const prop of entityDecl.getProperties()) {\n const name = prop.getName();\n if (name.startsWith('$') || name.startsWith('_') || name.startsWith('[')) continue;\n if (prop.isStatic()) continue;\n\n const fullName = prefix ? `${prefix}.${name}` : name;\n const isRelation = prop.getDecorators().some((d) => RELATION_DECORATORS.has(d.getName()));\n\n if (isRelation) {\n const relEntity = resolveRelationEntity(prop, sourceFile, project);\n if (relEntity) {\n // Classify each relation leaf against the relation's own source file.\n fields.push(\n ...collectEntityFields(relEntity, relEntity.getSourceFile(), project, fullName, visited),\n );\n }\n } else {\n fields.push(toFilterFieldType(fullName, classifyFieldType(prop, sourceFile, project)));\n }\n }\n return fields;\n}\n\n/**\n * Given a relation property (e.g. `tasks = new Collection<Task>(this)`),\n * resolve the target entity class declaration.\n */\nfunction resolveRelationEntity(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassDeclaration | null {\n // Try from decorator argument: @OneToMany({ entity: () => Task, ... })\n for (const dec of prop.getDecorators()) {\n if (!RELATION_DECORATORS.has(dec.getName())) continue;\n const args = dec.getArguments();\n if (args.length === 0) continue;\n const arg = args[0];\n if (Node.isObjectLiteralExpression(arg)) {\n const entityProp = arg.getProperty('entity');\n if (entityProp && Node.isPropertyAssignment(entityProp)) {\n const init = entityProp.getInitializer();\n // () => Task\n if (init && Node.isArrowFunction(init)) {\n const body = init.getBody();\n if (Node.isIdentifier(body)) {\n const resolved = findType(body.getText(), prop.getSourceFile(), project);\n if (resolved?.kind === 'class') return resolved.decl as ClassDeclaration;\n }\n }\n }\n }\n // @ManyToOne(() => Task)\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) {\n const resolved = findType(body.getText(), prop.getSourceFile(), project);\n if (resolved?.kind === 'class') return resolved.decl as ClassDeclaration;\n }\n }\n }\n return null;\n}\n\n/** Classify each property of a filter DTO class into a FilterFieldType. */\nfunction extractClassPropertyTypes(\n classDecl: ClassDeclaration,\n project: Project,\n): FilterFieldType[] {\n const sourceFile = classDecl.getSourceFile();\n const fields: FilterFieldType[] = [];\n for (const prop of classDecl.getProperties()) {\n const name = prop.getName();\n if (name.startsWith('$') || name.startsWith('_')) continue;\n fields.push(toFilterFieldType(name, classifyFieldType(prop, sourceFile, project)));\n }\n return fields;\n}\n\n/**\n * When a filter class uses `@Filterable({ entity: X, autoFields: true })`,\n * resolve entity X and extract its property names (fields decorated with\n * `@Property`, `@PrimaryKey`, `@Enum`, etc. — skipping relations).\n */\nfunction extractFilterableEntityFields(\n filterClass: ClassDeclaration,\n project: Project,\n): FilterFieldType[] {\n const filterableDecorator = filterClass.getDecorators().find((d) => d.getName() === 'Filterable');\n if (!filterableDecorator) return [];\n const args = filterableDecorator.getArguments();\n if (args.length === 0) return [];\n\n const optionsArg = args[0];\n if (!Node.isObjectLiteralExpression(optionsArg)) return [];\n\n const entityProp = optionsArg.getProperty('entity');\n if (!entityProp || !Node.isPropertyAssignment(entityProp)) return [];\n\n const entityInit = entityProp.getInitializer();\n if (!entityInit || !Node.isIdentifier(entityInit)) return [];\n\n const entityName = entityInit.getText();\n const filterSourceFile = filterClass.getSourceFile();\n const resolvedEntity = findType(entityName, filterSourceFile, project);\n if (!resolvedEntity || resolvedEntity.kind !== 'class') return [];\n\n const entityDecl = resolvedEntity.decl as ClassDeclaration;\n const fields = collectEntityFields(\n entityDecl,\n entityDecl.getSourceFile(),\n project,\n '',\n new Set(),\n );\n\n // Also include keys declared via @Relations({ rel: { keys: [...] } }).\n // These string keys carry no resolvable type → kind: 'unknown'.\n const relationsDecorator = filterClass.getDecorators().find((d) => d.getName() === 'Relations');\n if (relationsDecorator) {\n const relArgs = relationsDecorator.getArguments();\n if (relArgs.length > 0 && Node.isObjectLiteralExpression(relArgs[0])) {\n for (const relProp of relArgs[0].getProperties()) {\n if (!Node.isPropertyAssignment(relProp)) continue;\n const relInit = relProp.getInitializer();\n if (!relInit || !Node.isObjectLiteralExpression(relInit)) continue;\n const keysProp = relInit.getProperty('keys');\n if (!keysProp || !Node.isPropertyAssignment(keysProp)) continue;\n const keysInit = keysProp.getInitializer();\n if (!keysInit || !Node.isArrayLiteralExpression(keysInit)) continue;\n for (const el of keysInit.getElements()) {\n if (Node.isStringLiteral(el)) {\n // Route through the single constructor (keeps the typeRef invariant\n // enforced in one place); these relation keys carry no type → unknown.\n fields.push(toFilterFieldType(el.getLiteralValue(), { kind: 'unknown' }));\n }\n }\n }\n }\n }\n\n return fields;\n}\n","import {\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport { resolveEnumValues } from './enum-resolution.js';\nimport type { FieldTypeKind, FilterFieldType, TypeRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Field-type classification (mirrors mapTypeOrmType / mapMikroOrmType so codegen\n// and the runtime adapters can never diverge). See nestjs-filter\n// packages/typeorm/src/typeorm.adapter.ts:190 (mapTypeOrmType).\n// ---------------------------------------------------------------------------\n\n/** Reference: typeorm.adapter.ts keyword tables (kept in sync intentionally). */\nconst STRING_TYPE_KEYWORDS = ['varchar', 'text', 'string', 'char', 'uuid', 'enum'];\nconst NUMBER_TYPE_KEYWORDS = ['int', 'float', 'double', 'decimal', 'number', 'numeric', 'real'];\nconst BOOLEAN_TYPE_KEYWORDS = ['bool', 'boolean', 'bit'];\nconst DATE_TYPE_KEYWORDS = ['date', 'time', 'timestamp', 'datetime'];\nconst JSON_TYPE_KEYWORDS = ['json', 'jsonb'];\n\n/** Classify a column/property type literal (e.g. 'varchar') the same way mapTypeOrmType does. */\nexport function classifyTypeKeyword(raw: string): FieldTypeKind | null {\n const t = raw.toLowerCase();\n if (STRING_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'string';\n if (NUMBER_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'number';\n if (BOOLEAN_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'boolean';\n if (DATE_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'date';\n if (JSON_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'json';\n return null;\n}\n\nexport interface ClassifyResult {\n kind: FieldTypeKind;\n enumValues?: string[];\n nullable?: boolean;\n numericEnum?: boolean;\n /** Importable reference to a named enum / type alias / interface (option B). */\n typeRef?: TypeRef;\n}\n\n/**\n * Return `r` with `nullable: true` set only when `nullable` is true.\n * Avoids assigning `undefined` to an optional prop under exactOptionalPropertyTypes.\n */\nexport function markNullable(r: ClassifyResult, nullable: boolean): ClassifyResult {\n return nullable ? { ...r, nullable: true } : r;\n}\n\n/**\n * Options for {@link classifyTypeNode}. When `resolveRef` is supplied and the\n * type node is a named reference (not a primitive / well-known name), it is\n * called with the symbol name; a non-null result is attached as `typeRef` on the\n * returned `ClassifyResult`. This lets `classifyFilterForParam` classify ONCE and\n * pick up the importable ref in the same pass.\n */\nexport interface ClassifyTypeNodeOptions {\n resolveRef?: (refName: string) => TypeRef | null;\n}\n\n/** Classify a TS type node into a field-type kind (+ enum members / nullable). */\nexport function classifyTypeNode(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n opts?: ClassifyTypeNodeOptions,\n): ClassifyResult {\n // Union: strip null/undefined, collect literal members, recurse otherwise.\n if (Node.isUnionTypeNode(typeNode)) {\n let nullable = false;\n const stringLits: string[] = [];\n const numberLits: string[] = [];\n const others: TypeNode[] = [];\n for (const member of typeNode.getTypeNodes()) {\n const kind = member.getKind();\n if (kind === SyntaxKind.NullKeyword || kind === SyntaxKind.UndefinedKeyword) {\n nullable = true;\n continue;\n }\n if (Node.isLiteralTypeNode(member)) {\n const lit = member.getLiteral();\n if (Node.isStringLiteral(lit)) {\n stringLits.push(lit.getLiteralValue());\n continue;\n }\n if (Node.isNumericLiteral(lit)) {\n numberLits.push(lit.getText());\n continue;\n }\n if (lit.getKind() === SyntaxKind.NullKeyword) {\n nullable = true;\n continue;\n }\n }\n others.push(member);\n }\n\n if (others.length === 0 && stringLits.length > 0 && numberLits.length === 0) {\n return markNullable({ kind: 'string', enumValues: stringLits }, nullable);\n }\n if (others.length === 0 && numberLits.length > 0 && stringLits.length === 0) {\n return markNullable({ kind: 'number', enumValues: numberLits, numericEnum: true }, nullable);\n }\n if (others.length === 1) {\n const inner = classifyTypeNode(others[0]!, sourceFile, project, opts);\n return markNullable(inner, nullable || inner.nullable === true);\n }\n return markNullable({ kind: 'unknown' }, nullable);\n }\n\n switch (typeNode.getKind()) {\n case SyntaxKind.StringKeyword:\n return { kind: 'string' };\n case SyntaxKind.NumberKeyword:\n return { kind: 'number' };\n case SyntaxKind.BooleanKeyword:\n return { kind: 'boolean' };\n case SyntaxKind.AnyKeyword:\n case SyntaxKind.UnknownKeyword:\n return { kind: 'unknown' };\n default:\n break;\n }\n\n if (Node.isTypeReference(typeNode)) {\n const refName = typeNode.getTypeName().getText();\n if (refName === 'Date') return { kind: 'date' };\n if (refName === 'Record' || refName === 'Object') return { kind: 'json' };\n // An importable named ref (enum / type alias / interface / class) wins for\n // emit when the caller supplied a resolver and a safe import path exists.\n const typeRef = opts?.resolveRef?.(refName) ?? null;\n // Possibly an enum type used as a property type.\n const en = resolveEnumValues(refName, sourceFile, project);\n if (en) {\n const base: ClassifyResult = en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n return typeRef ? { ...base, typeRef } : base;\n }\n if (typeRef) return { kind: 'unknown', typeRef };\n return { kind: 'unknown' };\n }\n\n if (Node.isTypeLiteral(typeNode)) return { kind: 'json' };\n\n return { kind: 'unknown' };\n}\n\n/** Resolve an enum from @Enum decorator args: `() => Status` or `{ items: () => Status }`. */\nexport function enumFromDecoratorArgs(\n args: Node[],\n sourceFile: SourceFile,\n project: Project,\n): { values: string[]; numeric: boolean } | null {\n for (const arg of args) {\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) {\n const en = resolveEnumValues(body.getText(), sourceFile, project);\n if (en) return en;\n }\n }\n if (Node.isObjectLiteralExpression(arg)) {\n const itemsProp = arg.getProperty('items');\n if (itemsProp && Node.isPropertyAssignment(itemsProp)) {\n const init = itemsProp.getInitializer();\n if (init && Node.isArrowFunction(init)) {\n const body = init.getBody();\n if (Node.isIdentifier(body)) {\n const en = resolveEnumValues(body.getText(), sourceFile, project);\n if (en) return en;\n }\n }\n }\n }\n }\n return null;\n}\n\n/** Classify a property from `@Column`/`@Property`/`@Enum` decorator options. */\nexport function classifyFromColumnDecorator(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult | null {\n for (const dec of prop.getDecorators()) {\n const decName = dec.getName();\n if (decName !== 'Column' && decName !== 'Property' && decName !== 'Enum') continue;\n const args = dec.getArguments();\n\n // @Enum({ items: () => Status }) or @Enum(() => Status)\n if (decName === 'Enum') {\n const en = enumFromDecoratorArgs(args, sourceFile, project);\n if (en) {\n return en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n }\n return { kind: 'string' };\n }\n\n for (const arg of args) {\n // @Column('varchar')\n if (Node.isStringLiteral(arg)) {\n const raw = arg.getLiteralValue();\n const kind = classifyTypeKeyword(raw);\n if (kind) {\n // @Column('enum', { enum: Status }) → resolve via the options object below\n if (kind === 'string' && raw.toLowerCase().includes('enum')) continue;\n return { kind };\n }\n }\n // @Column({ type: 'datetime' }) / @Property({ type: 'int' }) / { enum: Status }\n if (Node.isObjectLiteralExpression(arg)) {\n const enumProp = arg.getProperty('enum');\n if (enumProp && Node.isPropertyAssignment(enumProp)) {\n const init = enumProp.getInitializer();\n if (init && Node.isIdentifier(init)) {\n const en = resolveEnumValues(init.getText(), sourceFile, project);\n if (en) {\n return en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n }\n return { kind: 'string' };\n }\n }\n const typeProp = arg.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const init = typeProp.getInitializer();\n if (init && Node.isStringLiteral(init)) {\n const kind = classifyTypeKeyword(init.getLiteralValue());\n if (kind) return { kind };\n }\n }\n }\n }\n // Decorator present but no recognisable type info.\n return null;\n }\n return null;\n}\n\n/**\n * Classify a single entity/DTO property into a ClassifyResult (kind + enum + nullable),\n * mirroring the runtime ORM type mapping. Falls back to 'unknown' when unresolvable.\n */\nexport function classifyFieldType(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult {\n let nullable = prop.hasQuestionToken();\n const typeNode = prop.getTypeNode();\n\n if (typeNode) {\n const r = classifyTypeNode(typeNode, sourceFile, project);\n if (r.nullable) nullable = true;\n if (r.kind !== 'unknown') return markNullable(r, nullable);\n }\n\n const fromDecorator = classifyFromColumnDecorator(prop, sourceFile, project);\n if (fromDecorator) {\n return markNullable(fromDecorator, nullable || fromDecorator.nullable === true);\n }\n\n return markNullable({ kind: 'unknown' }, nullable);\n}\n\n/**\n * The single normalizing constructor for a {@link FilterFieldType} from a\n * classification. Concentrates the `typeRef` precedence invariant (see the\n * `FilterFieldType` doc): `kind`/`enumValues`/`numericEnum` are always recorded\n * best-effort, and `typeRef` (when present) is what the emitter actually uses.\n * Build `FilterFieldType` values through here — not inline — so the convention\n * has exactly one enforcement point.\n */\nexport function toFilterFieldType(name: string, r: ClassifyResult): FilterFieldType {\n const ft: FilterFieldType = { name, kind: r.kind };\n if (r.enumValues && r.enumValues.length > 0) ft.enumValues = r.enumValues;\n if (r.nullable) ft.nullable = true;\n if (r.numericEnum) ft.numericEnum = true;\n if (r.typeRef) ft.typeRef = r.typeRef;\n return ft;\n}\n","import type { Project, SourceFile } from 'ts-morph';\nimport { findType } from './type-ref-resolution.js';\n\n/**\n * Resolve an enum identifier to its raw member values + numeric flag.\n *\n * KNOWN LIMITATION — mixed enums with a computed member: `findType` serializes\n * each enum member with `JSON.stringify` of its static value, falling back to the\n * QUOTED member NAME for any member whose value can't be resolved statically\n * (e.g. a computed member). Here we re-derive `numeric` by `JSON.parse`-ing each\n * member: any string member (including that quoted-name fallback) flips `numeric`\n * to `false` for the WHOLE enum. So a primarily-numeric enum that contains a\n * single computed member is treated as a string enum, and its numeric members\n * are emitted as quoted string literals. This is a rare edge case; fixing it\n * would require threading per-member numeric-ness out of `findType` rather than\n * inferring it from the stringified members. Pure numeric and pure string enums\n * (the overwhelmingly common cases) are unaffected.\n */\nexport function resolveEnumValues(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): { values: string[]; numeric: boolean } | null {\n const resolved = findType(name, sourceFile, project);\n if (!resolved || resolved.kind !== 'enum') return null;\n // members are JSON.stringify'd (\"A\" / \"0\"); strip quotes to raw values.\n let numeric = true;\n const values = resolved.members.map((m) => {\n const parsed = JSON.parse(m) as string | number;\n if (typeof parsed === 'string') numeric = false;\n return String(parsed);\n });\n if (values.length === 0) return null;\n return { values, numeric };\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { Project } from 'ts-morph';\nimport type { ResolvedConfig } from './config/types.js';\nimport { discoverPages } from './discovery/pages.js';\nimport type { SharedPropsResult } from './discovery/shared-props.js';\nimport { discoverSharedProps } from './discovery/shared-props.js';\nimport type { RouteDescriptor } from './discovery/types.js';\nimport { emitApi } from './emit/emit-api.js';\nimport { emitCache } from './emit/emit-cache.js';\nimport { emitForms } from './emit/emit-forms.js';\nimport { emitIndex } from './emit/emit-index.js';\nimport { emitPages } from './emit/emit-pages.js';\nimport { emitRoutes } from './emit/emit-routes.js';\nimport {\n applyTransformRoutes,\n collectEmittedFiles,\n createExtensionContext,\n} from './extension/registry.js';\n\n/**\n * Run one full codegen pass: discover pages, emit pages.d.ts, components.json, index.d.ts.\n * Route discovery is deliberately skipped — it requires spawning a Nest app and is\n * not appropriate for the hot path of a file watcher.\n *\n * Optionally accepts pre-discovered routes (e.g. from a full generate + route-discovery pass).\n * When routes are present, emits routes.ts.\n * When routes with contracts are present, also emits api.ts.\n */\nexport async function generate(\n config: ResolvedConfig,\n inputRoutes: RouteDescriptor[] = [],\n): Promise<void> {\n // Extensions: run transformRoutes (chained) before any emit so routes.ts/api.ts/\n // forms.ts all see the augmented IR. ctx.routes is a live getter over the active set.\n const extensions = config.extensions ?? [];\n let routes = inputRoutes;\n const ctx = createExtensionContext(config, () => routes);\n if (extensions.length > 0) {\n routes = await applyTransformRoutes(routes, extensions, ctx);\n }\n\n // Inertia page discovery is opt-in — skip entirely when `pages` isn't configured.\n if (config.pages) {\n const pagesConfig = config.pages;\n const pages = await discoverPages({\n glob: pagesConfig.glob,\n cwd: config.codegen.cwd,\n propsExport: pagesConfig.propsExport,\n componentNameStrategy: pagesConfig.componentNameStrategy,\n });\n\n let sharedProps: SharedPropsResult | null = null;\n if (config.app?.moduleEntry) {\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 sharedProps = discoverSharedProps(project, config.app.moduleEntry);\n } catch {\n // Graceful fallback — skip shared props if anything goes wrong\n }\n }\n\n await emitPages(pages, config.codegen.outDir, {\n propsExport: pagesConfig.propsExport,\n sharedProps,\n });\n await emitCache(pages, config.codegen.outDir);\n }\n\n const hasRoutes = routes.length > 0;\n const hasContracts = routes.some((r) => r.contract);\n\n if (hasRoutes) {\n await emitRoutes(routes, config.codegen.outDir);\n }\n\n if (hasContracts) {\n await emitApi(routes, config.codegen.outDir, {\n ...(config.fetcher?.importPath ? { fetcherImportPath: config.fetcher.importPath } : {}),\n extensions,\n ctx,\n });\n }\n\n const hasForms = await emitForms(routes, config.codegen.outDir, config.forms, config.validation);\n\n await emitIndex(config.codegen.outDir, hasContracts, hasForms);\n\n // Extensions: write any extra files (collision-checked against each other + core files).\n if (extensions.length > 0) {\n const extraFiles = await collectEmittedFiles(extensions, ctx);\n for (const file of extraFiles) {\n const dest = join(config.codegen.outDir, file.path);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, file.contents, 'utf8');\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport fg from 'fast-glob';\n\nexport interface DiscoveredPage {\n name: string;\n absolutePath: string;\n relativePath: string;\n propsSource: string | null;\n}\n\nexport interface DiscoverPagesOptions {\n glob: string;\n cwd: string;\n propsExport: string;\n componentNameStrategy: 'relative-no-ext' | 'kebab' | ((path: string) => string);\n}\n\n// Files matching these patterns are never treated as Inertia pages even if\n// they sit inside the pages directory and would match the user's glob.\n// Without this filter, vitest test files (`*.test.tsx`) get registered as\n// pages, their imports get pulled into the typecheck graph, and any\n// transitive matcher errors leak into the user's project.\nconst NON_PAGE_FILE_RE = /\\.(?:test|spec|stories|story)\\.(?:tsx?|jsx?|vue|svelte)$/i;\n\nexport async function discoverPages(opts: DiscoverPagesOptions): Promise<DiscoveredPage[]> {\n const allFiles = await fg(opts.glob, { cwd: opts.cwd, absolute: true });\n const files = allFiles.filter((f) => !NON_PAGE_FILE_RE.test(f));\n files.sort();\n // Extract the static prefix from the glob to make page names relative to the pages directory\n // e.g. glob 'inertia/pages/**/*.tsx' → pagesBase 'inertia/pages'\n const globStatic = opts.glob.split('*')[0]?.replace(/\\/$/, '') ?? '';\n const pagesBase = join(opts.cwd, globStatic);\n const out: DiscoveredPage[] = [];\n for (const file of files) {\n const rel = relative(opts.cwd, file);\n const nameRel = relative(pagesBase, file);\n const name = computeName(nameRel, opts.componentNameStrategy);\n const source = await readFile(file, 'utf8');\n const propsSource = extractPropsSource(source, opts.propsExport);\n out.push({ name, absolutePath: file, relativePath: rel, propsSource });\n }\n return out;\n}\n\nfunction computeName(rel: string, strat: DiscoverPagesOptions['componentNameStrategy']): string {\n if (typeof strat === 'function') return strat(rel);\n const noExt = rel.replace(/\\.(tsx?|vue|svelte)$/, '');\n if (strat === 'kebab') return noExt.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n return noExt;\n}\n\nfunction extractPropsSource(source: string, exportName: string): string | null {\n const re = new RegExp(`export\\\\s+type\\\\s+${exportName}\\\\s*=\\\\s*`, 'm');\n const m = source.match(re);\n if (!m) return null;\n const start = m.index! + m[0].length;\n // Brace counting to capture type body\n let i = start;\n let depth = 0;\n let started = false;\n while (i < source.length) {\n const c = source[i];\n if (c === '{') {\n depth++;\n started = true;\n } else if (c === '}') {\n depth--;\n if (started && depth === 0) {\n return source.slice(start, i + 1);\n }\n } else if (c === ';' && !started) return source.slice(start, i);\n i++;\n }\n return source.slice(start);\n}\n","/**\n * Static AST-based discovery of shared props from `InertiaModule.forRoot({ share: ... })`.\n *\n * Analyzes the `share` property in the forRoot call to infer the return type\n * of the share function and generate typed shared props.\n *\n * Gracefully returns null when the share function cannot be analyzed\n * (complex logic, service calls, external references, etc.).\n */\nimport { Node, type Project, type SourceFile, SyntaxKind } from 'ts-morph';\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 * Find `InertiaModule.forRoot(...)` call expression in a source file.\n * Searches all call expressions in the file.\n */\nfunction findForRootCall(sourceFile: SourceFile): Node | null {\n const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);\n\n for (const call of callExpressions) {\n const expr = call.getExpression();\n if (!Node.isPropertyAccessExpression(expr)) continue;\n\n const methodName = expr.getName();\n const objectExpr = expr.getExpression();\n\n if (methodName === 'forRoot' && Node.isIdentifier(objectExpr)) {\n const name = objectExpr.getText();\n if (name === 'InertiaModule') {\n return call;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Extract the initializer of the `share` property from the first argument of `forRoot(...)`.\n * Returns the initializer node (the value assigned to `share`), or null if not found.\n */\nfunction findShareInitializer(forRootCall: Node): Node | null {\n if (!Node.isCallExpression(forRootCall)) return null;\n\n const args = forRootCall.getArguments();\n const firstArg = args[0];\n if (!firstArg || !Node.isObjectLiteralExpression(firstArg)) return null;\n\n for (const prop of firstArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'share') {\n return prop.getInitializer() ?? null;\n }\n }\n\n return null;\n}\n\n/**\n * Extract the return type of the share value.\n * Handles:\n * - Arrow functions: `(req) => ({ ... })`\n * - Arrow functions with block body: `(req) => { return { ... }; }`\n * - Function expressions: `function(req) { return { ... }; }`\n * - Async variants of the above\n * - Object literals (plain `share: { ... }`)\n * - Functions with explicit return type annotations\n */\nfunction extractShareType(\n node: Node,\n sourceFile: SourceFile,\n project: Project,\n): SharedPropsResult | null {\n // Priority 1: Reference to a named function → use ReturnType<typeof import(...)>\n if (Node.isIdentifier(node)) {\n const ref = resolveIdentifierToImportRef(node, sourceFile, project);\n if (ref) {\n return {\n typeString: `Awaited<ReturnType<typeof import('${ref.importPath}').${ref.exportName}>>`,\n properties: null,\n isImportRef: true,\n };\n }\n }\n\n // Priority 2: Arrow function → try inline extraction\n if (Node.isArrowFunction(node)) {\n const result = extractFromFunctionLike(node, sourceFile);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n // Priority 3: Function expression → try inline extraction\n if (Node.isFunctionExpression(node)) {\n const result = extractFromFunctionLike(node, sourceFile);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n // Priority 4: Object literal (share: { key: value })\n if (Node.isObjectLiteralExpression(node)) {\n const result = extractFromObjectLiteral(node);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n return null;\n}\n\nfunction resolveIdentifierToImportRef(\n id: Node,\n sourceFile: SourceFile,\n project: Project,\n): { importPath: string; exportName: string } | null {\n if (!Node.isIdentifier(id)) return null;\n const name = id.getText();\n\n const localFunc = sourceFile.getFunction(name);\n if (localFunc?.isExported()) {\n const filePath = sourceFile.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: name };\n }\n\n const localVar = sourceFile.getVariableDeclaration(name);\n if (localVar?.isExported()) {\n const filePath = sourceFile.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: name };\n }\n\n for (const imp of sourceFile.getImportDeclarations()) {\n for (const named of imp.getNamedImports()) {\n const importedName = named.getAliasNode()?.getText() ?? named.getName();\n if (importedName !== name) continue;\n const resolvedSource = imp.getModuleSpecifierSourceFile();\n if (!resolvedSource) continue;\n const originalName = named.getName();\n const fn = resolvedSource.getFunction(originalName);\n if (fn?.isExported()) {\n const filePath = resolvedSource.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: originalName };\n }\n const v = resolvedSource.getVariableDeclaration(originalName);\n if (v?.isExported()) {\n const filePath = resolvedSource.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: originalName };\n }\n }\n }\n\n return null;\n}\n\n/**\n * Extract shared props type from an arrow function or function expression.\n * First tries the return type annotation; falls back to inferring from the return value.\n */\nfunction extractFromFunctionLike(node: Node, _sourceFile: SourceFile): SharedPropsResult | null {\n // Check for explicit return type annotation\n const returnTypeNode =\n Node.isArrowFunction(node) || Node.isFunctionExpression(node) ? node.getReturnTypeNode() : null;\n\n if (returnTypeNode) {\n return extractFromReturnTypeAnnotation(returnTypeNode);\n }\n\n // Infer from body\n if (Node.isArrowFunction(node)) {\n const body = node.getBody();\n\n // Concise body: (req) => ({ auth: ..., flash: ... })\n if (Node.isParenthesizedExpression(body)) {\n const inner = body.getExpression();\n if (Node.isObjectLiteralExpression(inner)) {\n return extractFromObjectLiteral(inner);\n }\n }\n\n // Direct object literal (less common but possible with as const)\n if (Node.isObjectLiteralExpression(body)) {\n return extractFromObjectLiteral(body);\n }\n\n // Block body: (req) => { return { ... }; }\n if (Node.isBlock(body)) {\n return extractFromBlockReturn(body);\n }\n }\n\n if (Node.isFunctionExpression(node)) {\n const body = node.getBody();\n if (Node.isBlock(body)) {\n return extractFromBlockReturn(body);\n }\n }\n\n return null;\n}\n\n/**\n * Extract type from a return type annotation on the share function.\n * e.g. `(req): { auth: User | null; flash: {} } => ...`\n */\nfunction extractFromReturnTypeAnnotation(typeNode: Node): SharedPropsResult | null {\n // Unwrap Promise<T> if async\n if (Node.isTypeReference(typeNode)) {\n const typeName = typeNode.getTypeName();\n if (Node.isIdentifier(typeName) && typeName.getText() === 'Promise') {\n const typeArgs = typeNode.getTypeArguments();\n const firstArg = typeArgs[0];\n if (firstArg) {\n return extractFromReturnTypeAnnotation(firstArg);\n }\n return null;\n }\n }\n\n // TypeLiteral: { auth: ...; flash: ... }\n if (Node.isTypeLiteral(typeNode)) {\n const properties: Array<{ name: string; type: string }> = [];\n for (const member of typeNode.getMembers()) {\n if (Node.isPropertySignature(member)) {\n const name = member.getName();\n const memberTypeNode = member.getTypeNode();\n const type = memberTypeNode ? memberTypeNode.getText() : 'unknown';\n properties.push({ name, type });\n }\n }\n if (properties.length === 0) return null;\n const typeString = `{ ${properties.map((p) => `${p.name}: ${p.type}`).join('; ')} }`;\n return { typeString, properties, isImportRef: false };\n }\n\n return null;\n}\n\n/**\n * Extract shared props from a block body's return statement.\n * Only handles the simple case: a single return statement with an object literal.\n */\nfunction extractFromBlockReturn(block: Node): SharedPropsResult | null {\n if (!Node.isBlock(block)) return null;\n\n const statements = block.getStatements();\n // Find the last return statement\n for (let i = statements.length - 1; i >= 0; i--) {\n const stmt = statements[i];\n if (!Node.isReturnStatement(stmt)) continue;\n\n const expr = stmt.getExpression();\n if (!expr) continue;\n\n if (Node.isObjectLiteralExpression(expr)) {\n return extractFromObjectLiteral(expr);\n }\n\n // Parenthesized: return ({ ... })\n if (Node.isParenthesizedExpression(expr)) {\n const inner = expr.getExpression();\n if (Node.isObjectLiteralExpression(inner)) {\n return extractFromObjectLiteral(inner);\n }\n }\n\n break;\n }\n\n return null;\n}\n\n/**\n * Infer shared props type from an object literal expression.\n * Each property key becomes a shared prop; the value type is inferred from the value expression.\n */\nfunction extractFromObjectLiteral(objLiteral: Node): SharedPropsResult | null {\n if (!Node.isObjectLiteralExpression(objLiteral)) return null;\n\n const properties: Array<{ name: string; type: string }> = [];\n\n for (const prop of objLiteral.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n\n const name = prop.getName();\n const initializer = prop.getInitializer();\n if (!initializer) continue;\n\n const type = inferExpressionType(initializer);\n properties.push({ name, type });\n }\n\n if (properties.length === 0) return null;\n\n const typeString = `{ ${properties.map((p) => `${p.name}: ${p.type}`).join('; ')} }`;\n return { typeString, properties, isImportRef: false };\n}\n\n/**\n * Infer the TypeScript type of an expression.\n * Handles common patterns found in share functions:\n * - Object literals → `{ key: type; ... }`\n * - String literals → `string`\n * - Number literals → `number`\n * - Boolean literals → `boolean`\n * - Null → `null`\n * - Array literals → `Array<type>`\n * - Ternary expressions → `trueType | falseType`\n * - Property accesses and complex expressions → `unknown`\n * - Empty object literal → `Record<string, unknown>`\n */\nfunction inferExpressionType(node: Node): string {\n // String literal\n if (Node.isStringLiteral(node)) return 'string';\n\n // Template literal (backtick)\n if (Node.isTemplateExpression(node) || Node.isNoSubstitutionTemplateLiteral(node))\n return 'string';\n\n // Number literal\n if (Node.isNumericLiteral(node)) return 'number';\n\n // Boolean literal\n if (node.getKind() === SyntaxKind.TrueKeyword || node.getKind() === SyntaxKind.FalseKeyword) {\n return 'boolean';\n }\n\n // Null literal\n if (node.getKind() === SyntaxKind.NullKeyword) return 'null';\n\n // Undefined\n if (Node.isIdentifier(node) && node.getText() === 'undefined') return 'undefined';\n\n // Object literal\n if (Node.isObjectLiteralExpression(node)) {\n const props = node.getProperties();\n if (props.length === 0) return 'Record<string, unknown>';\n\n const entries: string[] = [];\n for (const prop of props) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const key = prop.getName();\n const init = prop.getInitializer();\n if (!init) continue;\n entries.push(`${key}: ${inferExpressionType(init)}`);\n }\n if (entries.length === 0) return 'Record<string, unknown>';\n return `{ ${entries.join('; ')} }`;\n }\n\n // Array literal\n if (Node.isArrayLiteralExpression(node)) {\n const elements = node.getElements();\n if (elements.length === 0) return 'Array<unknown>';\n // Infer from first element\n const first = elements[0];\n if (first) return `Array<${inferExpressionType(first)}>`;\n return 'Array<unknown>';\n }\n\n // Ternary (conditional) expression: x ? A : B → A | B\n if (Node.isConditionalExpression(node)) {\n const whenTrue = inferExpressionType(node.getWhenTrue());\n const whenFalse = inferExpressionType(node.getWhenFalse());\n if (whenTrue === whenFalse) return whenTrue;\n return `${whenTrue} | ${whenFalse}`;\n }\n\n // Parenthesized expression — unwrap\n if (Node.isParenthesizedExpression(node)) {\n return inferExpressionType(node.getExpression());\n }\n\n // As expression (type assertion): expr as Type → use the asserted type\n if (Node.isAsExpression(node)) {\n const typeNode = node.getTypeNode();\n if (typeNode) return typeNode.getText();\n }\n\n // For any other expression (property access, function calls, etc.), fall back to unknown\n return 'unknown';\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative } from 'node:path';\nimport type {\n ContractSource,\n ControllerRef,\n FieldTypeKind,\n FilterFieldType,\n RouteDescriptor,\n} from '../discovery/types.js';\nimport { resolveApiSlots } from '../extension/registry.js';\nimport type {\n ApiClientLayer,\n ApiTransport,\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; an `apiTransport` changes how requests are issued; `apiMembers` add handle\n * members; `apiHeader` contributes top-level imports/statements.\n */\nexport interface ApiEmitOptions {\n fetcherImportPath?: string;\n /** Registered extensions. Their api.ts hooks (transport/layer/members/header) are applied. */\n extensions?: CodegenExtension[];\n /** Shared extension context (from `generate()`). When omitted, a minimal one is built from routes. */\n ctx?: ExtensionContext;\n}\n\nexport async function emitApi(\n routes: RouteDescriptor[],\n outDir: string,\n opts: ApiEmitOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const content = buildApiFile(routes, outDir, opts);\n await writeFile(join(outDir, 'api.ts'), content, 'utf8');\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Split a dot-notation name into its path segments. */\nfunction splitName(name: string): string[] {\n return name.split('.');\n}\n\n/**\n * Check whether a segment is a valid JS identifier.\n * If not, we wrap it in quotes so it produces a valid object key.\n */\nfunction toObjectKey(segment: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(segment)) {\n return segment;\n }\n return JSON.stringify(segment);\n}\n\n/**\n * Convert an arbitrary string segment to camelCase by splitting on non-alphanumeric chars.\n */\nfunction toCamelCase(s: string): string {\n return s\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((word, i) =>\n i === 0\n ? word.charAt(0).toLowerCase() + word.slice(1)\n : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n )\n .join('');\n}\n\n/**\n * Validate that a single name segment matches camelCase: starts with a lowercase letter,\n * followed only by alphanumeric chars. Throws a descriptive error on invalid segments.\n */\nfunction validateNameSegment(seg: string, fullName: string): void {\n if (!/^[a-z][a-zA-Z0-9]*$/.test(seg)) {\n const suggested = toCamelCase(seg);\n throw new Error(\n `Contract name \"${fullName}\" has invalid segment \"${seg}\". Use camelCase identifiers only (lowercase letter then alphanumeric). Suggested: \"${suggested}\"`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nested tree helpers\n// ---------------------------------------------------------------------------\n\ntype LeafEntry = {\n kind: 'leaf';\n method: string;\n name: string;\n path: string;\n params: Array<{ name: string; source: string }>;\n controllerRef?: ControllerRef | undefined;\n // Reference the canonical discovery type directly rather than re-declaring a\n // parallel hand-maintained shape. The leaf is always built from a real\n // `ContractSource` (`contractSource: r.contract.contractSource`), so the extra\n // form/zod fields it carries are simply unused here.\n contractSource: ContractSource;\n};\n\ntype BranchEntry = {\n kind: 'branch';\n children: Map<string, TreeNode>;\n};\n\ntype TreeNode = LeafEntry | BranchEntry;\n\n/**\n * Insert a contracted route into the mutable tree.\n * Throws if a name conflict is detected.\n */\nfunction insertIntoTree(\n tree: Map<string, TreeNode>,\n segments: string[],\n leaf: LeafEntry,\n fullName: string,\n): void {\n const head = segments[0] as string;\n const rest = segments.slice(1);\n\n if (rest.length === 0) {\n // This is the final segment — insert as a leaf\n const existing = tree.get(head);\n if (existing !== undefined && existing.kind === 'branch') {\n throw new Error(\n `Contract name conflict: \"${fullName}\" cannot have both a direct entry and child entries`,\n );\n }\n tree.set(head, leaf);\n } else {\n // Need to recurse into a branch\n const existing = tree.get(head);\n if (existing !== undefined && existing.kind === 'leaf') {\n // The leaf's name is the prefix of fullName\n const prefixName = fullName\n .split('.')\n .slice(0, segments.length - rest.length)\n .join('.');\n throw new Error(\n `Contract name conflict: \"${prefixName}\" cannot have both a direct entry and child entries`,\n );\n }\n let branch: BranchEntry;\n if (existing === undefined) {\n branch = { kind: 'branch', children: new Map() };\n tree.set(head, branch);\n } else {\n branch = existing as BranchEntry;\n }\n insertIntoTree(branch.children, rest, leaf, fullName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Params helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build a TypeScript type literal for path params.\n * Returns 'never' when the route has no path params.\n */\nfunction buildParamsType(params: Array<{ name: string; source: string }>): string {\n const pathParams = params.filter((p) => p.source === 'path');\n if (pathParams.length === 0) return 'never';\n return `{ ${pathParams.map((p) => `${p.name}: string`).join('; ')} }`;\n}\n\n/**\n * Check whether a route has any path params.\n */\nfunction hasPathParams(params: Array<{ name: string; source: string }>): boolean {\n return params.some((p) => p.source === 'path');\n}\n\n// ---------------------------------------------------------------------------\n// Code generation helpers\n// ---------------------------------------------------------------------------\n\n/** Map a classified field kind (+ enum members) to a TS type literal. */\nfunction kindToTs(kind: FieldTypeKind, enumValues?: string[], numericEnum?: boolean): string {\n if (enumValues && enumValues.length > 0) {\n return enumValues.map((v) => (numericEnum ? v : JSON.stringify(v))).join(' | ');\n }\n switch (kind) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'date':\n return 'Date';\n case 'json':\n return 'Record<string, unknown>';\n default:\n return 'unknown';\n }\n}\n\n/**\n * Emit the per-field type map literal: `{ \"age\": number; \"status\": \"A\" | \"B\" }`.\n * This is the SOLE emit-side reader of `FilterFieldType` — it owns the `typeRef`\n * precedence invariant (a named ref wins over `kind`/`enumValues`; see the\n * `FilterFieldType` doc). No other emit code branches on `typeRef` vs `kind`.\n */\nfunction emitFieldTypesLiteral(fts: FilterFieldType[]): string {\n const entries = fts.map((f) => {\n // A named typeRef (enum / type alias / interface inferred from a @FilterFor\n // method parameter) wins — reference it by name; the import is emitted at\n // the top of the file by buildApiFile.\n let t = f.typeRef ? f.typeRef.name : kindToTs(f.kind, f.enumValues, f.numericEnum);\n if (f.nullable) t = `${t} | null`;\n return `${JSON.stringify(f.name)}: ${t}`;\n });\n return `{ ${entries.join('; ')} }`;\n}\n\n/** Build the type args for `_filterQueryTyped` — single union, or union + field-type map. */\nfunction emitFilterQueryTypeArgs(c: LeafEntry): string {\n const fieldsUnion = (c.contractSource.filterFields ?? [])\n .map((f) => JSON.stringify(f))\n .join(' | ');\n const fts = c.contractSource.filterFieldTypes;\n return fts?.length ? `${fieldsUnion}, ${emitFieldTypesLiteral(fts)}` : fieldsUnion;\n}\n\n/**\n * Build the `TypedFilterQuery<...>` TYPE for a query-source `@ApplyFilter` route's\n * `query` position. Built from the SAME `emitFilterQueryTypeArgs` used by the\n * `_filterQueryTyped<...>` factory so the two are byte-identical.\n */\nfunction emitFilterQueryType(c: LeafEntry): string {\n return `import('@dudousxd/nestjs-filter-client').TypedFilterQuery<${emitFilterQueryTypeArgs(c)}>`;\n}\n\n/**\n * Emit the nested ApiRouter type block.\n */\nfunction buildResponseType(c: LeafEntry, outDir: string): string {\n if (c.controllerRef) {\n let relPath = relative(outDir, c.controllerRef.filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n return `Awaited<ReturnType<import('${relPath}').${c.controllerRef.className}['${c.controllerRef.methodName}']>>`;\n }\n const respRef = c.contractSource.responseRef;\n if (respRef) {\n return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;\n }\n return c.contractSource.response;\n}\n\nfunction emitRouterTypeBlock(\n tree: Map<string, TreeNode>,\n indent: number,\n outDir: string,\n): string[] {\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n for (const [key, node] of tree) {\n const objKey = toObjectKey(key);\n if (node.kind === 'leaf') {\n const c = node;\n const method = c.method.toUpperCase();\n const queryRef = c.contractSource.queryRef;\n // A query-source `@ApplyFilter` route renders its `TypedFilterQuery<...>`\n // type here — from the same `filterFields`/`filterFieldTypes` data the\n // `_filterQueryTyped<...>` factory uses — so both are byte-identical.\n const isFilterQuery =\n c.contractSource.filterSource === 'query' && !!c.contractSource.filterFields?.length;\n const query = queryRef\n ? queryRef.isArray\n ? `Array<${queryRef.name}>`\n : queryRef.name\n : isFilterQuery\n ? emitFilterQueryType(c)\n : (c.contractSource.query ?? 'never');\n const bodyRef = c.contractSource.bodyRef;\n const body =\n method === 'GET'\n ? 'never'\n : bodyRef\n ? bodyRef.isArray\n ? `Array<${bodyRef.name}>`\n : bodyRef.name\n : (c.contractSource.body ?? 'never');\n const response = buildResponseType(c, outDir);\n const params = buildParamsType(c.params);\n const safeMethod = JSON.stringify(method);\n const safeUrl = JSON.stringify(c.path);\n // Filterable fields (from @dudousxd/nestjs-filter) as a string-literal\n // union, or `never` for routes without a filter. Purely type-level — no\n // runtime dependency on nestjs-filter is introduced by this member.\n const filterFields = c.contractSource.filterFields?.length\n ? c.contractSource.filterFields.map((f) => JSON.stringify(f)).join(' | ')\n : 'never';\n lines.push(\n `${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; params: ${params}; query: ${query}; body: ${body}; response: ${response}; filterFields: ${filterFields} };`,\n );\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));\n lines.push(`${pad}};`);\n }\n }\n\n return lines;\n}\n\n/**\n * Build the neutral per-leaf {@link RequestModel} from a discovered leaf. This is the\n * input every transport/layer/member-contributor reads — the seam the extension system\n * plugs into. Pure string-building; no I/O.\n */\nfunction buildRequestModel(c: LeafEntry): RequestModel {\n const isGet = c.method.toUpperCase() === 'GET';\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 const hasBody =\n !!c.contractSource.bodyRef ||\n (c.contractSource.body != null && c.contractSource.body !== 'never');\n // A filter-search route is a read even when POST — treat it as a query too.\n const isQuery = isGet || !!c.contractSource.filterFields?.length;\n // A route \"has a query\" when it carries a query contract — GET always can take one;\n // a mutation may too (query string alongside a body).\n const hasQuery =\n isGet ||\n !!c.contractSource.queryRef ||\n (c.contractSource.query != null && c.contractSource.query !== 'never');\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 bodyType: `${TA}['body']`,\n queryKeyExpr: `[${flat}, input] as const`,\n };\n}\n\n/**\n * The bundled default transport: a typed call on the injected `fetcher`. This is the\n * fallback when no extension claims `apiTransport`. Kept byte-identical to the legacy\n * `fetchExpr`. In Phase 3 the TanStack-specific layer below moves to a package; this\n * fetcher transport stays in core as the default.\n */\nfunction renderFetcherRequest(req: RequestModel): string {\n return `fetcher.${req.method}<${req.responseType}>(${req.urlExpr}, ${req.optsExpr})`;\n}\n\n/**\n * The `__req` runtime helper, emitted once per `api.ts`. Wraps a request thunk into an\n * **awaitable handle**: `await api.x.y({...})` runs the fetch (Tuyau-style), memoized so\n * repeated awaits hit the network once. Client-layer extensions (e.g. TanStack) spread\n * extra members (`queryOptions`/`mutationOptions`/…) onto the same handle.\n */\nfunction emitReqHelper(): string[] {\n return [\n '/** Awaitable request handle. `await api.x.y({...})` runs the fetch; extensions add query/mutation helpers. */',\n 'type __Req<R> = {',\n ' then<T1 = R, T2 = never>(',\n ' onfulfilled?: ((value: R) => T1 | PromiseLike<T1>) | null,',\n ' onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null,',\n ' ): Promise<T1 | T2>;',\n ' catch<T = never>(onrejected?: ((reason: unknown) => T | PromiseLike<T>) | null): Promise<R | T>;',\n ' finally(onfinally?: (() => void) | null): Promise<R>;',\n ' fetch(): Promise<R>;',\n '};',\n 'function __req<R>(run: () => Promise<R>): __Req<R> {',\n ' let __p: Promise<R> | undefined;',\n ' const __promise = () => {',\n ' __p ??= run();',\n ' return __p;',\n ' };',\n ' return {',\n ' then: (onfulfilled, onrejected) => __promise().then(onfulfilled, onrejected),',\n ' catch: (onrejected) => __promise().catch(onrejected),',\n ' finally: (onfinally) => __promise().finally(onfinally),',\n ' fetch: run,',\n ' };',\n '}',\n '',\n ];\n}\n\n/**\n * Render one leaf. Every leaf is an **awaitable handle**: the `__req(...)` base makes\n * `await api.x.y({...})` perform the request; any client-layer/member contributions\n * (TanStack options, filterQuery, …) are spread on alongside it.\n */\nfunction renderLeaf(\n pad: string,\n objKey: string,\n req: RequestModel,\n requestExpr: string,\n members: Record<string, string>,\n): string[] {\n const lines = [`${pad}${objKey}: (input?: ${req.inputType}) => ({`];\n lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);\n for (const [name, value] of Object.entries(members)) {\n lines.push(`${pad} ${name}: ${value},`);\n }\n lines.push(`${pad}}),`);\n return lines;\n}\n\n/** Resolved api.ts pipeline pieces, threaded through the recursive emit. */\ninterface ApiPipeline {\n transport?: ApiTransport;\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 → transport (default fetcher) → 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 // Reconstruct a RouteDescriptor view for extension hooks. The tree only retains the\n // LeafEntry (params typed as `source: string`), so cast back to the canonical shape.\n const route = {\n method: node.method,\n path: node.path,\n name: node.name,\n params: node.params,\n contract: { contractSource: node.contractSource },\n ...(node.controllerRef ? { controllerRef: node.controllerRef } : {}),\n } as unknown as RouteDescriptor;\n const leaf: LeafModel = { route, request: req, requestExpr: '' };\n leaf.requestExpr = p.transport\n ? p.transport.renderRequest(leaf, p.ctx)\n : renderFetcherRequest(req);\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.\n const members: Record<string, string> = {};\n if (p.layer) Object.assign(members, p.layer.buildMembers(leaf.requestExpr, leaf, p.ctx));\n for (const ext of p.memberExts) {\n const extra = ext.apiMembers?.(leaf, p.ctx);\n if (!extra) continue;\n for (const [name, value] of Object.entries(extra)) {\n if (name in members) {\n throw new Error(\n `api member \"${name}\" on route \"${req.routeName}\" is contributed by more than one extension (conflict at \"${ext.name}\").`,\n );\n }\n members[name] = value;\n }\n }\n\n lines.push(...renderLeaf(pad, objKey, req, leaf.requestExpr, members));\n }\n\n return lines;\n}\n\n/**\n * Build the ApiRouter type-access chain for a dot-separated name.\n * e.g. 'users.list' -> \"ApiRouter['users']['list']\"\n */\nfunction buildRouterTypeAccess(name: string): string {\n const segments = splitName(name);\n return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join('')}`;\n}\n\n// ---------------------------------------------------------------------------\n// Main builder\n// ---------------------------------------------------------------------------\n\nfunction buildApiFile(\n routes: RouteDescriptor[],\n outDir?: string,\n opts: ApiEmitOptions = {},\n): string {\n const fetcherImportPath = opts.fetcherImportPath;\n const extensions = opts.extensions ?? [];\n const { transport, layer } = resolveApiSlots(extensions);\n const memberExts = extensions.filter((e) => e.apiMembers);\n const headerExts = extensions.filter((e) => e.apiHeader);\n const contracted = routes.filter((r) => r.contract);\n\n // Extension context for the api.ts hooks. `generate()` passes the real one; standalone\n // `emitApi` calls (tests) get a minimal context exposing the routes (all the bundled\n // layer/transport read). `project()` is unavailable in the standalone path.\n const ctx: ExtensionContext =\n opts.ctx ??\n ({\n cwd: outDir ?? '',\n outDir: outDir ?? '',\n routes,\n config: {} as never,\n project: () => {\n throw new Error('ExtensionContext.project() is unavailable in standalone emitApi.');\n },\n } satisfies ExtensionContext);\n\n // Collect all type refs for import generation\n const importsByFile = new Map<string, Set<string>>();\n for (const r of contracted) {\n const cs = r.contract?.contractSource;\n if (!cs) continue;\n // When controllerRef exists, response uses ReturnType<import(...)> — skip response import\n const refs = r.controllerRef\n ? [cs.queryRef, cs.bodyRef]\n : [cs.queryRef, cs.bodyRef, cs.responseRef];\n for (const ref of refs) {\n if (!ref) continue;\n let names = importsByFile.get(ref.filePath);\n if (!names) {\n names = new Set();\n importsByFile.set(ref.filePath, names);\n }\n names.add(ref.name);\n }\n // Named enum / type-alias / interface refs inferred from @FilterFor method\n // params (the type map M references them by name → emit `import type` too).\n for (const ft of cs.filterFieldTypes ?? []) {\n if (!ft.typeRef) continue;\n let names = importsByFile.get(ft.typeRef.filePath);\n if (!names) {\n names = new Set();\n importsByFile.set(ft.typeRef.filePath, names);\n }\n names.add(ft.typeRef.name);\n }\n }\n\n const lines: string[] = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.', ''];\n\n // Extension-contributed module imports (transport + client layer + apiHeader), deduped\n // and emitted in order. e.g. the TanStack layer emits its queryOptions/mutationOptions\n // 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 transport?.imports?.(ctx) ?? []) pushImport(imp);\n for (const imp of layer?.imports?.(ctx) ?? []) pushImport(imp);\n for (const ext of headerExts) {\n for (const imp of ext.apiHeader?.(ctx)?.imports ?? []) pushImport(imp);\n }\n lines.push(...extImports);\n\n lines.push(\n \"import { route, ROUTES, type RouteName, type ExtractParams, type RouteParams } from './routes.js';\",\n );\n // Tuyau-style: the api is a factory that takes the fetcher at runtime, so the\n // app injects its own client (custom transport/axios, baseUrl, superjson) —\n // rather than the codegen hardcoding `import { fetcher } from '<path>'`.\n const runtimeImport = fetcherImportPath ?? '@dudousxd/nestjs-client';\n lines.push(`import type { Fetcher } from '${runtimeImport}';`);\n\n // Emit type imports from source files.\n // When two different files export the same type name, alias the duplicate\n // to avoid `Identifier has already been declared` parse errors.\n if (importsByFile.size > 0 && outDir) {\n lines.push('');\n const emittedNames = new Set<string>();\n for (const [filePath, names] of importsByFile) {\n // Bare module specifier (node_modules package) → import as-is. Local\n // source files are always absolute paths → compute a relative import.\n let relPath: string;\n if (isAbsolute(filePath)) {\n relPath = relative(outDir, filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n } else {\n relPath = filePath;\n }\n const specifiers: string[] = [];\n for (const name of [...names].sort()) {\n if (emittedNames.has(name)) {\n const alias = `${name}_${emittedNames.size}`;\n specifiers.push(`${name} as ${alias}`);\n emittedNames.add(alias);\n } else {\n specifiers.push(name);\n emittedNames.add(name);\n }\n }\n lines.push(`import type { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n }\n lines.push('');\n\n if (contracted.length === 0) {\n lines.push('export type ApiRouter = Record<string, never>;');\n lines.push('');\n lines.push('export function createApi(_fetcher: Fetcher): Record<string, never> {');\n lines.push(' return {};');\n lines.push('}');\n lines.push('export type Api = ReturnType<typeof createApi>;');\n lines.push('');\n lines.push('export namespace Route {');\n lines.push(' export type Response<K extends string> = never;');\n lines.push(' export type Body<K extends string> = never;');\n lines.push(' export type Query<K extends string> = never;');\n lines.push(' export type Params<K extends string> = never;');\n lines.push(' export type Error<K extends string> = never;');\n lines.push(' export type FilterFields<K extends string> = never;');\n lines.push(\n ' export type Request<K extends string> = { body: never; query: never; params: never };',\n );\n lines.push('}');\n lines.push('');\n lines.push('export namespace Path {');\n lines.push(' export type Response<M extends string, U extends string> = never;');\n lines.push(' export type Body<M extends string, U extends string> = never;');\n lines.push(' export type Query<M extends string, U extends string> = never;');\n lines.push(' export type Params<M extends string, U extends string> = never;');\n lines.push(' export type Error<M extends string, U extends string> = never;');\n lines.push(' export type FilterFields<M extends string, U extends string> = never;');\n lines.push('}');\n lines.push('');\n return lines.join('\\n');\n }\n\n // Build a nested tree from all contracted routes\n const tree = new Map<string, TreeNode>();\n\n for (const r of contracted) {\n const c = r.contract!;\n const name: string = r.name;\n const segments = splitName(name);\n // Validate each segment is a valid camelCase identifier\n for (const seg of segments) {\n validateNameSegment(seg, name);\n }\n const leaf: LeafEntry = {\n kind: 'leaf',\n method: r.method,\n name: name,\n path: r.path,\n params: r.params,\n controllerRef: r.controllerRef,\n contractSource: c.contractSource,\n };\n insertIntoTree(tree, segments, leaf, name);\n }\n\n // --- ApiRouter type ---\n lines.push('export type ApiRouter = {');\n lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ''));\n lines.push('};');\n lines.push('');\n\n // --- awaitable request handle helper ---\n lines.push(...emitReqHelper());\n\n // --- api factory (inject your fetcher at runtime) ---\n lines.push('export function createApi(fetcher: Fetcher) {');\n lines.push(' return {');\n lines.push(\n ...emitApiObjectBlock(tree, 4, {\n ...(transport ? { transport } : {}),\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 // --- Recursive helper type _RouterAt: walks nested ApiRouter by dot-path ---\n lines.push('type _RouterAt<R, P extends string> = P extends `${infer Head}.${infer Tail}`');\n lines.push(' ? Head extends keyof R ? _RouterAt<R[Head], Tail> : never');\n lines.push(' : P extends keyof R ? R[P] : never;');\n lines.push('');\n\n // --- ResolveByName: resolve a field from a dot-path name ---\n lines.push(\n 'type ResolveByName<K extends string, Field extends string> = _RouterAt<ApiRouter, K> extends infer R ? Field extends keyof R ? R[Field] : never : never;',\n );\n lines.push('');\n\n // --- ResolveByPath: scan all leaves for matching method + url ---\n // Flattens ApiRouter recursively and finds the entry whose method === M and url === U.\n lines.push('type _LeafValues<T> = T extends { method: string; url: string }');\n lines.push(' ? T');\n lines.push(' : T extends object ? _LeafValues<T[keyof T]> : never;');\n lines.push('');\n lines.push(\n 'type ResolveByPath<M extends string, U extends string, Field extends string> = _LeafValues<ApiRouter> extends infer L',\n );\n lines.push(' ? L extends { method: M; url: U }');\n lines.push(' ? Field extends keyof L ? L[Field] : never');\n lines.push(' : never');\n lines.push(' : never;');\n lines.push('');\n\n // --- Route namespace ---\n lines.push('export namespace Route {');\n lines.push(' export type Response<K extends string> = ResolveByName<K, \"response\">;');\n lines.push(' export type Body<K extends string> = ResolveByName<K, \"body\">;');\n lines.push(' export type Query<K extends string> = ResolveByName<K, \"query\">;');\n lines.push(' export type Params<K extends string> = ResolveByName<K, \"params\">;');\n lines.push(' export type Error<K extends string> = ResolveByName<K, \"error\">;');\n lines.push(' export type FilterFields<K extends string> = ResolveByName<K, \"filterFields\">;');\n lines.push(' export type Request<K extends string> = {');\n lines.push(' body: Body<K>;');\n lines.push(' query: Query<K>;');\n lines.push(' params: Params<K>;');\n lines.push(' };');\n lines.push('}');\n lines.push('');\n\n // --- Path namespace ---\n lines.push('export namespace Path {');\n lines.push(\n ' export type Response<M extends string, U extends string> = ResolveByPath<M, U, \"response\">;',\n );\n lines.push(\n ' export type Body<M extends string, U extends string> = ResolveByPath<M, U, \"body\">;',\n );\n lines.push(\n ' export type Query<M extends string, U extends string> = ResolveByPath<M, U, \"query\">;',\n );\n lines.push(\n ' export type Params<M extends string, U extends string> = ResolveByPath<M, U, \"params\">;',\n );\n lines.push(\n ' export type Error<M extends string, U extends string> = ResolveByPath<M, U, \"error\">;',\n );\n lines.push(\n ' export type FilterFields<M extends string, U extends string> = ResolveByPath<M, U, \"filterFields\">;',\n );\n lines.push('}');\n lines.push('');\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 {\n ApiClientLayer,\n ApiTransport,\n CodegenExtension,\n EmittedFile,\n ExtensionContext,\n} from './types.js';\n\n/**\n * Resolve the two single-slot api.ts hooks. At most one extension may claim each slot;\n * a second claimer throws a {@link CodegenError} naming both extensions. An unclaimed\n * `apiTransport` means the host falls back to the bundled fetcher transport; an unclaimed\n * `apiClientLayer` means leaves stay bare callables.\n */\nexport function resolveApiSlots(extensions: readonly CodegenExtension[]): {\n transport?: ApiTransport;\n layer?: ApiClientLayer;\n} {\n let transport: ApiTransport | undefined;\n let transportOwner: string | undefined;\n let layer: ApiClientLayer | undefined;\n let layerOwner: string | undefined;\n\n for (const ext of extensions) {\n if (ext.apiTransport) {\n if (transport) {\n throw new CodegenError(\n `api transport claimed by both \"${transportOwner}\" and \"${ext.name}\" — only one extension may set apiTransport.`,\n );\n }\n transport = ext.apiTransport;\n transportOwner = ext.name;\n }\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 ...(transport ? { transport } : {}),\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 * 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, 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 const prev = owners.get(key);\n if (prev !== undefined) {\n throw new CodegenError(\n `Output file \"${file.path}\" is emitted by both \"${prev}\" and \"${ext.name}\". Two extensions cannot write the same file.`,\n );\n }\n owners.set(key, ext.name);\n files.push(file);\n }\n }\n\n return files;\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\ninterface FormSchemaSource {\n /** `bodyZodRef`/`queryZodRef` re-export (Path A named const). */\n ref: TypeRef | null;\n /** Raw zod source text to inline (Path A inline call / Path B synthesized). */\n text: string | null;\n}\n\ninterface FormEntry {\n routeName: string;\n /** PascalCase base, e.g. `Login` (or `AuthLogin` on collision). */\n baseName: string;\n body: FormSchemaSource | undefined;\n query: FormSchemaSource | undefined;\n nestedSchemas: Record<string, string> | null;\n warnings: string[];\n}\n\n/**\n * Emits `forms.ts` into `outDir` — re-exported (Path A) or inlined/synthesized\n * (Path A inline / Path B) zod schemas per validatable route, plus a\n * `formSchemas` name→schema map.\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,\n adapter?: ValidationAdapter,\n): Promise<boolean> {\n if (config && config.enabled === false) return false;\n\n // Non-zod adapters render the neutral IR (class-validator DTOs only). The zod\n // path keeps the full machinery (defineContract re-exports, nested hoisting).\n if (adapter && adapter.name !== 'zod') {\n const content = buildFormsFileWithAdapter(routes, adapter);\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 const entries = collectFormEntries(routes);\n if (entries.length === 0) return false;\n\n await mkdir(outDir, { recursive: true });\n const content = buildFormsFile(entries, outDir, config);\n await writeFile(join(outDir, 'forms.ts'), content, 'utf8');\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Adapter-driven forms (valibot / arktype / any non-zod adapter)\n// ---------------------------------------------------------------------------\n\n/**\n * Render `forms.ts` from the neutral validation IR via `adapter`. Covers schemas\n * synthesized from class-validator DTOs (`bodySchema`/`querySchema`). Hand-written\n * `defineContract` zod schemas have no IR and are skipped with a warning (use the\n * zod adapter for those). Returns `null` when nothing to emit.\n */\nfunction buildFormsFileWithAdapter(\n routes: RouteDescriptor[],\n adapter: ValidationAdapter,\n): string | null {\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), matching the\n // zod path's behavior.\n const methodNameCounts = new Map<string, number>();\n for (const route of sorted) {\n const cs = route.contract!.contractSource;\n if (!cs.bodySchema && !cs.querySchema) continue;\n methodNameCounts.set(\n deriveBaseName(route.name).method,\n (methodNameCounts.get(deriveBaseName(route.name).method) ?? 0) + 1,\n );\n }\n\n const named = new Map<string, string>(); // hoisted nested schemas (deduped by name)\n const decls: string[] = [];\n const mapEntries: string[] = [];\n let used = false;\n\n for (const route of sorted) {\n const cs = route.contract!.contractSource;\n const { method, full } = deriveBaseName(route.name);\n const base = (methodNameCounts.get(method) ?? 0) > 1 ? full : method;\n\n const block: string[] = [];\n if (cs.bodyZodText && !cs.bodySchema) {\n block.push(\n `// warning: ${route.name} body is a defineContract (zod) schema; not translated to ${adapter.name} — use the zod adapter.`,\n );\n }\n let bodyConst: string | undefined;\n if (cs.bodySchema) {\n used = true;\n const r = adapter.renderModule(cs.bodySchema);\n for (const [n, t] of r.namedNestedSchemas) named.set(n, t);\n bodyConst = `${base}BodySchema`;\n block.push(`export const ${bodyConst} = ${r.schemaText};`);\n block.push(`export type ${base}Body = ${adapter.inferType(bodyConst)};`);\n }\n if (cs.querySchema) {\n used = true;\n const r = adapter.renderModule(cs.querySchema);\n for (const [n, t] of r.namedNestedSchemas) named.set(n, t);\n const queryConst = `${base}QuerySchema`;\n block.push(`export const ${queryConst} = ${r.schemaText};`);\n block.push(`export type ${base}Query = ${adapter.inferType(queryConst)};`);\n }\n if (block.length === 0) continue;\n decls.push(`// ${route.name}`, ...block, '');\n if (bodyConst) mapEntries.push(` ${JSON.stringify(route.name)}: ${bodyConst},`);\n }\n\n if (!used) return null;\n\n const lines: string[] = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.'];\n for (const imp of adapter.importStatements({ used: true })) lines.push(imp);\n lines.push('');\n if (named.size > 0) {\n lines.push('// Hoisted nested schemas (shared across endpoints).');\n for (const [n, t] of named) lines.push(`const ${n} = ${t};`);\n lines.push('');\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\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction hasSchema(src: FormSchemaSource | undefined): boolean {\n return !!src && (src.ref !== null || src.text !== null);\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\nfunction collectFormEntries(routes: RouteDescriptor[]): FormEntry[] {\n // Deterministic ordering: routes sorted by name.\n const sorted = [...routes].filter((r) => r.contract).sort((a, b) => a.name.localeCompare(b.name));\n\n // First pass: which base (method-only) names collide?\n const methodNameCounts = new Map<string, number>();\n const candidates: Array<{ route: RouteDescriptor; method: string; full: string }> = [];\n for (const route of sorted) {\n const cs = route.contract!.contractSource;\n const body: FormSchemaSource = { ref: cs.bodyZodRef ?? null, text: cs.bodyZodText ?? null };\n const query: FormSchemaSource = { ref: cs.queryZodRef ?? null, text: cs.queryZodText ?? null };\n if (!hasSchema(body) && !hasSchema(query)) continue;\n const { method, full } = deriveBaseName(route.name);\n methodNameCounts.set(method, (methodNameCounts.get(method) ?? 0) + 1);\n candidates.push({ route, method, full });\n }\n\n const entries: FormEntry[] = [];\n for (const { route, method, full } of candidates) {\n const cs = route.contract!.contractSource;\n const collision = (methodNameCounts.get(method) ?? 0) > 1;\n const baseName = collision ? full : method;\n const body: FormSchemaSource = { ref: cs.bodyZodRef ?? null, text: cs.bodyZodText ?? null };\n const query: FormSchemaSource = { ref: cs.queryZodRef ?? null, text: cs.queryZodText ?? null };\n entries.push({\n routeName: route.name,\n baseName,\n body: hasSchema(body) ? body : undefined,\n query: hasSchema(query) ? query : undefined,\n nestedSchemas: cs.formNestedSchemas ?? null,\n warnings: cs.formWarnings ?? [],\n });\n }\n return entries;\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\nfunction buildFormsFile(\n entries: FormEntry[],\n outDir: string,\n config?: ResolvedFormsConfig,\n): string {\n const zodImport = config?.zodImport ?? 'zod';\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-codegen. Do not edit.',\n `import { z } from '${zodImport}';`,\n ];\n\n // Collect re-export imports grouped by file. Alias on identifier collision.\n const importsByFile = new Map<string, Set<string>>();\n const refAlias = new Map<string, string>(); // `${filePath}\\0${root}` → alias\n for (const entry of entries) {\n for (const src of [entry.body, entry.query]) {\n // Only a ref WITHOUT inline text produces an import (text is preferred).\n if (src?.ref && !src.text) {\n const root = refRootIdentifier(src.ref.name);\n const set = importsByFile.get(src.ref.filePath) ?? new Set<string>();\n set.add(root);\n importsByFile.set(src.ref.filePath, set);\n }\n }\n }\n\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 lines.push(`import { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n }\n\n lines.push('');\n\n // ── Hoist nested schemas exactly once (dedup), disambiguating collisions ──\n // Each entry carries a `nestedSchemas` map (name → zod text) whose texts may\n // reference each other (and themselves) by name. A nested schema shared by N\n // endpoints must be declared ONCE; two unrelated schemas that happen to share\n // a name must NOT collapse into one. `planNestedSchemas` produces a global\n // registry of unique declarations plus a per-entry rename map applied to that\n // entry's body/query text.\n const { globalSchemas, renamesByEntry } = planNestedSchemas(entries);\n\n if (globalSchemas.size > 0) {\n lines.push('// Hoisted nested schemas (shared across endpoints).');\n for (const [name, text] of globalSchemas) {\n lines.push(`const ${name} = ${text};`);\n }\n lines.push('');\n }\n\n const mapEntries: string[] = [];\n\n for (const entry of entries) {\n lines.push(`// ${entry.routeName}`);\n\n if (entry.warnings && entry.warnings.length > 0) {\n for (const w of entry.warnings) {\n lines.push(`// warning: ${w}`);\n }\n }\n\n const rename = renamesByEntry.get(entry) ?? null;\n\n if (entry.body) {\n const schemaName = `${entry.baseName}BodySchema`;\n const typeName = `${entry.baseName}Body`;\n const text = applyRenames(renderSchema(entry.body, outDir, refAlias), rename);\n lines.push(`export const ${schemaName} = ${text};`);\n lines.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);\n mapEntries.push(` ${JSON.stringify(entry.routeName)}: ${schemaName},`);\n }\n\n if (entry.query) {\n const schemaName = `${entry.baseName}QuerySchema`;\n const typeName = `${entry.baseName}Query`;\n const text = applyRenames(renderSchema(entry.query, outDir, refAlias), rename);\n lines.push(`export const ${schemaName} = ${text};`);\n lines.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);\n }\n\n lines.push('');\n }\n\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\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Nested-schema hoisting: dedup + collision disambiguation + recursion guard.\n// ---------------------------------------------------------------------------\n\ninterface NestedSchemaPlan {\n /** Final unique name → declaration text, emitted once at the top. */\n globalSchemas: Map<string, string>;\n /** Per-entry name-rewrite map applied to that entry's body/query text. */\n renamesByEntry: Map<FormEntry, Map<string, string>>;\n}\n\n/**\n * Replace whole-identifier occurrences of each `from` name with its `to` name.\n * Uses a word boundary so `ColumnFilterSchema` is not matched inside\n * `ColumnFilterSchemaExtra`. A no-op when `renames` is null/empty.\n */\nfunction applyRenames(text: string, renames: Map<string, string> | null): string {\n if (!renames || renames.size === 0) return text;\n let out = text;\n for (const [from, to] of renames) {\n if (from === to) continue;\n out = out.replace(new RegExp(`\\\\b${escapeRegExp(from)}\\\\b`, 'g'), to);\n }\n return out;\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Does `text` reference its own declaration name (self-referential)? */\nfunction isSelfReferential(name: string, text: string): boolean {\n return new RegExp(`\\\\b${escapeRegExp(name)}\\\\b`).test(text);\n}\n\n/**\n * Build the global hoist registry + per-entry renames.\n *\n * Invariants enforced:\n * - Each unique (name, shape) pair is declared exactly once.\n * - Same name + same shape across entries → shared (no duplicate `const`).\n * - Same name + DIFFERENT shape → the later entry's copy is suffixed\n * (`Name_2`, `Name_3`, …) and every reference inside that entry is rewritten,\n * so the two distinct shapes never collide into one wrong schema.\n * - A self-referential (recursive) declaration is degraded to a valid\n * `z.unknown()` placeholder — never emitted as `const X = (… X …)` without a\n * type annotation (which would be implicit-any / fail to compile).\n */\nfunction planNestedSchemas(entries: FormEntry[]): NestedSchemaPlan {\n const globalSchemas = new Map<string, string>();\n // Canonical text already registered under a given final name (for shape match).\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 // Resolve a final, collision-free name for each local schema name. Iterate\n // to a fixpoint so that a rename of schema B (referenced by schema A) is\n // reflected when comparing A's text against the global registry.\n const rename = new Map<string, string>();\n for (const [name] of local) rename.set(name, name);\n\n // Helper: the entry-local text for a name with the CURRENT rename map applied.\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; // not yet registered → fine\n if (existing === text) continue; // same shape already registered → reuse\n // Collision: same name, different shape. Pick a fresh suffixed name.\n let i = 2;\n let candidate = `${name}_${i}`;\n while (\n (globalSchemas.has(candidate) && globalSchemas.get(candidate) !== textFor(name)) ||\n [...rename.values()].includes(candidate)\n ) {\n i += 1;\n candidate = `${name}_${i}`;\n }\n rename.set(name, candidate);\n changed = true;\n }\n }\n\n // Register each local schema under its final name, degrading recursion.\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 // If existing === text → already registered (shared). If it somehow still\n // differs after the fixpoint, keep the first registration and let the\n // rename map (which only rewrites references) point references elsewhere;\n // this branch is unreachable given the loop above but is a safe no-op.\n }\n\n renamesByEntry.set(entry, rename);\n }\n\n return { globalSchemas, renamesByEntry };\n}\n\nfunction renderSchema(\n src: FormSchemaSource,\n outDir: string,\n refAlias: Map<string, string>,\n): string {\n // Prefer inlining the raw zod text: re-exporting a named const from its source\n // (typically a controller) would pull server-only deps into the client bundle.\n // The text is byte-identical to the contract schema, so parity is preserved.\n if (src.text) return src.text;\n if (src.ref) {\n const root = refRootIdentifier(src.ref.name);\n const alias = refAlias.get(`${src.ref.filePath}\\0${root}`) ?? root;\n // Replace the root identifier with its (possibly aliased) import binding.\n const member = src.ref.name.slice(root.length); // e.g. `.body`\n return `${alias}${member}`;\n }\n return 'z.unknown()';\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function emitIndex(\n outDir: string,\n hasContracts = false,\n hasForms = false,\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const exports = [\"export * from './pages.js';\", \"export * from './routes.js';\"];\n if (hasContracts) {\n exports.push(\"export * from './api.js';\");\n }\n if (hasForms) {\n exports.push(\"export * from './forms.js';\");\n }\n const content = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.', ...exports, ''].join(\n '\\n',\n );\n await writeFile(join(outDir, 'index.d.ts'), content, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\nimport type { SharedPropsResult } from '../discovery/shared-props.js';\n\nexport interface EmitPagesOptions {\n /** The export name to reference in import() type expressions (default: 'ComponentProps'). */\n propsExport?: string;\n /** When true, infer props from the default export's first parameter instead of a named export. */\n inferFromDefault?: boolean;\n /** When provided, emit an InertiaSharedProps augmentation alongside the pages. */\n sharedProps?: SharedPropsResult | null;\n}\n\nexport async function emitPages(\n pages: DiscoveredPage[],\n outDir: string,\n _options: EmitPagesOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const pageNameUnion =\n pages.length > 0 ? pages.map((p) => JSON.stringify(p.name)).join(' | ') : 'never';\n\n const augBody = pages\n .map((p) => {\n const key = needsQuotes(p.name) ? JSON.stringify(p.name) : p.name;\n const valueType = buildAugmentationType(p, outDir);\n return ` ${key}: ${valueType};`;\n })\n .join('\\n');\n\n const propsHelper =\n \"\\nexport type InertiaProps<K extends InertiaPageName> = import('@dudousxd/nestjs-inertia').InertiaPages[K];\\n\";\n\n const sharedPropsBlock = buildSharedPropsBlock(_options.sharedProps ?? null);\n\n const content = `// Generated by @dudousxd/nestjs-codegen. Do not edit.\\n\\nexport type InertiaPageName = ${pageNameUnion};\\n${propsHelper}\\ndeclare module '@dudousxd/nestjs-inertia' {\\n interface InertiaPages {\\n${augBody}\\n }\\n${sharedPropsBlock}}\\n`;\n\n await writeFile(join(outDir, 'pages.d.ts'), content, 'utf8');\n}\n\n/**\n * Build the `InertiaSharedProps` interface augmentation block.\n * Returns an empty string when sharedProps is null (graceful fallback).\n *\n * When `isImportRef` is true, the type is expressed as a mapped type from an import reference.\n * When `properties` are available, they are emitted as individual interface members.\n */\nfunction buildSharedPropsBlock(sharedProps: SharedPropsResult | null): string {\n if (!sharedProps) return '';\n\n // isImportRef case: emit a type alias that re-exports the external type\n if (sharedProps.isImportRef) {\n return `\\n // eslint-disable-next-line @typescript-eslint/no-empty-interface\\n interface InertiaSharedProps extends ${sharedProps.typeString} {}\\n`;\n }\n\n // Inline properties case\n if (!sharedProps.properties || sharedProps.properties.length === 0) return '';\n\n const propsBody = sharedProps.properties.map((p) => ` ${p.name}: ${p.type};`).join('\\n');\n\n return `\\n interface InertiaSharedProps {\\n${propsBody}\\n }\\n`;\n}\n\n/**\n * Build the type for a page in the module augmentation.\n * Uses `Parameters<typeof import('...').default>[0]` to infer props\n * directly from the default export — no named export needed.\n */\nfunction buildAugmentationType(page: DiscoveredPage, outDir: string): string {\n let importPath = relative(outDir, page.absolutePath).replace(/\\.(tsx?|vue|svelte)$/, '');\n if (!importPath.startsWith('.')) {\n importPath = `./${importPath}`;\n }\n return `Parameters<typeof import('${importPath}').default>[0]`;\n}\n\nfunction needsQuotes(name: string): boolean {\n return !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * Emits `routes.ts` into `outDir` with:\n * - A `ROUTES` constant mapping name → path\n * - A `RouteName` union type of all route names\n * - A `RouteParams<K>` mapped type using template-literal `infer` to extract `:param` segments\n * - A runtime `route(name, params?)` helper that interpolates path params\n */\nexport async function emitRoutes(routes: RouteDescriptor[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const content = buildRoutesFile(routes);\n await writeFile(join(outDir, 'routes.ts'), content, 'utf8');\n}\n\nfunction buildRoutesFile(routes: RouteDescriptor[]): string {\n if (routes.length === 0) {\n return buildEmpty();\n }\n\n const entries = routes\n .map((r) => ` ${JSON.stringify(r.name)}: ${JSON.stringify(r.path)},`)\n .join('\\n');\n\n const routeNameUnion = routes.map((r) => ` | ${JSON.stringify(r.name)}`).join('\\n');\n\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-codegen. Do not edit.',\n '',\n '/** Map of route name → path pattern. */',\n 'export const ROUTES = {',\n entries,\n '} as const;',\n '',\n '/** Union of all known route names. */',\n 'export type RouteName =',\n `${routeNameUnion};`,\n '',\n '/**',\n ' * Extracts path-parameter names from a route path string.',\n ' * `ExtractParams<\"/users/:id\">` → `\"id\"`',\n ' */',\n 'export type ExtractParams<Path extends string> =',\n ' Path extends `${string}:${infer Param}/${infer Rest}`',\n ' ? Param | ExtractParams<`/${Rest}`>',\n ' : Path extends `${string}:${infer Param}`',\n ' ? Param',\n ' : never;',\n '',\n '/**',\n ' * Mapped type: given a `RouteName`, returns an object with each path param as `string`.',\n ' * `RouteParams<\"UsersController.show\">` → `{ id: string }`',\n ' * `RouteParams<\"UsersController.list\">` → `Record<string, never>`',\n ' */',\n 'export type RouteParams<K extends RouteName> =',\n ' ExtractParams<(typeof ROUTES)[K]> extends never',\n ' ? Record<string, never>',\n ' : { [P in ExtractParams<(typeof ROUTES)[K]>]: string };',\n '',\n '/**',\n ' * Map of every route name to its resolved params object.',\n ' * Use this for `InertiaRegistry` module augmentation.',\n ' */',\n 'export type RouteParamsMap = { [K in RouteName]: RouteParams<K> };',\n '',\n '/**',\n ' * Build a URL from a named route, interpolating path params and appending query string.',\n ' *',\n ' * @example',\n \" * route('UsersController.show', { id: '42' }) // → '/users/42'\",\n \" * route('UsersController.list') // → '/users'\",\n \" * route('users.list', undefined, { active: true }) // → '/api/users?active=true'\",\n ' */',\n 'export function route<K extends RouteName>(',\n ' name: K,',\n ' ...args: ExtractParams<(typeof ROUTES)[K]> extends never',\n ' ? [params?: undefined, query?: Record<string, unknown>]',\n ' : [params: RouteParams<K>, query?: Record<string, unknown>]',\n '): string {',\n ' const [params, query] = args as [Record<string, string> | undefined, Record<string, unknown> | undefined];',\n ' const path: string | undefined = ROUTES[name as RouteName];',\n ' if (path === undefined) {',\n \" const available = Object.keys(ROUTES).join(', ');\",\n ' throw new Error(',\n ' `[nestjs-codegen] Route \"${String(name)}\" does not exist.\\\\n\\\\n` +',\n ' `Available routes: ${available}\\\\n\\\\n` +',\n ' `This usually means:\\\\n` +',\n ' ` - The route name has a typo\\\\n` +',\n \" ` - The controller hasn't been scanned by codegen yet (run: nestjs-codegen codegen)\\\\n` +\",\n ' ` - The @As() decorator changed the route name\\\\n`',\n ' );',\n ' }',\n ' let resolvedPath: string = path;',\n ' if (params) {',\n ' resolvedPath = resolvedPath.replace(/:([^/]+)/g, (_, key) => {',\n ' const val = params[key];',\n ' if (val === undefined) throw new Error(`Missing route param: ${key}`);',\n ' return encodeURIComponent(val);',\n ' });',\n ' }',\n ' if (query && Object.keys(query).length > 0) {',\n ' const qs = new URLSearchParams();',\n ' for (const [k, v] of Object.entries(query)) {',\n ' if (v !== undefined && v !== null) qs.append(k, String(v));',\n ' }',\n ' const qStr = qs.toString();',\n ' if (qStr) {',\n \" const sep = resolvedPath.includes('?') ? '&' : '?';\",\n ' resolvedPath = `${resolvedPath}${sep}${qStr}`;',\n ' }',\n ' }',\n ' return resolvedPath;',\n '}',\n '',\n ];\n\n return lines.join('\\n');\n}\n\nfunction buildEmpty(): string {\n return [\n '// Generated by @dudousxd/nestjs-codegen. Do not edit.',\n '',\n 'export const ROUTES = {} as const;',\n 'export type RouteName = never;',\n 'export type ExtractParams<_Path extends string> = never;',\n 'export type RouteParams<_K extends RouteName> = Record<string, never>;',\n 'export function route(_name: never, _params?: undefined, _query?: Record<string, unknown>): string { return \"\"; }',\n '',\n ].join('\\n');\n}\n","import { 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":["messageRaw","readFile","join","join","resolve","Node","SyntaxKind","Node","resolve","reExportsName","sourceName","node","Node","Node","KNOWN_DECORATORS","toObjectKey","resolveTypeFactoryName","singularClassName","buildNestedReference","expr","applyPresence","baseFromType","firstArgText","numericArg","numericArgs","enumSchemaFromDecorator","inSchemaFromDecorator","aliasFor","firstArg","Node","Node","Node","Node","Node","resolve","join","Node","SyntaxKind","Node","SyntaxKind","firstArg","mkdir","writeFile","dirname","join","Project","join","relative","fg","Node","SyntaxKind","firstArg","isAbsolute","join","relative","Project","Project","join","toObjectKey","relative","isAbsolute","mkdir","writeFile","join","mkdir","writeFile","join","relative","content","mkdir","writeFile","join","mkdir","writeFile","join","relative","mkdir","writeFile","join","join","Project","mkdir","dirname","writeFile","mkdir","readFile","join","readFile","join"]}
|
|
1
|
+
{"version":3,"sources":["../../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/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-pages.ts","../../src/emit/emit-routes.ts","../../src/watch/lock-file.ts"],"sourcesContent":["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 // Use tsx ESM API to load TypeScript config files at runtime\n let tsImport:\n | ((specifier: string, options: string | { parentURL: string }) => Promise<unknown>)\n | undefined;\n try {\n const tsxEsm = await import('tsx/esm/api');\n tsImport = tsxEsm.tsImport;\n } catch {\n throw new ConfigError(\n 'Failed to load config: `tsx` is required for loading TypeScript config files. ' +\n 'Install it as a dev dependency: pnpm add -D tsx',\n );\n }\n\n const parentURL = pathToFileURL(`${filePath}__parent__`).href;\n const fileUrl = pathToFileURL(filePath).href;\n return tsImport(fileUrl, { parentURL });\n}\n\nfunction resolveAbsolute(cwd: string, p: string): string {\n if (isAbsolute(p)) return p;\n return resolve(cwd, p);\n}\n\n/**\n * Validates that `resolvedPath` is contained inside `cwd`.\n * Throws `ConfigError` if the path escapes the project root (e.g. via `..`\n * traversal or an absolute path outside cwd).\n */\nfunction assertInsideCwd(cwd: string, resolvedPath: string, fieldName: string): void {\n const rel = relative(cwd, resolvedPath);\n // relative() returns a path starting with '..' when the target is outside cwd,\n // and isAbsolute() catches platform edge-cases (e.g. Windows drive letters).\n if (rel.startsWith(`..${sep}`) || rel === '..' || isAbsolute(rel)) {\n throw new ConfigError(\n `\\`${fieldName}\\` must be inside the project cwd.\\n Resolved to: ${resolvedPath}\\n Project cwd: ${cwd}\\nIf this is intentional, move the file inside your project directory.`,\n );\n }\n}\n\n/**\n * Resolve a {@link UserConfig} (e.g. `NestjsCodegenModule.forRoot()` options) into a\n * fully-defaulted {@link ResolvedConfig} — without reading a config file. Used by the\n * Nest module and any programmatic caller that already holds the config in memory.\n *\n * @param userConfig the raw user config (forRoot options minus module-only fields)\n * @param cwd project root used to resolve globs / outDir. Defaults to `process.cwd()`.\n */\nexport function resolveConfig(userConfig: UserConfigInput, cwd?: string): ResolvedConfig {\n return applyDefaults(userConfig, cwd ?? process.cwd());\n}\n\n/**\n * Loosened {@link UserConfig} where `validation` may be absent. Both config entry\n * points accept this shape and enforce `validation` at runtime (it throws a clear\n * {@link ConfigError} when missing) — letting callers like the Nest module pass\n * partial options without a compile-time `validation` requirement.\n */\ntype UserConfigInput = Omit<UserConfig, 'validation'> & {\n validation?: UserConfig['validation'];\n};\n\n/**\n * Input validation shared by both config entry points ({@link loadConfig} and\n * {@link resolveConfig}). Guards user-provided fields before defaults are applied so\n * the file path and the programmatic `forRoot()` path reject the same bad input.\n */\nfunction validateUserConfig(userConfig: UserConfigInput): void {\n // `validation` is required — no adapter is bundled in core.\n if (userConfig.validation == null) {\n throw new ConfigError(\n 'validation adapter is required — install @dudousxd/nestjs-codegen-zod and pass zodAdapter, or use @dudousxd/nestjs-codegen-valibot / -arktype',\n );\n }\n // `pages` is Inertia-only and optional — but if present, `glob` must be a string.\n if (userConfig.pages && typeof userConfig.pages.glob !== 'string') {\n throw new ConfigError(\n 'Config validation failed: `pages.glob` must be a string when `pages` is set',\n );\n }\n}\n\nfunction applyDefaults(userConfig: UserConfigInput, cwd: string): ResolvedConfig {\n validateUserConfig(userConfig);\n\n const outDir = userConfig.codegen?.outDir\n ? resolveAbsolute(cwd, userConfig.codegen.outDir)\n : join(cwd, '.nestjs-codegen');\n\n const resolvedCwd = userConfig.codegen?.cwd ? resolveAbsolute(cwd, userConfig.codegen.cwd) : cwd;\n\n let app: ResolvedConfig['app'] = null;\n if (userConfig.app) {\n const resolvedEntry = resolveAbsolute(cwd, userConfig.app.moduleEntry);\n assertInsideCwd(cwd, resolvedEntry, 'app.moduleEntry');\n\n let resolvedTsconfig: string | null = null;\n if (userConfig.app.tsconfig) {\n resolvedTsconfig = resolveAbsolute(cwd, userConfig.app.tsconfig);\n assertInsideCwd(cwd, resolvedTsconfig, 'app.tsconfig');\n }\n\n app = {\n moduleEntry: resolvedEntry,\n tsconfig: resolvedTsconfig,\n };\n }\n\n return {\n extensions: userConfig.extensions ?? [],\n // Non-null: validateUserConfig() above throws when `validation` is absent.\n validation: resolveAdapter(userConfig.validation as NonNullable<typeof userConfig.validation>),\n pages: userConfig.pages\n ? {\n glob: userConfig.pages.glob,\n propsExport: userConfig.pages.propsExport ?? 'ComponentProps',\n componentNameStrategy: userConfig.pages.componentNameStrategy ?? 'relative-no-ext',\n }\n : null,\n contracts: {\n glob: userConfig.contracts?.glob ?? 'src/**/*.controller.ts',\n debounceMs: userConfig.contracts?.debounceMs ?? 500,\n },\n scopes: userConfig.scopes ?? {},\n codegen: {\n outDir,\n cwd: resolvedCwd,\n },\n app,\n fetcher: userConfig.fetcher ?? null,\n forms: {\n enabled: userConfig.forms?.enabled ?? true,\n watch: userConfig.forms?.watch ?? 'src/**/*.dto.ts',\n zodImport: userConfig.forms?.zodImport ?? 'zod',\n },\n };\n}\n\nexport async function loadConfig(cwd?: string): Promise<ResolvedConfig> {\n const resolvedCwd = cwd ?? process.cwd();\n\n let configPath: string | undefined;\n for (const name of CONFIG_FILES) {\n const candidate = join(resolvedCwd, name);\n if (await fileExists(candidate)) {\n configPath = candidate;\n break;\n }\n }\n\n if (!configPath) {\n throw new ConfigError(\n `Config file not found in ${resolvedCwd} (looked for ${CONFIG_FILES.join(', ')})\\nRun \\`nestjs-codegen init\\` to create a starter config.`,\n );\n }\n\n let mod: unknown;\n try {\n mod = await importTs(configPath);\n } catch (err) {\n if (err instanceof ConfigError) throw err;\n throw new ConfigError(`Failed to load config from ${configPath}`, { cause: err });\n }\n\n // tsImport returns a namespace module where `mod.default` is the module namespace object.\n // The actual `export default` value lives at `mod.default.default` (or `mod.default` for CJS interop).\n const modNs = (mod as Record<string, unknown>).default;\n const userConfig =\n modNs != null && typeof modNs === 'object' && 'default' in (modNs as object)\n ? ((modNs as Record<string, unknown>).default as UserConfig)\n : (modNs as UserConfig | undefined);\n\n if (!userConfig || typeof userConfig !== 'object') {\n throw new ConfigError(\n `Config file must have a default export. Did you forget \\`export default defineConfig({...})\\`? (${configPath})`,\n );\n }\n\n return applyDefaults(userConfig, resolvedCwd);\n}\n","export class ConfigError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'ConfigError';\n }\n}\n\nexport class CodegenError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'CodegenError';\n }\n}\n","import { ConfigError } from '../exceptions.js';\nimport type { ValidationAdapter } from './types.js';\n\n/** A built-in adapter name or a custom adapter instance. */\nexport type ValidationOption = 'zod' | 'valibot' | 'arktype' | ValidationAdapter;\n\n/**\n * Resolve a `validation` config value to a {@link ValidationAdapter}. No adapter is\n * bundled in core — the zod/valibot/arktype adapters ship as their own packages.\n * Import the adapter instance and pass it directly (it passes through here). A\n * custom adapter object also passes through.\n *\n * @example\n * import { zodAdapter } from '@dudousxd/nestjs-codegen-zod';\n * defineConfig({ validation: zodAdapter });\n */\nexport function resolveAdapter(option: ValidationOption): ValidationAdapter {\n if (typeof option !== 'string') return option;\n const pkg = `@dudousxd/nestjs-codegen-${option}`;\n const named = `${option}Adapter`;\n throw new ConfigError(\n `Validation adapter \"${option}\" is not bundled in core. Install ${pkg} and pass the adapter instance instead of the string:\\n\\n import { ${named} } from '${pkg}';\\n defineConfig({ validation: ${named} });`,\n );\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport chokidar from 'chokidar';\nimport type { ResolvedConfig } from '../config/types.js';\nimport { discoverContractsFast } from '../discovery/contracts-fast.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport { generate } from '../generate.js';\nimport { acquireLock } from './lock-file.js';\n\nconst PAGES_DEBOUNCE_MS = 150;\n\nexport interface Watcher {\n close(): Promise<void>;\n}\n\n/** No-op watcher returned when the lock is already held. */\nconst NO_OP_WATCHER: Watcher = { close: async () => {} };\n\n/**\n * Start two chokidar watchers:\n *\n * 1. **Pages watcher** (`config.pages.glob`, 150 ms debounce) — runs `generate(config)` on\n * any page file change, regenerating `pages.d.ts` and the cache manifest.\n *\n * 2. **Contracts watcher** (`config.contracts.glob`, configurable debounce — default 500 ms) —\n * re-runs static AST route discovery via ts-morph, then re-emits `routes.ts` and (when\n * contracts are present) `api.ts` + `index.d.ts`.\n *\n * Both watchers share a single lock file in `config.codegen.outDir`. If another live process\n * already holds the lock, logs a warning and returns a no-op watcher.\n */\nexport async function watch(config: ResolvedConfig, onChange?: () => void): Promise<Watcher> {\n const lock = await acquireLock(config.codegen.outDir);\n\n if (lock === null) {\n // Read the lock file to include the PID in the warning message\n let holderPid = 'unknown';\n try {\n const raw = await readFile(join(config.codegen.outDir, '.watcher.lock'), 'utf8');\n const data = JSON.parse(raw) as { pid?: number };\n if (data.pid !== undefined) holderPid = String(data.pid);\n } catch {\n // Lock file unreadable — fall back to generic warning\n }\n console.warn(\n `[nestjs-codegen] auto-watch skipped — another process (PID ${holderPid}) is already running the watcher in ${config.codegen.outDir}. Files will continue to regenerate from that process. To take over, stop the other watcher.`,\n );\n return NO_OP_WATCHER;\n }\n\n // Run an initial full pass: pages + routes + contracts (same as a one-shot `codegen` run)\n try {\n const initialRoutes = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n await generate(config, initialRoutes);\n } catch (err) {\n // Best-effort; don't crash the watcher on initial generation failure\n console.warn(\n `[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`,\n );\n try {\n await generate(config);\n } catch {\n /* fallback: pages only */\n }\n }\n\n // ── Pages watcher (fast path — no route discovery) ──────────────────────────\n let pagesDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n // No `pages` config → watch a path that matches nothing (pages are Inertia-only).\n const pagesGlob = config.pages?.glob ?? '.nestjs-codegen-no-pages';\n const pagesWatcher = chokidar.watch(join(config.codegen.cwd, pagesGlob), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n function schedulePagesRegenerate(): void {\n if (pagesDebounceTimer !== undefined) {\n clearTimeout(pagesDebounceTimer);\n }\n pagesDebounceTimer = setTimeout(async () => {\n pagesDebounceTimer = undefined;\n try {\n await generate(config);\n } catch (err) {\n console.error(\n '[nestjs-codegen] Pages generation failed:',\n err instanceof Error ? err.message : err,\n );\n }\n onChange?.();\n }, PAGES_DEBOUNCE_MS);\n }\n\n pagesWatcher.on('add', schedulePagesRegenerate);\n pagesWatcher.on('change', schedulePagesRegenerate);\n pagesWatcher.on('unlink', schedulePagesRegenerate);\n\n // ── Contracts watcher (static AST discovery via ts-morph) ────────────────────\n let contractsDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\n const contractsWatcher = chokidar.watch(join(config.codegen.cwd, config.contracts.glob), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n function scheduleContractsRegenerate(): void {\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n }\n contractsDebounceTimer = setTimeout(async () => {\n contractsDebounceTimer = undefined;\n try {\n const routes: RouteDescriptor[] = await discoverContractsFast({\n cwd: config.codegen.cwd,\n glob: config.contracts.glob,\n ...(config.app?.tsconfig ? { tsconfig: config.app.tsconfig } : {}),\n });\n\n // Route through generate() so the incremental pass honors the SAME emit\n // options as the initial pass (query / mutationClient / queryImport / fetcher\n // importPath + the validation adapter). Emitting api.ts/forms.ts directly here\n // would silently drop those settings on every contract edit.\n await generate(config, routes);\n } catch (err) {\n console.error(\n '[nestjs-codegen] Contracts generation failed:',\n err instanceof Error ? err.message : err,\n );\n }\n onChange?.();\n }, config.contracts.debounceMs);\n }\n\n contractsWatcher.on('add', scheduleContractsRegenerate);\n contractsWatcher.on('change', scheduleContractsRegenerate);\n contractsWatcher.on('unlink', scheduleContractsRegenerate);\n\n // ── DTO watcher (forms.ts synthesis from class-validator DTOs) ───────────────\n // DTO classes live in *.dto.ts files (not matched by the controller glob), but\n // changes to them affect the synthesized form schemas. Re-run discovery (which\n // re-emits forms.ts) on any DTO change, reusing the contracts debounce.\n const formsWatcher = chokidar.watch(join(config.codegen.cwd, config.forms.watch), {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 },\n });\n\n formsWatcher.on('add', scheduleContractsRegenerate);\n formsWatcher.on('change', scheduleContractsRegenerate);\n formsWatcher.on('unlink', scheduleContractsRegenerate);\n\n return {\n close: async () => {\n if (pagesDebounceTimer !== undefined) {\n clearTimeout(pagesDebounceTimer);\n pagesDebounceTimer = undefined;\n }\n if (contractsDebounceTimer !== undefined) {\n clearTimeout(contractsDebounceTimer);\n contractsDebounceTimer = undefined;\n }\n await pagesWatcher.close();\n await contractsWatcher.close();\n await formsWatcher.close();\n await lock.release();\n },\n };\n}\n","import { join, resolve } from 'node:path';\nimport fg from 'fast-glob';\n/**\n * Static AST-based contract discovery using ts-morph.\n * Cold start ~100-500 ms.\n */\nimport {\n type ClassDeclaration,\n type MethodDeclaration,\n Node,\n Project,\n type SourceFile,\n} from 'ts-morph';\nimport { extractDtoContract } from './dto-type-resolver.js';\nimport { loadTsconfigPaths, setDiscoveryContext } from './type-ref-resolution.js';\nimport type { ContractSource, RouteDescriptor, TypeRef } from './types.js';\nimport { type ParsedContractDef, parseDefineContractCall } from './zod-ast-to-ts.js';\n\n// Re-export so existing test import paths (`../discovery/contracts-fast.js`)\n// keep resolving these symbols after the decomposition into sibling modules.\nexport { extractDtoContract } from './dto-type-resolver.js';\nexport { zodAstToTs } from './zod-ast-to-ts.js';\n\nexport interface FastDiscoveryOptions {\n /** Absolute path to the project root. */\n cwd: string;\n /** Controllers glob, e.g. 'src/**\\/*.controller.ts' */\n glob: string;\n /** Optional tsconfig.json path; default 'tsconfig.json' in cwd */\n tsconfig?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport async function discoverContractsFast(\n opts: FastDiscoveryOptions,\n): Promise<RouteDescriptor[]> {\n const { cwd, glob, tsconfig } = opts;\n\n const tsconfigPath = tsconfig ? resolve(tsconfig) : join(cwd, 'tsconfig.json');\n\n // Try to use tsconfig if it exists; fall back to bare compiler options\n let project: Project;\n try {\n project = new Project({\n tsConfigFilePath: tsconfigPath,\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n });\n } catch {\n // tsconfig not found — create a minimal project without it\n project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: {\n allowJs: true,\n resolveJsonModule: false,\n strict: false,\n },\n });\n }\n\n // Resolve controller file paths\n const files = await fg(glob, { cwd, absolute: true, onlyFiles: true });\n\n for (const f of files) {\n project.addSourceFileAtPath(f);\n }\n\n const routes: RouteDescriptor[] = [];\n\n // Bind the discovery context to this invocation's Project. Each call owns its\n // own Project, so concurrent callers never share or corrupt context.\n setDiscoveryContext(project, {\n projectRoot: cwd,\n tsconfigPaths: loadTsconfigPaths(tsconfigPath),\n });\n\n for (const sourceFile of project.getSourceFiles()) {\n routes.push(...extractFromSourceFile(sourceFile, project));\n }\n\n return routes;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the string value from a decorator argument that is a string literal. */\nfunction decoratorStringArg(decoratorExpr: Node | undefined): string | undefined {\n if (!decoratorExpr) return undefined;\n if (Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();\n if (Node.isArrayLiteralExpression(decoratorExpr)) {\n const first = decoratorExpr.getElements()[0];\n if (first && Node.isStringLiteral(first)) return first.getLiteralValue();\n }\n return undefined;\n}\n\n/**\n * Derive the route name from a controller class name and method name.\n * Strips the `Controller` suffix from the class name and lowercases the first letter.\n * e.g. `UsersController.list` → `users.list`\n */\nexport function deriveRouteName(className: string, methodName: string): string {\n const noSuffix = className.replace(/Controller$/, '');\n if (!noSuffix) {\n throw new Error(\n `Controller class name \"${className}\" derives empty route segment after stripping \"Controller\". Add an @As(...) override.`,\n );\n }\n const segment = noSuffix.charAt(0).toLowerCase() + noSuffix.slice(1);\n return `${segment}.${methodName}`;\n}\n\n/**\n * Derive just the class segment (no method) from a controller class name.\n * Strips the `Controller` suffix and lowercases the first letter.\n */\nexport function deriveClassSegment(className: string): string {\n const noSuffix = className.replace(/Controller$/, '');\n if (!noSuffix) {\n throw new Error(\n `Controller class name \"${className}\" derives empty route segment after stripping \"Controller\". Add an @As(...) override at the class level.`,\n );\n }\n return noSuffix.charAt(0).toLowerCase() + noSuffix.slice(1);\n}\n\n/**\n * Compose the final route name from class-level and method-level @As decorators.\n * Rule:\n * classPortion = class @As value ?? deriveClassSegment(className)\n * methodPortion = method @As value ?? methodName\n * result = `${classPortion}.${methodPortion}`\n */\nexport function resolveRouteName(\n className: string,\n methodName: string,\n classAs: string | undefined,\n methodAs: string | undefined,\n): string {\n const classPortion = classAs ?? deriveClassSegment(className);\n const methodPortion = methodAs ?? methodName;\n return `${classPortion}.${methodPortion}`;\n}\n\n/** Join two URL path segments, normalising duplicate slashes. */\nexport function joinPaths(prefix: string, suffix: string): string {\n if (!prefix && !suffix) return '/';\n if (!prefix) return suffix.startsWith('/') ? suffix : `/${suffix}`;\n if (!suffix) return prefix.startsWith('/') ? prefix : `/${prefix}`;\n\n const p = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const s = suffix.startsWith('/') ? suffix : `/${suffix}`;\n const combined = p + s;\n return combined === '' ? '/' : combined;\n}\n\n/** Extract path params from a URL pattern string, e.g. `/users/:id` → [{name:'id',source:'path'}] */\nfunction extractParams(\n path: string,\n): Array<{ name: string; source: 'path' | 'query' | 'body' | 'header' }> {\n const matches = path.matchAll(/:(\\w+)/g);\n return Array.from(matches).map((m) => ({ name: m[1] as string, source: 'path' as const }));\n}\n\n// ---------------------------------------------------------------------------\n// HTTP method decorator names recognised by the fast path\n// ---------------------------------------------------------------------------\n\nconst HTTP_METHOD_DECORATORS: Record<string, string> = {\n Get: 'GET',\n Post: 'POST',\n Put: 'PUT',\n Patch: 'PATCH',\n Delete: 'DELETE',\n Options: 'OPTIONS',\n Head: 'HEAD',\n All: 'ALL',\n};\n\n// ---------------------------------------------------------------------------\n// Per-file extraction\n// ---------------------------------------------------------------------------\n\n/** Resolved HTTP verb + handler sub-path read from a method's NestJS verb decorator. */\ninterface ResolvedVerb {\n httpMethod: string;\n handlerPath: string;\n}\n\n/**\n * Read the HTTP verb + sub-path from a method's NestJS verb decorator\n * (`@Get`/`@Post`/…). Returns null when the method carries no verb decorator.\n */\nfunction resolveVerb(method: MethodDeclaration): ResolvedVerb | null {\n for (const [decoratorName, verb] of Object.entries(HTTP_METHOD_DECORATORS)) {\n const httpDecorator = method.getDecorator(decoratorName);\n if (httpDecorator) {\n const httpArgs = httpDecorator.getArguments();\n const pathArg = httpArgs[0];\n return { httpMethod: verb, handlerPath: decoratorStringArg(pathArg) ?? '' };\n }\n }\n return null;\n}\n\n/**\n * Read an `@As(...)` decorator value off a node (class or method).\n * Throws when the decorator is present but its argument is empty — preserving\n * the @ApplyContract arm's strict policy, unified across both route arms.\n * Returns undefined when no `@As` decorator is present.\n */\nfunction readAsDecorator(\n node: ClassDeclaration | MethodDeclaration,\n label: string,\n): string | undefined {\n const asDecorator = node.getDecorator('As');\n if (!asDecorator) return undefined;\n const asName = decoratorStringArg(asDecorator.getArguments()[0]);\n if (!asName) {\n throw new Error(`@As decorator on ${label} must have a non-empty string argument.`);\n }\n return asName;\n}\n\n/**\n * Build a {@link RouteDescriptor} and register its name for collision detection.\n * Throws on a duplicate route name across the file's contracted/plain routes.\n */\nfunction buildRoute(args: {\n className: string;\n methodName: string;\n resolvedMethod: string;\n combinedPath: string;\n classAs: string | undefined;\n methodAs: string | undefined;\n sourceFile: SourceFile;\n seenNames: Map<string, string>;\n contractSource: ContractSource;\n}): RouteDescriptor {\n const {\n className,\n methodName,\n resolvedMethod,\n combinedPath,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource,\n } = args;\n\n const routeName = resolveRouteName(className, methodName, classAs, methodAs);\n\n // Collision detection across routes in the same file.\n const qualifiedRef = `${className}.${methodName}`;\n const existing = seenNames.get(routeName);\n if (existing !== undefined) {\n throw new Error(\n `Route name collision: \"${routeName}\" is used by both \"${existing}\" and \"${qualifiedRef}\". Use @As(...) to give one of them a unique name.`,\n );\n }\n seenNames.set(routeName, qualifiedRef);\n\n return {\n method: resolvedMethod,\n path: combinedPath,\n name: routeName,\n params: extractParams(combinedPath),\n controllerRef: { className, methodName, filePath: sourceFile.getFilePath() },\n contract: { contractSource },\n };\n}\n\n/**\n * Build a route from an `@ApplyContract` method. Returns null when the contract\n * cannot be resolved or the method lacks an HTTP verb decorator.\n */\nfunction extractContractRoute(args: {\n cls: ClassDeclaration;\n method: MethodDeclaration;\n applyContractDecorator: import('ts-morph').Decorator;\n verb: ResolvedVerb | null;\n prefix: string;\n className: string;\n sourceFile: SourceFile;\n seenNames: Map<string, string>;\n}): RouteDescriptor | null {\n const { cls, method, applyContractDecorator, verb, prefix, className, sourceFile, seenNames } =\n args;\n\n const firstDecoratorArg = applyContractDecorator.getArguments()[0];\n if (!firstDecoratorArg) return null;\n\n // Resolve contract definition from inline call or identifier.\n let contractDef: ParsedContractDef | null = null;\n // When the contract is a named const we can import, re-export its members\n // (`<const>.body` / `<const>.query`) for perfect parity.\n let bodyZodRef: TypeRef | null = null;\n let queryZodRef: TypeRef | null = null;\n\n if (Node.isCallExpression(firstDecoratorArg)) {\n contractDef = parseDefineContractCall(firstDecoratorArg);\n } else if (Node.isIdentifier(firstDecoratorArg)) {\n const identName = firstDecoratorArg.getText();\n const varDecl = sourceFile.getVariableDeclaration(identName);\n if (!varDecl) {\n console.warn(\n `[nestjs-codegen/fast] Cannot resolve '${identName}' in ${sourceFile.getFilePath()} (cross-file imports are out-of-scope for v1) — skipping`,\n );\n return null;\n }\n\n const initializer = varDecl.getInitializer();\n if (!initializer) return null;\n\n contractDef = parseDefineContractCall(initializer);\n // Re-export the named contract's schema members (Path A). Only when the\n // const is exported so forms.ts can import it.\n if (contractDef && varDecl.isExported()) {\n const filePath = sourceFile.getFilePath();\n if (contractDef.body !== null) {\n bodyZodRef = { name: `${identName}.body`, filePath };\n }\n if (contractDef.query !== null) {\n queryZodRef = { name: `${identName}.query`, filePath };\n }\n }\n } else {\n console.warn(\n `[nestjs-codegen/fast] @ApplyContract arg is not an identifier or call expression in ${sourceFile.getFilePath()} — skipping`,\n );\n return null;\n }\n\n if (!contractDef) return null;\n\n // Method + path always come from NestJS decorators — skip if absent.\n if (!verb) return null;\n const resolvedPath = joinPaths(prefix, verb.handlerPath);\n const methodName = method.getName();\n\n const classAs = readAsDecorator(cls, `class ${className}`);\n const methodAs = readAsDecorator(method, `${className}.${methodName}`);\n\n return buildRoute({\n className,\n methodName,\n resolvedMethod: verb.httpMethod,\n combinedPath: resolvedPath,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource: {\n query: contractDef.query,\n body: contractDef.body,\n response: contractDef.response,\n // Path A: capture both the importable ref and the raw text. The emitter\n // prefers inlining the text (client-safe — re-exporting from a controller\n // would drag server-only deps into the client bundle).\n bodyZodRef,\n bodyZodText: contractDef.bodyZodText,\n queryZodRef,\n queryZodText: contractDef.queryZodText,\n },\n });\n}\n\n/**\n * Build a route from a plain HTTP-verb method (no `@ApplyContract`), extracting\n * any DTO-based contract info. Returns null when the method lacks a verb.\n */\nfunction extractDtoRoute(args: {\n cls: ClassDeclaration;\n method: MethodDeclaration;\n verb: ResolvedVerb | null;\n prefix: string;\n className: string;\n sourceFile: SourceFile;\n project: Project;\n seenNames: Map<string, string>;\n}): RouteDescriptor | null {\n const { cls, method, verb, prefix, className, sourceFile, project, seenNames } = args;\n\n if (!verb) return null;\n\n const combined = joinPaths(prefix, verb.handlerPath);\n const methodName = method.getName();\n\n const classAs = readAsDecorator(cls, `class ${className}`);\n const methodAs = readAsDecorator(method, `${className}.${methodName}`);\n\n const dtoContract = extractDtoContract(method, sourceFile, project);\n\n return buildRoute({\n className,\n methodName,\n resolvedMethod: verb.httpMethod,\n combinedPath: combined,\n classAs,\n methodAs,\n sourceFile,\n seenNames,\n contractSource: {\n query: dtoContract?.query ?? null,\n body: dtoContract?.body ?? null,\n response: dtoContract?.response ?? 'unknown',\n queryRef: dtoContract?.queryRef ?? null,\n bodyRef: dtoContract?.bodyRef ?? null,\n responseRef: dtoContract?.responseRef ?? null,\n filterFields: dtoContract?.filterFields ?? null,\n filterFieldTypes: dtoContract?.filterFieldTypes ?? null,\n filterSource: dtoContract?.filterSource ?? null,\n formWarnings: dtoContract?.formWarnings ?? [],\n bodySchema: dtoContract?.bodySchema ?? null,\n querySchema: dtoContract?.querySchema ?? null,\n },\n });\n}\n\nfunction extractFromSourceFile(sourceFile: SourceFile, project: Project): RouteDescriptor[] {\n const routes: RouteDescriptor[] = [];\n // Track derived/assigned names to detect collisions: name → fully-qualified method ref\n const seenNames = new Map<string, string>();\n\n for (const cls of sourceFile.getClasses()) {\n // Find @Controller(...) decorator\n const controllerDecorator = cls.getDecorator('Controller');\n if (!controllerDecorator) continue;\n\n // Determine controller path prefix\n const firstArg = controllerDecorator.getArguments()[0];\n const prefix = decoratorStringArg(firstArg) ?? '';\n\n const className = cls.getName() ?? 'Unknown';\n\n for (const method of cls.getMethods()) {\n const verb = resolveVerb(method);\n const applyContractDecorator = method.getDecorator('ApplyContract');\n\n const route = applyContractDecorator\n ? extractContractRoute({\n cls,\n method,\n applyContractDecorator,\n verb,\n prefix,\n className,\n sourceFile,\n seenNames,\n })\n : extractDtoRoute({\n cls,\n method,\n verb,\n prefix,\n className,\n sourceFile,\n project,\n seenNames,\n });\n\n if (route) routes.push(route);\n }\n }\n\n return routes;\n}\n","import {\n type ClassDeclaration,\n type InterfaceDeclaration,\n type MethodDeclaration,\n Node,\n type Project,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport { extractSchemaFromDto } from './dto-to-ir.js';\nimport { extractApplyFilterInfo } from './filter-for.js';\nimport {\n type TypeDeclResult,\n dbg,\n findType,\n resolveImportedType,\n resolveTypeRef,\n} from './type-ref-resolution.js';\nimport type { FilterFieldType, TypeRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// DTO-based contract extraction (standard NestJS patterns — no defineContract)\n// ---------------------------------------------------------------------------\n\n/**\n * Wrapper type names whose wire shape reduces to their first type argument.\n * - `unwrap` → emit the type-arg as-is (e.g. Promise<T> → T)\n * - `arrayOf` → wrap the type-arg in `Array<>` (e.g. Collection<T> → Array<T>)\n */\nconst WRAPPER_TYPES: Record<string, 'unwrap' | 'arrayOf'> = {\n // MikroORM Ref/Reference/LoadedReference/IdentifiedReference are server-side\n // wrappers around related entities; the wire shape is just the referenced\n // entity. Unwrap to the type argument.\n Ref: 'unwrap',\n Reference: 'unwrap',\n LoadedReference: 'unwrap',\n IdentifiedReference: 'unwrap',\n // MikroORM Opt<T> is a marker, Loaded<T, ...> is a wrapper; both reduce to T.\n Opt: 'unwrap',\n Loaded: 'unwrap',\n // Promise<T> — unwrap\n Promise: 'unwrap',\n // MikroORM Collection<T> serializes as an array of T on the wire.\n Collection: 'arrayOf',\n // Array<T> generic form\n Array: 'arrayOf',\n};\n\n/** Well-known utility types — preserve full text with type args. */\nconst PASSTHROUGH_UTILITY = new Set([\n 'Record',\n 'Omit',\n 'Pick',\n 'Partial',\n 'Required',\n 'Readonly',\n 'Map',\n 'Set',\n]);\n\n/**\n * Resolve a TypeNode to a TypeScript type-source string.\n * Follows imports across files via the ts-morph Project.\n * `depth` limits recursive expansion (guards against circular references).\n */\nfunction resolveTypeNodeToString(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (depth <= 0) return 'unknown';\n\n // Array<T> or T[] — unwrap and wrap\n if (Node.isArrayTypeNode(typeNode)) {\n const elementType = typeNode.getElementTypeNode();\n return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth)}>`;\n }\n\n // Union: A | B | C — resolve each member so named refs get inlined\n if (Node.isUnionTypeNode(typeNode)) {\n return typeNode\n .getTypeNodes()\n .map((t) => resolveTypeNodeToString(t, sourceFile, project, depth))\n .join(' | ');\n }\n\n // Intersection: A & B — same treatment\n if (Node.isIntersectionTypeNode(typeNode)) {\n return typeNode\n .getTypeNodes()\n .map((t) => resolveTypeNodeToString(t, sourceFile, project, depth))\n .join(' & ');\n }\n\n // Parenthesized: ( ... ) — unwrap\n if (Node.isParenthesizedTypeNode(typeNode)) {\n return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth)})`;\n }\n\n // TypeReference: Foo, Foo[], Array<Foo>, Promise<Foo>, etc.\n if (Node.isTypeReference(typeNode)) {\n const typeName = typeNode.getTypeName();\n const name = Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();\n\n // Well-known pass-through primitives and types\n if (name === 'string' || name === 'number' || name === 'boolean') return name;\n if (name === 'Date') return 'string';\n if (name === 'unknown' || name === 'any' || name === 'void') return 'unknown';\n // Server-only types that don't make sense on the client\n if (name === 'StreamableFile' || name === 'Observable' || name === 'ReadableStream')\n return 'unknown';\n\n // Known wrapper types — unwrap (or array-wrap) their first type argument.\n const wrapperMode = WRAPPER_TYPES[name];\n if (wrapperMode) {\n return unwrapFirstTypeArg(typeNode, sourceFile, project, depth, wrapperMode);\n }\n\n // Well-known utility types — preserve full text with type args\n if (PASSTHROUGH_UTILITY.has(name)) {\n return typeNode.getText();\n }\n\n // Try same file first, then follow imports (class, interface, type alias, enum)\n const resolved = findType(name, sourceFile, project);\n if (resolved) {\n return expandTypeDecl(resolved, project, depth - 1);\n }\n\n // Unresolvable type — use unknown instead of bare name to avoid TS errors in generated code\n dbg('unresolvable type:', name, 'in', sourceFile.getFilePath());\n return 'unknown';\n }\n\n // Primitive keyword types\n const kind = typeNode.getKind();\n if (kind === SyntaxKind.StringKeyword) return 'string';\n if (kind === SyntaxKind.NumberKeyword) return 'number';\n if (kind === SyntaxKind.BooleanKeyword) return 'boolean';\n if (kind === SyntaxKind.UnknownKeyword) return 'unknown';\n if (kind === SyntaxKind.AnyKeyword) return 'unknown';\n\n // Fallback: raw text\n return typeNode.getText();\n}\n\n/**\n * Unwrap the first type argument of a wrapper TypeReference. In `unwrap` mode\n * the type-arg is emitted as-is; in `arrayOf` mode it is wrapped in `Array<>`.\n * Falls back to `'unknown'` / `'Array<unknown>'` when no type-arg is present.\n */\nfunction unwrapFirstTypeArg(\n typeNode: import('ts-morph').TypeReferenceNode,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n mode: 'unwrap' | 'arrayOf',\n): string {\n const typeArgs = typeNode.getTypeArguments();\n const firstTypeArg = typeArgs[0];\n if (typeArgs.length > 0 && firstTypeArg !== undefined) {\n const inner = resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);\n return mode === 'arrayOf' ? `Array<${inner}>` : inner;\n }\n return mode === 'arrayOf' ? 'Array<unknown>' : 'unknown';\n}\n\n/**\n * Expand a TypeDeclResult into an inline TS type string.\n */\nfunction expandTypeDecl(result: TypeDeclResult, project: Project, depth: number): string {\n if (depth < 0) return 'unknown';\n switch (result.kind) {\n case 'class':\n return resolvePropertied(result.decl, result.file, project, depth);\n case 'interface':\n return resolvePropertied(result.decl, result.file, project, depth);\n case 'typeAlias':\n // Recursively resolve the alias body so that any named types it\n // references (e.g. `A | B | C`) are expanded inline rather than left\n // as bare identifiers, which would be undefined in the emitted code.\n if (result.typeNode) {\n return resolveTypeNodeToString(result.typeNode, result.file, project, depth);\n }\n return result.text;\n case 'enum':\n return result.members.join(' | ');\n }\n}\n\n/**\n * Turn a class or interface declaration's properties into a TS object type string like\n * `{ id: string; title: string; page?: number }`.\n */\nfunction resolvePropertied(\n decl: ClassDeclaration | InterfaceDeclaration,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (depth < 0) return 'unknown';\n\n const lines: string[] = [];\n for (const prop of decl.getProperties()) {\n const propName = prop.getName();\n const isOptional = prop.hasQuestionToken();\n const propTypeNode = prop.getTypeNode();\n let propType = 'unknown';\n if (propTypeNode) {\n propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth);\n }\n lines.push(`${propName}${isOptional ? '?' : ''}: ${propType}`);\n }\n return `{ ${lines.join('; ')} }`;\n}\n\n/**\n * Extract the body type from a `@Body()` (no-arg) decorated parameter.\n * Returns a TS type string or null.\n */\nfunction extractBodyType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string | null {\n for (const param of method.getParameters()) {\n const bodyDecorator = param.getDecorators().find((d) => d.getName() === 'Body');\n if (!bodyDecorator) continue;\n const bodyArgs = bodyDecorator.getArguments();\n if (bodyArgs.length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n return null;\n}\n\n/**\n * Extract the query type from a `@Query()` (no-arg) decorated parameter.\n * Returns a TS type string or null.\n */\nfunction extractQueryType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string | null {\n for (const param of method.getParameters()) {\n const queryDecorator = param.getDecorators().find((d) => d.getName() === 'Query');\n if (!queryDecorator) continue;\n const queryArgs = queryDecorator.getArguments();\n if (queryArgs.length > 0) continue;\n const typeNode = param.getTypeNode();\n if (typeNode) {\n return resolveTypeNodeToString(typeNode, sourceFile, project, 3);\n }\n }\n return null;\n}\n\n/**\n * Collect `@Param('name')` decorated parameters into a `{ name: type; ... }` string.\n * Returns a TS type string or null when no @Param decorators are present.\n */\nfunction extractParamsType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string | null {\n const entries: string[] = [];\n for (const param of method.getParameters()) {\n const paramDecorator = param.getDecorators().find((d) => d.getName() === 'Param');\n if (!paramDecorator) continue;\n const paramArgs = paramDecorator.getArguments();\n if (paramArgs.length === 0) continue;\n const nameArg = paramArgs[0];\n if (!Node.isStringLiteral(nameArg)) continue;\n const paramName = nameArg.getLiteralValue();\n const typeNode = param.getTypeNode();\n const paramType = typeNode\n ? resolveTypeNodeToString(typeNode, sourceFile, project, 3)\n : 'string';\n entries.push(`${paramName}: ${paramType}`);\n }\n return entries.length > 0 ? `{ ${entries.join('; ')} }` : null;\n}\n\n/**\n * Extract the response type from `@ApiResponse({ type: X })` or `@ApiResponse({ type: [X] })`.\n * Falls back to the method return type annotation (unwrapping `Promise<>`).\n * Returns a TS type string (never null — falls back to 'unknown').\n */\nfunction extractResponseType(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): string {\n // 1. Try @ApiResponse\n const apiResponseDecorator = method.getDecorator('ApiResponse');\n if (apiResponseDecorator) {\n const args = apiResponseDecorator.getArguments();\n const optsArg = args[0];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n if (prop.getName() !== 'type') continue;\n const val = prop.getInitializer();\n if (!val) continue;\n\n // type: [PostDto] — array syntax\n if (Node.isArrayLiteralExpression(val)) {\n const elements = val.getElements();\n const firstEl = elements[0];\n if (elements.length > 0 && firstEl !== undefined) {\n const innerType = resolveIdentifierToClassType(firstEl, sourceFile, project, 3);\n return `Array<${innerType}>`;\n }\n return 'Array<unknown>';\n }\n\n // type: PostDto — single class reference\n return resolveIdentifierToClassType(val, sourceFile, project, 3);\n }\n }\n }\n\n // 2. Fall back to return type annotation\n const returnTypeNode = method.getReturnTypeNode();\n if (returnTypeNode) {\n return resolveTypeNodeToString(returnTypeNode, sourceFile, project, 3);\n }\n\n return 'unknown';\n}\n\n/**\n * Resolve an expression (expected to be a class identifier) to its expanded type string.\n * E.g. the `PostDto` identifier in `@ApiResponse({ type: PostDto })`.\n */\nfunction resolveIdentifierToClassType(\n node: Node,\n sourceFile: SourceFile,\n project: Project,\n depth: number,\n): string {\n if (!Node.isIdentifier(node)) return 'unknown';\n const name = node.getText();\n const resolved = findType(name, sourceFile, project);\n if (resolved) {\n return expandTypeDecl(resolved, project, depth - 1);\n }\n return name;\n}\n\n/**\n * Resolve a `@Body()` / `@Query()` param or return-type `TypeNode` to a named\n * exported class/interface ref (unwrapping `Promise<T>` / `Array<T>` / `T[]`).\n * Thin wrapper over the shared {@link resolveTypeRef}.\n */\nfunction resolveBodyQueryResponseRef(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n): TypeRef | null {\n return resolveTypeRef(typeNode, sourceFile, project, {\n kinds: ['class', 'interface'],\n unwrapContainers: true,\n });\n}\n\n/**\n * Determine whether a method has any DTO-based contract info worth emitting\n * (body, query, params, or non-unknown response).\n * Returns a ContractSource-shaped object or null.\n */\nexport function extractDtoContract(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): {\n query: string | null;\n body: string | null;\n response: string;\n params: string | null;\n queryRef?: TypeRef | null;\n bodyRef?: TypeRef | null;\n responseRef?: TypeRef | null;\n filterFields?: string[] | null;\n filterFieldTypes?: FilterFieldType[] | null;\n filterSource?: 'body' | 'query' | null;\n formWarnings?: string[];\n bodySchema?: import('../ir/schema-node.js').SchemaModule | null;\n querySchema?: import('../ir/schema-node.js').SchemaModule | null;\n} | null {\n let body = extractBodyType(method, sourceFile, project);\n const filterInfo = extractApplyFilterInfo(method, sourceFile, project);\n const query = extractQueryType(method, sourceFile, project);\n\n // Place filter type on the correct field based on @ApplyFilter source. The\n // body-source case still pre-renders a fixed `FilterQueryResult` here; the\n // query-source TypedFilterQuery TYPE is rendered in emit-api.ts (from\n // filterFields + filterFieldTypes) so it is byte-identical to the\n // `_filterQueryTyped<...>` factory args.\n if (filterInfo && filterInfo.source === 'body') {\n const bodyType = \"import('@dudousxd/nestjs-filter-client').FilterQueryResult\";\n body = body ?? bodyType;\n }\n\n const paramsType = extractParamsType(method, sourceFile, project);\n const response = extractResponseType(method, sourceFile, project);\n\n // Only emit a contract if there is at least something useful. A query-source\n // `@ApplyFilter` route carries no pre-rendered `query` string anymore (the\n // TypedFilterQuery type is rendered in emit-api), so it must be kept alive via\n // `filterInfo` even when every other field is empty.\n if (\n body === null &&\n query === null &&\n paramsType === null &&\n response === 'unknown' &&\n filterInfo === null\n ) {\n return null;\n }\n\n // Capture type references for import generation\n let bodyRef: TypeRef | null = null;\n let queryRef: TypeRef | null = null;\n let responseRef: TypeRef | null = null;\n\n for (const param of method.getParameters()) {\n if (param.getDecorators().some((d) => d.getName() === 'Body') && param.getTypeNode()) {\n bodyRef = resolveBodyQueryResponseRef(param.getTypeNode()!, sourceFile, project);\n }\n if (param.getDecorators().some((d) => d.getName() === 'Query') && param.getTypeNode()) {\n queryRef = resolveBodyQueryResponseRef(param.getTypeNode()!, sourceFile, project);\n }\n }\n\n const returnTypeNode = method.getReturnTypeNode();\n if (returnTypeNode) {\n responseRef = resolveBodyQueryResponseRef(returnTypeNode, sourceFile, project);\n }\n // Also check @ApiResponse\n if (!responseRef) {\n const apiResp = method.getDecorator('ApiResponse');\n if (apiResp) {\n const args = apiResp.getArguments();\n const optsArg = args[0];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n for (const prop of optsArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'type') {\n const val = prop.getInitializer();\n if (val && Node.isIdentifier(val)) {\n const name = val.getText();\n const localDecl =\n sourceFile.getInterface(name) ||\n sourceFile.getClass(name) ||\n sourceFile.getTypeAlias(name);\n if (localDecl?.isExported()) {\n responseRef = { name, filePath: sourceFile.getFilePath() };\n } else {\n const resolved = resolveImportedType(name, sourceFile, project);\n if (\n resolved &&\n (resolved.kind === 'class' || resolved.kind === 'interface') &&\n resolved.decl.isExported()\n ) {\n responseRef = { name, filePath: resolved.file.getFilePath() };\n }\n }\n }\n }\n }\n }\n }\n }\n\n // ── Synthesize the neutral validation IR from class-validator DTOs (Path B) ─\n // Resolve the @Body()/@Query() param to a class declaration and translate its\n // decorators into the neutral IR, which emit-forms renders via any adapter\n // (zod included). A defineContract schema always wins, so this only runs on\n // the plain-verb path where no contract schema is present.\n let bodySchema: import('../ir/schema-node.js').SchemaModule | null = null;\n let querySchema: import('../ir/schema-node.js').SchemaModule | null = null;\n const formWarnings: string[] = [];\n\n const bodyClass = resolveParamClass(method, 'Body', sourceFile, project);\n if (bodyClass) {\n bodySchema = extractSchemaFromDto(bodyClass.decl, bodyClass.file, project);\n formWarnings.push(...bodySchema.warnings);\n }\n const queryClass = resolveParamClass(method, 'Query', sourceFile, project);\n if (queryClass) {\n querySchema = extractSchemaFromDto(queryClass.decl, queryClass.file, project);\n formWarnings.push(...querySchema.warnings);\n }\n\n return {\n query,\n body,\n response,\n params: paramsType,\n queryRef,\n bodyRef,\n responseRef,\n filterFields: filterInfo?.fieldNames ?? null,\n filterFieldTypes: filterInfo?.fieldTypes ?? null,\n filterSource: filterInfo?.source ?? null,\n formWarnings,\n bodySchema,\n querySchema,\n };\n}\n\n/**\n * Resolve a `@Body()` / `@Query()` parameter's TS type to a class declaration\n * (following imports). Returns null for interfaces / plain types / unresolved.\n */\nfunction resolveParamClass(\n method: MethodDeclaration,\n decoratorName: 'Body' | 'Query',\n sourceFile: SourceFile,\n project: Project,\n): { decl: ClassDeclaration; file: SourceFile } | null {\n for (const param of method.getParameters()) {\n if (!param.getDecorators().some((d) => d.getName() === decoratorName)) continue;\n const typeNode = param.getTypeNode();\n if (!typeNode) continue;\n // Strip array suffix — translate the element class.\n const text = typeNode.getText().replace(/\\[\\]$/, '');\n if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(text)) continue;\n const resolved = findType(text, sourceFile, project);\n if (resolved && resolved.kind === 'class') {\n return { decl: resolved.decl, file: resolved.file };\n }\n }\n return null;\n}\n","/**\n * Pure-AST translation of class-validator-decorated DTO classes into the neutral\n * {@link SchemaModule} IR. Reads decorator names + literal args via ts-morph — it\n * never imports class-validator at runtime. A `ValidationAdapter` renders the IR.\n *\n * This is the sole DTO translator: it emits neutral `SchemaNode` IR (replacing\n * the former `dto-to-zod.ts` text path). A `ValidationAdapter` renders the IR;\n * the bundled zod adapter reproduces the original zod-text output byte-for-byte.\n */\nimport {\n type ClassDeclaration,\n type Decorator,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport type { NumberCheck, SchemaModule, SchemaNode, StringCheck } from '../ir/schema-node.js';\nimport { findType } from './type-ref-resolution.js';\n\ninterface BuildContext {\n sourceFile: SourceFile;\n project: Project;\n named: Map<string, SchemaNode>;\n warnings: string[];\n warnedDecorators: Set<string>;\n emittedClasses: Map<string, string>;\n visiting: Set<string>;\n recursiveSchemas: Set<string>;\n depth: number;\n}\n\nconst KNOWN_DECORATORS = new Set([\n 'IsString',\n 'IsNumber',\n 'IsInt',\n 'IsBoolean',\n 'IsDate',\n 'IsEmail',\n 'IsUrl',\n 'IsUUID',\n 'MinLength',\n 'MaxLength',\n 'Length',\n 'Min',\n 'Max',\n 'IsPositive',\n 'IsNegative',\n 'Matches',\n 'IsEnum',\n 'IsIn',\n 'IsOptional',\n 'IsNotEmpty',\n 'IsArray',\n 'ValidateNested',\n 'Type',\n 'IsObject',\n 'Allow',\n 'IsDefined',\n]);\n\nexport function extractSchemaFromDto(\n classDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): SchemaModule {\n const ctx: BuildContext = {\n sourceFile,\n project,\n named: new Map(),\n warnings: [],\n warnedDecorators: new Set(),\n emittedClasses: new Map(),\n visiting: new Set(),\n recursiveSchemas: new Set(),\n depth: 0,\n };\n const root = buildObject(classDecl, sourceFile, ctx);\n // Recursive schemas cannot be hoisted as a plain `const X = (... X ...)` without\n // a type annotation. Degrade any self-referential nested schema to a neutral\n // `unknown` placeholder; each adapter renders its own lib's `unknown` + comment.\n for (const schemaName of ctx.recursiveSchemas) {\n ctx.named.set(schemaName, { kind: 'unknown', note: 'recursive type — not expanded' });\n }\n return { root, named: ctx.named, warnings: ctx.warnings };\n}\n\n// ---------------------------------------------------------------------------\n// Object builder\n// ---------------------------------------------------------------------------\n\nfunction buildObject(\n classDecl: ClassDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n const props = classDecl.getProperties();\n if (props.length === 0) {\n return { kind: 'object', fields: [], passthrough: true };\n }\n const fields: Array<{ key: string; value: SchemaNode }> = [];\n for (const prop of props) {\n fields.push({ key: prop.getName(), value: buildProperty(prop, classFile, ctx) });\n }\n return { kind: 'object', fields, passthrough: false };\n}\n\n// ---------------------------------------------------------------------------\n// Property builder — the §2.2 mapping table lives here.\n// ---------------------------------------------------------------------------\n\nfunction buildProperty(\n prop: PropertyDeclaration,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n const decorators = new Map<string, Decorator>();\n for (const d of prop.getDecorators()) decorators.set(d.getName(), d);\n const has = (n: string): boolean => decorators.has(n);\n const dec = (n: string): Decorator | undefined => decorators.get(n);\n\n const typeNode = prop.getTypeNode();\n const typeText = typeNode?.getText() ?? 'unknown';\n const isArrayType = !!typeNode && typeNode.getText().endsWith('[]');\n\n // ── Nested / array-of-nested via @ValidateNested + @Type ────────────────\n const typeRefName = resolveTypeFactoryName(dec('Type'));\n if (has('ValidateNested') || typeRefName) {\n const childName = typeRefName ?? singularClassName(typeText);\n if (childName) {\n const childNode = buildNestedReference(childName, classFile, ctx);\n const wrapArray = has('IsArray') || isArrayType;\n const node: SchemaNode = wrapArray ? { kind: 'array', element: childNode } : childNode;\n return applyPresence(node, decorators);\n }\n }\n\n // ── Base type (TS property type), then decorator refinements ────────────\n let base = baseFromType(typeText, isArrayType);\n const stringChecks: StringCheck[] = [];\n const numberChecks: NumberCheck[] = [];\n\n // Type overrides\n if (has('IsString')) base = { kind: 'string', checks: stringChecks };\n if (has('IsBoolean')) base = { kind: 'boolean' };\n if (has('IsDate')) base = { kind: 'date' };\n if (has('IsNumber')) base = { kind: 'number', checks: numberChecks };\n if (has('IsInt')) {\n base = { kind: 'number', checks: numberChecks };\n numberChecks.push({ check: 'int' });\n }\n if (has('IsObject') && !has('ValidateNested')) {\n base = { kind: 'object', fields: [], passthrough: true };\n }\n if (has('Allow')) base = { kind: 'unknown' };\n\n const ensureString = (): void => {\n if (base.kind !== 'string') base = { kind: 'string', checks: stringChecks };\n };\n\n // String format refinements (these also imply string base).\n if (has('IsEmail')) {\n ensureString();\n const m = messageRaw(dec('IsEmail'));\n stringChecks.push(m === undefined ? { check: 'email' } : { check: 'email', messageRaw: m });\n }\n if (has('IsUrl')) {\n ensureString();\n const m = messageRaw(dec('IsUrl'));\n stringChecks.push(m === undefined ? { check: 'url' } : { check: 'url', messageRaw: m });\n }\n if (has('IsUUID')) {\n ensureString();\n const m = messageRaw(dec('IsUUID'));\n stringChecks.push(m === undefined ? { check: 'uuid' } : { check: 'uuid', messageRaw: m });\n }\n if (has('Matches')) {\n const re = firstArgText(dec('Matches'));\n if (re) {\n ensureString();\n stringChecks.push({ check: 'regex', pattern: re });\n }\n }\n\n // Length / size refinements\n if (has('MinLength')) {\n const n = numericArg(dec('MinLength'));\n if (n !== null) stringChecks.push({ check: 'min', value: n });\n }\n if (has('MaxLength')) {\n const n = numericArg(dec('MaxLength'));\n if (n !== null) stringChecks.push({ check: 'max', value: n });\n }\n if (has('Length')) {\n const [min, max] = numericArgs(dec('Length'));\n if (min !== null) stringChecks.push({ check: 'min', value: min });\n if (max !== null) stringChecks.push({ check: 'max', value: max });\n }\n if (has('Min')) {\n const n = numericArg(dec('Min'));\n if (n !== null) numberChecks.push({ check: 'min', value: n });\n }\n if (has('Max')) {\n const n = numericArg(dec('Max'));\n if (n !== null) numberChecks.push({ check: 'max', value: n });\n }\n if (has('IsPositive')) numberChecks.push({ check: 'positive' });\n if (has('IsNegative')) numberChecks.push({ check: 'negative' });\n if (has('IsNotEmpty') && base.kind === 'string') stringChecks.push({ check: 'min', value: '1' });\n\n // Enum / membership (replaces base).\n if (has('IsEnum')) {\n const enumNode = enumSchemaFromDecorator(dec('IsEnum'), classFile, ctx);\n if (enumNode) base = enumNode;\n }\n if (has('IsIn')) {\n const inNode = inSchemaFromDecorator(dec('IsIn'));\n if (inNode) base = inNode;\n }\n\n // ── Unmappable decorators → warn + comment, keep base ───────────────────\n const unmappable: string[] = [];\n for (const name of decorators.keys()) {\n if (!KNOWN_DECORATORS.has(name)) {\n unmappable.push(name);\n if (!ctx.warnedDecorators.has(name)) {\n ctx.warnedDecorators.add(name);\n const msg = `@${name} is not translatable to a client validation schema and was skipped (server-only validation).`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n }\n }\n\n // Attach the collected refinements to the base. `base` may have been created\n // by `baseFromType` (with its own empty checks array) or by an override, so\n // rebuild it here to guarantee the accumulated checks are the ones emitted.\n if (base.kind === 'string') base = { kind: 'string', checks: stringChecks };\n else if (base.kind === 'number') base = { kind: 'number', checks: numberChecks };\n\n let node: SchemaNode = base;\n\n // Array wrapping when the TS type is `T[]` and no nested handling occurred.\n if (isArrayType && node.kind !== 'array') {\n node = { kind: 'array', element: node };\n }\n\n node = applyPresence(node, decorators);\n\n if (unmappable.length > 0) {\n node = { kind: 'annotated', inner: node, unmappable };\n }\n return node;\n}\n\n/** `.optional()` / required handling from @IsOptional / @IsDefined. */\nfunction applyPresence(node: SchemaNode, decorators: Map<string, Decorator>): SchemaNode {\n if (decorators.has('IsDefined')) return node; // explicitly required\n if (decorators.has('IsOptional')) return { kind: 'optional', inner: node };\n return node;\n}\n\n// ---------------------------------------------------------------------------\n// Base type from the TS property type\n// ---------------------------------------------------------------------------\n\nfunction baseFromType(typeText: string, isArrayType: boolean): SchemaNode {\n const inner = isArrayType ? typeText.slice(0, -2).trim() : typeText;\n switch (inner) {\n case 'string':\n return { kind: 'string', checks: [] };\n case 'number':\n return { kind: 'number', checks: [] };\n case 'boolean':\n return { kind: 'boolean' };\n case 'Date':\n return { kind: 'date' };\n case 'File':\n case 'Express.Multer.File':\n return { kind: 'instanceof', ctor: 'File' };\n default:\n return { kind: 'unknown' };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nested DTO references (hoisted named consts)\n// ---------------------------------------------------------------------------\n\nfunction buildNestedReference(\n className: string,\n fromFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode {\n // Recursion guard FIRST.\n if (ctx.visiting.has(className) || ctx.depth >= 8) {\n const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);\n ctx.emittedClasses.set(className, reserved);\n ctx.recursiveSchemas.add(reserved);\n if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {\n ctx.warnedDecorators.add(`recursive:${reserved}`);\n const msg = `${className} is a recursive type and was not expanded; the generated schema uses unknown for it.`;\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'lazyRef', name: reserved };\n }\n\n const existing = ctx.emittedClasses.get(className);\n if (existing) return { kind: 'ref', name: existing };\n\n const schemaName = aliasFor(className, ctx);\n const resolved = findType(className, fromFile, ctx.project);\n if (!resolved || resolved.kind !== 'class') {\n return { kind: 'object', fields: [], passthrough: true };\n }\n\n ctx.emittedClasses.set(className, schemaName);\n ctx.visiting.add(className);\n ctx.depth += 1;\n const childNode = buildObject(resolved.decl, resolved.file, ctx);\n ctx.depth -= 1;\n ctx.visiting.delete(className);\n\n ctx.named.set(schemaName, childNode);\n return { kind: 'ref', name: schemaName };\n}\n\nfunction aliasFor(className: string, ctx: BuildContext): string {\n const baseName = `${className}Schema`;\n let candidate = baseName;\n let i = 1;\n const used = new Set(ctx.named.keys());\n for (const v of ctx.emittedClasses.values()) used.add(v);\n while (used.has(candidate)) {\n candidate = `${baseName}_${i}`;\n i += 1;\n }\n return candidate;\n}\n\n// ---------------------------------------------------------------------------\n// Decorator argument readers (pure AST)\n// ---------------------------------------------------------------------------\n\nfunction firstArg(decorator: Decorator | undefined): Node | undefined {\n return decorator?.getArguments()[0];\n}\n\nfunction firstArgText(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n return arg ? arg.getText() : null;\n}\n\nfunction numericArg(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (arg && Node.isNumericLiteral(arg)) return arg.getText();\n return null;\n}\n\nfunction numericArgs(decorator: Decorator | undefined): [string | null, string | null] {\n const args = decorator?.getArguments() ?? [];\n const num = (n: Node | undefined): string | null =>\n n && Node.isNumericLiteral(n) ? n.getText() : null;\n return [num(args[0]), num(args[1])];\n}\n\n/** Reads a `{ message: '...' }` options object → the verbatim message literal text. */\nfunction messageRaw(decorator: Decorator | undefined): string | undefined {\n const args = decorator?.getArguments() ?? [];\n for (const arg of args) {\n if (Node.isObjectLiteralExpression(arg)) {\n for (const prop of arg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'message') {\n const init = prop.getInitializer();\n if (init && Node.isStringLiteral(init)) return init.getText();\n }\n }\n }\n }\n return undefined;\n}\n\n/** Resolve `@Type(() => Child)` → `'Child'`. */\nfunction resolveTypeFactoryName(decorator: Decorator | undefined): string | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) return body.getText();\n }\n return null;\n}\n\n/** Drop array suffix from a type text → class name (`Child[]` → `Child`). */\nfunction singularClassName(typeText: string): string | null {\n const inner = typeText.endsWith('[]') ? typeText.slice(0, -2).trim() : typeText;\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(inner) ? inner : null;\n}\n\n/** `@IsEnum(E)` → enum node (or verbatim fallback when unresolvable). */\nfunction enumSchemaFromDecorator(\n decorator: Decorator | undefined,\n classFile: SourceFile,\n ctx: BuildContext,\n): SchemaNode | null {\n const arg = firstArg(decorator);\n if (!arg) return null;\n if (Node.isIdentifier(arg)) {\n const name = arg.getText();\n const resolved = findType(name, classFile, ctx.project);\n if (resolved && resolved.kind === 'enum') {\n return { kind: 'enum', literals: resolved.members };\n }\n const msg = `@IsEnum(${name}): enum could not be resolved to literal members and is not importable into the generated schema; falling back to unknown.`;\n if (!ctx.warnedDecorators.has(`IsEnum:${name}`)) {\n ctx.warnedDecorators.add(`IsEnum:${name}`);\n ctx.warnings.push(msg);\n console.warn(`[nestjs-codegen] ${msg}`);\n }\n return { kind: 'unknown', note: `@IsEnum(${name}): enum not resolvable to literals` };\n }\n if (Node.isObjectLiteralExpression(arg)) {\n const values: string[] = [];\n for (const p of arg.getProperties()) {\n if (!Node.isPropertyAssignment(p)) continue;\n const init = p.getInitializer();\n if (init && Node.isStringLiteral(init)) values.push(init.getText());\n }\n if (values.length > 0) return { kind: 'enum', literals: values };\n }\n return null;\n}\n\n/** `@IsIn(['a','b'])` → enum node; non-string members → union of literals. */\nfunction inSchemaFromDecorator(decorator: Decorator | undefined): SchemaNode | null {\n const arg = firstArg(decorator);\n if (arg && Node.isArrayLiteralExpression(arg)) {\n const elements = arg.getElements();\n const allStrings = elements.every((e) => Node.isStringLiteral(e));\n if (allStrings && elements.length > 0) {\n return { kind: 'enum', literals: elements.map((e) => e.getText()) };\n }\n if (elements.length > 0) {\n return {\n kind: 'union',\n options: elements.map((e) => ({ kind: 'literal', raw: e.getText() })),\n };\n }\n }\n return null;\n}\n","import { readFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport {\n type ClassDeclaration,\n type InterfaceDeclaration,\n Node,\n type Project,\n type SourceFile,\n type TypeNode,\n} from 'ts-morph';\nimport type { TypeRef } from './types.js';\n\n/**\n * Type-reference resolution: the leaf module of the discovery DAG. Owns the\n * per-invocation discovery context (project root + tsconfig path aliases) and\n * the \"follow a name/TypeNode to its declaring file\" machinery shared by every\n * other discovery module.\n */\n\n// ---------------------------------------------------------------------------\n// Discovery context — scoped per `discoverContractsFast` invocation.\n// Keyed off the per-invocation ts-morph `Project` (every resolution entry point\n// already threads it), so concurrent invocations each get an isolated context\n// with no shared mutable global to corrupt.\n// ---------------------------------------------------------------------------\n\nexport interface DiscoveryContext {\n projectRoot: string;\n tsconfigPaths: Record<string, string[]> | null;\n}\n\nconst _EMPTY_CTX: DiscoveryContext = { projectRoot: '', tsconfigPaths: null };\n\n/** Per-`Project` discovery context. WeakMap so contexts die with their project. */\nconst _ctxByProject = new WeakMap<Project, DiscoveryContext>();\n\n/** Associate a discovery context with a `Project` for the duration of a run. */\nexport function setDiscoveryContext(project: Project, ctx: DiscoveryContext): void {\n _ctxByProject.set(project, ctx);\n}\n\nfunction _ctxFor(project: Project): DiscoveryContext {\n return _ctxByProject.get(project) ?? _EMPTY_CTX;\n}\n\nconst _debug = process.env.NESTJS_INERTIA_DEBUG === '1';\nexport function dbg(...args: unknown[]) {\n if (_debug) console.log('[codegen:debug]', ...args);\n}\n\nexport function loadTsconfigPaths(tsconfigPath: string): Record<string, string[]> | null {\n try {\n const raw = readFileSync(tsconfigPath, 'utf8');\n // Strip single-line comments (tsconfig allows them)\n const stripped = raw.replace(/\\/\\/.*$/gm, '');\n const parsed = JSON.parse(stripped) as {\n compilerOptions?: { paths?: Record<string, string[]> };\n };\n return parsed.compilerOptions?.paths ?? null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type-declaration lookup\n// ---------------------------------------------------------------------------\n\nexport type TypeDeclResult =\n | { kind: 'class'; decl: ClassDeclaration; file: SourceFile }\n | { kind: 'interface'; decl: InterfaceDeclaration; file: SourceFile }\n | { kind: 'typeAlias'; typeNode: TypeNode | undefined; file: SourceFile; text: string }\n | { kind: 'enum'; members: string[] };\n\n/**\n * Try to find a type declaration (class, interface, type alias, enum) in a source file.\n */\nexport function findTypeInFile(name: string, file: SourceFile): TypeDeclResult | null {\n const cls = file.getClass(name);\n if (cls) return { kind: 'class', decl: cls, file };\n\n const iface = file.getInterface(name);\n if (iface) return { kind: 'interface', decl: iface, file };\n\n const alias = file.getTypeAlias(name);\n if (alias) {\n const typeNode = alias.getTypeNode();\n return {\n kind: 'typeAlias',\n typeNode,\n file,\n text: typeNode ? typeNode.getText() : 'unknown',\n };\n }\n\n const enumDecl = file.getEnum(name);\n if (enumDecl) {\n const members = enumDecl.getMembers().map((m) => {\n const val = m.getValue();\n // String value → quoted literal (\"active\"); numeric value → numeric\n // literal (1). Fall back to the member NAME only when the value can't be\n // resolved statically (e.g. a computed member).\n if (typeof val === 'string' || typeof val === 'number') return JSON.stringify(val);\n return JSON.stringify(m.getName());\n });\n return { kind: 'enum', members };\n }\n\n return null;\n}\n\n/**\n * Follow import declarations to find a type in another file.\n */\nexport function resolveModuleSpecifier(\n moduleSpecifier: string,\n sourceFile: SourceFile,\n project: Project,\n): string[] {\n if (moduleSpecifier.startsWith('.')) {\n const dir = dirname(sourceFile.getFilePath());\n // Strip an explicit ESM `.js`/`.ts` extension so `./x.dto.js` resolves to\n // `./x.dto.ts` (NodeNext import style).\n const noExt = moduleSpecifier.replace(/\\.(js|ts)$/, '');\n return [\n resolve(dir, `${noExt}.ts`),\n resolve(dir, `${moduleSpecifier}.ts`),\n resolve(dir, moduleSpecifier, 'index.ts'),\n ];\n }\n\n // Try to resolve path aliases via tsconfig paths (read directly from JSON)\n const ctx = _ctxFor(project);\n const baseUrl = ctx.projectRoot;\n const tsconfigPaths = ctx.tsconfigPaths;\n\n dbg(\n 'resolveModuleSpecifier',\n moduleSpecifier,\n 'paths:',\n JSON.stringify(tsconfigPaths),\n 'baseUrl:',\n baseUrl,\n );\n\n if (tsconfigPaths) {\n for (const [pattern, mappings] of Object.entries(tsconfigPaths)) {\n const prefix = pattern.replace('*', '');\n if (moduleSpecifier.startsWith(prefix)) {\n const rest = moduleSpecifier.slice(prefix.length);\n const candidates: string[] = [];\n for (const mapping of mappings) {\n const resolved = resolve(baseUrl, mapping.replace('*', rest));\n candidates.push(`${resolved}.ts`, resolve(resolved, 'index.ts'));\n }\n dbg(' resolved candidates:', candidates);\n return candidates;\n }\n }\n }\n\n return [];\n}\n\nexport function resolveImportedType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);\n if (!namedImport) continue;\n\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);\n if (candidates.length === 0) continue;\n\n for (const candidate of candidates) {\n let importedFile = project.getSourceFile(candidate);\n if (!importedFile) {\n try {\n importedFile = project.addSourceFileAtPath(candidate);\n } catch {\n continue;\n }\n }\n const result = findTypeInFile(name, importedFile);\n if (result) return result;\n // The target module may itself re-export the symbol from elsewhere\n // (`export { X } from './mod'` or `import { X } ...; export { X }`).\n const viaReExport = resolveReExportedType(name, importedFile, project, new Set());\n if (viaReExport) return viaReExport;\n }\n }\n // The current file may re-export the symbol from another module.\n return resolveReExportedType(name, sourceFile, project, new Set());\n}\n\n/**\n * Follow `export { X } from './mod'` / `export * from './mod'` re-exports, and\n * bare `export { X }` statements that re-publish a previously-imported symbol,\n * to find a type declaration in a sibling module. Guards against import cycles\n * via `seen`.\n */\nfunction resolveReExportedType(\n name: string,\n file: SourceFile,\n project: Project,\n seen: Set<string>,\n): TypeDeclResult | null {\n const filePath = file.getFilePath();\n if (seen.has(filePath)) return null;\n seen.add(filePath);\n\n for (const exportDecl of file.getExportDeclarations()) {\n const moduleSpecifier = exportDecl.getModuleSpecifierValue();\n const namedExports = exportDecl.getNamedExports();\n\n // `export { X } from './mod'` — only follow when X (or its alias source) matches.\n if (moduleSpecifier) {\n const hasStar = namedExports.length === 0; // `export * from './mod'`\n const reExportsName = namedExports.some(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!hasStar && !reExportsName) continue;\n // The source-side name (before any alias rename).\n const sourceName = hasStar\n ? name\n : (namedExports\n .find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)\n ?.getName() ?? name);\n const target = followModuleForType(sourceName, moduleSpecifier, file, project, seen);\n if (target) return target;\n continue;\n }\n\n // `export { X }` (no module specifier) — X was imported above into this file.\n const reExportsName = namedExports.some(\n (n) => (n.getAliasNode()?.getText() ?? n.getName()) === name,\n );\n if (!reExportsName) continue;\n const sourceName =\n namedExports.find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)?.getName() ??\n name;\n const local = findTypeInFile(sourceName, file);\n if (local) return local;\n const imported = resolveImportedType(sourceName, file, project);\n if (imported) return imported;\n }\n return null;\n}\n\nfunction followModuleForType(\n name: string,\n moduleSpecifier: string,\n fromFile: SourceFile,\n project: Project,\n seen: Set<string>,\n): TypeDeclResult | null {\n const candidates = resolveModuleSpecifier(moduleSpecifier, fromFile, project);\n for (const candidate of candidates) {\n let importedFile = project.getSourceFile(candidate);\n if (!importedFile) {\n try {\n importedFile = project.addSourceFileAtPath(candidate);\n } catch {\n continue;\n }\n }\n const result = findTypeInFile(name, importedFile);\n if (result) return result;\n const viaReExport = resolveReExportedType(name, importedFile, project, seen);\n if (viaReExport) return viaReExport;\n }\n return null;\n}\n\n/**\n * Find a type declaration by name: first in the current file, then by following imports.\n */\nexport function findType(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): TypeDeclResult | null {\n const local = findTypeInFile(name, sourceFile);\n if (local) return local;\n return resolveImportedType(name, sourceFile, project);\n}\n\n// ---------------------------------------------------------------------------\n// Importable named-ref resolution\n// ---------------------------------------------------------------------------\n\n/** The declaration kinds a `resolveTypeRef` call will accept as an importable ref. */\nexport type TypeRefKind = 'class' | 'interface' | 'typeAlias' | 'enum';\n\nexport interface ResolveTypeRefOptions {\n /**\n * Declaration kinds accepted as an importable named ref (applied identically\n * to local and imported declarations). The two call sites differ only here:\n * - body/query/response refs accept class + interface;\n * - `@FilterFor` param refs also accept enum + type alias.\n */\n kinds: TypeRefKind[];\n /**\n * Honour a bare (node_modules) import specifier — emit `{ name, filePath: spec }`\n * so the emitter imports straight from the package. tsconfig path aliases are\n * excluded (they resolve to files instead). Off for the body/query/response\n * path (which only ever points at project source files).\n */\n allowBareSpecifier?: boolean;\n /**\n * Unwrap `Promise<T>`, `Array<T>` and `T[]` to the inner named type (marking\n * array forms with `isArray`). Used for the body/query/response path which\n * receives a raw return/param `TypeNode`; the `@FilterFor` path passes a bare\n * symbol name and needs no unwrapping.\n */\n unwrapContainers?: boolean;\n}\n\n/** Skip-list of primitive / well-known names that never resolve to a named ref. */\nconst _NON_REF_NAMES = new Set(['string', 'number', 'boolean', 'void', 'unknown', 'any', 'Date']);\n\n/** Does an exported declaration found by `findTypeInFile` match the accepted kinds? */\nfunction _localDeclForKinds(name: string, file: SourceFile, kinds: TypeRefKind[]): boolean {\n if (kinds.includes('class') && file.getClass(name)?.isExported()) return true;\n if (kinds.includes('interface') && file.getInterface(name)?.isExported()) return true;\n if (kinds.includes('typeAlias') && file.getTypeAlias(name)?.isExported()) return true;\n if (kinds.includes('enum') && file.getEnum(name)?.isExported()) return true;\n return false;\n}\n\n/**\n * Resolve a type reference to an importable `TypeRef` — the symbol name plus the\n * absolute path of its declaring source file (for a relative import) OR the bare\n * module specifier (for a node_modules package). Accepts either a raw `TypeNode`\n * (with `unwrapContainers` to peel `Promise`/`Array`) or a bare symbol name.\n *\n * Walks: local exported decl → `{ name, thisFile }`; else the file's import\n * declarations to a matching exported decl → `{ name, importedFile }`. The\n * accepted declaration kinds (and bare-specifier / container-unwrap support) are\n * controlled by `opts`, letting both former resolvers share this one body.\n * Returns null when the symbol is not exported, not resolvable, or its import\n * path cannot be safely computed.\n */\nexport function resolveTypeRef(\n nodeOrName: TypeNode | string,\n sourceFile: SourceFile,\n project: Project,\n opts: ResolveTypeRefOptions,\n): TypeRef | null {\n // ── Resolve the bare symbol name (peeling containers for the TypeNode form) ──\n let name: string;\n if (typeof nodeOrName === 'string') {\n name = nodeOrName;\n } else {\n const typeNode = nodeOrName;\n\n if (opts.unwrapContainers && Node.isArrayTypeNode(typeNode)) {\n const inner = resolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project, opts);\n return inner ? { ...inner, isArray: true } : null;\n }\n\n if (!Node.isTypeReference(typeNode)) return null;\n const typeName = typeNode.getTypeName();\n const refName = Node.isIdentifier(typeName) ? typeName.getText() : null;\n if (!refName) return null;\n\n if (opts.unwrapContainers && refName === 'Promise') {\n const first = typeNode.getTypeArguments()[0];\n return first ? resolveTypeRef(first, sourceFile, project, opts) : null;\n }\n if (opts.unwrapContainers && refName === 'Array') {\n const first = typeNode.getTypeArguments()[0];\n if (!first) return null;\n const inner = resolveTypeRef(first, sourceFile, project, opts);\n return inner ? { ...inner, isArray: true } : null;\n }\n\n if (_NON_REF_NAMES.has(refName)) return null;\n name = refName;\n }\n\n // 1. Declared (and exported) in the current file → relative import to it.\n if (_localDeclForKinds(name, sourceFile, opts.kinds)) {\n return { name, filePath: sourceFile.getFilePath() };\n }\n\n // 2. Imported from another module — follow the import declaration.\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);\n if (!namedImport) continue;\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n\n // Bare specifier (node_modules package) → import directly by specifier.\n if (\n opts.allowBareSpecifier &&\n !moduleSpecifier.startsWith('.') &&\n !moduleSpecifier.startsWith('/')\n ) {\n // Only honour it if not a tsconfig path alias (those resolve to files).\n const tsconfigPaths = _ctxFor(project).tsconfigPaths;\n const isAlias =\n tsconfigPaths != null &&\n Object.keys(tsconfigPaths).some((p) => {\n const prefix = p.replace('*', '');\n return moduleSpecifier.startsWith(prefix);\n });\n if (!isAlias) {\n return { name, filePath: moduleSpecifier };\n }\n }\n\n // Local / aliased source file → resolve to its absolute path so the emitter\n // can compute a relative import from the generated output dir.\n const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);\n for (const candidate of candidates) {\n let importedFile = project.getSourceFile(candidate);\n if (!importedFile) {\n try {\n importedFile = project.addSourceFileAtPath(candidate);\n } catch {\n continue;\n }\n }\n if (_localDeclForKinds(name, importedFile, opts.kinds)) {\n return { name, filePath: importedFile.getFilePath() };\n }\n }\n }\n\n return null;\n}\n","import {\n type ClassDeclaration,\n type MethodDeclaration,\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n} from 'ts-morph';\nimport {\n type ClassifyResult,\n classifyFieldType,\n classifyTypeNode,\n toFilterFieldType,\n} from './filter-field-types.js';\nimport { findType, resolveTypeRef } from './type-ref-resolution.js';\nimport type { FilterFieldType } from './types.js';\n\n/**\n * `@FilterFor` / `@ApplyFilter` discovery: resolve the virtual + entity-derived\n * filter fields (with their classified types) for a filter class referenced by\n * an `@ApplyFilter(FilterClass)` parameter.\n */\n\n/**\n * Map a single `@FilterFor` `type` hint token (read statically from the AST) to a\n * `ClassifyResult`. Supports the four primitive tokens plus a string-literal\n * array (enum) → literal string union. Returns null for anything unrecognised so\n * the caller falls back to the current permissive (`unknown`) behavior.\n */\nexport function classifyFilterForHint(typeInit: Node): ClassifyResult | null {\n // Primitive token: 'string' | 'number' | 'boolean' | 'Date'\n if (Node.isStringLiteral(typeInit)) {\n switch (typeInit.getLiteralValue()) {\n case 'string':\n return { kind: 'string' };\n case 'number':\n return { kind: 'number' };\n case 'boolean':\n return { kind: 'boolean' };\n case 'Date':\n return { kind: 'date' };\n default:\n return null;\n }\n }\n\n // Enum: a readonly array of string literals → literal string union.\n if (Node.isArrayLiteralExpression(typeInit)) {\n const values: string[] = [];\n for (const el of typeInit.getElements()) {\n if (!Node.isStringLiteral(el)) return null; // non-literal → bail to permissive\n values.push(el.getLiteralValue());\n }\n if (values.length === 0) return null;\n return { kind: 'string', enumValues: values };\n }\n\n return null;\n}\n\n/**\n * Classify the type of the FIRST parameter of a `@FilterFor` method (the new\n * primary inference mechanism). Precedence inside this function:\n * - primitive `number`/`string`/`boolean`/`Date` → emit directly.\n * - literal unions (`'a' | 'b'`, `1 | 2`) → emit the union text.\n * - named enum / type alias / interface → emit a `typeRef` (named import,\n * option B) when an import path is resolvable; otherwise fall back to\n * literal-union expansion for enums/unions, else skip.\n * - any/unknown/no-param/unresolvable → null (caller falls back).\n */\nexport function classifyFilterForParam(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult | null {\n const param = method.getParameters()[0];\n if (!param) return null;\n const typeNode = param.getTypeNode();\n if (!typeNode) return null;\n\n // Classify ONCE. `resolveRef` attaches an importable named ref (option B) when\n // the symbol resolves to an exported enum / type alias / interface / class with\n // a safe import path; the emitter prefers that `typeRef` over the `kind`. The\n // best-effort `kind` is still recorded so non-emit consumers (tests) see a\n // sensible classification.\n const wellKnown = ['string', 'number', 'boolean', 'Date', 'any', 'unknown'];\n const result = classifyTypeNode(typeNode, sourceFile, project, {\n resolveRef: (refName) => {\n if (wellKnown.includes(refName)) return null;\n // Only attempt a named import for symbols we can resolve to a declaration.\n if (!findType(refName, sourceFile, project)) return null;\n return resolveTypeRef(refName, sourceFile, project, {\n kinds: ['class', 'interface', 'typeAlias', 'enum'],\n allowBareSpecifier: true,\n });\n },\n });\n\n // A resolved `typeRef` is always usable (even with kind 'unknown' — the emitter\n // references the ref by name). Otherwise skip permissive `unknown` results.\n if (result.typeRef) return result;\n return result.kind === 'unknown' ? null : result;\n}\n\n/**\n * Discover virtual filter fields declared via `@FilterFor('key', { type })`\n * method decorators on the filter class. Field-type resolution precedence (high\n * wins): (1) explicit `{ type }` hint, (2) the method's first-parameter type\n * (named enums/aliases → real `import type` refs), (3+) fall back to existing\n * class-property / entity-column / `unknown` behavior (handled by the caller).\n *\n * Returns a map of inputKey → classified type for every `@FilterFor` that\n * carries a usable hint OR a usable first-parameter type. Keys with neither are\n * intentionally omitted here (they remain permissive / fall back).\n */\nexport function extractFilterForHints(\n classDecl: ClassDeclaration,\n project: Project,\n): Map<string, ClassifyResult> {\n const hints = new Map<string, ClassifyResult>();\n const sourceFile = classDecl.getSourceFile();\n for (const method of classDecl.getMethods()) {\n const filterForDec = method.getDecorators().find((d) => d.getName() === 'FilterFor');\n if (!filterForDec) continue;\n\n const args = filterForDec.getArguments();\n // inputKey: first string-literal arg, else the method name.\n const keyArg = args[0];\n const inputKey =\n keyArg && Node.isStringLiteral(keyArg) ? keyArg.getLiteralValue() : method.getName();\n\n // (1) Explicit `{ type }` hint — highest precedence, unchanged behavior.\n const optsArg = args[1];\n if (optsArg && Node.isObjectLiteralExpression(optsArg)) {\n const typeProp = optsArg.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const typeInit = typeProp.getInitializer();\n if (typeInit) {\n const classified = classifyFilterForHint(typeInit);\n if (classified) {\n hints.set(inputKey, classified);\n continue;\n }\n }\n }\n }\n\n // (2) Method first-parameter type — the new primary inference mechanism.\n const fromParam = classifyFilterForParam(method, sourceFile, project);\n if (fromParam) hints.set(inputKey, fromParam);\n }\n return hints;\n}\n\n/**\n * Extract the filter field data from an `@ApplyFilter(FilterClass)` decorated\n * parameter. Resolves the filter class and reads its properties (excluding\n * inherited base class members). Returns the field names + classified types +\n * filter source, or null when no resolvable filter is present.\n */\nexport function extractApplyFilterInfo(\n method: MethodDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): {\n fieldNames: string[];\n fieldTypes: FilterFieldType[];\n source: 'body' | 'query';\n} | null {\n for (const param of method.getParameters()) {\n const filterDecorator = param.getDecorators().find((d) => d.getName() === 'ApplyFilter');\n if (!filterDecorator) continue;\n const args = filterDecorator.getArguments();\n if (args.length === 0) continue;\n const filterClassArg = args[0];\n if (!filterClassArg || !Node.isIdentifier(filterClassArg)) continue;\n\n // Read { source: \"body\" | \"query\" } from second argument\n let source: 'body' | 'query' = 'query';\n const optionsArg = args[1];\n if (optionsArg && Node.isObjectLiteralExpression(optionsArg)) {\n const sourceProp = optionsArg.getProperty('source');\n if (sourceProp && Node.isPropertyAssignment(sourceProp)) {\n const init = sourceProp.getInitializer();\n if (init && Node.isStringLiteral(init) && init.getLiteralValue() === 'body') {\n source = 'body';\n }\n }\n }\n\n const filterClassName = filterClassArg.getText();\n const resolved = findType(filterClassName, sourceFile, project);\n if (resolved && resolved.kind === 'class') {\n const classDecl = resolved.decl as ClassDeclaration;\n let fieldTypes = extractClassPropertyTypes(classDecl, project);\n\n // autoFields: if the filter class has no properties, resolve fields\n // from the entity referenced in @Filterable({ entity: X })\n if (fieldTypes.length === 0) {\n fieldTypes = extractFilterableEntityFields(classDecl, project);\n }\n\n // Merge in explicit @FilterFor('key', { type }) hints. An explicit hint\n // WINS over entity-column / class-property inference for the same key;\n // genuinely-virtual keys (no property, no column) are appended so they\n // appear in the Fields union and the type map M.\n const filterForHints = extractFilterForHints(classDecl, project);\n if (filterForHints.size > 0) {\n const byName = new Map(fieldTypes.map((f) => [f.name, f] as const));\n for (const [key, classified] of filterForHints) {\n byName.set(key, toFilterFieldType(key, classified));\n }\n fieldTypes = [...byName.values()];\n }\n\n if (fieldTypes.length === 0) return null;\n const fieldNames = fieldTypes.map((f) => f.name);\n return {\n fieldNames,\n fieldTypes,\n source,\n };\n }\n }\n return null;\n}\n\nconst RELATION_DECORATORS = new Set(['OneToMany', 'ManyToOne', 'ManyToMany', 'OneToOne']);\n\n/**\n * Recursively collect entity fields including dot-notation relation fields.\n * e.g. for PipelineRun with tasks: OneToMany<Task>, produces:\n * [\"id\", \"name\", \"status\", ..., \"tasks.id\", \"tasks.name\", ...]\n */\nfunction collectEntityFields(\n entityDecl: ClassDeclaration,\n sourceFile: SourceFile,\n project: Project,\n prefix: string,\n visited: Set<string>,\n): FilterFieldType[] {\n const entityName = entityDecl.getName() ?? '';\n if (visited.has(entityName)) return [];\n visited.add(entityName);\n\n const fields: FilterFieldType[] = [];\n for (const prop of entityDecl.getProperties()) {\n const name = prop.getName();\n if (name.startsWith('$') || name.startsWith('_') || name.startsWith('[')) continue;\n if (prop.isStatic()) continue;\n\n const fullName = prefix ? `${prefix}.${name}` : name;\n const isRelation = prop.getDecorators().some((d) => RELATION_DECORATORS.has(d.getName()));\n\n if (isRelation) {\n const relEntity = resolveRelationEntity(prop, sourceFile, project);\n if (relEntity) {\n // Classify each relation leaf against the relation's own source file.\n fields.push(\n ...collectEntityFields(relEntity, relEntity.getSourceFile(), project, fullName, visited),\n );\n }\n } else {\n fields.push(toFilterFieldType(fullName, classifyFieldType(prop, sourceFile, project)));\n }\n }\n return fields;\n}\n\n/**\n * Given a relation property (e.g. `tasks = new Collection<Task>(this)`),\n * resolve the target entity class declaration.\n */\nfunction resolveRelationEntity(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassDeclaration | null {\n // Try from decorator argument: @OneToMany({ entity: () => Task, ... })\n for (const dec of prop.getDecorators()) {\n if (!RELATION_DECORATORS.has(dec.getName())) continue;\n const args = dec.getArguments();\n if (args.length === 0) continue;\n const arg = args[0];\n if (Node.isObjectLiteralExpression(arg)) {\n const entityProp = arg.getProperty('entity');\n if (entityProp && Node.isPropertyAssignment(entityProp)) {\n const init = entityProp.getInitializer();\n // () => Task\n if (init && Node.isArrowFunction(init)) {\n const body = init.getBody();\n if (Node.isIdentifier(body)) {\n const resolved = findType(body.getText(), prop.getSourceFile(), project);\n if (resolved?.kind === 'class') return resolved.decl as ClassDeclaration;\n }\n }\n }\n }\n // @ManyToOne(() => Task)\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) {\n const resolved = findType(body.getText(), prop.getSourceFile(), project);\n if (resolved?.kind === 'class') return resolved.decl as ClassDeclaration;\n }\n }\n }\n return null;\n}\n\n/** Classify each property of a filter DTO class into a FilterFieldType. */\nfunction extractClassPropertyTypes(\n classDecl: ClassDeclaration,\n project: Project,\n): FilterFieldType[] {\n const sourceFile = classDecl.getSourceFile();\n const fields: FilterFieldType[] = [];\n for (const prop of classDecl.getProperties()) {\n const name = prop.getName();\n if (name.startsWith('$') || name.startsWith('_')) continue;\n fields.push(toFilterFieldType(name, classifyFieldType(prop, sourceFile, project)));\n }\n return fields;\n}\n\n/**\n * When a filter class uses `@Filterable({ entity: X, autoFields: true })`,\n * resolve entity X and extract its property names (fields decorated with\n * `@Property`, `@PrimaryKey`, `@Enum`, etc. — skipping relations).\n */\nfunction extractFilterableEntityFields(\n filterClass: ClassDeclaration,\n project: Project,\n): FilterFieldType[] {\n const filterableDecorator = filterClass.getDecorators().find((d) => d.getName() === 'Filterable');\n if (!filterableDecorator) return [];\n const args = filterableDecorator.getArguments();\n if (args.length === 0) return [];\n\n const optionsArg = args[0];\n if (!Node.isObjectLiteralExpression(optionsArg)) return [];\n\n const entityProp = optionsArg.getProperty('entity');\n if (!entityProp || !Node.isPropertyAssignment(entityProp)) return [];\n\n const entityInit = entityProp.getInitializer();\n if (!entityInit || !Node.isIdentifier(entityInit)) return [];\n\n const entityName = entityInit.getText();\n const filterSourceFile = filterClass.getSourceFile();\n const resolvedEntity = findType(entityName, filterSourceFile, project);\n if (!resolvedEntity || resolvedEntity.kind !== 'class') return [];\n\n const entityDecl = resolvedEntity.decl as ClassDeclaration;\n const fields = collectEntityFields(\n entityDecl,\n entityDecl.getSourceFile(),\n project,\n '',\n new Set(),\n );\n\n // Also include keys declared via @Relations({ rel: { keys: [...] } }).\n // These string keys carry no resolvable type → kind: 'unknown'.\n const relationsDecorator = filterClass.getDecorators().find((d) => d.getName() === 'Relations');\n if (relationsDecorator) {\n const relArgs = relationsDecorator.getArguments();\n if (relArgs.length > 0 && Node.isObjectLiteralExpression(relArgs[0])) {\n for (const relProp of relArgs[0].getProperties()) {\n if (!Node.isPropertyAssignment(relProp)) continue;\n const relInit = relProp.getInitializer();\n if (!relInit || !Node.isObjectLiteralExpression(relInit)) continue;\n const keysProp = relInit.getProperty('keys');\n if (!keysProp || !Node.isPropertyAssignment(keysProp)) continue;\n const keysInit = keysProp.getInitializer();\n if (!keysInit || !Node.isArrayLiteralExpression(keysInit)) continue;\n for (const el of keysInit.getElements()) {\n if (Node.isStringLiteral(el)) {\n // Route through the single constructor (keeps the typeRef invariant\n // enforced in one place); these relation keys carry no type → unknown.\n fields.push(toFilterFieldType(el.getLiteralValue(), { kind: 'unknown' }));\n }\n }\n }\n }\n }\n\n return fields;\n}\n","import {\n Node,\n type Project,\n type PropertyDeclaration,\n type SourceFile,\n SyntaxKind,\n type TypeNode,\n} from 'ts-morph';\nimport { resolveEnumValues } from './enum-resolution.js';\nimport type { FieldTypeKind, FilterFieldType, TypeRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Field-type classification (mirrors mapTypeOrmType / mapMikroOrmType so codegen\n// and the runtime adapters can never diverge). See nestjs-filter\n// packages/typeorm/src/typeorm.adapter.ts:190 (mapTypeOrmType).\n// ---------------------------------------------------------------------------\n\n/** Reference: typeorm.adapter.ts keyword tables (kept in sync intentionally). */\nconst STRING_TYPE_KEYWORDS = ['varchar', 'text', 'string', 'char', 'uuid', 'enum'];\nconst NUMBER_TYPE_KEYWORDS = ['int', 'float', 'double', 'decimal', 'number', 'numeric', 'real'];\nconst BOOLEAN_TYPE_KEYWORDS = ['bool', 'boolean', 'bit'];\nconst DATE_TYPE_KEYWORDS = ['date', 'time', 'timestamp', 'datetime'];\nconst JSON_TYPE_KEYWORDS = ['json', 'jsonb'];\n\n/** Classify a column/property type literal (e.g. 'varchar') the same way mapTypeOrmType does. */\nexport function classifyTypeKeyword(raw: string): FieldTypeKind | null {\n const t = raw.toLowerCase();\n if (STRING_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'string';\n if (NUMBER_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'number';\n if (BOOLEAN_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'boolean';\n if (DATE_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'date';\n if (JSON_TYPE_KEYWORDS.some((s) => t.includes(s))) return 'json';\n return null;\n}\n\nexport interface ClassifyResult {\n kind: FieldTypeKind;\n enumValues?: string[];\n nullable?: boolean;\n numericEnum?: boolean;\n /** Importable reference to a named enum / type alias / interface (option B). */\n typeRef?: TypeRef;\n}\n\n/**\n * Return `r` with `nullable: true` set only when `nullable` is true.\n * Avoids assigning `undefined` to an optional prop under exactOptionalPropertyTypes.\n */\nexport function markNullable(r: ClassifyResult, nullable: boolean): ClassifyResult {\n return nullable ? { ...r, nullable: true } : r;\n}\n\n/**\n * Options for {@link classifyTypeNode}. When `resolveRef` is supplied and the\n * type node is a named reference (not a primitive / well-known name), it is\n * called with the symbol name; a non-null result is attached as `typeRef` on the\n * returned `ClassifyResult`. This lets `classifyFilterForParam` classify ONCE and\n * pick up the importable ref in the same pass.\n */\nexport interface ClassifyTypeNodeOptions {\n resolveRef?: (refName: string) => TypeRef | null;\n}\n\n/** Classify a TS type node into a field-type kind (+ enum members / nullable). */\nexport function classifyTypeNode(\n typeNode: TypeNode,\n sourceFile: SourceFile,\n project: Project,\n opts?: ClassifyTypeNodeOptions,\n): ClassifyResult {\n // Union: strip null/undefined, collect literal members, recurse otherwise.\n if (Node.isUnionTypeNode(typeNode)) {\n let nullable = false;\n const stringLits: string[] = [];\n const numberLits: string[] = [];\n const others: TypeNode[] = [];\n for (const member of typeNode.getTypeNodes()) {\n const kind = member.getKind();\n if (kind === SyntaxKind.NullKeyword || kind === SyntaxKind.UndefinedKeyword) {\n nullable = true;\n continue;\n }\n if (Node.isLiteralTypeNode(member)) {\n const lit = member.getLiteral();\n if (Node.isStringLiteral(lit)) {\n stringLits.push(lit.getLiteralValue());\n continue;\n }\n if (Node.isNumericLiteral(lit)) {\n numberLits.push(lit.getText());\n continue;\n }\n if (lit.getKind() === SyntaxKind.NullKeyword) {\n nullable = true;\n continue;\n }\n }\n others.push(member);\n }\n\n if (others.length === 0 && stringLits.length > 0 && numberLits.length === 0) {\n return markNullable({ kind: 'string', enumValues: stringLits }, nullable);\n }\n if (others.length === 0 && numberLits.length > 0 && stringLits.length === 0) {\n return markNullable({ kind: 'number', enumValues: numberLits, numericEnum: true }, nullable);\n }\n if (others.length === 1) {\n const inner = classifyTypeNode(others[0]!, sourceFile, project, opts);\n return markNullable(inner, nullable || inner.nullable === true);\n }\n return markNullable({ kind: 'unknown' }, nullable);\n }\n\n switch (typeNode.getKind()) {\n case SyntaxKind.StringKeyword:\n return { kind: 'string' };\n case SyntaxKind.NumberKeyword:\n return { kind: 'number' };\n case SyntaxKind.BooleanKeyword:\n return { kind: 'boolean' };\n case SyntaxKind.AnyKeyword:\n case SyntaxKind.UnknownKeyword:\n return { kind: 'unknown' };\n default:\n break;\n }\n\n if (Node.isTypeReference(typeNode)) {\n const refName = typeNode.getTypeName().getText();\n if (refName === 'Date') return { kind: 'date' };\n if (refName === 'Record' || refName === 'Object') return { kind: 'json' };\n // An importable named ref (enum / type alias / interface / class) wins for\n // emit when the caller supplied a resolver and a safe import path exists.\n const typeRef = opts?.resolveRef?.(refName) ?? null;\n // Possibly an enum type used as a property type.\n const en = resolveEnumValues(refName, sourceFile, project);\n if (en) {\n const base: ClassifyResult = en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n return typeRef ? { ...base, typeRef } : base;\n }\n if (typeRef) return { kind: 'unknown', typeRef };\n return { kind: 'unknown' };\n }\n\n if (Node.isTypeLiteral(typeNode)) return { kind: 'json' };\n\n return { kind: 'unknown' };\n}\n\n/** Resolve an enum from @Enum decorator args: `() => Status` or `{ items: () => Status }`. */\nexport function enumFromDecoratorArgs(\n args: Node[],\n sourceFile: SourceFile,\n project: Project,\n): { values: string[]; numeric: boolean } | null {\n for (const arg of args) {\n if (Node.isArrowFunction(arg)) {\n const body = arg.getBody();\n if (Node.isIdentifier(body)) {\n const en = resolveEnumValues(body.getText(), sourceFile, project);\n if (en) return en;\n }\n }\n if (Node.isObjectLiteralExpression(arg)) {\n const itemsProp = arg.getProperty('items');\n if (itemsProp && Node.isPropertyAssignment(itemsProp)) {\n const init = itemsProp.getInitializer();\n if (init && Node.isArrowFunction(init)) {\n const body = init.getBody();\n if (Node.isIdentifier(body)) {\n const en = resolveEnumValues(body.getText(), sourceFile, project);\n if (en) return en;\n }\n }\n }\n }\n }\n return null;\n}\n\n/** Classify a property from `@Column`/`@Property`/`@Enum` decorator options. */\nexport function classifyFromColumnDecorator(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult | null {\n for (const dec of prop.getDecorators()) {\n const decName = dec.getName();\n if (decName !== 'Column' && decName !== 'Property' && decName !== 'Enum') continue;\n const args = dec.getArguments();\n\n // @Enum({ items: () => Status }) or @Enum(() => Status)\n if (decName === 'Enum') {\n const en = enumFromDecoratorArgs(args, sourceFile, project);\n if (en) {\n return en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n }\n return { kind: 'string' };\n }\n\n for (const arg of args) {\n // @Column('varchar')\n if (Node.isStringLiteral(arg)) {\n const raw = arg.getLiteralValue();\n const kind = classifyTypeKeyword(raw);\n if (kind) {\n // @Column('enum', { enum: Status }) → resolve via the options object below\n if (kind === 'string' && raw.toLowerCase().includes('enum')) continue;\n return { kind };\n }\n }\n // @Column({ type: 'datetime' }) / @Property({ type: 'int' }) / { enum: Status }\n if (Node.isObjectLiteralExpression(arg)) {\n const enumProp = arg.getProperty('enum');\n if (enumProp && Node.isPropertyAssignment(enumProp)) {\n const init = enumProp.getInitializer();\n if (init && Node.isIdentifier(init)) {\n const en = resolveEnumValues(init.getText(), sourceFile, project);\n if (en) {\n return en.numeric\n ? { kind: 'number', enumValues: en.values, numericEnum: true }\n : { kind: 'string', enumValues: en.values };\n }\n return { kind: 'string' };\n }\n }\n const typeProp = arg.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const init = typeProp.getInitializer();\n if (init && Node.isStringLiteral(init)) {\n const kind = classifyTypeKeyword(init.getLiteralValue());\n if (kind) return { kind };\n }\n }\n }\n }\n // Decorator present but no recognisable type info.\n return null;\n }\n return null;\n}\n\n/**\n * Classify a single entity/DTO property into a ClassifyResult (kind + enum + nullable),\n * mirroring the runtime ORM type mapping. Falls back to 'unknown' when unresolvable.\n */\nexport function classifyFieldType(\n prop: PropertyDeclaration,\n sourceFile: SourceFile,\n project: Project,\n): ClassifyResult {\n let nullable = prop.hasQuestionToken();\n const typeNode = prop.getTypeNode();\n\n if (typeNode) {\n const r = classifyTypeNode(typeNode, sourceFile, project);\n if (r.nullable) nullable = true;\n if (r.kind !== 'unknown') return markNullable(r, nullable);\n }\n\n const fromDecorator = classifyFromColumnDecorator(prop, sourceFile, project);\n if (fromDecorator) {\n return markNullable(fromDecorator, nullable || fromDecorator.nullable === true);\n }\n\n return markNullable({ kind: 'unknown' }, nullable);\n}\n\n/**\n * The single normalizing constructor for a {@link FilterFieldType} from a\n * classification. Concentrates the `typeRef` precedence invariant (see the\n * `FilterFieldType` doc): `kind`/`enumValues`/`numericEnum` are always recorded\n * best-effort, and `typeRef` (when present) is what the emitter actually uses.\n * Build `FilterFieldType` values through here — not inline — so the convention\n * has exactly one enforcement point.\n */\nexport function toFilterFieldType(name: string, r: ClassifyResult): FilterFieldType {\n const ft: FilterFieldType = { name, kind: r.kind };\n if (r.enumValues && r.enumValues.length > 0) ft.enumValues = r.enumValues;\n if (r.nullable) ft.nullable = true;\n if (r.numericEnum) ft.numericEnum = true;\n if (r.typeRef) ft.typeRef = r.typeRef;\n return ft;\n}\n","import type { Project, SourceFile } from 'ts-morph';\nimport { findType } from './type-ref-resolution.js';\n\n/**\n * Resolve an enum identifier to its raw member values + numeric flag.\n *\n * KNOWN LIMITATION — mixed enums with a computed member: `findType` serializes\n * each enum member with `JSON.stringify` of its static value, falling back to the\n * QUOTED member NAME for any member whose value can't be resolved statically\n * (e.g. a computed member). Here we re-derive `numeric` by `JSON.parse`-ing each\n * member: any string member (including that quoted-name fallback) flips `numeric`\n * to `false` for the WHOLE enum. So a primarily-numeric enum that contains a\n * single computed member is treated as a string enum, and its numeric members\n * are emitted as quoted string literals. This is a rare edge case; fixing it\n * would require threading per-member numeric-ness out of `findType` rather than\n * inferring it from the stringified members. Pure numeric and pure string enums\n * (the overwhelmingly common cases) are unaffected.\n */\nexport function resolveEnumValues(\n name: string,\n sourceFile: SourceFile,\n project: Project,\n): { values: string[]; numeric: boolean } | null {\n const resolved = findType(name, sourceFile, project);\n if (!resolved || resolved.kind !== 'enum') return null;\n // members are JSON.stringify'd (\"A\" / \"0\"); strip quotes to raw values.\n let numeric = true;\n const values = resolved.members.map((m) => {\n const parsed = JSON.parse(m) as string | number;\n if (typeof parsed === 'string') numeric = false;\n return String(parsed);\n });\n if (values.length === 0) return null;\n return { values, numeric };\n}\n","import { Node, SyntaxKind } from 'ts-morph';\n\n/**\n * Convert a ts-morph Node (expression) representing a Zod schema call to a\n * TypeScript type-source string. Falls back to `'unknown'` for anything\n * unrecognised.\n */\nexport function zodAstToTs(node: Node): string {\n // We only handle call expressions (e.g. z.string(), z.object({…}).optional())\n if (!Node.isCallExpression(node)) return 'unknown';\n\n const expr = node.getExpression();\n\n // ── Chained calls: z.xxx().optional() / .nullable() ──────────────────────\n if (Node.isPropertyAccessExpression(expr)) {\n const methodName = expr.getName();\n const receiver = expr.getExpression();\n\n if (methodName === 'optional') {\n return `${zodAstToTs(receiver)} | undefined`;\n }\n if (methodName === 'nullable') {\n return `${zodAstToTs(receiver)} | null`;\n }\n\n // ── z.<method>(…) top-level calls ────────────────────────────────────────\n const args = node.getArguments();\n\n switch (methodName) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'unknown':\n return 'unknown';\n case 'any':\n return 'unknown';\n\n case 'literal': {\n const lit = args[0];\n if (!lit) return 'unknown';\n if (Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());\n if (Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();\n if (lit.getKind() === SyntaxKind.TrueKeyword) return 'true';\n if (lit.getKind() === SyntaxKind.FalseKeyword) return 'false';\n return 'unknown';\n }\n\n case 'enum': {\n // z.enum([\"a\",\"b\",\"c\"])\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n const members = arrArg\n .getElements()\n .map((el) =>\n Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : 'unknown',\n );\n return members.join(' | ');\n }\n\n case 'array': {\n const inner = args[0];\n if (!inner) return 'unknown';\n return `Array<${zodAstToTs(inner)}>`;\n }\n\n case 'object': {\n const objArg = args[0];\n if (!objArg || !Node.isObjectLiteralExpression(objArg)) return 'unknown';\n const lines: string[] = [];\n for (const prop of objArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const key = prop.getName();\n const valNode = prop.getInitializer();\n if (!valNode) continue;\n const tsType = zodAstToTs(valNode);\n // Mark optional if the value is .optional()\n const isOpt = isOptionalChain(valNode);\n lines.push(`${key}${isOpt ? '?' : ''}: ${tsType}`);\n }\n return `{ ${lines.join('; ')} }`;\n }\n\n case 'union': {\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n return arrArg.getElements().map(zodAstToTs).join(' | ');\n }\n\n case 'record': {\n // z.record(V) or z.record(K, V) — always emit Record<string, V>\n const valArg = args.length === 1 ? args[0] : args[1];\n if (!valArg) return 'unknown';\n return `Record<string, ${zodAstToTs(valArg)}>`;\n }\n\n case 'tuple': {\n const arrArg = args[0];\n if (!arrArg || !Node.isArrayLiteralExpression(arrArg)) return 'unknown';\n return `[${arrArg.getElements().map(zodAstToTs).join(', ')}]`;\n }\n\n default:\n return 'unknown';\n }\n }\n\n return 'unknown';\n}\n\n/** Return true when `node` is a CallExpression ending in `.optional()`. */\nfunction isOptionalChain(node: Node): boolean {\n if (!Node.isCallExpression(node)) return false;\n const expr = node.getExpression();\n return Node.isPropertyAccessExpression(expr) && expr.getName() === 'optional';\n}\n\n/**\n * Parse a defineContract({...}) call expression.\n * Returns { query, body, response } or null if unrecognised.\n */\nexport interface ParsedContractDef {\n query: string | null;\n body: string | null;\n response: string;\n /** Raw zod source text of the body initializer (for inline forms emit). */\n bodyZodText: string | null;\n /** Raw zod source text of the query initializer (for inline forms emit). */\n queryZodText: string | null;\n}\n\nexport function parseDefineContractCall(callExpr: Node): ParsedContractDef | null {\n if (!Node.isCallExpression(callExpr)) return null;\n\n const callee = callExpr.getExpression();\n // Accept both `defineContract(...)` and any identifier named defineContract\n const calleeName = Node.isIdentifier(callee)\n ? callee.getText()\n : Node.isPropertyAccessExpression(callee)\n ? callee.getName()\n : '';\n\n if (calleeName !== 'defineContract') return null;\n\n const args = callExpr.getArguments();\n const optsArg = args[0];\n if (!optsArg || !Node.isObjectLiteralExpression(optsArg)) return null;\n\n let query: string | null = null;\n let body: string | null = null;\n let response = 'unknown';\n let bodyZodText: string | null = null;\n let queryZodText: string | null = null;\n\n for (const prop of optsArg.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const propName = prop.getName();\n const val = prop.getInitializer();\n if (!val) continue;\n\n if (propName === 'query') {\n query = zodAstToTs(val);\n queryZodText = val.getText();\n } else if (propName === 'body') {\n body = zodAstToTs(val);\n bodyZodText = val.getText();\n } else if (propName === 'response') {\n response = zodAstToTs(val);\n }\n }\n\n return { query, body, response, bodyZodText, queryZodText };\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport type { ResolvedConfig } from './config/types.js';\nimport { discoverPages } from './discovery/pages.js';\nimport { discoverSharedPropsFromConfig } from './discovery/shared-props.js';\nimport type { RouteDescriptor } from './discovery/types.js';\nimport { emitApi } from './emit/emit-api.js';\nimport { emitCache } from './emit/emit-cache.js';\nimport { emitForms } from './emit/emit-forms.js';\nimport { emitIndex } from './emit/emit-index.js';\nimport { emitPages } from './emit/emit-pages.js';\nimport { emitRoutes } from './emit/emit-routes.js';\nimport {\n applyTransformRoutes,\n collectEmittedFiles,\n createExtensionContext,\n} from './extension/registry.js';\n\n/**\n * Run one full codegen pass: discover pages, emit pages.d.ts, components.json, index.d.ts.\n * Route discovery is deliberately skipped — it requires spawning a Nest app and is\n * not appropriate for the hot path of a file watcher.\n *\n * Optionally accepts pre-discovered routes (e.g. from a full generate + route-discovery pass).\n * When routes are present, emits routes.ts.\n * When routes with contracts are present, also emits api.ts.\n */\nexport async function generate(\n config: ResolvedConfig,\n inputRoutes: RouteDescriptor[] = [],\n): Promise<void> {\n // Extensions: run transformRoutes (chained) before any emit so routes.ts/api.ts/\n // forms.ts all see the augmented IR. ctx.routes is a live getter over the active set.\n const extensions = config.extensions ?? [];\n let routes = inputRoutes;\n const ctx = createExtensionContext(config, () => routes);\n if (extensions.length > 0) {\n routes = await applyTransformRoutes(routes, extensions, ctx);\n }\n\n // Inertia page discovery is opt-in — skip entirely when `pages` isn't configured.\n if (config.pages) {\n const pagesConfig = config.pages;\n const pages = await discoverPages({\n glob: pagesConfig.glob,\n cwd: config.codegen.cwd,\n propsExport: pagesConfig.propsExport,\n componentNameStrategy: pagesConfig.componentNameStrategy,\n });\n\n const sharedProps = discoverSharedPropsFromConfig(config);\n\n await emitPages(pages, config.codegen.outDir, {\n propsExport: pagesConfig.propsExport,\n sharedProps,\n });\n await emitCache(pages, config.codegen.outDir);\n }\n\n const hasRoutes = routes.length > 0;\n const hasContracts = routes.some((r) => r.contract);\n\n if (hasRoutes) {\n await emitRoutes(routes, config.codegen.outDir);\n }\n\n if (hasContracts) {\n await emitApi(routes, config.codegen.outDir, {\n ...(config.fetcher?.importPath ? { fetcherImportPath: config.fetcher.importPath } : {}),\n extensions,\n ctx,\n });\n }\n\n const hasForms = await emitForms(routes, config.codegen.outDir, config.forms, config.validation);\n\n await emitIndex(config.codegen.outDir, hasContracts, hasForms);\n\n // Extensions: write any extra files (collision-checked against each other + core files).\n if (extensions.length > 0) {\n const extraFiles = await collectEmittedFiles(extensions, ctx);\n for (const file of extraFiles) {\n const dest = join(config.codegen.outDir, file.path);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, file.contents, 'utf8');\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport fg from 'fast-glob';\n\nexport interface DiscoveredPage {\n name: string;\n absolutePath: string;\n relativePath: string;\n propsSource: string | null;\n}\n\nexport interface DiscoverPagesOptions {\n glob: string;\n cwd: string;\n propsExport: string;\n componentNameStrategy: 'relative-no-ext' | 'kebab' | ((path: string) => string);\n}\n\n// Files matching these patterns are never treated as Inertia pages even if\n// they sit inside the pages directory and would match the user's glob.\n// Without this filter, vitest test files (`*.test.tsx`) get registered as\n// pages, their imports get pulled into the typecheck graph, and any\n// transitive matcher errors leak into the user's project.\nconst NON_PAGE_FILE_RE = /\\.(?:test|spec|stories|story)\\.(?:tsx?|jsx?|vue|svelte)$/i;\n\nexport async function discoverPages(opts: DiscoverPagesOptions): Promise<DiscoveredPage[]> {\n const allFiles = await fg(opts.glob, { cwd: opts.cwd, absolute: true });\n const files = allFiles.filter((f) => !NON_PAGE_FILE_RE.test(f));\n files.sort();\n // Extract the static prefix from the glob to make page names relative to the pages directory\n // e.g. glob 'inertia/pages/**/*.tsx' → pagesBase 'inertia/pages'\n const globStatic = opts.glob.split('*')[0]?.replace(/\\/$/, '') ?? '';\n const pagesBase = join(opts.cwd, globStatic);\n const out: DiscoveredPage[] = [];\n for (const file of files) {\n const rel = relative(opts.cwd, file);\n const nameRel = relative(pagesBase, file);\n const name = computeName(nameRel, opts.componentNameStrategy);\n const source = await readFile(file, 'utf8');\n const propsSource = extractPropsSource(source, opts.propsExport);\n out.push({ name, absolutePath: file, relativePath: rel, propsSource });\n }\n return out;\n}\n\nfunction computeName(rel: string, strat: DiscoverPagesOptions['componentNameStrategy']): string {\n if (typeof strat === 'function') return strat(rel);\n const noExt = rel.replace(/\\.(tsx?|vue|svelte)$/, '');\n if (strat === 'kebab') return noExt.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n return noExt;\n}\n\nfunction extractPropsSource(source: string, exportName: string): string | null {\n const re = new RegExp(`export\\\\s+type\\\\s+${exportName}\\\\s*=\\\\s*`, 'm');\n const m = source.match(re);\n if (!m) return null;\n const start = m.index! + m[0].length;\n // Brace counting to capture type body\n let i = start;\n let depth = 0;\n let started = false;\n while (i < source.length) {\n const c = source[i];\n if (c === '{') {\n depth++;\n started = true;\n } else if (c === '}') {\n depth--;\n if (started && depth === 0) {\n return source.slice(start, i + 1);\n }\n } else if (c === ';' && !started) return source.slice(start, i);\n i++;\n }\n return source.slice(start);\n}\n","/**\n * Static AST-based discovery of shared props from `InertiaModule.forRoot({ share: ... })`.\n *\n * Analyzes the `share` property in the forRoot call to infer the return type\n * of the share function and generate typed shared props.\n *\n * Gracefully returns null when the share function cannot be analyzed\n * (complex logic, service calls, external references, etc.).\n */\nimport { join } from 'node:path';\nimport { Node, Project, type SourceFile, SyntaxKind } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\n\nexport interface SharedPropsResult {\n /** The TS type string — either `Awaited<ReturnType<typeof import('...').fn>>` or an inline object type */\n typeString: string;\n /** Individual property entries for emitting into an interface body (null when using ReturnType) */\n properties: Array<{ name: string; type: string }> | null;\n /** When true, typeString is a ReturnType<import(...)> expression (not inline) */\n isImportRef: boolean;\n}\n\n/**\n * Discover shared props by analyzing `InertiaModule.forRoot({ share: ... })` in the given module entry file.\n *\n * @param project - ts-morph Project (caller creates it)\n * @param moduleEntry - Absolute path to the NestJS module entry file (e.g. `src/app.module.ts`)\n * @returns SharedPropsResult or null if no share function found or it can't be inferred\n */\nexport function discoverSharedProps(\n project: Project,\n moduleEntry: string,\n): SharedPropsResult | null {\n try {\n let sourceFile = project.getSourceFile(moduleEntry);\n if (!sourceFile) {\n try {\n sourceFile = project.addSourceFileAtPath(moduleEntry);\n } catch {\n return null;\n }\n }\n\n const forRootCall = findForRootCall(sourceFile);\n if (!forRootCall) return null;\n\n const initializer = findShareInitializer(forRootCall);\n if (!initializer) return null;\n\n return extractShareType(initializer, sourceFile, project);\n } catch {\n // Graceful fallback — any unexpected error means we skip shared props typing\n return null;\n }\n}\n\n/**\n * Resolve shared props from a fully-resolved config: builds the ts-morph Project,\n * resolves the tsconfig path, and analyzes the module entry's `forRoot({ share })`.\n *\n * Returns null (swallowing any error) when `app.moduleEntry` isn't configured or\n * anything goes wrong while constructing the project / discovering props — preserving\n * the previous graceful-fallback behavior of the generate orchestrator.\n */\nexport function discoverSharedPropsFromConfig(config: ResolvedConfig): SharedPropsResult | null {\n if (!config.app?.moduleEntry) return null;\n\n try {\n const tsconfigPath = config.app.tsconfig ?? join(config.codegen.cwd, 'tsconfig.json');\n let project: Project;\n try {\n project = new Project({\n tsConfigFilePath: tsconfigPath,\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n });\n } catch {\n project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: { allowJs: true, strict: false },\n });\n }\n return discoverSharedProps(project, config.app.moduleEntry);\n } catch {\n // Graceful fallback — skip shared props if anything goes wrong\n return null;\n }\n}\n\n/**\n * Find `InertiaModule.forRoot(...)` call expression in a source file.\n * Searches all call expressions in the file.\n */\nfunction findForRootCall(sourceFile: SourceFile): Node | null {\n const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);\n\n for (const call of callExpressions) {\n const expr = call.getExpression();\n if (!Node.isPropertyAccessExpression(expr)) continue;\n\n const methodName = expr.getName();\n const objectExpr = expr.getExpression();\n\n if (methodName === 'forRoot' && Node.isIdentifier(objectExpr)) {\n const name = objectExpr.getText();\n if (name === 'InertiaModule') {\n return call;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Extract the initializer of the `share` property from the first argument of `forRoot(...)`.\n * Returns the initializer node (the value assigned to `share`), or null if not found.\n */\nfunction findShareInitializer(forRootCall: Node): Node | null {\n if (!Node.isCallExpression(forRootCall)) return null;\n\n const args = forRootCall.getArguments();\n const firstArg = args[0];\n if (!firstArg || !Node.isObjectLiteralExpression(firstArg)) return null;\n\n for (const prop of firstArg.getProperties()) {\n if (Node.isPropertyAssignment(prop) && prop.getName() === 'share') {\n return prop.getInitializer() ?? null;\n }\n }\n\n return null;\n}\n\n/**\n * Extract the return type of the share value.\n * Handles:\n * - Arrow functions: `(req) => ({ ... })`\n * - Arrow functions with block body: `(req) => { return { ... }; }`\n * - Function expressions: `function(req) { return { ... }; }`\n * - Async variants of the above\n * - Object literals (plain `share: { ... }`)\n * - Functions with explicit return type annotations\n */\nfunction extractShareType(\n node: Node,\n sourceFile: SourceFile,\n project: Project,\n): SharedPropsResult | null {\n // Priority 1: Reference to a named function → use ReturnType<typeof import(...)>\n if (Node.isIdentifier(node)) {\n const ref = resolveIdentifierToImportRef(node, sourceFile, project);\n if (ref) {\n return {\n typeString: `Awaited<ReturnType<typeof import('${ref.importPath}').${ref.exportName}>>`,\n properties: null,\n isImportRef: true,\n };\n }\n }\n\n // Priority 2: Arrow function → try inline extraction\n if (Node.isArrowFunction(node)) {\n const result = extractFromFunctionLike(node, sourceFile);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n // Priority 3: Function expression → try inline extraction\n if (Node.isFunctionExpression(node)) {\n const result = extractFromFunctionLike(node, sourceFile);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n // Priority 4: Object literal (share: { key: value })\n if (Node.isObjectLiteralExpression(node)) {\n const result = extractFromObjectLiteral(node);\n return result ? { ...result, isImportRef: false } : null;\n }\n\n return null;\n}\n\nfunction resolveIdentifierToImportRef(\n id: Node,\n sourceFile: SourceFile,\n project: Project,\n): { importPath: string; exportName: string } | null {\n if (!Node.isIdentifier(id)) return null;\n const name = id.getText();\n\n const localFunc = sourceFile.getFunction(name);\n if (localFunc?.isExported()) {\n const filePath = sourceFile.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: name };\n }\n\n const localVar = sourceFile.getVariableDeclaration(name);\n if (localVar?.isExported()) {\n const filePath = sourceFile.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: name };\n }\n\n for (const imp of sourceFile.getImportDeclarations()) {\n for (const named of imp.getNamedImports()) {\n const importedName = named.getAliasNode()?.getText() ?? named.getName();\n if (importedName !== name) continue;\n const resolvedSource = imp.getModuleSpecifierSourceFile();\n if (!resolvedSource) continue;\n const originalName = named.getName();\n const fn = resolvedSource.getFunction(originalName);\n if (fn?.isExported()) {\n const filePath = resolvedSource.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: originalName };\n }\n const v = resolvedSource.getVariableDeclaration(originalName);\n if (v?.isExported()) {\n const filePath = resolvedSource.getFilePath().replace(/\\.ts$/, '');\n return { importPath: filePath, exportName: originalName };\n }\n }\n }\n\n return null;\n}\n\n/**\n * Extract shared props type from an arrow function or function expression.\n * First tries the return type annotation; falls back to inferring from the return value.\n */\nfunction extractFromFunctionLike(node: Node, _sourceFile: SourceFile): SharedPropsResult | null {\n // Check for explicit return type annotation\n const returnTypeNode =\n Node.isArrowFunction(node) || Node.isFunctionExpression(node) ? node.getReturnTypeNode() : null;\n\n if (returnTypeNode) {\n return extractFromReturnTypeAnnotation(returnTypeNode);\n }\n\n // Infer from body\n if (Node.isArrowFunction(node)) {\n const body = node.getBody();\n\n // Concise body: (req) => ({ auth: ..., flash: ... })\n if (Node.isParenthesizedExpression(body)) {\n const inner = body.getExpression();\n if (Node.isObjectLiteralExpression(inner)) {\n return extractFromObjectLiteral(inner);\n }\n }\n\n // Direct object literal (less common but possible with as const)\n if (Node.isObjectLiteralExpression(body)) {\n return extractFromObjectLiteral(body);\n }\n\n // Block body: (req) => { return { ... }; }\n if (Node.isBlock(body)) {\n return extractFromBlockReturn(body);\n }\n }\n\n if (Node.isFunctionExpression(node)) {\n const body = node.getBody();\n if (Node.isBlock(body)) {\n return extractFromBlockReturn(body);\n }\n }\n\n return null;\n}\n\n/**\n * Extract type from a return type annotation on the share function.\n * e.g. `(req): { auth: User | null; flash: {} } => ...`\n */\nfunction extractFromReturnTypeAnnotation(typeNode: Node): SharedPropsResult | null {\n // Unwrap Promise<T> if async\n if (Node.isTypeReference(typeNode)) {\n const typeName = typeNode.getTypeName();\n if (Node.isIdentifier(typeName) && typeName.getText() === 'Promise') {\n const typeArgs = typeNode.getTypeArguments();\n const firstArg = typeArgs[0];\n if (firstArg) {\n return extractFromReturnTypeAnnotation(firstArg);\n }\n return null;\n }\n }\n\n // TypeLiteral: { auth: ...; flash: ... }\n if (Node.isTypeLiteral(typeNode)) {\n const properties: Array<{ name: string; type: string }> = [];\n for (const member of typeNode.getMembers()) {\n if (Node.isPropertySignature(member)) {\n const name = member.getName();\n const memberTypeNode = member.getTypeNode();\n const type = memberTypeNode ? memberTypeNode.getText() : 'unknown';\n properties.push({ name, type });\n }\n }\n if (properties.length === 0) return null;\n const typeString = `{ ${properties.map((p) => `${p.name}: ${p.type}`).join('; ')} }`;\n return { typeString, properties, isImportRef: false };\n }\n\n return null;\n}\n\n/**\n * Extract shared props from a block body's return statement.\n * Only handles the simple case: a single return statement with an object literal.\n */\nfunction extractFromBlockReturn(block: Node): SharedPropsResult | null {\n if (!Node.isBlock(block)) return null;\n\n const statements = block.getStatements();\n // Find the last return statement\n for (let i = statements.length - 1; i >= 0; i--) {\n const stmt = statements[i];\n if (!Node.isReturnStatement(stmt)) continue;\n\n const expr = stmt.getExpression();\n if (!expr) continue;\n\n if (Node.isObjectLiteralExpression(expr)) {\n return extractFromObjectLiteral(expr);\n }\n\n // Parenthesized: return ({ ... })\n if (Node.isParenthesizedExpression(expr)) {\n const inner = expr.getExpression();\n if (Node.isObjectLiteralExpression(inner)) {\n return extractFromObjectLiteral(inner);\n }\n }\n\n break;\n }\n\n return null;\n}\n\n/**\n * Infer shared props type from an object literal expression.\n * Each property key becomes a shared prop; the value type is inferred from the value expression.\n */\nfunction extractFromObjectLiteral(objLiteral: Node): SharedPropsResult | null {\n if (!Node.isObjectLiteralExpression(objLiteral)) return null;\n\n const properties: Array<{ name: string; type: string }> = [];\n\n for (const prop of objLiteral.getProperties()) {\n if (!Node.isPropertyAssignment(prop)) continue;\n\n const name = prop.getName();\n const initializer = prop.getInitializer();\n if (!initializer) continue;\n\n const type = inferExpressionType(initializer);\n properties.push({ name, type });\n }\n\n if (properties.length === 0) return null;\n\n const typeString = `{ ${properties.map((p) => `${p.name}: ${p.type}`).join('; ')} }`;\n return { typeString, properties, isImportRef: false };\n}\n\n/**\n * Infer the TypeScript type of an expression.\n * Handles common patterns found in share functions:\n * - Object literals → `{ key: type; ... }`\n * - String literals → `string`\n * - Number literals → `number`\n * - Boolean literals → `boolean`\n * - Null → `null`\n * - Array literals → `Array<type>`\n * - Ternary expressions → `trueType | falseType`\n * - Property accesses and complex expressions → `unknown`\n * - Empty object literal → `Record<string, unknown>`\n */\nfunction inferExpressionType(node: Node): string {\n // String literal\n if (Node.isStringLiteral(node)) return 'string';\n\n // Template literal (backtick)\n if (Node.isTemplateExpression(node) || Node.isNoSubstitutionTemplateLiteral(node))\n return 'string';\n\n // Number literal\n if (Node.isNumericLiteral(node)) return 'number';\n\n // Boolean literal\n if (node.getKind() === SyntaxKind.TrueKeyword || node.getKind() === SyntaxKind.FalseKeyword) {\n return 'boolean';\n }\n\n // Null literal\n if (node.getKind() === SyntaxKind.NullKeyword) return 'null';\n\n // Undefined\n if (Node.isIdentifier(node) && node.getText() === 'undefined') return 'undefined';\n\n // Object literal\n if (Node.isObjectLiteralExpression(node)) {\n const props = node.getProperties();\n if (props.length === 0) return 'Record<string, unknown>';\n\n const entries: string[] = [];\n for (const prop of props) {\n if (!Node.isPropertyAssignment(prop)) continue;\n const key = prop.getName();\n const init = prop.getInitializer();\n if (!init) continue;\n entries.push(`${key}: ${inferExpressionType(init)}`);\n }\n if (entries.length === 0) return 'Record<string, unknown>';\n return `{ ${entries.join('; ')} }`;\n }\n\n // Array literal\n if (Node.isArrayLiteralExpression(node)) {\n const elements = node.getElements();\n if (elements.length === 0) return 'Array<unknown>';\n // Infer from first element\n const first = elements[0];\n if (first) return `Array<${inferExpressionType(first)}>`;\n return 'Array<unknown>';\n }\n\n // Ternary (conditional) expression: x ? A : B → A | B\n if (Node.isConditionalExpression(node)) {\n const whenTrue = inferExpressionType(node.getWhenTrue());\n const whenFalse = inferExpressionType(node.getWhenFalse());\n if (whenTrue === whenFalse) return whenTrue;\n return `${whenTrue} | ${whenFalse}`;\n }\n\n // Parenthesized expression — unwrap\n if (Node.isParenthesizedExpression(node)) {\n return inferExpressionType(node.getExpression());\n }\n\n // As expression (type assertion): expr as Type → use the asserted type\n if (Node.isAsExpression(node)) {\n const typeNode = node.getTypeNode();\n if (typeNode) return typeNode.getText();\n }\n\n // For any other expression (property access, function calls, etc.), fall back to unknown\n return 'unknown';\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative } from 'node:path';\nimport type {\n ContractSource,\n ControllerRef,\n FieldTypeKind,\n FilterFieldType,\n RouteDescriptor,\n} from '../discovery/types.js';\nimport { mergeExclusive, resolveApiSlots } from '../extension/registry.js';\nimport { requestShape } from '../extension/types.js';\nimport type {\n ApiClientLayer,\n CodegenExtension,\n ExtensionContext,\n LeafModel,\n RequestModel,\n} from '../extension/types.js';\n\n/**\n * Emits `api.ts` into `outDir` for all routes that carry a `.contract`.\n *\n * By default each leaf is a bare typed-fetch callable. Registered extensions shape the\n * output: an `apiClientLayer` (e.g. `@dudousxd/nestjs-codegen-tanstack`) turns leaves into\n * handles wrapping the neutral fetcher request; `apiMembers` add handle members; `apiHeader`\n * contributes top-level imports/statements.\n */\nexport interface ApiEmitOptions {\n fetcherImportPath?: string;\n /** Registered extensions. Their api.ts hooks (transport/layer/members/header) are applied. */\n extensions?: CodegenExtension[];\n /** Shared extension context (from `generate()`). When omitted, a minimal one is built from routes. */\n ctx?: ExtensionContext;\n}\n\nexport async function emitApi(\n routes: RouteDescriptor[],\n outDir: string,\n opts: ApiEmitOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const content = buildApiFile(routes, outDir, opts);\n await writeFile(join(outDir, 'api.ts'), content, 'utf8');\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Split a dot-notation name into its path segments. */\nfunction splitName(name: string): string[] {\n return name.split('.');\n}\n\n/**\n * Check whether a segment is a valid JS identifier.\n * If not, we wrap it in quotes so it produces a valid object key.\n */\nfunction toObjectKey(segment: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(segment)) {\n return segment;\n }\n return JSON.stringify(segment);\n}\n\n/**\n * Convert an arbitrary string segment to camelCase by splitting on non-alphanumeric chars.\n */\nfunction toCamelCase(s: string): string {\n return s\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((word, i) =>\n i === 0\n ? word.charAt(0).toLowerCase() + word.slice(1)\n : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n )\n .join('');\n}\n\n/**\n * Validate that a single name segment matches camelCase: starts with a lowercase letter,\n * followed only by alphanumeric chars. Throws a descriptive error on invalid segments.\n */\nfunction validateNameSegment(seg: string, fullName: string): void {\n if (!/^[a-z][a-zA-Z0-9]*$/.test(seg)) {\n const suggested = toCamelCase(seg);\n throw new Error(\n `Contract name \"${fullName}\" has invalid segment \"${seg}\". Use camelCase identifiers only (lowercase letter then alphanumeric). Suggested: \"${suggested}\"`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nested tree helpers\n// ---------------------------------------------------------------------------\n\ntype LeafEntry = {\n kind: 'leaf';\n method: string;\n name: string;\n path: string;\n params: Array<{ name: string; source: string }>;\n controllerRef?: ControllerRef | undefined;\n // Reference the canonical discovery type directly rather than re-declaring a\n // parallel hand-maintained shape. The leaf is always built from a real\n // `ContractSource` (`contractSource: r.contract.contractSource`), so the extra\n // form/zod fields it carries are simply unused here.\n contractSource: ContractSource;\n // The real, un-narrowed `RouteDescriptor` this leaf was built from. Stored so\n // extension hooks receive the canonical route with no reconstruction/force-cast.\n route: RouteDescriptor;\n};\n\ntype BranchEntry = {\n kind: 'branch';\n children: Map<string, TreeNode>;\n};\n\ntype TreeNode = LeafEntry | BranchEntry;\n\n/**\n * Insert a contracted route into the mutable tree.\n * Throws if a name conflict is detected.\n */\nfunction insertIntoTree(\n tree: Map<string, TreeNode>,\n segments: string[],\n leaf: LeafEntry,\n fullName: string,\n): void {\n const head = segments[0] as string;\n const rest = segments.slice(1);\n\n if (rest.length === 0) {\n // This is the final segment — insert as a leaf\n const existing = tree.get(head);\n if (existing !== undefined && existing.kind === 'branch') {\n throw new Error(\n `Contract name conflict: \"${fullName}\" cannot have both a direct entry and child entries`,\n );\n }\n tree.set(head, leaf);\n } else {\n // Need to recurse into a branch\n const existing = tree.get(head);\n if (existing !== undefined && existing.kind === 'leaf') {\n // The leaf's name is the prefix of fullName\n const prefixName = fullName\n .split('.')\n .slice(0, segments.length - rest.length)\n .join('.');\n throw new Error(\n `Contract name conflict: \"${prefixName}\" cannot have both a direct entry and child entries`,\n );\n }\n let branch: BranchEntry;\n if (existing === undefined) {\n branch = { kind: 'branch', children: new Map() };\n tree.set(head, branch);\n } else {\n branch = existing as BranchEntry;\n }\n insertIntoTree(branch.children, rest, leaf, fullName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Params helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build a TypeScript type literal for path params.\n * Returns 'never' when the route has no path params.\n */\nfunction buildParamsType(params: Array<{ name: string; source: string }>): string {\n const pathParams = params.filter((p) => p.source === 'path');\n if (pathParams.length === 0) return 'never';\n return `{ ${pathParams.map((p) => `${p.name}: string`).join('; ')} }`;\n}\n\n/**\n * Check whether a route has any path params.\n */\nfunction hasPathParams(params: Array<{ name: string; source: string }>): boolean {\n return params.some((p) => p.source === 'path');\n}\n\n// ---------------------------------------------------------------------------\n// Code generation helpers\n// ---------------------------------------------------------------------------\n\n/** Map a classified field kind (+ enum members) to a TS type literal. */\nfunction kindToTs(kind: FieldTypeKind, enumValues?: string[], numericEnum?: boolean): string {\n if (enumValues && enumValues.length > 0) {\n return enumValues.map((v) => (numericEnum ? v : JSON.stringify(v))).join(' | ');\n }\n switch (kind) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'date':\n return 'Date';\n case 'json':\n return 'Record<string, unknown>';\n default:\n return 'unknown';\n }\n}\n\n/**\n * Emit the per-field type map literal: `{ \"age\": number; \"status\": \"A\" | \"B\" }`.\n * This is the SOLE emit-side reader of `FilterFieldType` — it owns the `typeRef`\n * precedence invariant (a named ref wins over `kind`/`enumValues`; see the\n * `FilterFieldType` doc). No other emit code branches on `typeRef` vs `kind`.\n */\nfunction emitFieldTypesLiteral(fts: FilterFieldType[]): string {\n const entries = fts.map((f) => {\n // A named typeRef (enum / type alias / interface inferred from a @FilterFor\n // method parameter) wins — reference it by name; the import is emitted at\n // the top of the file by buildApiFile.\n let t = f.typeRef ? f.typeRef.name : kindToTs(f.kind, f.enumValues, f.numericEnum);\n if (f.nullable) t = `${t} | null`;\n return `${JSON.stringify(f.name)}: ${t}`;\n });\n return `{ ${entries.join('; ')} }`;\n}\n\n/** Build the type args for `_filterQueryTyped` — single union, or union + field-type map. */\nfunction emitFilterQueryTypeArgs(c: LeafEntry): string {\n const fieldsUnion = (c.contractSource.filterFields ?? [])\n .map((f) => JSON.stringify(f))\n .join(' | ');\n const fts = c.contractSource.filterFieldTypes;\n return fts?.length ? `${fieldsUnion}, ${emitFieldTypesLiteral(fts)}` : fieldsUnion;\n}\n\n/**\n * Build the `TypedFilterQuery<...>` TYPE for a query-source `@ApplyFilter` route's\n * `query` position. Built from the SAME `emitFilterQueryTypeArgs` used by the\n * `_filterQueryTyped<...>` factory so the two are byte-identical.\n */\nfunction emitFilterQueryType(c: LeafEntry): string {\n return `import('@dudousxd/nestjs-filter-client').TypedFilterQuery<${emitFilterQueryTypeArgs(c)}>`;\n}\n\n/**\n * Emit the nested ApiRouter type block.\n */\nfunction buildResponseType(c: LeafEntry, outDir: string): string {\n if (c.controllerRef) {\n let relPath = relative(outDir, c.controllerRef.filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n return `Awaited<ReturnType<import('${relPath}').${c.controllerRef.className}['${c.controllerRef.methodName}']>>`;\n }\n const respRef = c.contractSource.responseRef;\n if (respRef) {\n return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;\n }\n return c.contractSource.response;\n}\n\nfunction emitRouterTypeBlock(\n tree: Map<string, TreeNode>,\n indent: number,\n outDir: string,\n): string[] {\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n for (const [key, node] of tree) {\n const objKey = toObjectKey(key);\n if (node.kind === 'leaf') {\n const c = node;\n const method = c.method.toUpperCase();\n const queryRef = c.contractSource.queryRef;\n // A query-source `@ApplyFilter` route renders its `TypedFilterQuery<...>`\n // type here — from the same `filterFields`/`filterFieldTypes` data the\n // `_filterQueryTyped<...>` factory uses — so both are byte-identical.\n const isFilterQuery =\n c.contractSource.filterSource === 'query' && !!c.contractSource.filterFields?.length;\n const query = queryRef\n ? queryRef.isArray\n ? `Array<${queryRef.name}>`\n : queryRef.name\n : isFilterQuery\n ? emitFilterQueryType(c)\n : (c.contractSource.query ?? 'never');\n const bodyRef = c.contractSource.bodyRef;\n const body =\n method === 'GET'\n ? 'never'\n : bodyRef\n ? bodyRef.isArray\n ? `Array<${bodyRef.name}>`\n : bodyRef.name\n : (c.contractSource.body ?? 'never');\n const response = buildResponseType(c, outDir);\n const params = buildParamsType(c.params);\n const safeMethod = JSON.stringify(method);\n const safeUrl = JSON.stringify(c.path);\n // Filterable fields (from @dudousxd/nestjs-filter) as a string-literal\n // union, or `never` for routes without a filter. Purely type-level — no\n // runtime dependency on nestjs-filter is introduced by this member.\n const filterFields = c.contractSource.filterFields?.length\n ? c.contractSource.filterFields.map((f) => JSON.stringify(f)).join(' | ')\n : 'never';\n lines.push(\n `${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; params: ${params}; query: ${query}; body: ${body}; response: ${response}; filterFields: ${filterFields} };`,\n );\n } else {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));\n lines.push(`${pad}};`);\n }\n }\n\n return lines;\n}\n\n/**\n * Build the neutral per-leaf {@link RequestModel} from a discovered leaf. This is the\n * input every transport/layer/member-contributor reads — the seam the extension system\n * plugs into. Pure string-building; no I/O.\n */\nfunction buildRequestModel(c: LeafEntry): RequestModel {\n const m = c.method.toLowerCase() as RequestModel['method'];\n const flat = JSON.stringify(c.name);\n const path = JSON.stringify(c.path);\n const TA = buildRouterTypeAccess(c.name);\n const withParams = hasPathParams(c.params);\n // Request-shape flags (\"filter-search POST counts as a read\") computed in one place.\n const { isGet, isQuery, hasBody, hasQuery } = requestShape(c.route);\n\n const fields: string[] = [];\n if (withParams) fields.push(`params: ${TA}['params']`);\n if (hasQuery) fields.push(`query?: ${TA}['query']`);\n if (hasBody) fields.push(`body?: ${TA}['body']`);\n const inputType = fields.length ? `{ ${fields.join('; ')} }` : 'Record<string, never>';\n\n const urlExpr = withParams\n ? `route(${flat} as never, input?.params as never) || ${path}`\n : `route(${flat} as never) || ${path}`;\n const optsParts: string[] = [];\n if (hasQuery) optsParts.push('query: input?.query as Record<string, unknown> | undefined');\n if (hasBody) optsParts.push('body: input?.body');\n const optsExpr = optsParts.length ? `{ ${optsParts.join(', ')} }` : '{}';\n\n return {\n routeName: c.name,\n method: m,\n isGet,\n isQuery,\n hasParams: withParams,\n hasBody,\n inputType,\n urlExpr,\n optsExpr,\n responseType: `${TA}['response']`,\n queryKeyExpr: `[${flat}, input] as const`,\n };\n}\n\n/**\n * The neutral fetcher request: a typed call on the injected `fetcher`. Every leaf is built\n * on this; a registered `apiClientLayer` wraps it (e.g. into a TanStack handle), otherwise\n * the leaf is the bare awaitable callable.\n */\nfunction renderFetcherRequest(req: RequestModel): string {\n return `fetcher.${req.method}<${req.responseType}>(${req.urlExpr}, ${req.optsExpr})`;\n}\n\n/**\n * The `__req` runtime helper, emitted once per `api.ts`. Wraps a request thunk into an\n * **awaitable handle**: `await api.x.y({...})` runs the fetch (Tuyau-style), memoized so\n * repeated awaits hit the network once. Client-layer extensions (e.g. TanStack) spread\n * extra members (`queryOptions`/`mutationOptions`/…) onto the same handle.\n */\nfunction emitReqHelper(): string[] {\n return [\n '/** Awaitable request handle. `await api.x.y({...})` runs the fetch; extensions add query/mutation helpers. */',\n 'type __Req<R> = {',\n ' then<T1 = R, T2 = never>(',\n ' onfulfilled?: ((value: R) => T1 | PromiseLike<T1>) | null,',\n ' onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null,',\n ' ): Promise<T1 | T2>;',\n ' catch<T = never>(onrejected?: ((reason: unknown) => T | PromiseLike<T>) | null): Promise<R | T>;',\n ' finally(onfinally?: (() => void) | null): Promise<R>;',\n ' fetch(): Promise<R>;',\n '};',\n 'function __req<R>(run: () => Promise<R>): __Req<R> {',\n ' let __p: Promise<R> | undefined;',\n ' const __promise = () => {',\n ' __p ??= run();',\n ' return __p;',\n ' };',\n ' return {',\n ' then: (onfulfilled, onrejected) => __promise().then(onfulfilled, onrejected),',\n ' catch: (onrejected) => __promise().catch(onrejected),',\n ' finally: (onfinally) => __promise().finally(onfinally),',\n ' fetch: run,',\n ' };',\n '}',\n '',\n ];\n}\n\n/**\n * Render one leaf. Every leaf is an **awaitable handle**: the `__req(...)` base makes\n * `await api.x.y({...})` perform the request; any client-layer/member contributions\n * (TanStack options, filterQuery, …) are spread on alongside it.\n */\nfunction renderLeaf(\n pad: string,\n objKey: string,\n req: RequestModel,\n requestExpr: string,\n members: Record<string, string>,\n): string[] {\n const lines = [`${pad}${objKey}: (input?: ${req.inputType}) => ({`];\n lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);\n for (const [name, value] of Object.entries(members)) {\n lines.push(`${pad} ${name}: ${value},`);\n }\n lines.push(`${pad}}),`);\n return lines;\n}\n\n/** Resolved api.ts pipeline pieces, threaded through the recursive emit. */\ninterface ApiPipeline {\n layer?: ApiClientLayer;\n memberExts: CodegenExtension[];\n ctx: ExtensionContext;\n}\n\n/**\n * Emit the nested `api` object body via the LeafModel pipeline:\n * build model → neutral fetcher request → layer (when a client layer is registered)\n * → member contributors (bundled filter + extensions' apiMembers) → render. With no layer\n * a leaf is a bare typed-fetch callable; a layer flips it into a handle.\n */\nfunction emitApiObjectBlock(tree: Map<string, TreeNode>, indent: number, p: ApiPipeline): string[] {\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n for (const [key, node] of tree) {\n const objKey = toObjectKey(key);\n if (node.kind === 'branch') {\n lines.push(`${pad}${objKey}: {`);\n lines.push(...emitApiObjectBlock(node.children, indent + 2, p));\n lines.push(`${pad}},`);\n continue;\n }\n\n const req = buildRequestModel(node);\n // Hand extension hooks the real, un-narrowed RouteDescriptor stored on the leaf —\n // no reconstruction or force-cast.\n const leaf: LeafModel = {\n route: node.route,\n request: req,\n requestExpr: renderFetcherRequest(req),\n };\n\n // Every leaf is an awaitable handle (the __req base). A client layer (TanStack) spreads\n // query/mutation helpers on top; extension apiMembers (e.g. nestjs-filter's filterQuery)\n // add further members. Member-name collisions across extensions are an error — enforced\n // by the same exclusive-ownership policy as file collisions.\n const owned = new Map<string, { value: string; owner: string }>();\n if (p.layer) {\n mergeExclusive(owned, Object.entries(p.layer.buildMembers(leaf.requestExpr, leaf, p.ctx)), {\n owner: p.layer.name,\n describe: (name, prevOwner, owner) =>\n `api member \"${name}\" on route \"${req.routeName}\" is contributed by more than one extension (conflict between \"${prevOwner}\" and \"${owner}\").`,\n });\n }\n for (const ext of p.memberExts) {\n const extra = ext.apiMembers?.(leaf, p.ctx);\n if (!extra) continue;\n mergeExclusive(owned, Object.entries(extra), {\n owner: ext.name,\n describe: (name, prevOwner, owner) =>\n `api member \"${name}\" on route \"${req.routeName}\" is contributed by more than one extension (conflict between \"${prevOwner}\" and \"${owner}\").`,\n });\n }\n const members: Record<string, string> = {};\n for (const [name, { value }] of owned) members[name] = value;\n\n lines.push(...renderLeaf(pad, objKey, req, leaf.requestExpr, members));\n }\n\n return lines;\n}\n\n/**\n * Build the ApiRouter type-access chain for a dot-separated name.\n * e.g. 'users.list' -> \"ApiRouter['users']['list']\"\n */\nfunction buildRouterTypeAccess(name: string): string {\n const segments = splitName(name);\n return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join('')}`;\n}\n\n// ---------------------------------------------------------------------------\n// Static api.ts text blocks\n// ---------------------------------------------------------------------------\n//\n// These are pure constants — the same bytes in every emitted api.ts — so they\n// live here as module-level templates rather than being assembled line-by-line\n// inside `buildApiFile`. `RESOLVER_HELPERS` + `ROUTE_NAMESPACE` + `PATH_NAMESPACE`\n// are the populated form (resolver-backed). `EMPTY_*` are the no-routes form,\n// where there is nothing to resolve so the namespaces collapse to `never` stubs\n// and the resolver helpers are omitted entirely. The two forms are intentionally\n// distinct text (the empty `Request` is a one-liner, the populated one is not),\n// so they are separate constants rather than one parameterised template.\n\n/** Recursive resolver helpers (`_RouterAt`/`ResolveByName`/`_LeafValues`/`ResolveByPath`). */\nconst RESOLVER_HELPERS: readonly string[] = [\n // --- Recursive helper type _RouterAt: walks nested ApiRouter by dot-path ---\n 'type _RouterAt<R, P extends string> = P extends `${infer Head}.${infer Tail}`',\n ' ? Head extends keyof R ? _RouterAt<R[Head], Tail> : never',\n ' : P extends keyof R ? R[P] : never;',\n '',\n // --- ResolveByName: resolve a field from a dot-path name ---\n 'type ResolveByName<K extends string, Field extends string> = _RouterAt<ApiRouter, K> extends infer R ? Field extends keyof R ? R[Field] : never : never;',\n '',\n // --- ResolveByPath: scan all leaves for matching method + url ---\n // Flattens ApiRouter recursively and finds the entry whose method === M and url === U.\n 'type _LeafValues<T> = T extends { method: string; url: string }',\n ' ? T',\n ' : T extends object ? _LeafValues<T[keyof T]> : never;',\n '',\n 'type ResolveByPath<M extends string, U extends string, Field extends string> = _LeafValues<ApiRouter> extends infer L',\n ' ? L extends { method: M; url: U }',\n ' ? Field extends keyof L ? L[Field] : never',\n ' : never',\n ' : never;',\n '',\n];\n\n/** Populated `Route` namespace — resolves fields by dot-path name. */\nconst ROUTE_NAMESPACE: readonly string[] = [\n 'export namespace Route {',\n ' export type Response<K extends string> = ResolveByName<K, \"response\">;',\n ' export type Body<K extends string> = ResolveByName<K, \"body\">;',\n ' export type Query<K extends string> = ResolveByName<K, \"query\">;',\n ' export type Params<K extends string> = ResolveByName<K, \"params\">;',\n ' export type Error<K extends string> = ResolveByName<K, \"error\">;',\n ' export type FilterFields<K extends string> = ResolveByName<K, \"filterFields\">;',\n ' export type Request<K extends string> = {',\n ' body: Body<K>;',\n ' query: Query<K>;',\n ' params: Params<K>;',\n ' };',\n '}',\n '',\n];\n\n/** Populated `Path` namespace — resolves fields by method + url. */\nconst PATH_NAMESPACE: readonly string[] = [\n 'export namespace Path {',\n ' export type Response<M extends string, U extends string> = ResolveByPath<M, U, \"response\">;',\n ' export type Body<M extends string, U extends string> = ResolveByPath<M, U, \"body\">;',\n ' export type Query<M extends string, U extends string> = ResolveByPath<M, U, \"query\">;',\n ' export type Params<M extends string, U extends string> = ResolveByPath<M, U, \"params\">;',\n ' export type Error<M extends string, U extends string> = ResolveByPath<M, U, \"error\">;',\n ' export type FilterFields<M extends string, U extends string> = ResolveByPath<M, U, \"filterFields\">;',\n '}',\n '',\n];\n\n/** Empty-routes form: nothing to resolve, so every namespace member is `never`. */\nconst EMPTY_ROUTE_NAMESPACE: readonly string[] = [\n 'export namespace Route {',\n ' export type Response<K extends string> = never;',\n ' export type Body<K extends string> = never;',\n ' export type Query<K extends string> = never;',\n ' export type Params<K extends string> = never;',\n ' export type Error<K extends string> = never;',\n ' export type FilterFields<K extends string> = never;',\n ' export type Request<K extends string> = { body: never; query: never; params: never };',\n '}',\n '',\n];\n\nconst EMPTY_PATH_NAMESPACE: readonly string[] = [\n 'export namespace Path {',\n ' export type Response<M extends string, U extends string> = never;',\n ' export type Body<M extends string, U extends string> = never;',\n ' export type Query<M extends string, U extends string> = never;',\n ' export type Params<M extends string, U extends string> = never;',\n ' export type Error<M extends string, U extends string> = never;',\n ' export type FilterFields<M extends string, U extends string> = never;',\n '}',\n '',\n];\n\n// ---------------------------------------------------------------------------\n// Main builder\n// ---------------------------------------------------------------------------\n\nfunction buildApiFile(\n routes: RouteDescriptor[],\n outDir?: string,\n opts: ApiEmitOptions = {},\n): string {\n const fetcherImportPath = opts.fetcherImportPath;\n const extensions = opts.extensions ?? [];\n const { layer } = resolveApiSlots(extensions);\n const memberExts = extensions.filter((e) => e.apiMembers);\n const headerExts = extensions.filter((e) => e.apiHeader);\n const contracted = routes.filter((r) => r.contract);\n\n // Extension context for the api.ts hooks. `generate()` passes the real one; standalone\n // `emitApi` calls (tests) get a minimal context exposing the routes (all the bundled\n // layer/transport read). `project()` is unavailable in the standalone path.\n const ctx: ExtensionContext =\n opts.ctx ??\n ({\n cwd: outDir ?? '',\n outDir: outDir ?? '',\n routes,\n config: {} as never,\n project: () => {\n throw new Error('ExtensionContext.project() is unavailable in standalone emitApi.');\n },\n } satisfies ExtensionContext);\n\n // Collect all type refs for import generation\n const importsByFile = new Map<string, Set<string>>();\n for (const r of contracted) {\n const cs = r.contract?.contractSource;\n if (!cs) continue;\n // When controllerRef exists, response uses ReturnType<import(...)> — skip response import\n const refs = r.controllerRef\n ? [cs.queryRef, cs.bodyRef]\n : [cs.queryRef, cs.bodyRef, cs.responseRef];\n for (const ref of refs) {\n if (!ref) continue;\n let names = importsByFile.get(ref.filePath);\n if (!names) {\n names = new Set();\n importsByFile.set(ref.filePath, names);\n }\n names.add(ref.name);\n }\n // Named enum / type-alias / interface refs inferred from @FilterFor method\n // params (the type map M references them by name → emit `import type` too).\n for (const ft of cs.filterFieldTypes ?? []) {\n if (!ft.typeRef) continue;\n let names = importsByFile.get(ft.typeRef.filePath);\n if (!names) {\n names = new Set();\n importsByFile.set(ft.typeRef.filePath, names);\n }\n names.add(ft.typeRef.name);\n }\n }\n\n const lines: string[] = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.', ''];\n\n // Extension-contributed module imports (client layer + apiHeader), deduped and emitted\n // in order. e.g. the TanStack layer emits its queryOptions/mutationOptions import here.\n const extImports: string[] = [];\n const seenImports = new Set<string>();\n const pushImport = (imp: string): void => {\n if (seenImports.has(imp)) return;\n seenImports.add(imp);\n extImports.push(imp);\n };\n for (const imp of layer?.imports?.(ctx) ?? []) pushImport(imp);\n for (const ext of headerExts) {\n for (const imp of ext.apiHeader?.(ctx)?.imports ?? []) pushImport(imp);\n }\n lines.push(...extImports);\n\n lines.push(\n \"import { route, ROUTES, type RouteName, type ExtractParams, type RouteParams } from './routes.js';\",\n );\n // Tuyau-style: the api is a factory that takes the fetcher at runtime, so the\n // app injects its own client (custom transport/axios, baseUrl, superjson) —\n // rather than the codegen hardcoding `import { fetcher } from '<path>'`.\n const runtimeImport = fetcherImportPath ?? '@dudousxd/nestjs-client';\n lines.push(`import type { Fetcher } from '${runtimeImport}';`);\n\n // Emit type imports from source files.\n // When two different files export the same type name, alias the duplicate\n // to avoid `Identifier has already been declared` parse errors.\n if (importsByFile.size > 0 && outDir) {\n lines.push('');\n const emittedNames = new Set<string>();\n for (const [filePath, names] of importsByFile) {\n // Bare module specifier (node_modules package) → import as-is. Local\n // source files are always absolute paths → compute a relative import.\n let relPath: string;\n if (isAbsolute(filePath)) {\n relPath = relative(outDir, filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n } else {\n relPath = filePath;\n }\n const specifiers: string[] = [];\n for (const name of [...names].sort()) {\n if (emittedNames.has(name)) {\n const alias = `${name}_${emittedNames.size}`;\n specifiers.push(`${name} as ${alias}`);\n emittedNames.add(alias);\n } else {\n specifiers.push(name);\n emittedNames.add(name);\n }\n }\n lines.push(`import type { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n }\n lines.push('');\n\n if (contracted.length === 0) {\n lines.push('export type ApiRouter = Record<string, never>;');\n lines.push('');\n lines.push('export function createApi(_fetcher: Fetcher): Record<string, never> {');\n lines.push(' return {};');\n lines.push('}');\n lines.push('export type Api = ReturnType<typeof createApi>;');\n lines.push('');\n lines.push(...EMPTY_ROUTE_NAMESPACE);\n lines.push(...EMPTY_PATH_NAMESPACE);\n return lines.join('\\n');\n }\n\n // Build a nested tree from all contracted routes\n const tree = new Map<string, TreeNode>();\n\n for (const r of contracted) {\n const c = r.contract!;\n const name: string = r.name;\n const segments = splitName(name);\n // Validate each segment is a valid camelCase identifier\n for (const seg of segments) {\n validateNameSegment(seg, name);\n }\n const leaf: LeafEntry = {\n kind: 'leaf',\n method: r.method,\n name: name,\n path: r.path,\n params: r.params,\n controllerRef: r.controllerRef,\n contractSource: c.contractSource,\n route: r,\n };\n insertIntoTree(tree, segments, leaf, name);\n }\n\n // --- ApiRouter type ---\n lines.push('export type ApiRouter = {');\n lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ''));\n lines.push('};');\n lines.push('');\n\n // --- awaitable request handle helper ---\n lines.push(...emitReqHelper());\n\n // --- api factory (inject your fetcher at runtime) ---\n lines.push('export function createApi(fetcher: Fetcher) {');\n lines.push(' return {');\n lines.push(\n ...emitApiObjectBlock(tree, 4, {\n ...(layer ? { layer } : {}),\n memberExts,\n ctx,\n }),\n );\n lines.push(' };');\n lines.push('}');\n lines.push('');\n lines.push('export type Api = ReturnType<typeof createApi>;');\n lines.push('');\n\n lines.push(...RESOLVER_HELPERS);\n lines.push(...ROUTE_NAMESPACE);\n lines.push(...PATH_NAMESPACE);\n\n // Extension-contributed top-level statements (e.g. the Inertia extension's navigate()).\n for (const ext of headerExts) {\n const statements = ext.apiHeader?.(ctx)?.statements;\n if (statements?.length) {\n lines.push(...statements, '');\n }\n }\n\n return lines.join('\\n');\n}\n","import { Project } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\nimport { CodegenError } from '../exceptions.js';\nimport type { ApiClientLayer, CodegenExtension, EmittedFile, ExtensionContext } from './types.js';\n\n/**\n * Resolve the single-slot `apiClientLayer` hook. At most one extension may claim it;\n * a second claimer throws a {@link CodegenError} naming both extensions. An unclaimed\n * `apiClientLayer` means leaves stay bare callables backed by the neutral fetcher.\n */\nexport function resolveApiSlots(extensions: readonly CodegenExtension[]): {\n layer?: ApiClientLayer;\n} {\n let layer: ApiClientLayer | undefined;\n let layerOwner: string | undefined;\n\n for (const ext of extensions) {\n if (ext.apiClientLayer) {\n if (layer) {\n throw new CodegenError(\n `api client layer claimed by both \"${layerOwner}\" and \"${ext.name}\" — only one extension may set apiClientLayer.`,\n );\n }\n layer = ext.apiClientLayer;\n layerOwner = ext.name;\n }\n }\n\n return {\n ...(layer ? { layer } : {}),\n };\n}\n\n/** Output filenames the core always owns — an extension emitting one of these is an error. */\nconst CORE_FILES = new Set(['routes.ts', 'api.ts', 'forms.ts', 'index.d.ts', 'pages.d.ts']);\n\n/**\n * Merge `incoming` entries into `target`, enforcing a single exclusive-ownership policy:\n * a key already present in `target` is a collision and throws, naming the prior owner and\n * the offending extension. One collision format for every \"two extensions both produced X\"\n * case (api members, emitted files, …).\n *\n * @param target the accumulating map (key → value); also records ownership.\n * @param incoming entries the current extension contributes.\n * @param owner the extension currently contributing (named in the error).\n * @param describe builds the error message given the colliding key, prior owner and owner.\n */\nexport function mergeExclusive<V>(\n target: Map<string, { value: V; owner: string }>,\n incoming: Iterable<readonly [string, V]>,\n {\n owner,\n describe,\n }: {\n owner: string;\n describe: (key: string, prevOwner: string, owner: string) => string;\n },\n): void {\n for (const [key, value] of incoming) {\n const prev = target.get(key);\n if (prev !== undefined) {\n throw new CodegenError(describe(key, prev.owner, owner));\n }\n target.set(key, { value, owner });\n }\n}\n\n/**\n * Build the shared {@link ExtensionContext}. `routes` is exposed as a live getter so an\n * extension reading `ctx.routes` during `emitFiles` sees the post-`transformRoutes` IR.\n * The ts-morph `Project` is created lazily on first `project()` call (extensions that do\n * no AST work never pay for it).\n */\nexport function createExtensionContext(\n config: ResolvedConfig,\n getRoutes: () => readonly RouteDescriptor[],\n): ExtensionContext {\n let project: Project | undefined;\n return {\n cwd: config.codegen.cwd,\n outDir: config.codegen.outDir,\n config,\n get routes() {\n return getRoutes();\n },\n project() {\n if (!project) {\n project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipLoadingLibFiles: true,\n skipFileDependencyResolution: true,\n compilerOptions: { allowJs: true, strict: false },\n });\n }\n return project;\n },\n };\n}\n\n/**\n * Run every extension's `transformRoutes` hook in registration order, chaining the\n * result (each sees the previous output). An extension may mutate in place and return\n * void, or return a new array.\n */\nexport async function applyTransformRoutes(\n routes: RouteDescriptor[],\n extensions: readonly CodegenExtension[],\n ctx: ExtensionContext,\n): Promise<RouteDescriptor[]> {\n let current = routes;\n for (const ext of extensions) {\n if (!ext.transformRoutes) continue;\n const result = await ext.transformRoutes(current, ctx);\n if (Array.isArray(result)) current = result;\n }\n return current;\n}\n\n/**\n * Run every extension's `emitFiles` hook and return the accumulated files. Throws a\n * {@link CodegenError} if two extensions emit the same path, or if an extension tries to\n * emit a core-owned file. Paths are normalized to forward slashes for collision checks.\n */\nexport async function collectEmittedFiles(\n extensions: readonly CodegenExtension[],\n ctx: ExtensionContext,\n): Promise<EmittedFile[]> {\n const files: EmittedFile[] = [];\n const owners = new Map<string, { value: EmittedFile; owner: string }>();\n\n for (const ext of extensions) {\n if (!ext.emitFiles) continue;\n const emitted = await ext.emitFiles(ctx);\n for (const file of emitted) {\n const key = file.path.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n if (CORE_FILES.has(key)) {\n throw new CodegenError(\n `Extension \"${ext.name}\" tried to emit the core-owned file \"${file.path}\". Core files (${[...CORE_FILES].join(', ')}) cannot be produced by extensions.`,\n );\n }\n mergeExclusive(owners, [[key, file] as const], {\n owner: ext.name,\n describe: (_key, prevOwner, owner) =>\n `Output file \"${file.path}\" is emitted by both \"${prevOwner}\" and \"${owner}\". Two extensions cannot write the same file.`,\n });\n files.push(file);\n }\n }\n\n return files;\n}\n","import type { Project } from 'ts-morph';\nimport type { ResolvedConfig } from '../config/types.js';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * The published, versioned extension contract for `@dudousxd/nestjs-codegen`.\n *\n * Extensions are **build-time** objects (usually returned by a factory so they can take\n * options) registered explicitly via `forRoot({ extensions: [...] })`. The host runs them\n * around the core discovery → IR → emit pipeline.\n *\n * Hooks split into **multi** (every extension runs; results accumulate or chain) and\n * **single-slot** (at most one extension may claim it — two claimers is a hard error).\n *\n * @remarks Semver 0.x — the shape may change until 1.0. Out-of-repo extensions should pin\n * a compatible `@dudousxd/nestjs-codegen` peer range.\n */\nexport interface CodegenExtension {\n /** Unique id. Used in conflict/collision errors and for deterministic ordering. */\n name: string;\n\n // ── multi hooks (every extension runs) ────────────────────────────────────\n\n /**\n * Mutate/augment the route IR before emit. Runs in registration order, chained\n * (each extension sees the previous one's output). Return the new array, or mutate\n * in place and return void. Example: the filter extension attaches `filterFields` to\n * matching routes here.\n */\n transformRoutes?(\n routes: RouteDescriptor[],\n ctx: ExtensionContext,\n ): RouteDescriptor[] | undefined | Promise<RouteDescriptor[] | undefined>;\n\n /**\n * Contribute extra output files (additive). Paths are relative to `outDir`; a path\n * claimed by two extensions is a hard error. Example: the Inertia extension does its\n * own page discovery via `ctx.project()` and emits `pages.d.ts` + `components.json`.\n */\n emitFiles?(ctx: ExtensionContext): EmittedFile[] | Promise<EmittedFile[]>;\n\n /**\n * Contribute top-level code to `api.ts` (imports + statements). Runs in registration\n * order; imports are deduped by the host. Example: the Inertia extension adds\n * `import { router } from '@inertiajs/react'` and the `navigate()` helper.\n */\n apiHeader?(ctx: ExtensionContext): ApiHeaderContribution | undefined;\n\n /**\n * Add named members to a **handle** leaf. Only runs when a client layer is active\n * (i.e. the leaf is a handle, not a bare callable). Member-name collisions across\n * extensions are a hard error. Example: the filter extension adds `filterQuery` to\n * leaves whose route carries `filterFields`.\n */\n apiMembers?(leaf: LeafModel, ctx: ExtensionContext): Record<string, string> | undefined;\n\n // ── single-slot hooks (at most one extension) ─────────────────────────────\n\n /**\n * Claims **what** a leaf returns and **how** it issues its request. At most one extension\n * may claim it. When unset, a leaf is a bare awaitable callable backed by the neutral\n * fetcher. Example: the TanStack extension wraps each leaf into a handle exposing\n * `{ fetch, queryKey, queryOptions | mutationOptions }`, composing with the fetcher\n * request the host passes in.\n */\n apiClientLayer?: ApiClientLayer;\n}\n\n/** Shared, read-only context handed to every extension hook. */\nexport interface ExtensionContext {\n cwd: string;\n outDir: string;\n routes: readonly RouteDescriptor[];\n config: ResolvedConfig;\n /** Lazily-created shared ts-morph Project for AST work (pages, custom decorators). */\n project(): Project;\n}\n\n/** A file contributed by an extension's `emitFiles` hook. */\nexport interface EmittedFile {\n /** Path relative to `outDir`. A collision across extensions throws. */\n path: string;\n contents: string;\n}\n\n/** Top-level `api.ts` contributions from an extension's `apiHeader` hook. */\nexport interface ApiHeaderContribution {\n /** Raw import lines (e.g. `import { router } from '@inertiajs/react';`), deduped by the host. */\n imports?: string[];\n /** Top-level statements appended after the api factory (e.g. the `navigate()` helper). */\n statements?: string[];\n}\n\n/**\n * The neutral, per-endpoint request model the host builds for each leaf before any\n * transport/layer runs. Extensions read this to render their output.\n */\nexport interface RequestModel {\n /** Dot-path route name, e.g. `users.show`. */\n routeName: string;\n method: 'get' | 'post' | 'put' | 'patch' | 'delete';\n isGet: boolean;\n /** True for reads: a GET, or a filter-search route (has `filterFields`) even when POST.\n * Client layers use this (not `isGet`) to decide query vs mutation helpers. */\n isQuery: boolean;\n hasParams: boolean;\n hasBody: boolean;\n /** Type of the leaf's `input` arg, e.g. `{ params: ...; query?: ... }` or `Record<string, never>`. */\n inputType: string;\n /** URL expression, e.g. `route('users.show', input?.params) || '/api/users/:id'`. */\n urlExpr: string;\n /** Request-options expression, e.g. `{ query: ... }` or `{ body: input?.body }`. */\n optsExpr: string;\n /** Response type access, e.g. `ApiRouter['users']['show']['response']`. */\n responseType: string;\n /** Stable query-key expression, e.g. `[\"users.show\", input] as const`. */\n queryKeyExpr: string;\n}\n\n/**\n * Per-leaf model passed through the api.ts pipeline: layer → member contributors → render.\n * `requestExpr` is the host's neutral fetcher request; `members`, when present, flips the\n * leaf from a bare callable to a handle.\n */\nexport interface LeafModel {\n route: RouteDescriptor;\n request: RequestModel;\n /** The expression that issues the request (the host's neutral fetcher call). */\n requestExpr: string;\n /** When present, the leaf renders as a handle exposing these members (ordered). */\n members?: Record<string, string>;\n}\n\n/**\n * Top-level `api.ts` imports a client layer depends on. A function of the context so it can\n * be route-aware (e.g. only import `mutationOptions` when a mutation exists). Imports are\n * deduped by the host across all extensions.\n */\nexport interface ApiModuleDeps {\n /** Raw import lines (e.g. `import { queryOptions as _q } from '@tanstack/react-query';`). */\n imports?(ctx: ExtensionContext): string[];\n}\n\n/** Single-slot: decides what a leaf returns (the handle members). */\nexport interface ApiClientLayer extends ApiModuleDeps {\n name: string;\n /**\n * Given the request expression (from the transport) and the leaf, return the handle's\n * members as an ordered `name → value` map (value is the expression after `name: `).\n * Returning members flips the leaf from a bare callable to a handle.\n */\n buildMembers(requestExpr: string, leaf: LeafModel, ctx: ExtensionContext): Record<string, string>;\n}\n\n/**\n * The four request-shape flags derived from a route's method + contract. Computed in ONE\n * place ({@link requestShape}) and read by both the host emitter and client-layer\n * extensions, so the \"filter-search POST counts as a read\" rule is encoded exactly once.\n */\nexport interface RequestShape {\n /** The route is a `GET`. */\n isGet: boolean;\n /** True for reads: a GET, or a filter-search route (carries `filterFields`) even when POST.\n * Client layers use this (not `isGet`) to decide query vs mutation helpers. */\n isQuery: boolean;\n /** The route carries a body contract (a mutation payload). */\n hasBody: boolean;\n /** The route can take a query string — always for GET; a mutation may too (query + body). */\n hasQuery: boolean;\n}\n\n/**\n * Compute the {@link RequestShape} flags for a route from its method and contract. This is\n * the SINGLE source of truth for these flags — `buildRequestModel`, the TanStack layer's\n * `imports()`, and any other reader must call this rather than re-deriving. The\n * \"filter-search POST counts as a read\" rule lives here and nowhere else.\n */\nexport function requestShape(route: RouteDescriptor): RequestShape {\n const cs = route.contract?.contractSource;\n const isGet = route.method.toUpperCase() === 'GET';\n const isQuery = isGet || !!cs?.filterFields?.length;\n const hasBody = !!cs?.bodyRef || (cs?.body != null && cs.body !== 'never');\n const hasQuery = isGet || !!cs?.queryRef || (cs?.query != null && cs.query !== 'never');\n return { isGet, isQuery, hasBody, hasQuery };\n}\n\n/** Identity helper for authoring extensions with full type inference. */\nexport function defineExtension(ext: CodegenExtension): CodegenExtension {\n return ext;\n}\n","import { mkdir, stat, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\n\nexport interface CacheEntry {\n name: string;\n relativePath: string;\n mtime: string;\n}\n\nexport interface ComponentsCache {\n pages: CacheEntry[];\n}\n\nexport async function emitCache(pages: DiscoveredPage[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const entries: CacheEntry[] = await Promise.all(\n pages.map(async (p) => {\n const s = await stat(p.absolutePath);\n return {\n name: p.name,\n relativePath: p.relativePath,\n mtime: s.mtime.toISOString(),\n };\n }),\n );\n const cache: ComponentsCache = { pages: entries };\n await writeFile(join(outDir, 'components.json'), `${JSON.stringify(cache, null, 2)}\\n`, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { ValidationAdapter } from '../adapters/types.js';\nimport type { ResolvedFormsConfig } from '../config/types.js';\nimport type { RouteDescriptor, TypeRef } from '../discovery/types.js';\n\n/**\n * Emits `forms.ts` into `outDir`. Every validatable route is rendered through a\n * single {@link ValidationAdapter} path (IR → `adapter.renderModule`). The adapter\n * is required — `validation` is a mandatory config field.\n *\n * Two schema sources exist per route:\n * - Neutral IR (`bodySchema`/`querySchema`) synthesized from class-validator\n * DTOs — renderable through ANY adapter.\n * - Hand-written zod from `defineContract` (`bodyZodText`/`queryZodText` raw\n * source, or `bodyZodRef`/`queryZodRef` re-exports). This is genuine zod\n * source with no IR; it passes through verbatim only when the adapter sets\n * `acceptsRawZodSource` (the zod adapter), and is skipped with a warning\n * under any other adapter.\n *\n * Returns `true` when a `forms.ts` was written (drives the index export).\n */\nexport async function emitForms(\n routes: RouteDescriptor[],\n outDir: string,\n config: ResolvedFormsConfig | undefined,\n adapter: ValidationAdapter,\n): Promise<boolean> {\n if (config && config.enabled === false) return false;\n\n const content = buildFormsFileWithAdapter(routes, outDir, adapter, config);\n if (content === null) return false;\n await mkdir(outDir, { recursive: true });\n await writeFile(join(outDir, 'forms.ts'), content, 'utf8');\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** PascalCase from a single dot/identifier segment. */\nfunction pascal(segment: string): string {\n return segment\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('');\n}\n\n/**\n * PascalCase base name for a route. Uses the method segment (last dot-part);\n * the full dotted name is used to disambiguate collisions.\n */\nfunction deriveBaseName(routeName: string): { method: string; full: string } {\n const segments = routeName.split('.');\n const method = pascal(segments[segments.length - 1] ?? routeName);\n const full = segments.map(pascal).join('');\n return { method, full };\n}\n\n/** Relative import specifier from outDir to a source file (no extension). */\nfunction relImport(outDir: string, filePath: string): string {\n let relPath = relative(outDir, filePath).replace(/\\.ts$/, '');\n if (!relPath.startsWith('.')) relPath = `./${relPath}`;\n return relPath;\n}\n\n/** The root identifier of a ref name like `loginContract.body` → `loginContract`. */\nfunction refRootIdentifier(refName: string): string {\n return refName.split('.')[0] ?? refName;\n}\n\n/**\n * A renderable form schema source. The IR is preferred (works through any\n * adapter); `zodText`/`zodRef` are the zod-only `defineContract` fallbacks.\n */\ninterface FormSource {\n /** Neutral IR — rendered via the active adapter. */\n schema?: import('../ir/schema-node.js').SchemaModule | null;\n /** Raw zod source text (defineContract inline / synthesized). */\n zodText?: string | null;\n /** Importable named const re-export (defineContract Path A). */\n zodRef?: TypeRef | null;\n}\n\nfunction hasSource(src: FormSource): boolean {\n return !!(src.schema || src.zodText || src.zodRef);\n}\n\n// ---------------------------------------------------------------------------\n// Nested-schema hoisting: dedup + collision disambiguation + recursion guard.\n// (Used for the zod-only `formNestedSchemas` text path.)\n// ---------------------------------------------------------------------------\n\ninterface FormEntry {\n routeName: string;\n baseName: string;\n body: FormSource | undefined;\n query: FormSource | undefined;\n /** zod-only nested schemas (name → zod text) for the text path. */\n nestedSchemas: Record<string, string> | null;\n warnings: string[];\n}\n\ninterface NestedSchemaPlan {\n globalSchemas: Map<string, string>;\n renamesByEntry: Map<FormEntry, Map<string, string>>;\n}\n\nfunction applyRenames(text: string, renames: Map<string, string> | null): string {\n if (!renames || renames.size === 0) return text;\n let out = text;\n for (const [from, to] of renames) {\n if (from === to) continue;\n out = out.replace(new RegExp(`\\\\b${escapeRegExp(from)}\\\\b`, 'g'), to);\n }\n return out;\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isSelfReferential(name: string, text: string): boolean {\n return new RegExp(`\\\\b${escapeRegExp(name)}\\\\b`).test(text);\n}\n\n/**\n * Build the global hoist registry + per-entry renames for zod-only nested\n * schema texts. See the original design notes: each unique (name, shape) is\n * declared once; same-name different-shape is suffixed; recursion is degraded.\n */\nfunction planNestedSchemas(entries: FormEntry[]): NestedSchemaPlan {\n const globalSchemas = new Map<string, string>();\n const renamesByEntry = new Map<FormEntry, Map<string, string>>();\n\n for (const entry of entries) {\n if (!entry.nestedSchemas) continue;\n const local = Object.entries(entry.nestedSchemas);\n if (local.length === 0) continue;\n\n const rename = new Map<string, string>();\n for (const [name] of local) rename.set(name, name);\n\n const textFor = (name: string): string => {\n const raw = entry.nestedSchemas?.[name] ?? '';\n return applyRenames(raw, rename);\n };\n\n let changed = true;\n let guard = 0;\n while (changed && guard < local.length + 2) {\n changed = false;\n guard += 1;\n for (const [name] of local) {\n const finalName = rename.get(name) ?? name;\n const text = textFor(name);\n const existing = globalSchemas.get(finalName);\n if (existing === undefined) continue;\n if (existing === text) continue;\n let i = 2;\n let candidate = `${name}_${i}`;\n while (\n (globalSchemas.has(candidate) && globalSchemas.get(candidate) !== textFor(name)) ||\n [...rename.values()].includes(candidate)\n ) {\n i += 1;\n candidate = `${name}_${i}`;\n }\n rename.set(name, candidate);\n changed = true;\n }\n }\n\n for (const [name] of local) {\n const finalName = rename.get(name) ?? name;\n let text = textFor(name);\n if (isSelfReferential(finalName, text)) {\n text = 'z.unknown() /* recursive type — not expanded */';\n }\n const existing = globalSchemas.get(finalName);\n if (existing === undefined) {\n globalSchemas.set(finalName, text);\n }\n }\n\n renamesByEntry.set(entry, rename);\n }\n\n return { globalSchemas, renamesByEntry };\n}\n\n// ---------------------------------------------------------------------------\n// Single adapter-driven forms builder\n// ---------------------------------------------------------------------------\n\n/**\n * Render `forms.ts` from the neutral validation IR via `adapter`, plus the\n * zod-only `defineContract` text/ref fallbacks (zod adapter only). Returns\n * `null` when nothing to emit.\n */\nfunction buildFormsFileWithAdapter(\n routes: RouteDescriptor[],\n outDir: string,\n adapter: ValidationAdapter,\n config?: ResolvedFormsConfig,\n): string | null {\n const acceptsRawZod = adapter.acceptsRawZodSource === true;\n const sorted = [...routes].filter((r) => r.contract).sort((a, b) => a.name.localeCompare(b.name));\n\n // Base-name collision pass (method-only name vs full dotted name).\n const methodNameCounts = new Map<string, number>();\n const candidates: FormEntry[] = [];\n for (const route of sorted) {\n const cs = route.contract!.contractSource;\n const body: FormSource = {\n schema: cs.bodySchema ?? null,\n zodText: cs.bodyZodText ?? null,\n zodRef: cs.bodyZodRef ?? null,\n };\n const query: FormSource = {\n schema: cs.querySchema ?? null,\n zodText: cs.queryZodText ?? null,\n zodRef: cs.queryZodRef ?? null,\n };\n if (!hasSource(body) && !hasSource(query)) continue;\n const { method, full } = deriveBaseName(route.name);\n methodNameCounts.set(method, (methodNameCounts.get(method) ?? 0) + 1);\n candidates.push({\n routeName: route.name,\n baseName: full, // resolved below\n body: hasSource(body) ? body : undefined,\n query: hasSource(query) ? query : undefined,\n nestedSchemas: cs.formNestedSchemas ?? null,\n warnings: cs.formWarnings ?? [],\n });\n }\n\n const entries: FormEntry[] = candidates.map((c) => {\n const { method, full } = deriveBaseName(c.routeName);\n const collision = (methodNameCounts.get(method) ?? 0) > 1;\n return { ...c, baseName: collision ? full : method };\n });\n\n if (entries.length === 0) return null;\n\n // Re-export imports (zod-only refs without inline text), grouped by file.\n const importsByFile = new Map<string, Set<string>>();\n const refAlias = new Map<string, string>();\n for (const entry of entries) {\n for (const src of [entry.body, entry.query]) {\n if (src?.zodRef && !src.zodText && !src.schema) {\n const root = refRootIdentifier(src.zodRef.name);\n const set = importsByFile.get(src.zodRef.filePath) ?? new Set<string>();\n set.add(root);\n importsByFile.set(src.zodRef.filePath, set);\n }\n }\n }\n\n const importLines: string[] = [];\n if (importsByFile.size > 0) {\n const emitted = new Set<string>();\n for (const [filePath, roots] of [...importsByFile.entries()].sort()) {\n const relPath = relImport(outDir, filePath);\n const specifiers: string[] = [];\n for (const root of [...roots].sort()) {\n if (emitted.has(root)) {\n const alias = `${root}_${emitted.size}`;\n specifiers.push(`${root} as ${alias}`);\n emitted.add(alias);\n refAlias.set(`${filePath}\\0${root}`, alias);\n } else {\n specifiers.push(root);\n emitted.add(root);\n refAlias.set(`${filePath}\\0${root}`, root);\n }\n }\n importLines.push(`import { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n }\n\n // Hoist zod-only nested schemas (text path) once, with collision handling.\n const { globalSchemas, renamesByEntry } = planNestedSchemas(entries);\n\n // Hoisted IR nested schemas (rendered via adapter, deduped by name).\n const irNamed = new Map<string, string>();\n const decls: string[] = [];\n const mapEntries: string[] = [];\n let used = false;\n\n const renderSource = (\n src: FormSource,\n rename: Map<string, string> | null,\n ): { text: string; warn?: string } | null => {\n // Prefer the neutral IR — works through any adapter.\n if (src.schema) {\n const r = adapter.renderModule(src.schema);\n for (const [n, t] of r.namedNestedSchemas) irNamed.set(n, t);\n return { text: r.schemaText };\n }\n // zod-only defineContract fallbacks: text or re-export ref.\n if (src.zodText) {\n if (!acceptsRawZod) {\n return {\n text: '',\n warn: `is a defineContract (zod) schema; not translated to ${adapter.name} — use the zod adapter.`,\n };\n }\n return { text: applyRenames(src.zodText, rename) };\n }\n if (src.zodRef) {\n if (!acceptsRawZod) {\n return {\n text: '',\n warn: `is a defineContract (zod) schema; not translated to ${adapter.name} — use the zod adapter.`,\n };\n }\n const root = refRootIdentifier(src.zodRef.name);\n const alias = refAlias.get(`${src.zodRef.filePath}\\0${root}`) ?? root;\n const member = src.zodRef.name.slice(root.length);\n return { text: `${alias}${member}` };\n }\n return null;\n };\n\n for (const entry of entries) {\n const block: string[] = [];\n const rename = renamesByEntry.get(entry) ?? null;\n let bodyConst: string | undefined;\n\n if (entry.warnings && entry.warnings.length > 0) {\n for (const w of entry.warnings) block.push(`// warning: ${w}`);\n }\n\n if (entry.body) {\n const rendered = renderSource(entry.body, rename);\n if (rendered?.warn) {\n block.push(`// warning: ${entry.routeName} body ${rendered.warn}`);\n } else if (rendered) {\n used = true;\n bodyConst = `${entry.baseName}BodySchema`;\n block.push(`export const ${bodyConst} = ${rendered.text};`);\n block.push(`export type ${entry.baseName}Body = ${adapter.inferType(bodyConst)};`);\n }\n }\n if (entry.query) {\n const rendered = renderSource(entry.query, rename);\n if (rendered?.warn) {\n block.push(`// warning: ${entry.routeName} query ${rendered.warn}`);\n } else if (rendered) {\n used = true;\n const queryConst = `${entry.baseName}QuerySchema`;\n block.push(`export const ${queryConst} = ${rendered.text};`);\n block.push(`export type ${entry.baseName}Query = ${adapter.inferType(queryConst)};`);\n }\n }\n\n if (block.length === 0) continue;\n decls.push(`// ${entry.routeName}`, ...block, '');\n if (bodyConst) mapEntries.push(` ${JSON.stringify(entry.routeName)}: ${bodyConst},`);\n }\n\n if (!used) return null;\n\n const lines: string[] = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.'];\n if (acceptsRawZod) {\n const zodImport = config?.zodImport ?? 'zod';\n lines.push(`import { z } from '${zodImport}';`);\n } else {\n for (const imp of adapter.importStatements({ used: true })) lines.push(imp);\n }\n lines.push(...importLines);\n lines.push('');\n\n // Merge hoisted nested schemas: zod-only text path + IR-rendered nested.\n const allNested = new Map<string, string>();\n for (const [n, t] of globalSchemas) allNested.set(n, t);\n for (const [n, t] of irNamed) if (!allNested.has(n)) allNested.set(n, t);\n\n if (allNested.size > 0) {\n lines.push('// Hoisted nested schemas (shared across endpoints).');\n for (const [n, t] of allNested) lines.push(`const ${n} = ${t};`);\n lines.push('');\n }\n\n lines.push(...decls);\n lines.push('/** Route name → body schema map. */');\n lines.push('export const formSchemas = {');\n lines.push(...mapEntries);\n lines.push('} as const;');\n lines.push('');\n return lines.join('\\n');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function emitIndex(\n outDir: string,\n hasContracts = false,\n hasForms = false,\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n const exports = [\"export * from './pages.js';\", \"export * from './routes.js';\"];\n if (hasContracts) {\n exports.push(\"export * from './api.js';\");\n }\n if (hasForms) {\n exports.push(\"export * from './forms.js';\");\n }\n const content = ['// Generated by @dudousxd/nestjs-codegen. Do not edit.', ...exports, ''].join(\n '\\n',\n );\n await writeFile(join(outDir, 'index.d.ts'), content, 'utf8');\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { DiscoveredPage } from '../discovery/pages.js';\nimport type { SharedPropsResult } from '../discovery/shared-props.js';\n\nexport interface EmitPagesOptions {\n /** The export name to reference in import() type expressions (default: 'ComponentProps'). */\n propsExport?: string;\n /** When true, infer props from the default export's first parameter instead of a named export. */\n inferFromDefault?: boolean;\n /** When provided, emit an InertiaSharedProps augmentation alongside the pages. */\n sharedProps?: SharedPropsResult | null;\n}\n\nexport async function emitPages(\n pages: DiscoveredPage[],\n outDir: string,\n _options: EmitPagesOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const pageNameUnion =\n pages.length > 0 ? pages.map((p) => JSON.stringify(p.name)).join(' | ') : 'never';\n\n const augBody = pages\n .map((p) => {\n const key = needsQuotes(p.name) ? JSON.stringify(p.name) : p.name;\n const valueType = buildAugmentationType(p, outDir);\n return ` ${key}: ${valueType};`;\n })\n .join('\\n');\n\n const propsHelper =\n \"\\nexport type InertiaProps<K extends InertiaPageName> = import('@dudousxd/nestjs-inertia').InertiaPages[K];\\n\";\n\n const sharedPropsBlock = buildSharedPropsBlock(_options.sharedProps ?? null);\n\n const content = `// Generated by @dudousxd/nestjs-codegen. Do not edit.\\n\\nexport type InertiaPageName = ${pageNameUnion};\\n${propsHelper}\\ndeclare module '@dudousxd/nestjs-inertia' {\\n interface InertiaPages {\\n${augBody}\\n }\\n${sharedPropsBlock}}\\n`;\n\n await writeFile(join(outDir, 'pages.d.ts'), content, 'utf8');\n}\n\n/**\n * Build the `InertiaSharedProps` interface augmentation block.\n * Returns an empty string when sharedProps is null (graceful fallback).\n *\n * When `isImportRef` is true, the type is expressed as a mapped type from an import reference.\n * When `properties` are available, they are emitted as individual interface members.\n */\nfunction buildSharedPropsBlock(sharedProps: SharedPropsResult | null): string {\n if (!sharedProps) return '';\n\n // isImportRef case: emit a type alias that re-exports the external type\n if (sharedProps.isImportRef) {\n return `\\n // eslint-disable-next-line @typescript-eslint/no-empty-interface\\n interface InertiaSharedProps extends ${sharedProps.typeString} {}\\n`;\n }\n\n // Inline properties case\n if (!sharedProps.properties || sharedProps.properties.length === 0) return '';\n\n const propsBody = sharedProps.properties.map((p) => ` ${p.name}: ${p.type};`).join('\\n');\n\n return `\\n interface InertiaSharedProps {\\n${propsBody}\\n }\\n`;\n}\n\n/**\n * Build the type for a page in the module augmentation.\n * Uses `Parameters<typeof import('...').default>[0]` to infer props\n * directly from the default export — no named export needed.\n */\nfunction buildAugmentationType(page: DiscoveredPage, outDir: string): string {\n let importPath = relative(outDir, page.absolutePath).replace(/\\.(tsx?|vue|svelte)$/, '');\n if (!importPath.startsWith('.')) {\n importPath = `./${importPath}`;\n }\n return `Parameters<typeof import('${importPath}').default>[0]`;\n}\n\nfunction needsQuotes(name: string): boolean {\n return !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteDescriptor } from '../discovery/types.js';\n\n/**\n * Emits `routes.ts` into `outDir` with:\n * - A `ROUTES` constant mapping name → path\n * - A `RouteName` union type of all route names\n * - A `RouteParams<K>` mapped type using template-literal `infer` to extract `:param` segments\n * - A runtime `route(name, params?)` helper that interpolates path params\n */\nexport async function emitRoutes(routes: RouteDescriptor[], outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const content = buildRoutesFile(routes);\n await writeFile(join(outDir, 'routes.ts'), content, 'utf8');\n}\n\nfunction buildRoutesFile(routes: RouteDescriptor[]): string {\n if (routes.length === 0) {\n return buildEmpty();\n }\n\n const entries = routes\n .map((r) => ` ${JSON.stringify(r.name)}: ${JSON.stringify(r.path)},`)\n .join('\\n');\n\n const routeNameUnion = routes.map((r) => ` | ${JSON.stringify(r.name)}`).join('\\n');\n\n const lines: string[] = [\n '// Generated by @dudousxd/nestjs-codegen. Do not edit.',\n '',\n '/** Map of route name → path pattern. */',\n 'export const ROUTES = {',\n entries,\n '} as const;',\n '',\n '/** Union of all known route names. */',\n 'export type RouteName =',\n `${routeNameUnion};`,\n '',\n '/**',\n ' * Extracts path-parameter names from a route path string.',\n ' * `ExtractParams<\"/users/:id\">` → `\"id\"`',\n ' */',\n 'export type ExtractParams<Path extends string> =',\n ' Path extends `${string}:${infer Param}/${infer Rest}`',\n ' ? Param | ExtractParams<`/${Rest}`>',\n ' : Path extends `${string}:${infer Param}`',\n ' ? Param',\n ' : never;',\n '',\n '/**',\n ' * Mapped type: given a `RouteName`, returns an object with each path param as `string`.',\n ' * `RouteParams<\"UsersController.show\">` → `{ id: string }`',\n ' * `RouteParams<\"UsersController.list\">` → `Record<string, never>`',\n ' */',\n 'export type RouteParams<K extends RouteName> =',\n ' ExtractParams<(typeof ROUTES)[K]> extends never',\n ' ? Record<string, never>',\n ' : { [P in ExtractParams<(typeof ROUTES)[K]>]: string };',\n '',\n '/**',\n ' * Map of every route name to its resolved params object.',\n ' * Use this for `InertiaRegistry` module augmentation.',\n ' */',\n 'export type RouteParamsMap = { [K in RouteName]: RouteParams<K> };',\n '',\n '/**',\n ' * Build a URL from a named route, interpolating path params and appending query string.',\n ' *',\n ' * @example',\n \" * route('UsersController.show', { id: '42' }) // → '/users/42'\",\n \" * route('UsersController.list') // → '/users'\",\n \" * route('users.list', undefined, { active: true }) // → '/api/users?active=true'\",\n ' */',\n 'export function route<K extends RouteName>(',\n ' name: K,',\n ' ...args: ExtractParams<(typeof ROUTES)[K]> extends never',\n ' ? [params?: undefined, query?: Record<string, unknown>]',\n ' : [params: RouteParams<K>, query?: Record<string, unknown>]',\n '): string {',\n ' const [params, query] = args as [Record<string, string> | undefined, Record<string, unknown> | undefined];',\n ' const path: string | undefined = ROUTES[name as RouteName];',\n ' if (path === undefined) {',\n \" const available = Object.keys(ROUTES).join(', ');\",\n ' throw new Error(',\n ' `[nestjs-codegen] Route \"${String(name)}\" does not exist.\\\\n\\\\n` +',\n ' `Available routes: ${available}\\\\n\\\\n` +',\n ' `This usually means:\\\\n` +',\n ' ` - The route name has a typo\\\\n` +',\n \" ` - The controller hasn't been scanned by codegen yet (run: nestjs-codegen codegen)\\\\n` +\",\n ' ` - The @As() decorator changed the route name\\\\n`',\n ' );',\n ' }',\n ' let resolvedPath: string = path;',\n ' if (params) {',\n ' resolvedPath = resolvedPath.replace(/:([^/]+)/g, (_, key) => {',\n ' const val = params[key];',\n ' if (val === undefined) throw new Error(`Missing route param: ${key}`);',\n ' return encodeURIComponent(val);',\n ' });',\n ' }',\n ' if (query && Object.keys(query).length > 0) {',\n ' const qs = new URLSearchParams();',\n ' for (const [k, v] of Object.entries(query)) {',\n ' if (v !== undefined && v !== null) qs.append(k, String(v));',\n ' }',\n ' const qStr = qs.toString();',\n ' if (qStr) {',\n \" const sep = resolvedPath.includes('?') ? '&' : '?';\",\n ' resolvedPath = `${resolvedPath}${sep}${qStr}`;',\n ' }',\n ' }',\n ' return resolvedPath;',\n '}',\n '',\n ];\n\n return lines.join('\\n');\n}\n\nfunction buildEmpty(): string {\n return [\n '// Generated by @dudousxd/nestjs-codegen. Do not edit.',\n '',\n 'export const ROUTES = {} as const;',\n 'export type RouteName = never;',\n 'export type ExtractParams<_Path extends string> = never;',\n 'export type RouteParams<_K extends RouteName> = Record<string, never>;',\n 'export function route(_name: never, _params?: undefined, _query?: Record<string, unknown>): string { return \"\"; }',\n '',\n ].join('\\n');\n}\n","import { 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":";;;;;;;;;;;;;AACA,SAAS,QAAQ,YAAY,QAAQ,cAAc;;;ACDnD,SAAS,cAAc;AACvB,SAAS,YAAY,MAAM,UAAU,SAAS,WAAW;AACzD,SAAS,qBAAqB;;;ACFvB,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;;;ACIO,SAAS,eAAe,QAA6C;AAC1E,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,QAAM,MAAM,4BAA4B,MAAM;AAC9C,QAAM,QAAQ,GAAG,MAAM;AACvB,QAAM,IAAI;AAAA,IACR,uBAAuB,MAAM,qCAAqC,GAAG;AAAA;AAAA,aAAuE,KAAK,YAAY,GAAG;AAAA,+BAAoC,KAAK;AAAA,EAC3M;AACF;;;AFiBA,SAAS,gBAAgB,KAAa,GAAmB;AACvD,MAAI,WAAW,CAAC,EAAG,QAAO;AAC1B,SAAO,QAAQ,KAAK,CAAC;AACvB;AAOA,SAAS,gBAAgB,KAAa,cAAsB,WAAyB;AACnF,QAAM,MAAM,SAAS,KAAK,YAAY;AAGtC,MAAI,IAAI,WAAW,KAAK,GAAG,EAAE,KAAK,QAAQ,QAAQ,WAAW,GAAG,GAAG;AACjE,UAAM,IAAI;AAAA,MACR,KAAK,SAAS;AAAA,iBAAsD,YAAY;AAAA,iBAAoB,GAAG;AAAA;AAAA,IACzG;AAAA,EACF;AACF;AAUO,SAAS,cAAc,YAA6B,KAA8B;AACvF,SAAO,cAAc,YAAY,OAAO,QAAQ,IAAI,CAAC;AACvD;AAiBA,SAAS,mBAAmB,YAAmC;AAE7D,MAAI,WAAW,cAAc,MAAM;AACjC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,WAAW,SAAS,OAAO,WAAW,MAAM,SAAS,UAAU;AACjE,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,cAAc,YAA6B,KAA6B;AAC/E,qBAAmB,UAAU;AAE7B,QAAM,SAAS,WAAW,SAAS,SAC/B,gBAAgB,KAAK,WAAW,QAAQ,MAAM,IAC9C,KAAK,KAAK,iBAAiB;AAE/B,QAAM,cAAc,WAAW,SAAS,MAAM,gBAAgB,KAAK,WAAW,QAAQ,GAAG,IAAI;AAE7F,MAAI,MAA6B;AACjC,MAAI,WAAW,KAAK;AAClB,UAAM,gBAAgB,gBAAgB,KAAK,WAAW,IAAI,WAAW;AACrE,oBAAgB,KAAK,eAAe,iBAAiB;AAErD,QAAI,mBAAkC;AACtC,QAAI,WAAW,IAAI,UAAU;AAC3B,yBAAmB,gBAAgB,KAAK,WAAW,IAAI,QAAQ;AAC/D,sBAAgB,KAAK,kBAAkB,cAAc;AAAA,IACvD;AAEA,UAAM;AAAA,MACJ,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO;AAAA,IACL,YAAY,WAAW,cAAc,CAAC;AAAA;AAAA,IAEtC,YAAY,eAAe,WAAW,UAAuD;AAAA,IAC7F,OAAO,WAAW,QACd;AAAA,MACE,MAAM,WAAW,MAAM;AAAA,MACvB,aAAa,WAAW,MAAM,eAAe;AAAA,MAC7C,uBAAuB,WAAW,MAAM,yBAAyB;AAAA,IACnE,IACA;AAAA,IACJ,WAAW;AAAA,MACT,MAAM,WAAW,WAAW,QAAQ;AAAA,MACpC,YAAY,WAAW,WAAW,cAAc;AAAA,IAClD;AAAA,IACA,QAAQ,WAAW,UAAU,CAAC;AAAA,IAC9B,SAAS;AAAA,MACP;AAAA,MACA,KAAK;AAAA,IACP;AAAA,IACA;AAAA,IACA,SAAS,WAAW,WAAW;AAAA,IAC/B,OAAO;AAAA,MACL,SAAS,WAAW,OAAO,WAAW;AAAA,MACtC,OAAO,WAAW,OAAO,SAAS;AAAA,MAClC,WAAW,WAAW,OAAO,aAAa;AAAA,IAC5C;AAAA,EACF;AACF;;;AG7JA,SAAS,YAAAA,iBAAgB;AACzB,SAAS,QAAAC,cAAY;AACrB,OAAO,cAAc;;;ACFrB,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,OAAO,QAAQ;AAKf;AAAA,EAGE,QAAAC;AAAA,EACA;AAAA,OAEK;;;ACZP;AAAA,EAIE,QAAAC;AAAA,EAGA,cAAAC;AAAA,OAEK;;;ACAP;AAAA,EAGE,QAAAC;AAAA,OAIK;;;AChBP,SAAS,oBAAoB;AAC7B,SAAS,SAAS,WAAAC,gBAAe;AACjC;AAAA,EAGE;AAAA,OAIK;AAsBP,IAAM,aAA+B,EAAE,aAAa,IAAI,eAAe,KAAK;AAG5E,IAAM,gBAAgB,oBAAI,QAAmC;AAGtD,SAAS,oBAAoB,SAAkB,KAA6B;AACjF,gBAAc,IAAI,SAAS,GAAG;AAChC;AAEA,SAAS,QAAQ,SAAoC;AACnD,SAAO,cAAc,IAAI,OAAO,KAAK;AACvC;AAEA,IAAM,SAAS,QAAQ,IAAI,yBAAyB;AAC7C,SAAS,OAAO,MAAiB;AACtC,MAAI,OAAQ,SAAQ,IAAI,mBAAmB,GAAG,IAAI;AACpD;AAEO,SAAS,kBAAkB,cAAuD;AACvF,MAAI;AACF,UAAM,MAAM,aAAa,cAAc,MAAM;AAE7C,UAAM,WAAW,IAAI,QAAQ,aAAa,EAAE;AAC5C,UAAM,SAAS,KAAK,MAAM,QAAQ;AAGlC,WAAO,OAAO,iBAAiB,SAAS;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAeO,SAAS,eAAe,MAAc,MAAyC;AACpF,QAAM,MAAM,KAAK,SAAS,IAAI;AAC9B,MAAI,IAAK,QAAO,EAAE,MAAM,SAAS,MAAM,KAAK,KAAK;AAEjD,QAAM,QAAQ,KAAK,aAAa,IAAI;AACpC,MAAI,MAAO,QAAO,EAAE,MAAM,aAAa,MAAM,OAAO,KAAK;AAEzD,QAAM,QAAQ,KAAK,aAAa,IAAI;AACpC,MAAI,OAAO;AACT,UAAM,WAAW,MAAM,YAAY;AACnC,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,MAAM,WAAW,SAAS,QAAQ,IAAI;AAAA,IACxC;AAAA,EACF;AAEA,QAAM,WAAW,KAAK,QAAQ,IAAI;AAClC,MAAI,UAAU;AACZ,UAAM,UAAU,SAAS,WAAW,EAAE,IAAI,CAAC,MAAM;AAC/C,YAAM,MAAM,EAAE,SAAS;AAIvB,UAAI,OAAO,QAAQ,YAAY,OAAO,QAAQ,SAAU,QAAO,KAAK,UAAU,GAAG;AACjF,aAAO,KAAK,UAAU,EAAE,QAAQ,CAAC;AAAA,IACnC,CAAC;AACD,WAAO,EAAE,MAAM,QAAQ,QAAQ;AAAA,EACjC;AAEA,SAAO;AACT;AAKO,SAAS,uBACd,iBACA,YACA,SACU;AACV,MAAI,gBAAgB,WAAW,GAAG,GAAG;AACnC,UAAM,MAAM,QAAQ,WAAW,YAAY,CAAC;AAG5C,UAAM,QAAQ,gBAAgB,QAAQ,cAAc,EAAE;AACtD,WAAO;AAAA,MACLA,SAAQ,KAAK,GAAG,KAAK,KAAK;AAAA,MAC1BA,SAAQ,KAAK,GAAG,eAAe,KAAK;AAAA,MACpCA,SAAQ,KAAK,iBAAiB,UAAU;AAAA,IAC1C;AAAA,EACF;AAGA,QAAM,MAAM,QAAQ,OAAO;AAC3B,QAAM,UAAU,IAAI;AACpB,QAAM,gBAAgB,IAAI;AAE1B;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,UAAU,aAAa;AAAA,IAC5B;AAAA,IACA;AAAA,EACF;AAEA,MAAI,eAAe;AACjB,eAAW,CAAC,SAAS,QAAQ,KAAK,OAAO,QAAQ,aAAa,GAAG;AAC/D,YAAM,SAAS,QAAQ,QAAQ,KAAK,EAAE;AACtC,UAAI,gBAAgB,WAAW,MAAM,GAAG;AACtC,cAAM,OAAO,gBAAgB,MAAM,OAAO,MAAM;AAChD,cAAM,aAAuB,CAAC;AAC9B,mBAAW,WAAW,UAAU;AAC9B,gBAAM,WAAWA,SAAQ,SAAS,QAAQ,QAAQ,KAAK,IAAI,CAAC;AAC5D,qBAAW,KAAK,GAAG,QAAQ,OAAOA,SAAQ,UAAU,UAAU,CAAC;AAAA,QACjE;AACA,YAAI,0BAA0B,UAAU;AACxC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAAC;AACV;AAEO,SAAS,oBACd,MACA,YACA,SACuB;AACvB,aAAW,cAAc,WAAW,sBAAsB,GAAG;AAC3D,UAAM,cAAc,WAAW,gBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,IAAI;AACjF,QAAI,CAAC,YAAa;AAElB,UAAM,kBAAkB,WAAW,wBAAwB;AAC3D,UAAM,aAAa,uBAAuB,iBAAiB,YAAY,OAAO;AAC9E,QAAI,WAAW,WAAW,EAAG;AAE7B,eAAW,aAAa,YAAY;AAClC,UAAI,eAAe,QAAQ,cAAc,SAAS;AAClD,UAAI,CAAC,cAAc;AACjB,YAAI;AACF,yBAAe,QAAQ,oBAAoB,SAAS;AAAA,QACtD,QAAQ;AACN;AAAA,QACF;AAAA,MACF;AACA,YAAM,SAAS,eAAe,MAAM,YAAY;AAChD,UAAI,OAAQ,QAAO;AAGnB,YAAM,cAAc,sBAAsB,MAAM,cAAc,SAAS,oBAAI,IAAI,CAAC;AAChF,UAAI,YAAa,QAAO;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO,sBAAsB,MAAM,YAAY,SAAS,oBAAI,IAAI,CAAC;AACnE;AAQA,SAAS,sBACP,MACA,MACA,SACA,MACuB;AACvB,QAAM,WAAW,KAAK,YAAY;AAClC,MAAI,KAAK,IAAI,QAAQ,EAAG,QAAO;AAC/B,OAAK,IAAI,QAAQ;AAEjB,aAAW,cAAc,KAAK,sBAAsB,GAAG;AACrD,UAAM,kBAAkB,WAAW,wBAAwB;AAC3D,UAAM,eAAe,WAAW,gBAAgB;AAGhD,QAAI,iBAAiB;AACnB,YAAM,UAAU,aAAa,WAAW;AACxC,YAAMC,iBAAgB,aAAa;AAAA,QACjC,CAAC,OAAO,EAAE,aAAa,GAAG,QAAQ,KAAK,EAAE,QAAQ,OAAO;AAAA,MAC1D;AACA,UAAI,CAAC,WAAW,CAACA,eAAe;AAEhC,YAAMC,cAAa,UACf,OACC,aACE,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,QAAQ,KAAK,EAAE,QAAQ,OAAO,IAAI,GAChE,QAAQ,KAAK;AACrB,YAAM,SAAS,oBAAoBA,aAAY,iBAAiB,MAAM,SAAS,IAAI;AACnF,UAAI,OAAQ,QAAO;AACnB;AAAA,IACF;AAGA,UAAM,gBAAgB,aAAa;AAAA,MACjC,CAAC,OAAO,EAAE,aAAa,GAAG,QAAQ,KAAK,EAAE,QAAQ,OAAO;AAAA,IAC1D;AACA,QAAI,CAAC,cAAe;AACpB,UAAM,aACJ,aAAa,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,QAAQ,KAAK,EAAE,QAAQ,OAAO,IAAI,GAAG,QAAQ,KACzF;AACF,UAAM,QAAQ,eAAe,YAAY,IAAI;AAC7C,QAAI,MAAO,QAAO;AAClB,UAAM,WAAW,oBAAoB,YAAY,MAAM,OAAO;AAC9D,QAAI,SAAU,QAAO;AAAA,EACvB;AACA,SAAO;AACT;AAEA,SAAS,oBACP,MACA,iBACA,UACA,SACA,MACuB;AACvB,QAAM,aAAa,uBAAuB,iBAAiB,UAAU,OAAO;AAC5E,aAAW,aAAa,YAAY;AAClC,QAAI,eAAe,QAAQ,cAAc,SAAS;AAClD,QAAI,CAAC,cAAc;AACjB,UAAI;AACF,uBAAe,QAAQ,oBAAoB,SAAS;AAAA,MACtD,QAAQ;AACN;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,eAAe,MAAM,YAAY;AAChD,QAAI,OAAQ,QAAO;AACnB,UAAM,cAAc,sBAAsB,MAAM,cAAc,SAAS,IAAI;AAC3E,QAAI,YAAa,QAAO;AAAA,EAC1B;AACA,SAAO;AACT;AAKO,SAAS,SACd,MACA,YACA,SACuB;AACvB,QAAM,QAAQ,eAAe,MAAM,UAAU;AAC7C,MAAI,MAAO,QAAO;AAClB,SAAO,oBAAoB,MAAM,YAAY,OAAO;AACtD;AAkCA,IAAM,iBAAiB,oBAAI,IAAI,CAAC,UAAU,UAAU,WAAW,QAAQ,WAAW,OAAO,MAAM,CAAC;AAGhG,SAAS,mBAAmB,MAAc,MAAkB,OAA+B;AACzF,MAAI,MAAM,SAAS,OAAO,KAAK,KAAK,SAAS,IAAI,GAAG,WAAW,EAAG,QAAO;AACzE,MAAI,MAAM,SAAS,WAAW,KAAK,KAAK,aAAa,IAAI,GAAG,WAAW,EAAG,QAAO;AACjF,MAAI,MAAM,SAAS,WAAW,KAAK,KAAK,aAAa,IAAI,GAAG,WAAW,EAAG,QAAO;AACjF,MAAI,MAAM,SAAS,MAAM,KAAK,KAAK,QAAQ,IAAI,GAAG,WAAW,EAAG,QAAO;AACvE,SAAO;AACT;AAeO,SAAS,eACd,YACA,YACA,SACA,MACgB;AAEhB,MAAI;AACJ,MAAI,OAAO,eAAe,UAAU;AAClC,WAAO;AAAA,EACT,OAAO;AACL,UAAM,WAAW;AAEjB,QAAI,KAAK,oBAAoB,KAAK,gBAAgB,QAAQ,GAAG;AAC3D,YAAM,QAAQ,eAAe,SAAS,mBAAmB,GAAG,YAAY,SAAS,IAAI;AACrF,aAAO,QAAQ,EAAE,GAAG,OAAO,SAAS,KAAK,IAAI;AAAA,IAC/C;AAEA,QAAI,CAAC,KAAK,gBAAgB,QAAQ,EAAG,QAAO;AAC5C,UAAM,WAAW,SAAS,YAAY;AACtC,UAAM,UAAU,KAAK,aAAa,QAAQ,IAAI,SAAS,QAAQ,IAAI;AACnE,QAAI,CAAC,QAAS,QAAO;AAErB,QAAI,KAAK,oBAAoB,YAAY,WAAW;AAClD,YAAM,QAAQ,SAAS,iBAAiB,EAAE,CAAC;AAC3C,aAAO,QAAQ,eAAe,OAAO,YAAY,SAAS,IAAI,IAAI;AAAA,IACpE;AACA,QAAI,KAAK,oBAAoB,YAAY,SAAS;AAChD,YAAM,QAAQ,SAAS,iBAAiB,EAAE,CAAC;AAC3C,UAAI,CAAC,MAAO,QAAO;AACnB,YAAM,QAAQ,eAAe,OAAO,YAAY,SAAS,IAAI;AAC7D,aAAO,QAAQ,EAAE,GAAG,OAAO,SAAS,KAAK,IAAI;AAAA,IAC/C;AAEA,QAAI,eAAe,IAAI,OAAO,EAAG,QAAO;AACxC,WAAO;AAAA,EACT;AAGA,MAAI,mBAAmB,MAAM,YAAY,KAAK,KAAK,GAAG;AACpD,WAAO,EAAE,MAAM,UAAU,WAAW,YAAY,EAAE;AAAA,EACpD;AAGA,aAAW,cAAc,WAAW,sBAAsB,GAAG;AAC3D,UAAM,cAAc,WAAW,gBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,IAAI;AACjF,QAAI,CAAC,YAAa;AAClB,UAAM,kBAAkB,WAAW,wBAAwB;AAG3D,QACE,KAAK,sBACL,CAAC,gBAAgB,WAAW,GAAG,KAC/B,CAAC,gBAAgB,WAAW,GAAG,GAC/B;AAEA,YAAM,gBAAgB,QAAQ,OAAO,EAAE;AACvC,YAAM,UACJ,iBAAiB,QACjB,OAAO,KAAK,aAAa,EAAE,KAAK,CAAC,MAAM;AACrC,cAAM,SAAS,EAAE,QAAQ,KAAK,EAAE;AAChC,eAAO,gBAAgB,WAAW,MAAM;AAAA,MAC1C,CAAC;AACH,UAAI,CAAC,SAAS;AACZ,eAAO,EAAE,MAAM,UAAU,gBAAgB;AAAA,MAC3C;AAAA,IACF;AAIA,UAAM,aAAa,uBAAuB,iBAAiB,YAAY,OAAO;AAC9E,eAAW,aAAa,YAAY;AAClC,UAAI,eAAe,QAAQ,cAAc,SAAS;AAClD,UAAI,CAAC,cAAc;AACjB,YAAI;AACF,yBAAe,QAAQ,oBAAoB,SAAS;AAAA,QACtD,QAAQ;AACN;AAAA,QACF;AAAA,MACF;AACA,UAAI,mBAAmB,MAAM,cAAc,KAAK,KAAK,GAAG;AACtD,eAAO,EAAE,MAAM,UAAU,aAAa,YAAY,EAAE;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ADjZA,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,qBACd,WACA,YACA,SACc;AACd,QAAM,MAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA,OAAO,oBAAI,IAAI;AAAA,IACf,UAAU,CAAC;AAAA,IACX,kBAAkB,oBAAI,IAAI;AAAA,IAC1B,gBAAgB,oBAAI,IAAI;AAAA,IACxB,UAAU,oBAAI,IAAI;AAAA,IAClB,kBAAkB,oBAAI,IAAI;AAAA,IAC1B,OAAO;AAAA,EACT;AACA,QAAM,OAAO,YAAY,WAAW,YAAY,GAAG;AAInD,aAAW,cAAc,IAAI,kBAAkB;AAC7C,QAAI,MAAM,IAAI,YAAY,EAAE,MAAM,WAAW,MAAM,qCAAgC,CAAC;AAAA,EACtF;AACA,SAAO,EAAE,MAAM,OAAO,IAAI,OAAO,UAAU,IAAI,SAAS;AAC1D;AAMA,SAAS,YACP,WACA,WACA,KACY;AACZ,QAAM,QAAQ,UAAU,cAAc;AACtC,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,MAAM,UAAU,QAAQ,CAAC,GAAG,aAAa,KAAK;AAAA,EACzD;AACA,QAAM,SAAoD,CAAC;AAC3D,aAAW,QAAQ,OAAO;AACxB,WAAO,KAAK,EAAE,KAAK,KAAK,QAAQ,GAAG,OAAO,cAAc,MAAM,WAAW,GAAG,EAAE,CAAC;AAAA,EACjF;AACA,SAAO,EAAE,MAAM,UAAU,QAAQ,aAAa,MAAM;AACtD;AAMA,SAAS,cACP,MACA,WACA,KACY;AACZ,QAAM,aAAa,oBAAI,IAAuB;AAC9C,aAAW,KAAK,KAAK,cAAc,EAAG,YAAW,IAAI,EAAE,QAAQ,GAAG,CAAC;AACnE,QAAM,MAAM,CAAC,MAAuB,WAAW,IAAI,CAAC;AACpD,QAAM,MAAM,CAAC,MAAqC,WAAW,IAAI,CAAC;AAElE,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,WAAW,UAAU,QAAQ,KAAK;AACxC,QAAM,cAAc,CAAC,CAAC,YAAY,SAAS,QAAQ,EAAE,SAAS,IAAI;AAGlE,QAAM,cAAc,uBAAuB,IAAI,MAAM,CAAC;AACtD,MAAI,IAAI,gBAAgB,KAAK,aAAa;AACxC,UAAM,YAAY,eAAe,kBAAkB,QAAQ;AAC3D,QAAI,WAAW;AACb,YAAM,YAAY,qBAAqB,WAAW,WAAW,GAAG;AAChE,YAAM,YAAY,IAAI,SAAS,KAAK;AACpC,YAAMC,QAAmB,YAAY,EAAE,MAAM,SAAS,SAAS,UAAU,IAAI;AAC7E,aAAO,cAAcA,OAAM,UAAU;AAAA,IACvC;AAAA,EACF;AAGA,MAAI,OAAO,aAAa,UAAU,WAAW;AAC7C,QAAM,eAA8B,CAAC;AACrC,QAAM,eAA8B,CAAC;AAGrC,MAAI,IAAI,UAAU,EAAG,QAAO,EAAE,MAAM,UAAU,QAAQ,aAAa;AACnE,MAAI,IAAI,WAAW,EAAG,QAAO,EAAE,MAAM,UAAU;AAC/C,MAAI,IAAI,QAAQ,EAAG,QAAO,EAAE,MAAM,OAAO;AACzC,MAAI,IAAI,UAAU,EAAG,QAAO,EAAE,MAAM,UAAU,QAAQ,aAAa;AACnE,MAAI,IAAI,OAAO,GAAG;AAChB,WAAO,EAAE,MAAM,UAAU,QAAQ,aAAa;AAC9C,iBAAa,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,EACpC;AACA,MAAI,IAAI,UAAU,KAAK,CAAC,IAAI,gBAAgB,GAAG;AAC7C,WAAO,EAAE,MAAM,UAAU,QAAQ,CAAC,GAAG,aAAa,KAAK;AAAA,EACzD;AACA,MAAI,IAAI,OAAO,EAAG,QAAO,EAAE,MAAM,UAAU;AAE3C,QAAM,eAAe,MAAY;AAC/B,QAAI,KAAK,SAAS,SAAU,QAAO,EAAE,MAAM,UAAU,QAAQ,aAAa;AAAA,EAC5E;AAGA,MAAI,IAAI,SAAS,GAAG;AAClB,iBAAa;AACb,UAAM,IAAI,WAAW,IAAI,SAAS,CAAC;AACnC,iBAAa,KAAK,MAAM,SAAY,EAAE,OAAO,QAAQ,IAAI,EAAE,OAAO,SAAS,YAAY,EAAE,CAAC;AAAA,EAC5F;AACA,MAAI,IAAI,OAAO,GAAG;AAChB,iBAAa;AACb,UAAM,IAAI,WAAW,IAAI,OAAO,CAAC;AACjC,iBAAa,KAAK,MAAM,SAAY,EAAE,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO,YAAY,EAAE,CAAC;AAAA,EACxF;AACA,MAAI,IAAI,QAAQ,GAAG;AACjB,iBAAa;AACb,UAAM,IAAI,WAAW,IAAI,QAAQ,CAAC;AAClC,iBAAa,KAAK,MAAM,SAAY,EAAE,OAAO,OAAO,IAAI,EAAE,OAAO,QAAQ,YAAY,EAAE,CAAC;AAAA,EAC1F;AACA,MAAI,IAAI,SAAS,GAAG;AAClB,UAAM,KAAK,aAAa,IAAI,SAAS,CAAC;AACtC,QAAI,IAAI;AACN,mBAAa;AACb,mBAAa,KAAK,EAAE,OAAO,SAAS,SAAS,GAAG,CAAC;AAAA,IACnD;AAAA,EACF;AAGA,MAAI,IAAI,WAAW,GAAG;AACpB,UAAM,IAAI,WAAW,IAAI,WAAW,CAAC;AACrC,QAAI,MAAM,KAAM,cAAa,KAAK,EAAE,OAAO,OAAO,OAAO,EAAE,CAAC;AAAA,EAC9D;AACA,MAAI,IAAI,WAAW,GAAG;AACpB,UAAM,IAAI,WAAW,IAAI,WAAW,CAAC;AACrC,QAAI,MAAM,KAAM,cAAa,KAAK,EAAE,OAAO,OAAO,OAAO,EAAE,CAAC;AAAA,EAC9D;AACA,MAAI,IAAI,QAAQ,GAAG;AACjB,UAAM,CAAC,KAAK,GAAG,IAAI,YAAY,IAAI,QAAQ,CAAC;AAC5C,QAAI,QAAQ,KAAM,cAAa,KAAK,EAAE,OAAO,OAAO,OAAO,IAAI,CAAC;AAChE,QAAI,QAAQ,KAAM,cAAa,KAAK,EAAE,OAAO,OAAO,OAAO,IAAI,CAAC;AAAA,EAClE;AACA,MAAI,IAAI,KAAK,GAAG;AACd,UAAM,IAAI,WAAW,IAAI,KAAK,CAAC;AAC/B,QAAI,MAAM,KAAM,cAAa,KAAK,EAAE,OAAO,OAAO,OAAO,EAAE,CAAC;AAAA,EAC9D;AACA,MAAI,IAAI,KAAK,GAAG;AACd,UAAM,IAAI,WAAW,IAAI,KAAK,CAAC;AAC/B,QAAI,MAAM,KAAM,cAAa,KAAK,EAAE,OAAO,OAAO,OAAO,EAAE,CAAC;AAAA,EAC9D;AACA,MAAI,IAAI,YAAY,EAAG,cAAa,KAAK,EAAE,OAAO,WAAW,CAAC;AAC9D,MAAI,IAAI,YAAY,EAAG,cAAa,KAAK,EAAE,OAAO,WAAW,CAAC;AAC9D,MAAI,IAAI,YAAY,KAAK,KAAK,SAAS,SAAU,cAAa,KAAK,EAAE,OAAO,OAAO,OAAO,IAAI,CAAC;AAG/F,MAAI,IAAI,QAAQ,GAAG;AACjB,UAAM,WAAW,wBAAwB,IAAI,QAAQ,GAAG,WAAW,GAAG;AACtE,QAAI,SAAU,QAAO;AAAA,EACvB;AACA,MAAI,IAAI,MAAM,GAAG;AACf,UAAM,SAAS,sBAAsB,IAAI,MAAM,CAAC;AAChD,QAAI,OAAQ,QAAO;AAAA,EACrB;AAGA,QAAM,aAAuB,CAAC;AAC9B,aAAW,QAAQ,WAAW,KAAK,GAAG;AACpC,QAAI,CAAC,iBAAiB,IAAI,IAAI,GAAG;AAC/B,iBAAW,KAAK,IAAI;AACpB,UAAI,CAAC,IAAI,iBAAiB,IAAI,IAAI,GAAG;AACnC,YAAI,iBAAiB,IAAI,IAAI;AAC7B,cAAM,MAAM,IAAI,IAAI;AACpB,YAAI,SAAS,KAAK,GAAG;AACrB,gBAAQ,KAAK,oBAAoB,GAAG,EAAE;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAKA,MAAI,KAAK,SAAS,SAAU,QAAO,EAAE,MAAM,UAAU,QAAQ,aAAa;AAAA,WACjE,KAAK,SAAS,SAAU,QAAO,EAAE,MAAM,UAAU,QAAQ,aAAa;AAE/E,MAAI,OAAmB;AAGvB,MAAI,eAAe,KAAK,SAAS,SAAS;AACxC,WAAO,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,EACxC;AAEA,SAAO,cAAc,MAAM,UAAU;AAErC,MAAI,WAAW,SAAS,GAAG;AACzB,WAAO,EAAE,MAAM,aAAa,OAAO,MAAM,WAAW;AAAA,EACtD;AACA,SAAO;AACT;AAGA,SAAS,cAAc,MAAkB,YAAgD;AACvF,MAAI,WAAW,IAAI,WAAW,EAAG,QAAO;AACxC,MAAI,WAAW,IAAI,YAAY,EAAG,QAAO,EAAE,MAAM,YAAY,OAAO,KAAK;AACzE,SAAO;AACT;AAMA,SAAS,aAAa,UAAkB,aAAkC;AACxE,QAAM,QAAQ,cAAc,SAAS,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI;AAC3D,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,EAAE,MAAM,UAAU,QAAQ,CAAC,EAAE;AAAA,IACtC,KAAK;AACH,aAAO,EAAE,MAAM,UAAU,QAAQ,CAAC,EAAE;AAAA,IACtC,KAAK;AACH,aAAO,EAAE,MAAM,UAAU;AAAA,IAC3B,KAAK;AACH,aAAO,EAAE,MAAM,OAAO;AAAA,IACxB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,EAAE,MAAM,cAAc,MAAM,OAAO;AAAA,IAC5C;AACE,aAAO,EAAE,MAAM,UAAU;AAAA,EAC7B;AACF;AAMA,SAAS,qBACP,WACA,UACA,KACY;AAEZ,MAAI,IAAI,SAAS,IAAI,SAAS,KAAK,IAAI,SAAS,GAAG;AACjD,UAAM,WAAW,IAAI,eAAe,IAAI,SAAS,KAAK,SAAS,WAAW,GAAG;AAC7E,QAAI,eAAe,IAAI,WAAW,QAAQ;AAC1C,QAAI,iBAAiB,IAAI,QAAQ;AACjC,QAAI,CAAC,IAAI,iBAAiB,IAAI,aAAa,QAAQ,EAAE,GAAG;AACtD,UAAI,iBAAiB,IAAI,aAAa,QAAQ,EAAE;AAChD,YAAM,MAAM,GAAG,SAAS;AACxB,UAAI,SAAS,KAAK,GAAG;AACrB,cAAQ,KAAK,oBAAoB,GAAG,EAAE;AAAA,IACxC;AACA,WAAO,EAAE,MAAM,WAAW,MAAM,SAAS;AAAA,EAC3C;AAEA,QAAM,WAAW,IAAI,eAAe,IAAI,SAAS;AACjD,MAAI,SAAU,QAAO,EAAE,MAAM,OAAO,MAAM,SAAS;AAEnD,QAAM,aAAa,SAAS,WAAW,GAAG;AAC1C,QAAM,WAAW,SAAS,WAAW,UAAU,IAAI,OAAO;AAC1D,MAAI,CAAC,YAAY,SAAS,SAAS,SAAS;AAC1C,WAAO,EAAE,MAAM,UAAU,QAAQ,CAAC,GAAG,aAAa,KAAK;AAAA,EACzD;AAEA,MAAI,eAAe,IAAI,WAAW,UAAU;AAC5C,MAAI,SAAS,IAAI,SAAS;AAC1B,MAAI,SAAS;AACb,QAAM,YAAY,YAAY,SAAS,MAAM,SAAS,MAAM,GAAG;AAC/D,MAAI,SAAS;AACb,MAAI,SAAS,OAAO,SAAS;AAE7B,MAAI,MAAM,IAAI,YAAY,SAAS;AACnC,SAAO,EAAE,MAAM,OAAO,MAAM,WAAW;AACzC;AAEA,SAAS,SAAS,WAAmB,KAA2B;AAC9D,QAAM,WAAW,GAAG,SAAS;AAC7B,MAAI,YAAY;AAChB,MAAI,IAAI;AACR,QAAM,OAAO,IAAI,IAAI,IAAI,MAAM,KAAK,CAAC;AACrC,aAAW,KAAK,IAAI,eAAe,OAAO,EAAG,MAAK,IAAI,CAAC;AACvD,SAAO,KAAK,IAAI,SAAS,GAAG;AAC1B,gBAAY,GAAG,QAAQ,IAAI,CAAC;AAC5B,SAAK;AAAA,EACP;AACA,SAAO;AACT;AAMA,SAAS,SAAS,WAAoD;AACpE,SAAO,WAAW,aAAa,EAAE,CAAC;AACpC;AAEA,SAAS,aAAa,WAAiD;AACrE,QAAM,MAAM,SAAS,SAAS;AAC9B,SAAO,MAAM,IAAI,QAAQ,IAAI;AAC/B;AAEA,SAAS,WAAW,WAAiD;AACnE,QAAM,MAAM,SAAS,SAAS;AAC9B,MAAI,OAAOC,MAAK,iBAAiB,GAAG,EAAG,QAAO,IAAI,QAAQ;AAC1D,SAAO;AACT;AAEA,SAAS,YAAY,WAAkE;AACrF,QAAM,OAAO,WAAW,aAAa,KAAK,CAAC;AAC3C,QAAM,MAAM,CAAC,MACX,KAAKA,MAAK,iBAAiB,CAAC,IAAI,EAAE,QAAQ,IAAI;AAChD,SAAO,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC;AACpC;AAGA,SAAS,WAAW,WAAsD;AACxE,QAAM,OAAO,WAAW,aAAa,KAAK,CAAC;AAC3C,aAAW,OAAO,MAAM;AACtB,QAAIA,MAAK,0BAA0B,GAAG,GAAG;AACvC,iBAAW,QAAQ,IAAI,cAAc,GAAG;AACtC,YAAIA,MAAK,qBAAqB,IAAI,KAAK,KAAK,QAAQ,MAAM,WAAW;AACnE,gBAAM,OAAO,KAAK,eAAe;AACjC,cAAI,QAAQA,MAAK,gBAAgB,IAAI,EAAG,QAAO,KAAK,QAAQ;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,uBAAuB,WAAiD;AAC/E,QAAM,MAAM,SAAS,SAAS;AAC9B,MAAI,CAAC,IAAK,QAAO;AACjB,MAAIA,MAAK,gBAAgB,GAAG,GAAG;AAC7B,UAAM,OAAO,IAAI,QAAQ;AACzB,QAAIA,MAAK,aAAa,IAAI,EAAG,QAAO,KAAK,QAAQ;AAAA,EACnD;AACA,SAAO;AACT;AAGA,SAAS,kBAAkB,UAAiC;AAC1D,QAAM,QAAQ,SAAS,SAAS,IAAI,IAAI,SAAS,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI;AACvE,SAAO,6BAA6B,KAAK,KAAK,IAAI,QAAQ;AAC5D;AAGA,SAAS,wBACP,WACA,WACA,KACmB;AACnB,QAAM,MAAM,SAAS,SAAS;AAC9B,MAAI,CAAC,IAAK,QAAO;AACjB,MAAIA,MAAK,aAAa,GAAG,GAAG;AAC1B,UAAM,OAAO,IAAI,QAAQ;AACzB,UAAM,WAAW,SAAS,MAAM,WAAW,IAAI,OAAO;AACtD,QAAI,YAAY,SAAS,SAAS,QAAQ;AACxC,aAAO,EAAE,MAAM,QAAQ,UAAU,SAAS,QAAQ;AAAA,IACpD;AACA,UAAM,MAAM,WAAW,IAAI;AAC3B,QAAI,CAAC,IAAI,iBAAiB,IAAI,UAAU,IAAI,EAAE,GAAG;AAC/C,UAAI,iBAAiB,IAAI,UAAU,IAAI,EAAE;AACzC,UAAI,SAAS,KAAK,GAAG;AACrB,cAAQ,KAAK,oBAAoB,GAAG,EAAE;AAAA,IACxC;AACA,WAAO,EAAE,MAAM,WAAW,MAAM,WAAW,IAAI,qCAAqC;AAAA,EACtF;AACA,MAAIA,MAAK,0BAA0B,GAAG,GAAG;AACvC,UAAM,SAAmB,CAAC;AAC1B,eAAW,KAAK,IAAI,cAAc,GAAG;AACnC,UAAI,CAACA,MAAK,qBAAqB,CAAC,EAAG;AACnC,YAAM,OAAO,EAAE,eAAe;AAC9B,UAAI,QAAQA,MAAK,gBAAgB,IAAI,EAAG,QAAO,KAAK,KAAK,QAAQ,CAAC;AAAA,IACpE;AACA,QAAI,OAAO,SAAS,EAAG,QAAO,EAAE,MAAM,QAAQ,UAAU,OAAO;AAAA,EACjE;AACA,SAAO;AACT;AAGA,SAAS,sBAAsB,WAAqD;AAClF,QAAM,MAAM,SAAS,SAAS;AAC9B,MAAI,OAAOA,MAAK,yBAAyB,GAAG,GAAG;AAC7C,UAAM,WAAW,IAAI,YAAY;AACjC,UAAM,aAAa,SAAS,MAAM,CAAC,MAAMA,MAAK,gBAAgB,CAAC,CAAC;AAChE,QAAI,cAAc,SAAS,SAAS,GAAG;AACrC,aAAO,EAAE,MAAM,QAAQ,UAAU,SAAS,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;AAAA,IACpE;AACA,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,SAAS,IAAI,CAAC,OAAO,EAAE,MAAM,WAAW,KAAK,EAAE,QAAQ,EAAE,EAAE;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;AEncA;AAAA,EAGE,QAAAC;AAAA,OAIK;;;ACPP;AAAA,EACE,QAAAC;AAAA,EAIA;AAAA,OAEK;;;ACWA,SAAS,kBACd,MACA,YACA,SAC+C;AAC/C,QAAM,WAAW,SAAS,MAAM,YAAY,OAAO;AACnD,MAAI,CAAC,YAAY,SAAS,SAAS,OAAQ,QAAO;AAElD,MAAI,UAAU;AACd,QAAM,SAAS,SAAS,QAAQ,IAAI,CAAC,MAAM;AACzC,UAAM,SAAS,KAAK,MAAM,CAAC;AAC3B,QAAI,OAAO,WAAW,SAAU,WAAU;AAC1C,WAAO,OAAO,MAAM;AAAA,EACtB,CAAC;AACD,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,SAAO,EAAE,QAAQ,QAAQ;AAC3B;;;ADhBA,IAAM,uBAAuB,CAAC,WAAW,QAAQ,UAAU,QAAQ,QAAQ,MAAM;AACjF,IAAM,uBAAuB,CAAC,OAAO,SAAS,UAAU,WAAW,UAAU,WAAW,MAAM;AAC9F,IAAM,wBAAwB,CAAC,QAAQ,WAAW,KAAK;AACvD,IAAM,qBAAqB,CAAC,QAAQ,QAAQ,aAAa,UAAU;AACnE,IAAM,qBAAqB,CAAC,QAAQ,OAAO;AAGpC,SAAS,oBAAoB,KAAmC;AACrE,QAAM,IAAI,IAAI,YAAY;AAC1B,MAAI,qBAAqB,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAAG,QAAO;AAC5D,MAAI,qBAAqB,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAAG,QAAO;AAC5D,MAAI,sBAAsB,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAAG,QAAO;AAC7D,MAAI,mBAAmB,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAAG,QAAO;AAC1D,MAAI,mBAAmB,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAAG,QAAO;AAC1D,SAAO;AACT;AAeO,SAAS,aAAa,GAAmB,UAAmC;AACjF,SAAO,WAAW,EAAE,GAAG,GAAG,UAAU,KAAK,IAAI;AAC/C;AAcO,SAAS,iBACd,UACA,YACA,SACA,MACgB;AAEhB,MAAIC,MAAK,gBAAgB,QAAQ,GAAG;AAClC,QAAI,WAAW;AACf,UAAM,aAAuB,CAAC;AAC9B,UAAM,aAAuB,CAAC;AAC9B,UAAM,SAAqB,CAAC;AAC5B,eAAW,UAAU,SAAS,aAAa,GAAG;AAC5C,YAAM,OAAO,OAAO,QAAQ;AAC5B,UAAI,SAAS,WAAW,eAAe,SAAS,WAAW,kBAAkB;AAC3E,mBAAW;AACX;AAAA,MACF;AACA,UAAIA,MAAK,kBAAkB,MAAM,GAAG;AAClC,cAAM,MAAM,OAAO,WAAW;AAC9B,YAAIA,MAAK,gBAAgB,GAAG,GAAG;AAC7B,qBAAW,KAAK,IAAI,gBAAgB,CAAC;AACrC;AAAA,QACF;AACA,YAAIA,MAAK,iBAAiB,GAAG,GAAG;AAC9B,qBAAW,KAAK,IAAI,QAAQ,CAAC;AAC7B;AAAA,QACF;AACA,YAAI,IAAI,QAAQ,MAAM,WAAW,aAAa;AAC5C,qBAAW;AACX;AAAA,QACF;AAAA,MACF;AACA,aAAO,KAAK,MAAM;AAAA,IACpB;AAEA,QAAI,OAAO,WAAW,KAAK,WAAW,SAAS,KAAK,WAAW,WAAW,GAAG;AAC3E,aAAO,aAAa,EAAE,MAAM,UAAU,YAAY,WAAW,GAAG,QAAQ;AAAA,IAC1E;AACA,QAAI,OAAO,WAAW,KAAK,WAAW,SAAS,KAAK,WAAW,WAAW,GAAG;AAC3E,aAAO,aAAa,EAAE,MAAM,UAAU,YAAY,YAAY,aAAa,KAAK,GAAG,QAAQ;AAAA,IAC7F;AACA,QAAI,OAAO,WAAW,GAAG;AACvB,YAAM,QAAQ,iBAAiB,OAAO,CAAC,GAAI,YAAY,SAAS,IAAI;AACpE,aAAO,aAAa,OAAO,YAAY,MAAM,aAAa,IAAI;AAAA,IAChE;AACA,WAAO,aAAa,EAAE,MAAM,UAAU,GAAG,QAAQ;AAAA,EACnD;AAEA,UAAQ,SAAS,QAAQ,GAAG;AAAA,IAC1B,KAAK,WAAW;AACd,aAAO,EAAE,MAAM,SAAS;AAAA,IAC1B,KAAK,WAAW;AACd,aAAO,EAAE,MAAM,SAAS;AAAA,IAC1B,KAAK,WAAW;AACd,aAAO,EAAE,MAAM,UAAU;AAAA,IAC3B,KAAK,WAAW;AAAA,IAChB,KAAK,WAAW;AACd,aAAO,EAAE,MAAM,UAAU;AAAA,IAC3B;AACE;AAAA,EACJ;AAEA,MAAIA,MAAK,gBAAgB,QAAQ,GAAG;AAClC,UAAM,UAAU,SAAS,YAAY,EAAE,QAAQ;AAC/C,QAAI,YAAY,OAAQ,QAAO,EAAE,MAAM,OAAO;AAC9C,QAAI,YAAY,YAAY,YAAY,SAAU,QAAO,EAAE,MAAM,OAAO;AAGxE,UAAM,UAAU,MAAM,aAAa,OAAO,KAAK;AAE/C,UAAM,KAAK,kBAAkB,SAAS,YAAY,OAAO;AACzD,QAAI,IAAI;AACN,YAAM,OAAuB,GAAG,UAC5B,EAAE,MAAM,UAAU,YAAY,GAAG,QAAQ,aAAa,KAAK,IAC3D,EAAE,MAAM,UAAU,YAAY,GAAG,OAAO;AAC5C,aAAO,UAAU,EAAE,GAAG,MAAM,QAAQ,IAAI;AAAA,IAC1C;AACA,QAAI,QAAS,QAAO,EAAE,MAAM,WAAW,QAAQ;AAC/C,WAAO,EAAE,MAAM,UAAU;AAAA,EAC3B;AAEA,MAAIA,MAAK,cAAc,QAAQ,EAAG,QAAO,EAAE,MAAM,OAAO;AAExD,SAAO,EAAE,MAAM,UAAU;AAC3B;AAGO,SAAS,sBACd,MACA,YACA,SAC+C;AAC/C,aAAW,OAAO,MAAM;AACtB,QAAIA,MAAK,gBAAgB,GAAG,GAAG;AAC7B,YAAM,OAAO,IAAI,QAAQ;AACzB,UAAIA,MAAK,aAAa,IAAI,GAAG;AAC3B,cAAM,KAAK,kBAAkB,KAAK,QAAQ,GAAG,YAAY,OAAO;AAChE,YAAI,GAAI,QAAO;AAAA,MACjB;AAAA,IACF;AACA,QAAIA,MAAK,0BAA0B,GAAG,GAAG;AACvC,YAAM,YAAY,IAAI,YAAY,OAAO;AACzC,UAAI,aAAaA,MAAK,qBAAqB,SAAS,GAAG;AACrD,cAAM,OAAO,UAAU,eAAe;AACtC,YAAI,QAAQA,MAAK,gBAAgB,IAAI,GAAG;AACtC,gBAAM,OAAO,KAAK,QAAQ;AAC1B,cAAIA,MAAK,aAAa,IAAI,GAAG;AAC3B,kBAAM,KAAK,kBAAkB,KAAK,QAAQ,GAAG,YAAY,OAAO;AAChE,gBAAI,GAAI,QAAO;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,4BACd,MACA,YACA,SACuB;AACvB,aAAW,OAAO,KAAK,cAAc,GAAG;AACtC,UAAM,UAAU,IAAI,QAAQ;AAC5B,QAAI,YAAY,YAAY,YAAY,cAAc,YAAY,OAAQ;AAC1E,UAAM,OAAO,IAAI,aAAa;AAG9B,QAAI,YAAY,QAAQ;AACtB,YAAM,KAAK,sBAAsB,MAAM,YAAY,OAAO;AAC1D,UAAI,IAAI;AACN,eAAO,GAAG,UACN,EAAE,MAAM,UAAU,YAAY,GAAG,QAAQ,aAAa,KAAK,IAC3D,EAAE,MAAM,UAAU,YAAY,GAAG,OAAO;AAAA,MAC9C;AACA,aAAO,EAAE,MAAM,SAAS;AAAA,IAC1B;AAEA,eAAW,OAAO,MAAM;AAEtB,UAAIA,MAAK,gBAAgB,GAAG,GAAG;AAC7B,cAAM,MAAM,IAAI,gBAAgB;AAChC,cAAM,OAAO,oBAAoB,GAAG;AACpC,YAAI,MAAM;AAER,cAAI,SAAS,YAAY,IAAI,YAAY,EAAE,SAAS,MAAM,EAAG;AAC7D,iBAAO,EAAE,KAAK;AAAA,QAChB;AAAA,MACF;AAEA,UAAIA,MAAK,0BAA0B,GAAG,GAAG;AACvC,cAAM,WAAW,IAAI,YAAY,MAAM;AACvC,YAAI,YAAYA,MAAK,qBAAqB,QAAQ,GAAG;AACnD,gBAAM,OAAO,SAAS,eAAe;AACrC,cAAI,QAAQA,MAAK,aAAa,IAAI,GAAG;AACnC,kBAAM,KAAK,kBAAkB,KAAK,QAAQ,GAAG,YAAY,OAAO;AAChE,gBAAI,IAAI;AACN,qBAAO,GAAG,UACN,EAAE,MAAM,UAAU,YAAY,GAAG,QAAQ,aAAa,KAAK,IAC3D,EAAE,MAAM,UAAU,YAAY,GAAG,OAAO;AAAA,YAC9C;AACA,mBAAO,EAAE,MAAM,SAAS;AAAA,UAC1B;AAAA,QACF;AACA,cAAM,WAAW,IAAI,YAAY,MAAM;AACvC,YAAI,YAAYA,MAAK,qBAAqB,QAAQ,GAAG;AACnD,gBAAM,OAAO,SAAS,eAAe;AACrC,cAAI,QAAQA,MAAK,gBAAgB,IAAI,GAAG;AACtC,kBAAM,OAAO,oBAAoB,KAAK,gBAAgB,CAAC;AACvD,gBAAI,KAAM,QAAO,EAAE,KAAK;AAAA,UAC1B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAMO,SAAS,kBACd,MACA,YACA,SACgB;AAChB,MAAI,WAAW,KAAK,iBAAiB;AACrC,QAAM,WAAW,KAAK,YAAY;AAElC,MAAI,UAAU;AACZ,UAAM,IAAI,iBAAiB,UAAU,YAAY,OAAO;AACxD,QAAI,EAAE,SAAU,YAAW;AAC3B,QAAI,EAAE,SAAS,UAAW,QAAO,aAAa,GAAG,QAAQ;AAAA,EAC3D;AAEA,QAAM,gBAAgB,4BAA4B,MAAM,YAAY,OAAO;AAC3E,MAAI,eAAe;AACjB,WAAO,aAAa,eAAe,YAAY,cAAc,aAAa,IAAI;AAAA,EAChF;AAEA,SAAO,aAAa,EAAE,MAAM,UAAU,GAAG,QAAQ;AACnD;AAUO,SAAS,kBAAkB,MAAc,GAAoC;AAClF,QAAM,KAAsB,EAAE,MAAM,MAAM,EAAE,KAAK;AACjD,MAAI,EAAE,cAAc,EAAE,WAAW,SAAS,EAAG,IAAG,aAAa,EAAE;AAC/D,MAAI,EAAE,SAAU,IAAG,WAAW;AAC9B,MAAI,EAAE,YAAa,IAAG,cAAc;AACpC,MAAI,EAAE,QAAS,IAAG,UAAU,EAAE;AAC9B,SAAO;AACT;;;ADlQO,SAAS,sBAAsB,UAAuC;AAE3E,MAAIC,MAAK,gBAAgB,QAAQ,GAAG;AAClC,YAAQ,SAAS,gBAAgB,GAAG;AAAA,MAClC,KAAK;AACH,eAAO,EAAE,MAAM,SAAS;AAAA,MAC1B,KAAK;AACH,eAAO,EAAE,MAAM,SAAS;AAAA,MAC1B,KAAK;AACH,eAAO,EAAE,MAAM,UAAU;AAAA,MAC3B,KAAK;AACH,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAGA,MAAIA,MAAK,yBAAyB,QAAQ,GAAG;AAC3C,UAAM,SAAmB,CAAC;AAC1B,eAAW,MAAM,SAAS,YAAY,GAAG;AACvC,UAAI,CAACA,MAAK,gBAAgB,EAAE,EAAG,QAAO;AACtC,aAAO,KAAK,GAAG,gBAAgB,CAAC;AAAA,IAClC;AACA,QAAI,OAAO,WAAW,EAAG,QAAO;AAChC,WAAO,EAAE,MAAM,UAAU,YAAY,OAAO;AAAA,EAC9C;AAEA,SAAO;AACT;AAYO,SAAS,uBACd,QACA,YACA,SACuB;AACvB,QAAM,QAAQ,OAAO,cAAc,EAAE,CAAC;AACtC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,WAAW,MAAM,YAAY;AACnC,MAAI,CAAC,SAAU,QAAO;AAOtB,QAAM,YAAY,CAAC,UAAU,UAAU,WAAW,QAAQ,OAAO,SAAS;AAC1E,QAAM,SAAS,iBAAiB,UAAU,YAAY,SAAS;AAAA,IAC7D,YAAY,CAAC,YAAY;AACvB,UAAI,UAAU,SAAS,OAAO,EAAG,QAAO;AAExC,UAAI,CAAC,SAAS,SAAS,YAAY,OAAO,EAAG,QAAO;AACpD,aAAO,eAAe,SAAS,YAAY,SAAS;AAAA,QAClD,OAAO,CAAC,SAAS,aAAa,aAAa,MAAM;AAAA,QACjD,oBAAoB;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAID,MAAI,OAAO,QAAS,QAAO;AAC3B,SAAO,OAAO,SAAS,YAAY,OAAO;AAC5C;AAaO,SAAS,sBACd,WACA,SAC6B;AAC7B,QAAM,QAAQ,oBAAI,IAA4B;AAC9C,QAAM,aAAa,UAAU,cAAc;AAC3C,aAAW,UAAU,UAAU,WAAW,GAAG;AAC3C,UAAM,eAAe,OAAO,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,WAAW;AACnF,QAAI,CAAC,aAAc;AAEnB,UAAM,OAAO,aAAa,aAAa;AAEvC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,WACJ,UAAUA,MAAK,gBAAgB,MAAM,IAAI,OAAO,gBAAgB,IAAI,OAAO,QAAQ;AAGrF,UAAM,UAAU,KAAK,CAAC;AACtB,QAAI,WAAWA,MAAK,0BAA0B,OAAO,GAAG;AACtD,YAAM,WAAW,QAAQ,YAAY,MAAM;AAC3C,UAAI,YAAYA,MAAK,qBAAqB,QAAQ,GAAG;AACnD,cAAM,WAAW,SAAS,eAAe;AACzC,YAAI,UAAU;AACZ,gBAAM,aAAa,sBAAsB,QAAQ;AACjD,cAAI,YAAY;AACd,kBAAM,IAAI,UAAU,UAAU;AAC9B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,YAAY,uBAAuB,QAAQ,YAAY,OAAO;AACpE,QAAI,UAAW,OAAM,IAAI,UAAU,SAAS;AAAA,EAC9C;AACA,SAAO;AACT;AAQO,SAAS,uBACd,QACA,YACA,SAKO;AACP,aAAW,SAAS,OAAO,cAAc,GAAG;AAC1C,UAAM,kBAAkB,MAAM,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,aAAa;AACvF,QAAI,CAAC,gBAAiB;AACtB,UAAM,OAAO,gBAAgB,aAAa;AAC1C,QAAI,KAAK,WAAW,EAAG;AACvB,UAAM,iBAAiB,KAAK,CAAC;AAC7B,QAAI,CAAC,kBAAkB,CAACA,MAAK,aAAa,cAAc,EAAG;AAG3D,QAAI,SAA2B;AAC/B,UAAM,aAAa,KAAK,CAAC;AACzB,QAAI,cAAcA,MAAK,0BAA0B,UAAU,GAAG;AAC5D,YAAM,aAAa,WAAW,YAAY,QAAQ;AAClD,UAAI,cAAcA,MAAK,qBAAqB,UAAU,GAAG;AACvD,cAAM,OAAO,WAAW,eAAe;AACvC,YAAI,QAAQA,MAAK,gBAAgB,IAAI,KAAK,KAAK,gBAAgB,MAAM,QAAQ;AAC3E,mBAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAEA,UAAM,kBAAkB,eAAe,QAAQ;AAC/C,UAAM,WAAW,SAAS,iBAAiB,YAAY,OAAO;AAC9D,QAAI,YAAY,SAAS,SAAS,SAAS;AACzC,YAAM,YAAY,SAAS;AAC3B,UAAI,aAAa,0BAA0B,WAAW,OAAO;AAI7D,UAAI,WAAW,WAAW,GAAG;AAC3B,qBAAa,8BAA8B,WAAW,OAAO;AAAA,MAC/D;AAMA,YAAM,iBAAiB,sBAAsB,WAAW,OAAO;AAC/D,UAAI,eAAe,OAAO,GAAG;AAC3B,cAAM,SAAS,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAU,CAAC;AAClE,mBAAW,CAAC,KAAK,UAAU,KAAK,gBAAgB;AAC9C,iBAAO,IAAI,KAAK,kBAAkB,KAAK,UAAU,CAAC;AAAA,QACpD;AACA,qBAAa,CAAC,GAAG,OAAO,OAAO,CAAC;AAAA,MAClC;AAEA,UAAI,WAAW,WAAW,EAAG,QAAO;AACpC,YAAM,aAAa,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI;AAC/C,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,sBAAsB,oBAAI,IAAI,CAAC,aAAa,aAAa,cAAc,UAAU,CAAC;AAOxF,SAAS,oBACP,YACA,YACA,SACA,QACA,SACmB;AACnB,QAAM,aAAa,WAAW,QAAQ,KAAK;AAC3C,MAAI,QAAQ,IAAI,UAAU,EAAG,QAAO,CAAC;AACrC,UAAQ,IAAI,UAAU;AAEtB,QAAM,SAA4B,CAAC;AACnC,aAAW,QAAQ,WAAW,cAAc,GAAG;AAC7C,UAAM,OAAO,KAAK,QAAQ;AAC1B,QAAI,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,EAAG;AAC1E,QAAI,KAAK,SAAS,EAAG;AAErB,UAAM,WAAW,SAAS,GAAG,MAAM,IAAI,IAAI,KAAK;AAChD,UAAM,aAAa,KAAK,cAAc,EAAE,KAAK,CAAC,MAAM,oBAAoB,IAAI,EAAE,QAAQ,CAAC,CAAC;AAExF,QAAI,YAAY;AACd,YAAM,YAAY,sBAAsB,MAAM,YAAY,OAAO;AACjE,UAAI,WAAW;AAEb,eAAO;AAAA,UACL,GAAG,oBAAoB,WAAW,UAAU,cAAc,GAAG,SAAS,UAAU,OAAO;AAAA,QACzF;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,KAAK,kBAAkB,UAAU,kBAAkB,MAAM,YAAY,OAAO,CAAC,CAAC;AAAA,IACvF;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,sBACP,MACA,YACA,SACyB;AAEzB,aAAW,OAAO,KAAK,cAAc,GAAG;AACtC,QAAI,CAAC,oBAAoB,IAAI,IAAI,QAAQ,CAAC,EAAG;AAC7C,UAAM,OAAO,IAAI,aAAa;AAC9B,QAAI,KAAK,WAAW,EAAG;AACvB,UAAM,MAAM,KAAK,CAAC;AAClB,QAAIA,MAAK,0BAA0B,GAAG,GAAG;AACvC,YAAM,aAAa,IAAI,YAAY,QAAQ;AAC3C,UAAI,cAAcA,MAAK,qBAAqB,UAAU,GAAG;AACvD,cAAM,OAAO,WAAW,eAAe;AAEvC,YAAI,QAAQA,MAAK,gBAAgB,IAAI,GAAG;AACtC,gBAAM,OAAO,KAAK,QAAQ;AAC1B,cAAIA,MAAK,aAAa,IAAI,GAAG;AAC3B,kBAAM,WAAW,SAAS,KAAK,QAAQ,GAAG,KAAK,cAAc,GAAG,OAAO;AACvE,gBAAI,UAAU,SAAS,QAAS,QAAO,SAAS;AAAA,UAClD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAIA,MAAK,gBAAgB,GAAG,GAAG;AAC7B,YAAM,OAAO,IAAI,QAAQ;AACzB,UAAIA,MAAK,aAAa,IAAI,GAAG;AAC3B,cAAM,WAAW,SAAS,KAAK,QAAQ,GAAG,KAAK,cAAc,GAAG,OAAO;AACvE,YAAI,UAAU,SAAS,QAAS,QAAO,SAAS;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,0BACP,WACA,SACmB;AACnB,QAAM,aAAa,UAAU,cAAc;AAC3C,QAAM,SAA4B,CAAC;AACnC,aAAW,QAAQ,UAAU,cAAc,GAAG;AAC5C,UAAM,OAAO,KAAK,QAAQ;AAC1B,QAAI,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,EAAG;AAClD,WAAO,KAAK,kBAAkB,MAAM,kBAAkB,MAAM,YAAY,OAAO,CAAC,CAAC;AAAA,EACnF;AACA,SAAO;AACT;AAOA,SAAS,8BACP,aACA,SACmB;AACnB,QAAM,sBAAsB,YAAY,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,YAAY;AAChG,MAAI,CAAC,oBAAqB,QAAO,CAAC;AAClC,QAAM,OAAO,oBAAoB,aAAa;AAC9C,MAAI,KAAK,WAAW,EAAG,QAAO,CAAC;AAE/B,QAAM,aAAa,KAAK,CAAC;AACzB,MAAI,CAACA,MAAK,0BAA0B,UAAU,EAAG,QAAO,CAAC;AAEzD,QAAM,aAAa,WAAW,YAAY,QAAQ;AAClD,MAAI,CAAC,cAAc,CAACA,MAAK,qBAAqB,UAAU,EAAG,QAAO,CAAC;AAEnE,QAAM,aAAa,WAAW,eAAe;AAC7C,MAAI,CAAC,cAAc,CAACA,MAAK,aAAa,UAAU,EAAG,QAAO,CAAC;AAE3D,QAAM,aAAa,WAAW,QAAQ;AACtC,QAAM,mBAAmB,YAAY,cAAc;AACnD,QAAM,iBAAiB,SAAS,YAAY,kBAAkB,OAAO;AACrE,MAAI,CAAC,kBAAkB,eAAe,SAAS,QAAS,QAAO,CAAC;AAEhE,QAAM,aAAa,eAAe;AAClC,QAAM,SAAS;AAAA,IACb;AAAA,IACA,WAAW,cAAc;AAAA,IACzB;AAAA,IACA;AAAA,IACA,oBAAI,IAAI;AAAA,EACV;AAIA,QAAM,qBAAqB,YAAY,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,WAAW;AAC9F,MAAI,oBAAoB;AACtB,UAAM,UAAU,mBAAmB,aAAa;AAChD,QAAI,QAAQ,SAAS,KAAKA,MAAK,0BAA0B,QAAQ,CAAC,CAAC,GAAG;AACpE,iBAAW,WAAW,QAAQ,CAAC,EAAE,cAAc,GAAG;AAChD,YAAI,CAACA,MAAK,qBAAqB,OAAO,EAAG;AACzC,cAAM,UAAU,QAAQ,eAAe;AACvC,YAAI,CAAC,WAAW,CAACA,MAAK,0BAA0B,OAAO,EAAG;AAC1D,cAAM,WAAW,QAAQ,YAAY,MAAM;AAC3C,YAAI,CAAC,YAAY,CAACA,MAAK,qBAAqB,QAAQ,EAAG;AACvD,cAAM,WAAW,SAAS,eAAe;AACzC,YAAI,CAAC,YAAY,CAACA,MAAK,yBAAyB,QAAQ,EAAG;AAC3D,mBAAW,MAAM,SAAS,YAAY,GAAG;AACvC,cAAIA,MAAK,gBAAgB,EAAE,GAAG;AAG5B,mBAAO,KAAK,kBAAkB,GAAG,gBAAgB,GAAG,EAAE,MAAM,UAAU,CAAC,CAAC;AAAA,UAC1E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AHtWA,IAAM,gBAAsD;AAAA;AAAA;AAAA;AAAA,EAI1D,KAAK;AAAA,EACL,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,qBAAqB;AAAA;AAAA,EAErB,KAAK;AAAA,EACL,QAAQ;AAAA;AAAA,EAER,SAAS;AAAA;AAAA,EAET,YAAY;AAAA;AAAA,EAEZ,OAAO;AACT;AAGA,IAAM,sBAAsB,oBAAI,IAAI;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOD,SAAS,wBACP,UACA,YACA,SACA,OACQ;AACR,MAAI,SAAS,EAAG,QAAO;AAGvB,MAAIC,MAAK,gBAAgB,QAAQ,GAAG;AAClC,UAAM,cAAc,SAAS,mBAAmB;AAChD,WAAO,SAAS,wBAAwB,aAAa,YAAY,SAAS,KAAK,CAAC;AAAA,EAClF;AAGA,MAAIA,MAAK,gBAAgB,QAAQ,GAAG;AAClC,WAAO,SACJ,aAAa,EACb,IAAI,CAAC,MAAM,wBAAwB,GAAG,YAAY,SAAS,KAAK,CAAC,EACjE,KAAK,KAAK;AAAA,EACf;AAGA,MAAIA,MAAK,uBAAuB,QAAQ,GAAG;AACzC,WAAO,SACJ,aAAa,EACb,IAAI,CAAC,MAAM,wBAAwB,GAAG,YAAY,SAAS,KAAK,CAAC,EACjE,KAAK,KAAK;AAAA,EACf;AAGA,MAAIA,MAAK,wBAAwB,QAAQ,GAAG;AAC1C,WAAO,IAAI,wBAAwB,SAAS,YAAY,GAAG,YAAY,SAAS,KAAK,CAAC;AAAA,EACxF;AAGA,MAAIA,MAAK,gBAAgB,QAAQ,GAAG;AAClC,UAAM,WAAW,SAAS,YAAY;AACtC,UAAM,OAAOA,MAAK,aAAa,QAAQ,IAAI,SAAS,QAAQ,IAAI,SAAS,QAAQ;AAGjF,QAAI,SAAS,YAAY,SAAS,YAAY,SAAS,UAAW,QAAO;AACzE,QAAI,SAAS,OAAQ,QAAO;AAC5B,QAAI,SAAS,aAAa,SAAS,SAAS,SAAS,OAAQ,QAAO;AAEpE,QAAI,SAAS,oBAAoB,SAAS,gBAAgB,SAAS;AACjE,aAAO;AAGT,UAAM,cAAc,cAAc,IAAI;AACtC,QAAI,aAAa;AACf,aAAO,mBAAmB,UAAU,YAAY,SAAS,OAAO,WAAW;AAAA,IAC7E;AAGA,QAAI,oBAAoB,IAAI,IAAI,GAAG;AACjC,aAAO,SAAS,QAAQ;AAAA,IAC1B;AAGA,UAAM,WAAW,SAAS,MAAM,YAAY,OAAO;AACnD,QAAI,UAAU;AACZ,aAAO,eAAe,UAAU,SAAS,QAAQ,CAAC;AAAA,IACpD;AAGA,QAAI,sBAAsB,MAAM,MAAM,WAAW,YAAY,CAAC;AAC9D,WAAO;AAAA,EACT;AAGA,QAAM,OAAO,SAAS,QAAQ;AAC9B,MAAI,SAASC,YAAW,cAAe,QAAO;AAC9C,MAAI,SAASA,YAAW,cAAe,QAAO;AAC9C,MAAI,SAASA,YAAW,eAAgB,QAAO;AAC/C,MAAI,SAASA,YAAW,eAAgB,QAAO;AAC/C,MAAI,SAASA,YAAW,WAAY,QAAO;AAG3C,SAAO,SAAS,QAAQ;AAC1B;AAOA,SAAS,mBACP,UACA,YACA,SACA,OACA,MACQ;AACR,QAAM,WAAW,SAAS,iBAAiB;AAC3C,QAAM,eAAe,SAAS,CAAC;AAC/B,MAAI,SAAS,SAAS,KAAK,iBAAiB,QAAW;AACrD,UAAM,QAAQ,wBAAwB,cAAc,YAAY,SAAS,KAAK;AAC9E,WAAO,SAAS,YAAY,SAAS,KAAK,MAAM;AAAA,EAClD;AACA,SAAO,SAAS,YAAY,mBAAmB;AACjD;AAKA,SAAS,eAAe,QAAwB,SAAkB,OAAuB;AACvF,MAAI,QAAQ,EAAG,QAAO;AACtB,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,kBAAkB,OAAO,MAAM,OAAO,MAAM,SAAS,KAAK;AAAA,IACnE,KAAK;AACH,aAAO,kBAAkB,OAAO,MAAM,OAAO,MAAM,SAAS,KAAK;AAAA,IACnE,KAAK;AAIH,UAAI,OAAO,UAAU;AACnB,eAAO,wBAAwB,OAAO,UAAU,OAAO,MAAM,SAAS,KAAK;AAAA,MAC7E;AACA,aAAO,OAAO;AAAA,IAChB,KAAK;AACH,aAAO,OAAO,QAAQ,KAAK,KAAK;AAAA,EACpC;AACF;AAMA,SAAS,kBACP,MACA,YACA,SACA,OACQ;AACR,MAAI,QAAQ,EAAG,QAAO;AAEtB,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,KAAK,cAAc,GAAG;AACvC,UAAM,WAAW,KAAK,QAAQ;AAC9B,UAAM,aAAa,KAAK,iBAAiB;AACzC,UAAM,eAAe,KAAK,YAAY;AACtC,QAAI,WAAW;AACf,QAAI,cAAc;AAChB,iBAAW,wBAAwB,cAAc,YAAY,SAAS,KAAK;AAAA,IAC7E;AACA,UAAM,KAAK,GAAG,QAAQ,GAAG,aAAa,MAAM,EAAE,KAAK,QAAQ,EAAE;AAAA,EAC/D;AACA,SAAO,KAAK,MAAM,KAAK,IAAI,CAAC;AAC9B;AAMA,SAAS,gBACP,QACA,YACA,SACe;AACf,aAAW,SAAS,OAAO,cAAc,GAAG;AAC1C,UAAM,gBAAgB,MAAM,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,MAAM;AAC9E,QAAI,CAAC,cAAe;AACpB,UAAM,WAAW,cAAc,aAAa;AAC5C,QAAI,SAAS,SAAS,EAAG;AACzB,UAAM,WAAW,MAAM,YAAY;AACnC,QAAI,UAAU;AACZ,aAAO,wBAAwB,UAAU,YAAY,SAAS,CAAC;AAAA,IACjE;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,iBACP,QACA,YACA,SACe;AACf,aAAW,SAAS,OAAO,cAAc,GAAG;AAC1C,UAAM,iBAAiB,MAAM,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,OAAO;AAChF,QAAI,CAAC,eAAgB;AACrB,UAAM,YAAY,eAAe,aAAa;AAC9C,QAAI,UAAU,SAAS,EAAG;AAC1B,UAAM,WAAW,MAAM,YAAY;AACnC,QAAI,UAAU;AACZ,aAAO,wBAAwB,UAAU,YAAY,SAAS,CAAC;AAAA,IACjE;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,kBACP,QACA,YACA,SACe;AACf,QAAM,UAAoB,CAAC;AAC3B,aAAW,SAAS,OAAO,cAAc,GAAG;AAC1C,UAAM,iBAAiB,MAAM,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,OAAO;AAChF,QAAI,CAAC,eAAgB;AACrB,UAAM,YAAY,eAAe,aAAa;AAC9C,QAAI,UAAU,WAAW,EAAG;AAC5B,UAAM,UAAU,UAAU,CAAC;AAC3B,QAAI,CAACD,MAAK,gBAAgB,OAAO,EAAG;AACpC,UAAM,YAAY,QAAQ,gBAAgB;AAC1C,UAAM,WAAW,MAAM,YAAY;AACnC,UAAM,YAAY,WACd,wBAAwB,UAAU,YAAY,SAAS,CAAC,IACxD;AACJ,YAAQ,KAAK,GAAG,SAAS,KAAK,SAAS,EAAE;AAAA,EAC3C;AACA,SAAO,QAAQ,SAAS,IAAI,KAAK,QAAQ,KAAK,IAAI,CAAC,OAAO;AAC5D;AAOA,SAAS,oBACP,QACA,YACA,SACQ;AAER,QAAM,uBAAuB,OAAO,aAAa,aAAa;AAC9D,MAAI,sBAAsB;AACxB,UAAM,OAAO,qBAAqB,aAAa;AAC/C,UAAM,UAAU,KAAK,CAAC;AACtB,QAAI,WAAWA,MAAK,0BAA0B,OAAO,GAAG;AACtD,iBAAW,QAAQ,QAAQ,cAAc,GAAG;AAC1C,YAAI,CAACA,MAAK,qBAAqB,IAAI,EAAG;AACtC,YAAI,KAAK,QAAQ,MAAM,OAAQ;AAC/B,cAAM,MAAM,KAAK,eAAe;AAChC,YAAI,CAAC,IAAK;AAGV,YAAIA,MAAK,yBAAyB,GAAG,GAAG;AACtC,gBAAM,WAAW,IAAI,YAAY;AACjC,gBAAM,UAAU,SAAS,CAAC;AAC1B,cAAI,SAAS,SAAS,KAAK,YAAY,QAAW;AAChD,kBAAM,YAAY,6BAA6B,SAAS,YAAY,SAAS,CAAC;AAC9E,mBAAO,SAAS,SAAS;AAAA,UAC3B;AACA,iBAAO;AAAA,QACT;AAGA,eAAO,6BAA6B,KAAK,YAAY,SAAS,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAGA,QAAM,iBAAiB,OAAO,kBAAkB;AAChD,MAAI,gBAAgB;AAClB,WAAO,wBAAwB,gBAAgB,YAAY,SAAS,CAAC;AAAA,EACvE;AAEA,SAAO;AACT;AAMA,SAAS,6BACP,MACA,YACA,SACA,OACQ;AACR,MAAI,CAACA,MAAK,aAAa,IAAI,EAAG,QAAO;AACrC,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,WAAW,SAAS,MAAM,YAAY,OAAO;AACnD,MAAI,UAAU;AACZ,WAAO,eAAe,UAAU,SAAS,QAAQ,CAAC;AAAA,EACpD;AACA,SAAO;AACT;AAOA,SAAS,4BACP,UACA,YACA,SACgB;AAChB,SAAO,eAAe,UAAU,YAAY,SAAS;AAAA,IACnD,OAAO,CAAC,SAAS,WAAW;AAAA,IAC5B,kBAAkB;AAAA,EACpB,CAAC;AACH;AAOO,SAAS,mBACd,QACA,YACA,SAeO;AACP,MAAI,OAAO,gBAAgB,QAAQ,YAAY,OAAO;AACtD,QAAM,aAAa,uBAAuB,QAAQ,YAAY,OAAO;AACrE,QAAM,QAAQ,iBAAiB,QAAQ,YAAY,OAAO;AAO1D,MAAI,cAAc,WAAW,WAAW,QAAQ;AAC9C,UAAM,WAAW;AACjB,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,aAAa,kBAAkB,QAAQ,YAAY,OAAO;AAChE,QAAM,WAAW,oBAAoB,QAAQ,YAAY,OAAO;AAMhE,MACE,SAAS,QACT,UAAU,QACV,eAAe,QACf,aAAa,aACb,eAAe,MACf;AACA,WAAO;AAAA,EACT;AAGA,MAAI,UAA0B;AAC9B,MAAI,WAA2B;AAC/B,MAAI,cAA8B;AAElC,aAAW,SAAS,OAAO,cAAc,GAAG;AAC1C,QAAI,MAAM,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,MAAM,KAAK,MAAM,YAAY,GAAG;AACpF,gBAAU,4BAA4B,MAAM,YAAY,GAAI,YAAY,OAAO;AAAA,IACjF;AACA,QAAI,MAAM,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,OAAO,KAAK,MAAM,YAAY,GAAG;AACrF,iBAAW,4BAA4B,MAAM,YAAY,GAAI,YAAY,OAAO;AAAA,IAClF;AAAA,EACF;AAEA,QAAM,iBAAiB,OAAO,kBAAkB;AAChD,MAAI,gBAAgB;AAClB,kBAAc,4BAA4B,gBAAgB,YAAY,OAAO;AAAA,EAC/E;AAEA,MAAI,CAAC,aAAa;AAChB,UAAM,UAAU,OAAO,aAAa,aAAa;AACjD,QAAI,SAAS;AACX,YAAM,OAAO,QAAQ,aAAa;AAClC,YAAM,UAAU,KAAK,CAAC;AACtB,UAAI,WAAWA,MAAK,0BAA0B,OAAO,GAAG;AACtD,mBAAW,QAAQ,QAAQ,cAAc,GAAG;AAC1C,cAAIA,MAAK,qBAAqB,IAAI,KAAK,KAAK,QAAQ,MAAM,QAAQ;AAChE,kBAAM,MAAM,KAAK,eAAe;AAChC,gBAAI,OAAOA,MAAK,aAAa,GAAG,GAAG;AACjC,oBAAM,OAAO,IAAI,QAAQ;AACzB,oBAAM,YACJ,WAAW,aAAa,IAAI,KAC5B,WAAW,SAAS,IAAI,KACxB,WAAW,aAAa,IAAI;AAC9B,kBAAI,WAAW,WAAW,GAAG;AAC3B,8BAAc,EAAE,MAAM,UAAU,WAAW,YAAY,EAAE;AAAA,cAC3D,OAAO;AACL,sBAAM,WAAW,oBAAoB,MAAM,YAAY,OAAO;AAC9D,oBACE,aACC,SAAS,SAAS,WAAW,SAAS,SAAS,gBAChD,SAAS,KAAK,WAAW,GACzB;AACA,gCAAc,EAAE,MAAM,UAAU,SAAS,KAAK,YAAY,EAAE;AAAA,gBAC9D;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAOA,MAAI,aAAiE;AACrE,MAAI,cAAkE;AACtE,QAAM,eAAyB,CAAC;AAEhC,QAAM,YAAY,kBAAkB,QAAQ,QAAQ,YAAY,OAAO;AACvE,MAAI,WAAW;AACb,iBAAa,qBAAqB,UAAU,MAAM,UAAU,MAAM,OAAO;AACzE,iBAAa,KAAK,GAAG,WAAW,QAAQ;AAAA,EAC1C;AACA,QAAM,aAAa,kBAAkB,QAAQ,SAAS,YAAY,OAAO;AACzE,MAAI,YAAY;AACd,kBAAc,qBAAqB,WAAW,MAAM,WAAW,MAAM,OAAO;AAC5E,iBAAa,KAAK,GAAG,YAAY,QAAQ;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,YAAY,cAAc;AAAA,IACxC,kBAAkB,YAAY,cAAc;AAAA,IAC5C,cAAc,YAAY,UAAU;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAMA,SAAS,kBACP,QACA,eACA,YACA,SACqD;AACrD,aAAW,SAAS,OAAO,cAAc,GAAG;AAC1C,QAAI,CAAC,MAAM,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,aAAa,EAAG;AACvE,UAAM,WAAW,MAAM,YAAY;AACnC,QAAI,CAAC,SAAU;AAEf,UAAM,OAAO,SAAS,QAAQ,EAAE,QAAQ,SAAS,EAAE;AACnD,QAAI,CAAC,6BAA6B,KAAK,IAAI,EAAG;AAC9C,UAAM,WAAW,SAAS,MAAM,YAAY,OAAO;AACnD,QAAI,YAAY,SAAS,SAAS,SAAS;AACzC,aAAO,EAAE,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK;AAAA,IACpD;AAAA,EACF;AACA,SAAO;AACT;;;AM5hBA,SAAS,QAAAE,OAAM,cAAAC,mBAAkB;AAO1B,SAAS,WAAW,MAAoB;AAE7C,MAAI,CAACD,MAAK,iBAAiB,IAAI,EAAG,QAAO;AAEzC,QAAM,OAAO,KAAK,cAAc;AAGhC,MAAIA,MAAK,2BAA2B,IAAI,GAAG;AACzC,UAAM,aAAa,KAAK,QAAQ;AAChC,UAAM,WAAW,KAAK,cAAc;AAEpC,QAAI,eAAe,YAAY;AAC7B,aAAO,GAAG,WAAW,QAAQ,CAAC;AAAA,IAChC;AACA,QAAI,eAAe,YAAY;AAC7B,aAAO,GAAG,WAAW,QAAQ,CAAC;AAAA,IAChC;AAGA,UAAM,OAAO,KAAK,aAAa;AAE/B,YAAQ,YAAY;AAAA,MAClB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MAET,KAAK,WAAW;AACd,cAAM,MAAM,KAAK,CAAC;AAClB,YAAI,CAAC,IAAK,QAAO;AACjB,YAAIA,MAAK,gBAAgB,GAAG,EAAG,QAAO,KAAK,UAAU,IAAI,gBAAgB,CAAC;AAC1E,YAAIA,MAAK,iBAAiB,GAAG,EAAG,QAAO,IAAI,gBAAgB,EAAE,SAAS;AACtE,YAAI,IAAI,QAAQ,MAAMC,YAAW,YAAa,QAAO;AACrD,YAAI,IAAI,QAAQ,MAAMA,YAAW,aAAc,QAAO;AACtD,eAAO;AAAA,MACT;AAAA,MAEA,KAAK,QAAQ;AAEX,cAAM,SAAS,KAAK,CAAC;AACrB,YAAI,CAAC,UAAU,CAACD,MAAK,yBAAyB,MAAM,EAAG,QAAO;AAC9D,cAAM,UAAU,OACb,YAAY,EACZ;AAAA,UAAI,CAAC,OACJA,MAAK,gBAAgB,EAAE,IAAI,KAAK,UAAU,GAAG,gBAAgB,CAAC,IAAI;AAAA,QACpE;AACF,eAAO,QAAQ,KAAK,KAAK;AAAA,MAC3B;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,QAAQ,KAAK,CAAC;AACpB,YAAI,CAAC,MAAO,QAAO;AACnB,eAAO,SAAS,WAAW,KAAK,CAAC;AAAA,MACnC;AAAA,MAEA,KAAK,UAAU;AACb,cAAM,SAAS,KAAK,CAAC;AACrB,YAAI,CAAC,UAAU,CAACA,MAAK,0BAA0B,MAAM,EAAG,QAAO;AAC/D,cAAM,QAAkB,CAAC;AACzB,mBAAW,QAAQ,OAAO,cAAc,GAAG;AACzC,cAAI,CAACA,MAAK,qBAAqB,IAAI,EAAG;AACtC,gBAAM,MAAM,KAAK,QAAQ;AACzB,gBAAM,UAAU,KAAK,eAAe;AACpC,cAAI,CAAC,QAAS;AACd,gBAAM,SAAS,WAAW,OAAO;AAEjC,gBAAM,QAAQ,gBAAgB,OAAO;AACrC,gBAAM,KAAK,GAAG,GAAG,GAAG,QAAQ,MAAM,EAAE,KAAK,MAAM,EAAE;AAAA,QACnD;AACA,eAAO,KAAK,MAAM,KAAK,IAAI,CAAC;AAAA,MAC9B;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,SAAS,KAAK,CAAC;AACrB,YAAI,CAAC,UAAU,CAACA,MAAK,yBAAyB,MAAM,EAAG,QAAO;AAC9D,eAAO,OAAO,YAAY,EAAE,IAAI,UAAU,EAAE,KAAK,KAAK;AAAA,MACxD;AAAA,MAEA,KAAK,UAAU;AAEb,cAAM,SAAS,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;AACnD,YAAI,CAAC,OAAQ,QAAO;AACpB,eAAO,kBAAkB,WAAW,MAAM,CAAC;AAAA,MAC7C;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,SAAS,KAAK,CAAC;AACrB,YAAI,CAAC,UAAU,CAACA,MAAK,yBAAyB,MAAM,EAAG,QAAO;AAC9D,eAAO,IAAI,OAAO,YAAY,EAAE,IAAI,UAAU,EAAE,KAAK,IAAI,CAAC;AAAA,MAC5D;AAAA,MAEA;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;AAGA,SAAS,gBAAgB,MAAqB;AAC5C,MAAI,CAACA,MAAK,iBAAiB,IAAI,EAAG,QAAO;AACzC,QAAM,OAAO,KAAK,cAAc;AAChC,SAAOA,MAAK,2BAA2B,IAAI,KAAK,KAAK,QAAQ,MAAM;AACrE;AAgBO,SAAS,wBAAwB,UAA0C;AAChF,MAAI,CAACA,MAAK,iBAAiB,QAAQ,EAAG,QAAO;AAE7C,QAAM,SAAS,SAAS,cAAc;AAEtC,QAAM,aAAaA,MAAK,aAAa,MAAM,IACvC,OAAO,QAAQ,IACfA,MAAK,2BAA2B,MAAM,IACpC,OAAO,QAAQ,IACf;AAEN,MAAI,eAAe,iBAAkB,QAAO;AAE5C,QAAM,OAAO,SAAS,aAAa;AACnC,QAAM,UAAU,KAAK,CAAC;AACtB,MAAI,CAAC,WAAW,CAACA,MAAK,0BAA0B,OAAO,EAAG,QAAO;AAEjE,MAAI,QAAuB;AAC3B,MAAI,OAAsB;AAC1B,MAAI,WAAW;AACf,MAAI,cAA6B;AACjC,MAAI,eAA8B;AAElC,aAAW,QAAQ,QAAQ,cAAc,GAAG;AAC1C,QAAI,CAACA,MAAK,qBAAqB,IAAI,EAAG;AACtC,UAAM,WAAW,KAAK,QAAQ;AAC9B,UAAM,MAAM,KAAK,eAAe;AAChC,QAAI,CAAC,IAAK;AAEV,QAAI,aAAa,SAAS;AACxB,cAAQ,WAAW,GAAG;AACtB,qBAAe,IAAI,QAAQ;AAAA,IAC7B,WAAW,aAAa,QAAQ;AAC9B,aAAO,WAAW,GAAG;AACrB,oBAAc,IAAI,QAAQ;AAAA,IAC5B,WAAW,aAAa,YAAY;AAClC,iBAAW,WAAW,GAAG;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,MAAM,UAAU,aAAa,aAAa;AAC5D;;;AP1IA,eAAsB,sBACpB,MAC4B;AAC5B,QAAM,EAAE,KAAK,MAAM,SAAS,IAAI;AAEhC,QAAM,eAAe,WAAWE,SAAQ,QAAQ,IAAIC,MAAK,KAAK,eAAe;AAG7E,MAAI;AACJ,MAAI;AACF,cAAU,IAAI,QAAQ;AAAA,MACpB,kBAAkB;AAAA,MAClB,6BAA6B;AAAA,MAC7B,qBAAqB;AAAA,MACrB,8BAA8B;AAAA,IAChC,CAAC;AAAA,EACH,QAAQ;AAEN,cAAU,IAAI,QAAQ;AAAA,MACpB,6BAA6B;AAAA,MAC7B,qBAAqB;AAAA,MACrB,8BAA8B;AAAA,MAC9B,iBAAiB;AAAA,QACf,SAAS;AAAA,QACT,mBAAmB;AAAA,QACnB,QAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,QAAQ,MAAM,GAAG,MAAM,EAAE,KAAK,UAAU,MAAM,WAAW,KAAK,CAAC;AAErE,aAAW,KAAK,OAAO;AACrB,YAAQ,oBAAoB,CAAC;AAAA,EAC/B;AAEA,QAAM,SAA4B,CAAC;AAInC,sBAAoB,SAAS;AAAA,IAC3B,aAAa;AAAA,IACb,eAAe,kBAAkB,YAAY;AAAA,EAC/C,CAAC;AAED,aAAW,cAAc,QAAQ,eAAe,GAAG;AACjD,WAAO,KAAK,GAAG,sBAAsB,YAAY,OAAO,CAAC;AAAA,EAC3D;AAEA,SAAO;AACT;AAOA,SAAS,mBAAmB,eAAqD;AAC/E,MAAI,CAAC,cAAe,QAAO;AAC3B,MAAIC,MAAK,gBAAgB,aAAa,EAAG,QAAO,cAAc,gBAAgB;AAC9E,MAAIA,MAAK,yBAAyB,aAAa,GAAG;AAChD,UAAM,QAAQ,cAAc,YAAY,EAAE,CAAC;AAC3C,QAAI,SAASA,MAAK,gBAAgB,KAAK,EAAG,QAAO,MAAM,gBAAgB;AAAA,EACzE;AACA,SAAO;AACT;AAsBO,SAAS,mBAAmB,WAA2B;AAC5D,QAAM,WAAW,UAAU,QAAQ,eAAe,EAAE;AACpD,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR,0BAA0B,SAAS;AAAA,IACrC;AAAA,EACF;AACA,SAAO,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC;AAC5D;AASO,SAAS,iBACd,WACA,YACA,SACA,UACQ;AACR,QAAM,eAAe,WAAW,mBAAmB,SAAS;AAC5D,QAAM,gBAAgB,YAAY;AAClC,SAAO,GAAG,YAAY,IAAI,aAAa;AACzC;AAGO,SAAS,UAAU,QAAgB,QAAwB;AAChE,MAAI,CAAC,UAAU,CAAC,OAAQ,QAAO;AAC/B,MAAI,CAAC,OAAQ,QAAO,OAAO,WAAW,GAAG,IAAI,SAAS,IAAI,MAAM;AAChE,MAAI,CAAC,OAAQ,QAAO,OAAO,WAAW,GAAG,IAAI,SAAS,IAAI,MAAM;AAEhE,QAAM,IAAI,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;AACvD,QAAM,IAAI,OAAO,WAAW,GAAG,IAAI,SAAS,IAAI,MAAM;AACtD,QAAM,WAAW,IAAI;AACrB,SAAO,aAAa,KAAK,MAAM;AACjC;AAGA,SAAS,cACP,MACuE;AACvE,QAAM,UAAU,KAAK,SAAS,SAAS;AACvC,SAAO,MAAM,KAAK,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,GAAa,QAAQ,OAAgB,EAAE;AAC3F;AAMA,IAAM,yBAAiD;AAAA,EACrD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AACP;AAgBA,SAAS,YAAY,QAAgD;AACnE,aAAW,CAAC,eAAe,IAAI,KAAK,OAAO,QAAQ,sBAAsB,GAAG;AAC1E,UAAM,gBAAgB,OAAO,aAAa,aAAa;AACvD,QAAI,eAAe;AACjB,YAAM,WAAW,cAAc,aAAa;AAC5C,YAAM,UAAU,SAAS,CAAC;AAC1B,aAAO,EAAE,YAAY,MAAM,aAAa,mBAAmB,OAAO,KAAK,GAAG;AAAA,IAC5E;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,gBACP,MACA,OACoB;AACpB,QAAM,cAAc,KAAK,aAAa,IAAI;AAC1C,MAAI,CAAC,YAAa,QAAO;AACzB,QAAM,SAAS,mBAAmB,YAAY,aAAa,EAAE,CAAC,CAAC;AAC/D,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,oBAAoB,KAAK,yCAAyC;AAAA,EACpF;AACA,SAAO;AACT;AAMA,SAAS,WAAW,MAUA;AAClB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,YAAY,iBAAiB,WAAW,YAAY,SAAS,QAAQ;AAG3E,QAAM,eAAe,GAAG,SAAS,IAAI,UAAU;AAC/C,QAAM,WAAW,UAAU,IAAI,SAAS;AACxC,MAAI,aAAa,QAAW;AAC1B,UAAM,IAAI;AAAA,MACR,0BAA0B,SAAS,sBAAsB,QAAQ,UAAU,YAAY;AAAA,IACzF;AAAA,EACF;AACA,YAAU,IAAI,WAAW,YAAY;AAErC,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ,cAAc,YAAY;AAAA,IAClC,eAAe,EAAE,WAAW,YAAY,UAAU,WAAW,YAAY,EAAE;AAAA,IAC3E,UAAU,EAAE,eAAe;AAAA,EAC7B;AACF;AAMA,SAAS,qBAAqB,MASH;AACzB,QAAM,EAAE,KAAK,QAAQ,wBAAwB,MAAM,QAAQ,WAAW,YAAY,UAAU,IAC1F;AAEF,QAAM,oBAAoB,uBAAuB,aAAa,EAAE,CAAC;AACjE,MAAI,CAAC,kBAAmB,QAAO;AAG/B,MAAI,cAAwC;AAG5C,MAAI,aAA6B;AACjC,MAAI,cAA8B;AAElC,MAAIC,MAAK,iBAAiB,iBAAiB,GAAG;AAC5C,kBAAc,wBAAwB,iBAAiB;AAAA,EACzD,WAAWA,MAAK,aAAa,iBAAiB,GAAG;AAC/C,UAAM,YAAY,kBAAkB,QAAQ;AAC5C,UAAM,UAAU,WAAW,uBAAuB,SAAS;AAC3D,QAAI,CAAC,SAAS;AACZ,cAAQ;AAAA,QACN,yCAAyC,SAAS,QAAQ,WAAW,YAAY,CAAC;AAAA,MACpF;AACA,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,QAAQ,eAAe;AAC3C,QAAI,CAAC,YAAa,QAAO;AAEzB,kBAAc,wBAAwB,WAAW;AAGjD,QAAI,eAAe,QAAQ,WAAW,GAAG;AACvC,YAAM,WAAW,WAAW,YAAY;AACxC,UAAI,YAAY,SAAS,MAAM;AAC7B,qBAAa,EAAE,MAAM,GAAG,SAAS,SAAS,SAAS;AAAA,MACrD;AACA,UAAI,YAAY,UAAU,MAAM;AAC9B,sBAAc,EAAE,MAAM,GAAG,SAAS,UAAU,SAAS;AAAA,MACvD;AAAA,IACF;AAAA,EACF,OAAO;AACL,YAAQ;AAAA,MACN,uFAAuF,WAAW,YAAY,CAAC;AAAA,IACjH;AACA,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,YAAa,QAAO;AAGzB,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,eAAe,UAAU,QAAQ,KAAK,WAAW;AACvD,QAAM,aAAa,OAAO,QAAQ;AAElC,QAAM,UAAU,gBAAgB,KAAK,SAAS,SAAS,EAAE;AACzD,QAAM,WAAW,gBAAgB,QAAQ,GAAG,SAAS,IAAI,UAAU,EAAE;AAErE,SAAO,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA,gBAAgB,KAAK;AAAA,IACrB,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,MACd,OAAO,YAAY;AAAA,MACnB,MAAM,YAAY;AAAA,MAClB,UAAU,YAAY;AAAA;AAAA;AAAA;AAAA,MAItB;AAAA,MACA,aAAa,YAAY;AAAA,MACzB;AAAA,MACA,cAAc,YAAY;AAAA,IAC5B;AAAA,EACF,CAAC;AACH;AAMA,SAAS,gBAAgB,MASE;AACzB,QAAM,EAAE,KAAK,QAAQ,MAAM,QAAQ,WAAW,YAAY,SAAS,UAAU,IAAI;AAEjF,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,WAAW,UAAU,QAAQ,KAAK,WAAW;AACnD,QAAM,aAAa,OAAO,QAAQ;AAElC,QAAM,UAAU,gBAAgB,KAAK,SAAS,SAAS,EAAE;AACzD,QAAM,WAAW,gBAAgB,QAAQ,GAAG,SAAS,IAAI,UAAU,EAAE;AAErE,QAAM,cAAc,mBAAmB,QAAQ,YAAY,OAAO;AAElE,SAAO,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA,gBAAgB,KAAK;AAAA,IACrB,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,MACd,OAAO,aAAa,SAAS;AAAA,MAC7B,MAAM,aAAa,QAAQ;AAAA,MAC3B,UAAU,aAAa,YAAY;AAAA,MACnC,UAAU,aAAa,YAAY;AAAA,MACnC,SAAS,aAAa,WAAW;AAAA,MACjC,aAAa,aAAa,eAAe;AAAA,MACzC,cAAc,aAAa,gBAAgB;AAAA,MAC3C,kBAAkB,aAAa,oBAAoB;AAAA,MACnD,cAAc,aAAa,gBAAgB;AAAA,MAC3C,cAAc,aAAa,gBAAgB,CAAC;AAAA,MAC5C,YAAY,aAAa,cAAc;AAAA,MACvC,aAAa,aAAa,eAAe;AAAA,IAC3C;AAAA,EACF,CAAC;AACH;AAEA,SAAS,sBAAsB,YAAwB,SAAqC;AAC1F,QAAM,SAA4B,CAAC;AAEnC,QAAM,YAAY,oBAAI,IAAoB;AAE1C,aAAW,OAAO,WAAW,WAAW,GAAG;AAEzC,UAAM,sBAAsB,IAAI,aAAa,YAAY;AACzD,QAAI,CAAC,oBAAqB;AAG1B,UAAMC,YAAW,oBAAoB,aAAa,EAAE,CAAC;AACrD,UAAM,SAAS,mBAAmBA,SAAQ,KAAK;AAE/C,UAAM,YAAY,IAAI,QAAQ,KAAK;AAEnC,eAAW,UAAU,IAAI,WAAW,GAAG;AACrC,YAAM,OAAO,YAAY,MAAM;AAC/B,YAAM,yBAAyB,OAAO,aAAa,eAAe;AAElE,YAAM,QAAQ,yBACV,qBAAqB;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,IACD,gBAAgB;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAEL,UAAI,MAAO,QAAO,KAAK,KAAK;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AACT;;;AQ3dA,SAAS,SAAAC,QAAO,aAAAC,kBAAiB;AACjC,SAAS,WAAAC,UAAS,QAAAC,cAAY;;;ACD9B,SAAS,gBAAgB;AACzB,SAAS,QAAAC,OAAM,YAAAC,iBAAgB;AAC/B,OAAOC,SAAQ;AAqBf,IAAM,mBAAmB;AAEzB,eAAsB,cAAc,MAAuD;AACzF,QAAM,WAAW,MAAMA,IAAG,KAAK,MAAM,EAAE,KAAK,KAAK,KAAK,UAAU,KAAK,CAAC;AACtE,QAAM,QAAQ,SAAS,OAAO,CAAC,MAAM,CAAC,iBAAiB,KAAK,CAAC,CAAC;AAC9D,QAAM,KAAK;AAGX,QAAM,aAAa,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,QAAQ,OAAO,EAAE,KAAK;AAClE,QAAM,YAAYF,MAAK,KAAK,KAAK,UAAU;AAC3C,QAAM,MAAwB,CAAC;AAC/B,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAMC,UAAS,KAAK,KAAK,IAAI;AACnC,UAAM,UAAUA,UAAS,WAAW,IAAI;AACxC,UAAM,OAAO,YAAY,SAAS,KAAK,qBAAqB;AAC5D,UAAM,SAAS,MAAM,SAAS,MAAM,MAAM;AAC1C,UAAM,cAAc,mBAAmB,QAAQ,KAAK,WAAW;AAC/D,QAAI,KAAK,EAAE,MAAM,cAAc,MAAM,cAAc,KAAK,YAAY,CAAC;AAAA,EACvE;AACA,SAAO;AACT;AAEA,SAAS,YAAY,KAAa,OAA8D;AAC9F,MAAI,OAAO,UAAU,WAAY,QAAO,MAAM,GAAG;AACjD,QAAM,QAAQ,IAAI,QAAQ,wBAAwB,EAAE;AACpD,MAAI,UAAU,QAAS,QAAO,MAAM,QAAQ,sBAAsB,OAAO,EAAE,YAAY;AACvF,SAAO;AACT;AAEA,SAAS,mBAAmB,QAAgB,YAAmC;AAC7E,QAAM,KAAK,IAAI,OAAO,qBAAqB,UAAU,aAAa,GAAG;AACrE,QAAM,IAAI,OAAO,MAAM,EAAE;AACzB,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,QAAQ,EAAE,QAAS,EAAE,CAAC,EAAE;AAE9B,MAAI,IAAI;AACR,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,SAAO,IAAI,OAAO,QAAQ;AACxB,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,MAAM,KAAK;AACb;AACA,gBAAU;AAAA,IACZ,WAAW,MAAM,KAAK;AACpB;AACA,UAAI,WAAW,UAAU,GAAG;AAC1B,eAAO,OAAO,MAAM,OAAO,IAAI,CAAC;AAAA,MAClC;AAAA,IACF,WAAW,MAAM,OAAO,CAAC,QAAS,QAAO,OAAO,MAAM,OAAO,CAAC;AAC9D;AAAA,EACF;AACA,SAAO,OAAO,MAAM,KAAK;AAC3B;;;AClEA,SAAS,QAAAE,aAAY;AACrB,SAAS,QAAAC,OAAM,WAAAC,UAA0B,cAAAC,mBAAkB;AAmBpD,SAAS,oBACd,SACA,aAC0B;AAC1B,MAAI;AACF,QAAI,aAAa,QAAQ,cAAc,WAAW;AAClD,QAAI,CAAC,YAAY;AACf,UAAI;AACF,qBAAa,QAAQ,oBAAoB,WAAW;AAAA,MACtD,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,cAAc,gBAAgB,UAAU;AAC9C,QAAI,CAAC,YAAa,QAAO;AAEzB,UAAM,cAAc,qBAAqB,WAAW;AACpD,QAAI,CAAC,YAAa,QAAO;AAEzB,WAAO,iBAAiB,aAAa,YAAY,OAAO;AAAA,EAC1D,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAUO,SAAS,8BAA8B,QAAkD;AAC9F,MAAI,CAAC,OAAO,KAAK,YAAa,QAAO;AAErC,MAAI;AACF,UAAM,eAAe,OAAO,IAAI,YAAYH,MAAK,OAAO,QAAQ,KAAK,eAAe;AACpF,QAAI;AACJ,QAAI;AACF,gBAAU,IAAIE,SAAQ;AAAA,QACpB,kBAAkB;AAAA,QAClB,6BAA6B;AAAA,QAC7B,qBAAqB;AAAA,QACrB,8BAA8B;AAAA,MAChC,CAAC;AAAA,IACH,QAAQ;AACN,gBAAU,IAAIA,SAAQ;AAAA,QACpB,6BAA6B;AAAA,QAC7B,qBAAqB;AAAA,QACrB,8BAA8B;AAAA,QAC9B,iBAAiB,EAAE,SAAS,MAAM,QAAQ,MAAM;AAAA,MAClD,CAAC;AAAA,IACH;AACA,WAAO,oBAAoB,SAAS,OAAO,IAAI,WAAW;AAAA,EAC5D,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAMA,SAAS,gBAAgB,YAAqC;AAC5D,QAAM,kBAAkB,WAAW,qBAAqBC,YAAW,cAAc;AAEjF,aAAW,QAAQ,iBAAiB;AAClC,UAAM,OAAO,KAAK,cAAc;AAChC,QAAI,CAACF,MAAK,2BAA2B,IAAI,EAAG;AAE5C,UAAM,aAAa,KAAK,QAAQ;AAChC,UAAM,aAAa,KAAK,cAAc;AAEtC,QAAI,eAAe,aAAaA,MAAK,aAAa,UAAU,GAAG;AAC7D,YAAM,OAAO,WAAW,QAAQ;AAChC,UAAI,SAAS,iBAAiB;AAC5B,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,qBAAqB,aAAgC;AAC5D,MAAI,CAACA,MAAK,iBAAiB,WAAW,EAAG,QAAO;AAEhD,QAAM,OAAO,YAAY,aAAa;AACtC,QAAMG,YAAW,KAAK,CAAC;AACvB,MAAI,CAACA,aAAY,CAACH,MAAK,0BAA0BG,SAAQ,EAAG,QAAO;AAEnE,aAAW,QAAQA,UAAS,cAAc,GAAG;AAC3C,QAAIH,MAAK,qBAAqB,IAAI,KAAK,KAAK,QAAQ,MAAM,SAAS;AACjE,aAAO,KAAK,eAAe,KAAK;AAAA,IAClC;AAAA,EACF;AAEA,SAAO;AACT;AAYA,SAAS,iBACP,MACA,YACA,SAC0B;AAE1B,MAAIA,MAAK,aAAa,IAAI,GAAG;AAC3B,UAAM,MAAM,6BAA6B,MAAM,YAAY,OAAO;AAClE,QAAI,KAAK;AACP,aAAO;AAAA,QACL,YAAY,qCAAqC,IAAI,UAAU,MAAM,IAAI,UAAU;AAAA,QACnF,YAAY;AAAA,QACZ,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAIA,MAAK,gBAAgB,IAAI,GAAG;AAC9B,UAAM,SAAS,wBAAwB,MAAM,UAAU;AACvD,WAAO,SAAS,EAAE,GAAG,QAAQ,aAAa,MAAM,IAAI;AAAA,EACtD;AAGA,MAAIA,MAAK,qBAAqB,IAAI,GAAG;AACnC,UAAM,SAAS,wBAAwB,MAAM,UAAU;AACvD,WAAO,SAAS,EAAE,GAAG,QAAQ,aAAa,MAAM,IAAI;AAAA,EACtD;AAGA,MAAIA,MAAK,0BAA0B,IAAI,GAAG;AACxC,UAAM,SAAS,yBAAyB,IAAI;AAC5C,WAAO,SAAS,EAAE,GAAG,QAAQ,aAAa,MAAM,IAAI;AAAA,EACtD;AAEA,SAAO;AACT;AAEA,SAAS,6BACP,IACA,YACA,SACmD;AACnD,MAAI,CAACA,MAAK,aAAa,EAAE,EAAG,QAAO;AACnC,QAAM,OAAO,GAAG,QAAQ;AAExB,QAAM,YAAY,WAAW,YAAY,IAAI;AAC7C,MAAI,WAAW,WAAW,GAAG;AAC3B,UAAM,WAAW,WAAW,YAAY,EAAE,QAAQ,SAAS,EAAE;AAC7D,WAAO,EAAE,YAAY,UAAU,YAAY,KAAK;AAAA,EAClD;AAEA,QAAM,WAAW,WAAW,uBAAuB,IAAI;AACvD,MAAI,UAAU,WAAW,GAAG;AAC1B,UAAM,WAAW,WAAW,YAAY,EAAE,QAAQ,SAAS,EAAE;AAC7D,WAAO,EAAE,YAAY,UAAU,YAAY,KAAK;AAAA,EAClD;AAEA,aAAW,OAAO,WAAW,sBAAsB,GAAG;AACpD,eAAW,SAAS,IAAI,gBAAgB,GAAG;AACzC,YAAM,eAAe,MAAM,aAAa,GAAG,QAAQ,KAAK,MAAM,QAAQ;AACtE,UAAI,iBAAiB,KAAM;AAC3B,YAAM,iBAAiB,IAAI,6BAA6B;AACxD,UAAI,CAAC,eAAgB;AACrB,YAAM,eAAe,MAAM,QAAQ;AACnC,YAAM,KAAK,eAAe,YAAY,YAAY;AAClD,UAAI,IAAI,WAAW,GAAG;AACpB,cAAM,WAAW,eAAe,YAAY,EAAE,QAAQ,SAAS,EAAE;AACjE,eAAO,EAAE,YAAY,UAAU,YAAY,aAAa;AAAA,MAC1D;AACA,YAAM,IAAI,eAAe,uBAAuB,YAAY;AAC5D,UAAI,GAAG,WAAW,GAAG;AACnB,cAAM,WAAW,eAAe,YAAY,EAAE,QAAQ,SAAS,EAAE;AACjE,eAAO,EAAE,YAAY,UAAU,YAAY,aAAa;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,wBAAwB,MAAY,aAAmD;AAE9F,QAAM,iBACJA,MAAK,gBAAgB,IAAI,KAAKA,MAAK,qBAAqB,IAAI,IAAI,KAAK,kBAAkB,IAAI;AAE7F,MAAI,gBAAgB;AAClB,WAAO,gCAAgC,cAAc;AAAA,EACvD;AAGA,MAAIA,MAAK,gBAAgB,IAAI,GAAG;AAC9B,UAAM,OAAO,KAAK,QAAQ;AAG1B,QAAIA,MAAK,0BAA0B,IAAI,GAAG;AACxC,YAAM,QAAQ,KAAK,cAAc;AACjC,UAAIA,MAAK,0BAA0B,KAAK,GAAG;AACzC,eAAO,yBAAyB,KAAK;AAAA,MACvC;AAAA,IACF;AAGA,QAAIA,MAAK,0BAA0B,IAAI,GAAG;AACxC,aAAO,yBAAyB,IAAI;AAAA,IACtC;AAGA,QAAIA,MAAK,QAAQ,IAAI,GAAG;AACtB,aAAO,uBAAuB,IAAI;AAAA,IACpC;AAAA,EACF;AAEA,MAAIA,MAAK,qBAAqB,IAAI,GAAG;AACnC,UAAM,OAAO,KAAK,QAAQ;AAC1B,QAAIA,MAAK,QAAQ,IAAI,GAAG;AACtB,aAAO,uBAAuB,IAAI;AAAA,IACpC;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,gCAAgC,UAA0C;AAEjF,MAAIA,MAAK,gBAAgB,QAAQ,GAAG;AAClC,UAAM,WAAW,SAAS,YAAY;AACtC,QAAIA,MAAK,aAAa,QAAQ,KAAK,SAAS,QAAQ,MAAM,WAAW;AACnE,YAAM,WAAW,SAAS,iBAAiB;AAC3C,YAAMG,YAAW,SAAS,CAAC;AAC3B,UAAIA,WAAU;AACZ,eAAO,gCAAgCA,SAAQ;AAAA,MACjD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAIH,MAAK,cAAc,QAAQ,GAAG;AAChC,UAAM,aAAoD,CAAC;AAC3D,eAAW,UAAU,SAAS,WAAW,GAAG;AAC1C,UAAIA,MAAK,oBAAoB,MAAM,GAAG;AACpC,cAAM,OAAO,OAAO,QAAQ;AAC5B,cAAM,iBAAiB,OAAO,YAAY;AAC1C,cAAM,OAAO,iBAAiB,eAAe,QAAQ,IAAI;AACzD,mBAAW,KAAK,EAAE,MAAM,KAAK,CAAC;AAAA,MAChC;AAAA,IACF;AACA,QAAI,WAAW,WAAW,EAAG,QAAO;AACpC,UAAM,aAAa,KAAK,WAAW,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC;AAChF,WAAO,EAAE,YAAY,YAAY,aAAa,MAAM;AAAA,EACtD;AAEA,SAAO;AACT;AAMA,SAAS,uBAAuB,OAAuC;AACrE,MAAI,CAACA,MAAK,QAAQ,KAAK,EAAG,QAAO;AAEjC,QAAM,aAAa,MAAM,cAAc;AAEvC,WAAS,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK;AAC/C,UAAM,OAAO,WAAW,CAAC;AACzB,QAAI,CAACA,MAAK,kBAAkB,IAAI,EAAG;AAEnC,UAAM,OAAO,KAAK,cAAc;AAChC,QAAI,CAAC,KAAM;AAEX,QAAIA,MAAK,0BAA0B,IAAI,GAAG;AACxC,aAAO,yBAAyB,IAAI;AAAA,IACtC;AAGA,QAAIA,MAAK,0BAA0B,IAAI,GAAG;AACxC,YAAM,QAAQ,KAAK,cAAc;AACjC,UAAIA,MAAK,0BAA0B,KAAK,GAAG;AACzC,eAAO,yBAAyB,KAAK;AAAA,MACvC;AAAA,IACF;AAEA;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,yBAAyB,YAA4C;AAC5E,MAAI,CAACA,MAAK,0BAA0B,UAAU,EAAG,QAAO;AAExD,QAAM,aAAoD,CAAC;AAE3D,aAAW,QAAQ,WAAW,cAAc,GAAG;AAC7C,QAAI,CAACA,MAAK,qBAAqB,IAAI,EAAG;AAEtC,UAAM,OAAO,KAAK,QAAQ;AAC1B,UAAM,cAAc,KAAK,eAAe;AACxC,QAAI,CAAC,YAAa;AAElB,UAAM,OAAO,oBAAoB,WAAW;AAC5C,eAAW,KAAK,EAAE,MAAM,KAAK,CAAC;AAAA,EAChC;AAEA,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAM,aAAa,KAAK,WAAW,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC;AAChF,SAAO,EAAE,YAAY,YAAY,aAAa,MAAM;AACtD;AAeA,SAAS,oBAAoB,MAAoB;AAE/C,MAAIA,MAAK,gBAAgB,IAAI,EAAG,QAAO;AAGvC,MAAIA,MAAK,qBAAqB,IAAI,KAAKA,MAAK,gCAAgC,IAAI;AAC9E,WAAO;AAGT,MAAIA,MAAK,iBAAiB,IAAI,EAAG,QAAO;AAGxC,MAAI,KAAK,QAAQ,MAAME,YAAW,eAAe,KAAK,QAAQ,MAAMA,YAAW,cAAc;AAC3F,WAAO;AAAA,EACT;AAGA,MAAI,KAAK,QAAQ,MAAMA,YAAW,YAAa,QAAO;AAGtD,MAAIF,MAAK,aAAa,IAAI,KAAK,KAAK,QAAQ,MAAM,YAAa,QAAO;AAGtE,MAAIA,MAAK,0BAA0B,IAAI,GAAG;AACxC,UAAM,QAAQ,KAAK,cAAc;AACjC,QAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,UAAM,UAAoB,CAAC;AAC3B,eAAW,QAAQ,OAAO;AACxB,UAAI,CAACA,MAAK,qBAAqB,IAAI,EAAG;AACtC,YAAM,MAAM,KAAK,QAAQ;AACzB,YAAM,OAAO,KAAK,eAAe;AACjC,UAAI,CAAC,KAAM;AACX,cAAQ,KAAK,GAAG,GAAG,KAAK,oBAAoB,IAAI,CAAC,EAAE;AAAA,IACrD;AACA,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WAAO,KAAK,QAAQ,KAAK,IAAI,CAAC;AAAA,EAChC;AAGA,MAAIA,MAAK,yBAAyB,IAAI,GAAG;AACvC,UAAM,WAAW,KAAK,YAAY;AAClC,QAAI,SAAS,WAAW,EAAG,QAAO;AAElC,UAAM,QAAQ,SAAS,CAAC;AACxB,QAAI,MAAO,QAAO,SAAS,oBAAoB,KAAK,CAAC;AACrD,WAAO;AAAA,EACT;AAGA,MAAIA,MAAK,wBAAwB,IAAI,GAAG;AACtC,UAAM,WAAW,oBAAoB,KAAK,YAAY,CAAC;AACvD,UAAM,YAAY,oBAAoB,KAAK,aAAa,CAAC;AACzD,QAAI,aAAa,UAAW,QAAO;AACnC,WAAO,GAAG,QAAQ,MAAM,SAAS;AAAA,EACnC;AAGA,MAAIA,MAAK,0BAA0B,IAAI,GAAG;AACxC,WAAO,oBAAoB,KAAK,cAAc,CAAC;AAAA,EACjD;AAGA,MAAIA,MAAK,eAAe,IAAI,GAAG;AAC7B,UAAM,WAAW,KAAK,YAAY;AAClC,QAAI,SAAU,QAAO,SAAS,QAAQ;AAAA,EACxC;AAGA,SAAO;AACT;;;ACtcA,SAAS,OAAO,iBAAiB;AACjC,SAAkB,cAAAI,aAAY,QAAAC,OAAM,YAAAC,iBAAgB;;;ACDpD,SAAS,WAAAC,gBAAe;AAWjB,SAAS,gBAAgB,YAE9B;AACA,MAAI;AACJ,MAAI;AAEJ,aAAW,OAAO,YAAY;AAC5B,QAAI,IAAI,gBAAgB;AACtB,UAAI,OAAO;AACT,cAAM,IAAI;AAAA,UACR,qCAAqC,UAAU,UAAU,IAAI,IAAI;AAAA,QACnE;AAAA,MACF;AACA,cAAQ,IAAI;AACZ,mBAAa,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3B;AACF;AAGA,IAAM,aAAa,oBAAI,IAAI,CAAC,aAAa,UAAU,YAAY,cAAc,YAAY,CAAC;AAanF,SAAS,eACd,QACA,UACA;AAAA,EACE;AAAA,EACA;AACF,GAIM;AACN,aAAW,CAAC,KAAK,KAAK,KAAK,UAAU;AACnC,UAAM,OAAO,OAAO,IAAI,GAAG;AAC3B,QAAI,SAAS,QAAW;AACtB,YAAM,IAAI,aAAa,SAAS,KAAK,KAAK,OAAO,KAAK,CAAC;AAAA,IACzD;AACA,WAAO,IAAI,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,EAClC;AACF;AAQO,SAAS,uBACd,QACA,WACkB;AAClB,MAAI;AACJ,SAAO;AAAA,IACL,KAAK,OAAO,QAAQ;AAAA,IACpB,QAAQ,OAAO,QAAQ;AAAA,IACvB;AAAA,IACA,IAAI,SAAS;AACX,aAAO,UAAU;AAAA,IACnB;AAAA,IACA,UAAU;AACR,UAAI,CAAC,SAAS;AACZ,kBAAU,IAAIC,SAAQ;AAAA,UACpB,6BAA6B;AAAA,UAC7B,qBAAqB;AAAA,UACrB,8BAA8B;AAAA,UAC9B,iBAAiB,EAAE,SAAS,MAAM,QAAQ,MAAM;AAAA,QAClD,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAOA,eAAsB,qBACpB,QACA,YACA,KAC4B;AAC5B,MAAI,UAAU;AACd,aAAW,OAAO,YAAY;AAC5B,QAAI,CAAC,IAAI,gBAAiB;AAC1B,UAAM,SAAS,MAAM,IAAI,gBAAgB,SAAS,GAAG;AACrD,QAAI,MAAM,QAAQ,MAAM,EAAG,WAAU;AAAA,EACvC;AACA,SAAO;AACT;AAOA,eAAsB,oBACpB,YACA,KACwB;AACxB,QAAM,QAAuB,CAAC;AAC9B,QAAM,SAAS,oBAAI,IAAmD;AAEtE,aAAW,OAAO,YAAY;AAC5B,QAAI,CAAC,IAAI,UAAW;AACpB,UAAM,UAAU,MAAM,IAAI,UAAU,GAAG;AACvC,eAAW,QAAQ,SAAS;AAC1B,YAAM,MAAM,KAAK,KAAK,QAAQ,OAAO,GAAG,EAAE,QAAQ,SAAS,EAAE;AAC7D,UAAI,WAAW,IAAI,GAAG,GAAG;AACvB,cAAM,IAAI;AAAA,UACR,cAAc,IAAI,IAAI,wCAAwC,KAAK,IAAI,kBAAkB,CAAC,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC;AAAA,QACrH;AAAA,MACF;AACA,qBAAe,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAU,GAAG;AAAA,QAC7C,OAAO,IAAI;AAAA,QACX,UAAU,CAAC,MAAM,WAAW,UAC1B,gBAAgB,KAAK,IAAI,yBAAyB,SAAS,UAAU,KAAK;AAAA,MAC9E,CAAC;AACD,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AACT;;;AC0BO,SAAS,aAAa,OAAsC;AACjE,QAAM,KAAK,MAAM,UAAU;AAC3B,QAAM,QAAQ,MAAM,OAAO,YAAY,MAAM;AAC7C,QAAM,UAAU,SAAS,CAAC,CAAC,IAAI,cAAc;AAC7C,QAAM,UAAU,CAAC,CAAC,IAAI,WAAY,IAAI,QAAQ,QAAQ,GAAG,SAAS;AAClE,QAAM,WAAW,SAAS,CAAC,CAAC,IAAI,YAAa,IAAI,SAAS,QAAQ,GAAG,UAAU;AAC/E,SAAO,EAAE,OAAO,SAAS,SAAS,SAAS;AAC7C;;;AFrJA,eAAsB,QACpB,QACA,QACA,OAAuB,CAAC,GACT;AACf,QAAM,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,QAAM,UAAU,aAAa,QAAQ,QAAQ,IAAI;AACjD,QAAM,UAAUC,MAAK,QAAQ,QAAQ,GAAG,SAAS,MAAM;AACzD;AAOA,SAAS,UAAU,MAAwB;AACzC,SAAO,KAAK,MAAM,GAAG;AACvB;AAMA,SAAS,YAAY,SAAyB;AAC5C,MAAI,6BAA6B,KAAK,OAAO,GAAG;AAC9C,WAAO;AAAA,EACT;AACA,SAAO,KAAK,UAAU,OAAO;AAC/B;AAKA,SAAS,YAAY,GAAmB;AACtC,SAAO,EACJ,MAAM,eAAe,EACrB,OAAO,OAAO,EACd;AAAA,IAAI,CAAC,MAAM,MACV,MAAM,IACF,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,IAC3C,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY;AAAA,EAC/D,EACC,KAAK,EAAE;AACZ;AAMA,SAAS,oBAAoB,KAAa,UAAwB;AAChE,MAAI,CAAC,sBAAsB,KAAK,GAAG,GAAG;AACpC,UAAM,YAAY,YAAY,GAAG;AACjC,UAAM,IAAI;AAAA,MACR,kBAAkB,QAAQ,0BAA0B,GAAG,uFAAuF,SAAS;AAAA,IACzJ;AAAA,EACF;AACF;AAkCA,SAAS,eACP,MACA,UACA,MACA,UACM;AACN,QAAM,OAAO,SAAS,CAAC;AACvB,QAAM,OAAO,SAAS,MAAM,CAAC;AAE7B,MAAI,KAAK,WAAW,GAAG;AAErB,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,QAAI,aAAa,UAAa,SAAS,SAAS,UAAU;AACxD,YAAM,IAAI;AAAA,QACR,4BAA4B,QAAQ;AAAA,MACtC;AAAA,IACF;AACA,SAAK,IAAI,MAAM,IAAI;AAAA,EACrB,OAAO;AAEL,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,QAAI,aAAa,UAAa,SAAS,SAAS,QAAQ;AAEtD,YAAM,aAAa,SAChB,MAAM,GAAG,EACT,MAAM,GAAG,SAAS,SAAS,KAAK,MAAM,EACtC,KAAK,GAAG;AACX,YAAM,IAAI;AAAA,QACR,4BAA4B,UAAU;AAAA,MACxC;AAAA,IACF;AACA,QAAI;AACJ,QAAI,aAAa,QAAW;AAC1B,eAAS,EAAE,MAAM,UAAU,UAAU,oBAAI,IAAI,EAAE;AAC/C,WAAK,IAAI,MAAM,MAAM;AAAA,IACvB,OAAO;AACL,eAAS;AAAA,IACX;AACA,mBAAe,OAAO,UAAU,MAAM,MAAM,QAAQ;AAAA,EACtD;AACF;AAUA,SAAS,gBAAgB,QAAyD;AAChF,QAAM,aAAa,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM;AAC3D,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,SAAO,KAAK,WAAW,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,UAAU,EAAE,KAAK,IAAI,CAAC;AACnE;AAKA,SAAS,cAAc,QAA0D;AAC/E,SAAO,OAAO,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AAC/C;AAOA,SAAS,SAAS,MAAqB,YAAuB,aAA+B;AAC3F,MAAI,cAAc,WAAW,SAAS,GAAG;AACvC,WAAO,WAAW,IAAI,CAAC,MAAO,cAAc,IAAI,KAAK,UAAU,CAAC,CAAE,EAAE,KAAK,KAAK;AAAA,EAChF;AACA,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAQA,SAAS,sBAAsB,KAAgC;AAC7D,QAAM,UAAU,IAAI,IAAI,CAAC,MAAM;AAI7B,QAAI,IAAI,EAAE,UAAU,EAAE,QAAQ,OAAO,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW;AACjF,QAAI,EAAE,SAAU,KAAI,GAAG,CAAC;AACxB,WAAO,GAAG,KAAK,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC;AAAA,EACxC,CAAC;AACD,SAAO,KAAK,QAAQ,KAAK,IAAI,CAAC;AAChC;AAGA,SAAS,wBAAwB,GAAsB;AACrD,QAAM,eAAe,EAAE,eAAe,gBAAgB,CAAC,GACpD,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAC5B,KAAK,KAAK;AACb,QAAM,MAAM,EAAE,eAAe;AAC7B,SAAO,KAAK,SAAS,GAAG,WAAW,KAAK,sBAAsB,GAAG,CAAC,KAAK;AACzE;AAOA,SAAS,oBAAoB,GAAsB;AACjD,SAAO,6DAA6D,wBAAwB,CAAC,CAAC;AAChG;AAKA,SAAS,kBAAkB,GAAc,QAAwB;AAC/D,MAAI,EAAE,eAAe;AACnB,QAAI,UAAUC,UAAS,QAAQ,EAAE,cAAc,QAAQ,EAAE,QAAQ,SAAS,EAAE;AAC5E,QAAI,CAAC,QAAQ,WAAW,GAAG,EAAG,WAAU,KAAK,OAAO;AACpD,WAAO,8BAA8B,OAAO,MAAM,EAAE,cAAc,SAAS,KAAK,EAAE,cAAc,UAAU;AAAA,EAC5G;AACA,QAAM,UAAU,EAAE,eAAe;AACjC,MAAI,SAAS;AACX,WAAO,QAAQ,UAAU,SAAS,QAAQ,IAAI,MAAM,QAAQ;AAAA,EAC9D;AACA,SAAO,EAAE,eAAe;AAC1B;AAEA,SAAS,oBACP,MACA,QACA,QACU;AACV,QAAM,MAAM,IAAI,OAAO,MAAM;AAC7B,QAAM,QAAkB,CAAC;AAEzB,aAAW,CAAC,KAAK,IAAI,KAAK,MAAM;AAC9B,UAAM,SAAS,YAAY,GAAG;AAC9B,QAAI,KAAK,SAAS,QAAQ;AACxB,YAAM,IAAI;AACV,YAAM,SAAS,EAAE,OAAO,YAAY;AACpC,YAAM,WAAW,EAAE,eAAe;AAIlC,YAAM,gBACJ,EAAE,eAAe,iBAAiB,WAAW,CAAC,CAAC,EAAE,eAAe,cAAc;AAChF,YAAM,QAAQ,WACV,SAAS,UACP,SAAS,SAAS,IAAI,MACtB,SAAS,OACX,gBACE,oBAAoB,CAAC,IACpB,EAAE,eAAe,SAAS;AACjC,YAAM,UAAU,EAAE,eAAe;AACjC,YAAM,OACJ,WAAW,QACP,UACA,UACE,QAAQ,UACN,SAAS,QAAQ,IAAI,MACrB,QAAQ,OACT,EAAE,eAAe,QAAQ;AAClC,YAAM,WAAW,kBAAkB,GAAG,MAAM;AAC5C,YAAM,SAAS,gBAAgB,EAAE,MAAM;AACvC,YAAM,aAAa,KAAK,UAAU,MAAM;AACxC,YAAM,UAAU,KAAK,UAAU,EAAE,IAAI;AAIrC,YAAM,eAAe,EAAE,eAAe,cAAc,SAChD,EAAE,eAAe,aAAa,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,KAAK,IACtE;AACJ,YAAM;AAAA,QACJ,GAAG,GAAG,GAAG,MAAM,eAAe,UAAU,UAAU,OAAO,aAAa,MAAM,YAAY,KAAK,WAAW,IAAI,eAAe,QAAQ,mBAAmB,YAAY;AAAA,MACpK;AAAA,IACF,OAAO;AACL,YAAM,KAAK,GAAG,GAAG,GAAG,MAAM,KAAK;AAC/B,YAAM,KAAK,GAAG,oBAAoB,KAAK,UAAU,SAAS,GAAG,MAAM,CAAC;AACpE,YAAM,KAAK,GAAG,GAAG,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,SAAO;AACT;AAOA,SAAS,kBAAkB,GAA4B;AACrD,QAAM,IAAI,EAAE,OAAO,YAAY;AAC/B,QAAM,OAAO,KAAK,UAAU,EAAE,IAAI;AAClC,QAAM,OAAO,KAAK,UAAU,EAAE,IAAI;AAClC,QAAM,KAAK,sBAAsB,EAAE,IAAI;AACvC,QAAM,aAAa,cAAc,EAAE,MAAM;AAEzC,QAAM,EAAE,OAAO,SAAS,SAAS,SAAS,IAAI,aAAa,EAAE,KAAK;AAElE,QAAM,SAAmB,CAAC;AAC1B,MAAI,WAAY,QAAO,KAAK,WAAW,EAAE,YAAY;AACrD,MAAI,SAAU,QAAO,KAAK,WAAW,EAAE,WAAW;AAClD,MAAI,QAAS,QAAO,KAAK,UAAU,EAAE,UAAU;AAC/C,QAAM,YAAY,OAAO,SAAS,KAAK,OAAO,KAAK,IAAI,CAAC,OAAO;AAE/D,QAAM,UAAU,aACZ,SAAS,IAAI,yCAAyC,IAAI,KAC1D,SAAS,IAAI,iBAAiB,IAAI;AACtC,QAAM,YAAsB,CAAC;AAC7B,MAAI,SAAU,WAAU,KAAK,4DAA4D;AACzF,MAAI,QAAS,WAAU,KAAK,mBAAmB;AAC/C,QAAM,WAAW,UAAU,SAAS,KAAK,UAAU,KAAK,IAAI,CAAC,OAAO;AAEpE,SAAO;AAAA,IACL,WAAW,EAAE;AAAA,IACb,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,GAAG,EAAE;AAAA,IACnB,cAAc,IAAI,IAAI;AAAA,EACxB;AACF;AAOA,SAAS,qBAAqB,KAA2B;AACvD,SAAO,WAAW,IAAI,MAAM,IAAI,IAAI,YAAY,KAAK,IAAI,OAAO,KAAK,IAAI,QAAQ;AACnF;AAQA,SAAS,gBAA0B;AACjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAOA,SAAS,WACP,KACA,QACA,KACA,aACA,SACU;AACV,QAAM,QAAQ,CAAC,GAAG,GAAG,GAAG,MAAM,cAAc,IAAI,SAAS,SAAS;AAClE,QAAM,KAAK,GAAG,GAAG,cAAc,IAAI,YAAY,WAAW,WAAW,IAAI;AACzE,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AACnD,UAAM,KAAK,GAAG,GAAG,KAAK,IAAI,KAAK,KAAK,GAAG;AAAA,EACzC;AACA,QAAM,KAAK,GAAG,GAAG,KAAK;AACtB,SAAO;AACT;AAeA,SAAS,mBAAmB,MAA6B,QAAgB,GAA0B;AACjG,QAAM,MAAM,IAAI,OAAO,MAAM;AAC7B,QAAM,QAAkB,CAAC;AAEzB,aAAW,CAAC,KAAK,IAAI,KAAK,MAAM;AAC9B,UAAM,SAAS,YAAY,GAAG;AAC9B,QAAI,KAAK,SAAS,UAAU;AAC1B,YAAM,KAAK,GAAG,GAAG,GAAG,MAAM,KAAK;AAC/B,YAAM,KAAK,GAAG,mBAAmB,KAAK,UAAU,SAAS,GAAG,CAAC,CAAC;AAC9D,YAAM,KAAK,GAAG,GAAG,IAAI;AACrB;AAAA,IACF;AAEA,UAAM,MAAM,kBAAkB,IAAI;AAGlC,UAAM,OAAkB;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,SAAS;AAAA,MACT,aAAa,qBAAqB,GAAG;AAAA,IACvC;AAMA,UAAM,QAAQ,oBAAI,IAA8C;AAChE,QAAI,EAAE,OAAO;AACX,qBAAe,OAAO,OAAO,QAAQ,EAAE,MAAM,aAAa,KAAK,aAAa,MAAM,EAAE,GAAG,CAAC,GAAG;AAAA,QACzF,OAAO,EAAE,MAAM;AAAA,QACf,UAAU,CAAC,MAAM,WAAW,UAC1B,eAAe,IAAI,eAAe,IAAI,SAAS,kEAAkE,SAAS,UAAU,KAAK;AAAA,MAC7I,CAAC;AAAA,IACH;AACA,eAAW,OAAO,EAAE,YAAY;AAC9B,YAAM,QAAQ,IAAI,aAAa,MAAM,EAAE,GAAG;AAC1C,UAAI,CAAC,MAAO;AACZ,qBAAe,OAAO,OAAO,QAAQ,KAAK,GAAG;AAAA,QAC3C,OAAO,IAAI;AAAA,QACX,UAAU,CAAC,MAAM,WAAW,UAC1B,eAAe,IAAI,eAAe,IAAI,SAAS,kEAAkE,SAAS,UAAU,KAAK;AAAA,MAC7I,CAAC;AAAA,IACH;AACA,UAAM,UAAkC,CAAC;AACzC,eAAW,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAO,SAAQ,IAAI,IAAI;AAEvD,UAAM,KAAK,GAAG,WAAW,KAAK,QAAQ,KAAK,KAAK,aAAa,OAAO,CAAC;AAAA,EACvE;AAEA,SAAO;AACT;AAMA,SAAS,sBAAsB,MAAsB;AACnD,QAAM,WAAW,UAAU,IAAI;AAC/B,SAAO,YAAY,SAAS,IAAI,CAAC,MAAM,IAAI,KAAK,UAAU,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC;AAC3E;AAgBA,IAAM,mBAAsC;AAAA;AAAA,EAE1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,kBAAqC;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,iBAAoC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,wBAA2C;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,uBAA0C;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMA,SAAS,aACP,QACA,QACA,OAAuB,CAAC,GAChB;AACR,QAAM,oBAAoB,KAAK;AAC/B,QAAM,aAAa,KAAK,cAAc,CAAC;AACvC,QAAM,EAAE,MAAM,IAAI,gBAAgB,UAAU;AAC5C,QAAM,aAAa,WAAW,OAAO,CAAC,MAAM,EAAE,UAAU;AACxD,QAAM,aAAa,WAAW,OAAO,CAAC,MAAM,EAAE,SAAS;AACvD,QAAM,aAAa,OAAO,OAAO,CAAC,MAAM,EAAE,QAAQ;AAKlD,QAAM,MACJ,KAAK,OACJ;AAAA,IACC,KAAK,UAAU;AAAA,IACf,QAAQ,UAAU;AAAA,IAClB;AAAA,IACA,QAAQ,CAAC;AAAA,IACT,SAAS,MAAM;AACb,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACpF;AAAA,EACF;AAGF,QAAM,gBAAgB,oBAAI,IAAyB;AACnD,aAAW,KAAK,YAAY;AAC1B,UAAM,KAAK,EAAE,UAAU;AACvB,QAAI,CAAC,GAAI;AAET,UAAM,OAAO,EAAE,gBACX,CAAC,GAAG,UAAU,GAAG,OAAO,IACxB,CAAC,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW;AAC5C,eAAW,OAAO,MAAM;AACtB,UAAI,CAAC,IAAK;AACV,UAAI,QAAQ,cAAc,IAAI,IAAI,QAAQ;AAC1C,UAAI,CAAC,OAAO;AACV,gBAAQ,oBAAI,IAAI;AAChB,sBAAc,IAAI,IAAI,UAAU,KAAK;AAAA,MACvC;AACA,YAAM,IAAI,IAAI,IAAI;AAAA,IACpB;AAGA,eAAW,MAAM,GAAG,oBAAoB,CAAC,GAAG;AAC1C,UAAI,CAAC,GAAG,QAAS;AACjB,UAAI,QAAQ,cAAc,IAAI,GAAG,QAAQ,QAAQ;AACjD,UAAI,CAAC,OAAO;AACV,gBAAQ,oBAAI,IAAI;AAChB,sBAAc,IAAI,GAAG,QAAQ,UAAU,KAAK;AAAA,MAC9C;AACA,YAAM,IAAI,GAAG,QAAQ,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,QAAkB,CAAC,0DAA0D,EAAE;AAIrF,QAAM,aAAuB,CAAC;AAC9B,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,aAAa,CAAC,QAAsB;AACxC,QAAI,YAAY,IAAI,GAAG,EAAG;AAC1B,gBAAY,IAAI,GAAG;AACnB,eAAW,KAAK,GAAG;AAAA,EACrB;AACA,aAAW,OAAO,OAAO,UAAU,GAAG,KAAK,CAAC,EAAG,YAAW,GAAG;AAC7D,aAAW,OAAO,YAAY;AAC5B,eAAW,OAAO,IAAI,YAAY,GAAG,GAAG,WAAW,CAAC,EAAG,YAAW,GAAG;AAAA,EACvE;AACA,QAAM,KAAK,GAAG,UAAU;AAExB,QAAM;AAAA,IACJ;AAAA,EACF;AAIA,QAAM,gBAAgB,qBAAqB;AAC3C,QAAM,KAAK,iCAAiC,aAAa,IAAI;AAK7D,MAAI,cAAc,OAAO,KAAK,QAAQ;AACpC,UAAM,KAAK,EAAE;AACb,UAAM,eAAe,oBAAI,IAAY;AACrC,eAAW,CAAC,UAAU,KAAK,KAAK,eAAe;AAG7C,UAAI;AACJ,UAAIC,YAAW,QAAQ,GAAG;AACxB,kBAAUD,UAAS,QAAQ,QAAQ,EAAE,QAAQ,SAAS,EAAE;AACxD,YAAI,CAAC,QAAQ,WAAW,GAAG,EAAG,WAAU,KAAK,OAAO;AAAA,MACtD,OAAO;AACL,kBAAU;AAAA,MACZ;AACA,YAAM,aAAuB,CAAC;AAC9B,iBAAW,QAAQ,CAAC,GAAG,KAAK,EAAE,KAAK,GAAG;AACpC,YAAI,aAAa,IAAI,IAAI,GAAG;AAC1B,gBAAM,QAAQ,GAAG,IAAI,IAAI,aAAa,IAAI;AAC1C,qBAAW,KAAK,GAAG,IAAI,OAAO,KAAK,EAAE;AACrC,uBAAa,IAAI,KAAK;AAAA,QACxB,OAAO;AACL,qBAAW,KAAK,IAAI;AACpB,uBAAa,IAAI,IAAI;AAAA,QACvB;AAAA,MACF;AACA,YAAM,KAAK,iBAAiB,WAAW,KAAK,IAAI,CAAC,YAAY,OAAO,IAAI;AAAA,IAC1E;AAAA,EACF;AACA,QAAM,KAAK,EAAE;AAEb,MAAI,WAAW,WAAW,GAAG;AAC3B,UAAM,KAAK,gDAAgD;AAC3D,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,uEAAuE;AAClF,UAAM,KAAK,cAAc;AACzB,UAAM,KAAK,GAAG;AACd,UAAM,KAAK,iDAAiD;AAC5D,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,qBAAqB;AACnC,UAAM,KAAK,GAAG,oBAAoB;AAClC,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAGA,QAAM,OAAO,oBAAI,IAAsB;AAEvC,aAAW,KAAK,YAAY;AAC1B,UAAM,IAAI,EAAE;AACZ,UAAM,OAAe,EAAE;AACvB,UAAM,WAAW,UAAU,IAAI;AAE/B,eAAW,OAAO,UAAU;AAC1B,0BAAoB,KAAK,IAAI;AAAA,IAC/B;AACA,UAAM,OAAkB;AAAA,MACtB,MAAM;AAAA,MACN,QAAQ,EAAE;AAAA,MACV;AAAA,MACA,MAAM,EAAE;AAAA,MACR,QAAQ,EAAE;AAAA,MACV,eAAe,EAAE;AAAA,MACjB,gBAAgB,EAAE;AAAA,MAClB,OAAO;AAAA,IACT;AACA,mBAAe,MAAM,UAAU,MAAM,IAAI;AAAA,EAC3C;AAGA,QAAM,KAAK,2BAA2B;AACtC,QAAM,KAAK,GAAG,oBAAoB,MAAM,GAAG,UAAU,EAAE,CAAC;AACxD,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,GAAG,cAAc,CAAC;AAG7B,QAAM,KAAK,+CAA+C;AAC1D,QAAM,KAAK,YAAY;AACvB,QAAM;AAAA,IACJ,GAAG,mBAAmB,MAAM,GAAG;AAAA,MAC7B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MACzB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,iDAAiD;AAC5D,QAAM,KAAK,EAAE;AAEb,QAAM,KAAK,GAAG,gBAAgB;AAC9B,QAAM,KAAK,GAAG,eAAe;AAC7B,QAAM,KAAK,GAAG,cAAc;AAG5B,aAAW,OAAO,YAAY;AAC5B,UAAM,aAAa,IAAI,YAAY,GAAG,GAAG;AACzC,QAAI,YAAY,QAAQ;AACtB,YAAM,KAAK,GAAG,YAAY,EAAE;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AG1xBA,SAAS,SAAAE,QAAO,MAAM,aAAAC,kBAAiB;AACvC,SAAS,QAAAC,aAAY;AAarB,eAAsB,UAAU,OAAyB,QAA+B;AACtF,QAAMF,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,QAAM,UAAwB,MAAM,QAAQ;AAAA,IAC1C,MAAM,IAAI,OAAO,MAAM;AACrB,YAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,aAAO;AAAA,QACL,MAAM,EAAE;AAAA,QACR,cAAc,EAAE;AAAA,QAChB,OAAO,EAAE,MAAM,YAAY;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,QAAyB,EAAE,OAAO,QAAQ;AAChD,QAAMC,WAAUC,MAAK,QAAQ,iBAAiB,GAAG,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAChG;;;AC5BA,SAAS,SAAAC,QAAO,aAAAC,kBAAiB;AACjC,SAAS,QAAAC,OAAM,YAAAC,iBAAgB;AAqB/B,eAAsB,UACpB,QACA,QACA,QACA,SACkB;AAClB,MAAI,UAAU,OAAO,YAAY,MAAO,QAAO;AAE/C,QAAM,UAAU,0BAA0B,QAAQ,QAAQ,SAAS,MAAM;AACzE,MAAI,YAAY,KAAM,QAAO;AAC7B,QAAMH,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,QAAMC,WAAUC,MAAK,QAAQ,UAAU,GAAG,SAAS,MAAM;AACzD,SAAO;AACT;AAOA,SAAS,OAAO,SAAyB;AACvC,SAAO,QACJ,MAAM,eAAe,EACrB,OAAO,OAAO,EACd,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EACjD,KAAK,EAAE;AACZ;AAMA,SAAS,eAAe,WAAqD;AAC3E,QAAM,WAAW,UAAU,MAAM,GAAG;AACpC,QAAM,SAAS,OAAO,SAAS,SAAS,SAAS,CAAC,KAAK,SAAS;AAChE,QAAM,OAAO,SAAS,IAAI,MAAM,EAAE,KAAK,EAAE;AACzC,SAAO,EAAE,QAAQ,KAAK;AACxB;AAGA,SAAS,UAAU,QAAgB,UAA0B;AAC3D,MAAI,UAAUC,UAAS,QAAQ,QAAQ,EAAE,QAAQ,SAAS,EAAE;AAC5D,MAAI,CAAC,QAAQ,WAAW,GAAG,EAAG,WAAU,KAAK,OAAO;AACpD,SAAO;AACT;AAGA,SAAS,kBAAkB,SAAyB;AAClD,SAAO,QAAQ,MAAM,GAAG,EAAE,CAAC,KAAK;AAClC;AAeA,SAAS,UAAU,KAA0B;AAC3C,SAAO,CAAC,EAAE,IAAI,UAAU,IAAI,WAAW,IAAI;AAC7C;AAsBA,SAAS,aAAa,MAAc,SAA6C;AAC/E,MAAI,CAAC,WAAW,QAAQ,SAAS,EAAG,QAAO;AAC3C,MAAI,MAAM;AACV,aAAW,CAAC,MAAM,EAAE,KAAK,SAAS;AAChC,QAAI,SAAS,GAAI;AACjB,UAAM,IAAI,QAAQ,IAAI,OAAO,MAAM,aAAa,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE;AAAA,EACtE;AACA,SAAO;AACT;AAEA,SAAS,aAAa,GAAmB;AACvC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AAEA,SAAS,kBAAkB,MAAc,MAAuB;AAC9D,SAAO,IAAI,OAAO,MAAM,aAAa,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI;AAC5D;AAOA,SAAS,kBAAkB,SAAwC;AACjE,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,QAAM,iBAAiB,oBAAI,IAAoC;AAE/D,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,cAAe;AAC1B,UAAM,QAAQ,OAAO,QAAQ,MAAM,aAAa;AAChD,QAAI,MAAM,WAAW,EAAG;AAExB,UAAM,SAAS,oBAAI,IAAoB;AACvC,eAAW,CAAC,IAAI,KAAK,MAAO,QAAO,IAAI,MAAM,IAAI;AAEjD,UAAM,UAAU,CAAC,SAAyB;AACxC,YAAM,MAAM,MAAM,gBAAgB,IAAI,KAAK;AAC3C,aAAO,aAAa,KAAK,MAAM;AAAA,IACjC;AAEA,QAAI,UAAU;AACd,QAAI,QAAQ;AACZ,WAAO,WAAW,QAAQ,MAAM,SAAS,GAAG;AAC1C,gBAAU;AACV,eAAS;AACT,iBAAW,CAAC,IAAI,KAAK,OAAO;AAC1B,cAAM,YAAY,OAAO,IAAI,IAAI,KAAK;AACtC,cAAM,OAAO,QAAQ,IAAI;AACzB,cAAM,WAAW,cAAc,IAAI,SAAS;AAC5C,YAAI,aAAa,OAAW;AAC5B,YAAI,aAAa,KAAM;AACvB,YAAI,IAAI;AACR,YAAI,YAAY,GAAG,IAAI,IAAI,CAAC;AAC5B,eACG,cAAc,IAAI,SAAS,KAAK,cAAc,IAAI,SAAS,MAAM,QAAQ,IAAI,KAC9E,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,SAAS,SAAS,GACvC;AACA,eAAK;AACL,sBAAY,GAAG,IAAI,IAAI,CAAC;AAAA,QAC1B;AACA,eAAO,IAAI,MAAM,SAAS;AAC1B,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,eAAW,CAAC,IAAI,KAAK,OAAO;AAC1B,YAAM,YAAY,OAAO,IAAI,IAAI,KAAK;AACtC,UAAI,OAAO,QAAQ,IAAI;AACvB,UAAI,kBAAkB,WAAW,IAAI,GAAG;AACtC,eAAO;AAAA,MACT;AACA,YAAM,WAAW,cAAc,IAAI,SAAS;AAC5C,UAAI,aAAa,QAAW;AAC1B,sBAAc,IAAI,WAAW,IAAI;AAAA,MACnC;AAAA,IACF;AAEA,mBAAe,IAAI,OAAO,MAAM;AAAA,EAClC;AAEA,SAAO,EAAE,eAAe,eAAe;AACzC;AAWA,SAAS,0BACP,QACA,QACA,SACA,QACe;AACf,QAAM,gBAAgB,QAAQ,wBAAwB;AACtD,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAGhG,QAAM,mBAAmB,oBAAI,IAAoB;AACjD,QAAM,aAA0B,CAAC;AACjC,aAAW,SAAS,QAAQ;AAC1B,UAAM,KAAK,MAAM,SAAU;AAC3B,UAAM,OAAmB;AAAA,MACvB,QAAQ,GAAG,cAAc;AAAA,MACzB,SAAS,GAAG,eAAe;AAAA,MAC3B,QAAQ,GAAG,cAAc;AAAA,IAC3B;AACA,UAAM,QAAoB;AAAA,MACxB,QAAQ,GAAG,eAAe;AAAA,MAC1B,SAAS,GAAG,gBAAgB;AAAA,MAC5B,QAAQ,GAAG,eAAe;AAAA,IAC5B;AACA,QAAI,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,KAAK,EAAG;AAC3C,UAAM,EAAE,QAAQ,KAAK,IAAI,eAAe,MAAM,IAAI;AAClD,qBAAiB,IAAI,SAAS,iBAAiB,IAAI,MAAM,KAAK,KAAK,CAAC;AACpE,eAAW,KAAK;AAAA,MACd,WAAW,MAAM;AAAA,MACjB,UAAU;AAAA;AAAA,MACV,MAAM,UAAU,IAAI,IAAI,OAAO;AAAA,MAC/B,OAAO,UAAU,KAAK,IAAI,QAAQ;AAAA,MAClC,eAAe,GAAG,qBAAqB;AAAA,MACvC,UAAU,GAAG,gBAAgB,CAAC;AAAA,IAChC,CAAC;AAAA,EACH;AAEA,QAAM,UAAuB,WAAW,IAAI,CAAC,MAAM;AACjD,UAAM,EAAE,QAAQ,KAAK,IAAI,eAAe,EAAE,SAAS;AACnD,UAAM,aAAa,iBAAiB,IAAI,MAAM,KAAK,KAAK;AACxD,WAAO,EAAE,GAAG,GAAG,UAAU,YAAY,OAAO,OAAO;AAAA,EACrD,CAAC;AAED,MAAI,QAAQ,WAAW,EAAG,QAAO;AAGjC,QAAM,gBAAgB,oBAAI,IAAyB;AACnD,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,SAAS,SAAS;AAC3B,eAAW,OAAO,CAAC,MAAM,MAAM,MAAM,KAAK,GAAG;AAC3C,UAAI,KAAK,UAAU,CAAC,IAAI,WAAW,CAAC,IAAI,QAAQ;AAC9C,cAAM,OAAO,kBAAkB,IAAI,OAAO,IAAI;AAC9C,cAAM,MAAM,cAAc,IAAI,IAAI,OAAO,QAAQ,KAAK,oBAAI,IAAY;AACtE,YAAI,IAAI,IAAI;AACZ,sBAAc,IAAI,IAAI,OAAO,UAAU,GAAG;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAwB,CAAC;AAC/B,MAAI,cAAc,OAAO,GAAG;AAC1B,UAAM,UAAU,oBAAI,IAAY;AAChC,eAAW,CAAC,UAAU,KAAK,KAAK,CAAC,GAAG,cAAc,QAAQ,CAAC,EAAE,KAAK,GAAG;AACnE,YAAM,UAAU,UAAU,QAAQ,QAAQ;AAC1C,YAAM,aAAuB,CAAC;AAC9B,iBAAW,QAAQ,CAAC,GAAG,KAAK,EAAE,KAAK,GAAG;AACpC,YAAI,QAAQ,IAAI,IAAI,GAAG;AACrB,gBAAM,QAAQ,GAAG,IAAI,IAAI,QAAQ,IAAI;AACrC,qBAAW,KAAK,GAAG,IAAI,OAAO,KAAK,EAAE;AACrC,kBAAQ,IAAI,KAAK;AACjB,mBAAS,IAAI,GAAG,QAAQ,KAAK,IAAI,IAAI,KAAK;AAAA,QAC5C,OAAO;AACL,qBAAW,KAAK,IAAI;AACpB,kBAAQ,IAAI,IAAI;AAChB,mBAAS,IAAI,GAAG,QAAQ,KAAK,IAAI,IAAI,IAAI;AAAA,QAC3C;AAAA,MACF;AACA,kBAAY,KAAK,YAAY,WAAW,KAAK,IAAI,CAAC,YAAY,OAAO,IAAI;AAAA,IAC3E;AAAA,EACF;AAGA,QAAM,EAAE,eAAe,eAAe,IAAI,kBAAkB,OAAO;AAGnE,QAAM,UAAU,oBAAI,IAAoB;AACxC,QAAM,QAAkB,CAAC;AACzB,QAAM,aAAuB,CAAC;AAC9B,MAAI,OAAO;AAEX,QAAM,eAAe,CACnB,KACA,WAC2C;AAE3C,QAAI,IAAI,QAAQ;AACd,YAAM,IAAI,QAAQ,aAAa,IAAI,MAAM;AACzC,iBAAW,CAAC,GAAG,CAAC,KAAK,EAAE,mBAAoB,SAAQ,IAAI,GAAG,CAAC;AAC3D,aAAO,EAAE,MAAM,EAAE,WAAW;AAAA,IAC9B;AAEA,QAAI,IAAI,SAAS;AACf,UAAI,CAAC,eAAe;AAClB,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM,uDAAuD,QAAQ,IAAI;AAAA,QAC3E;AAAA,MACF;AACA,aAAO,EAAE,MAAM,aAAa,IAAI,SAAS,MAAM,EAAE;AAAA,IACnD;AACA,QAAI,IAAI,QAAQ;AACd,UAAI,CAAC,eAAe;AAClB,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM,uDAAuD,QAAQ,IAAI;AAAA,QAC3E;AAAA,MACF;AACA,YAAM,OAAO,kBAAkB,IAAI,OAAO,IAAI;AAC9C,YAAM,QAAQ,SAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,IAAI,EAAE,KAAK;AACjE,YAAM,SAAS,IAAI,OAAO,KAAK,MAAM,KAAK,MAAM;AAChD,aAAO,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;AAAA,IACrC;AACA,WAAO;AAAA,EACT;AAEA,aAAW,SAAS,SAAS;AAC3B,UAAM,QAAkB,CAAC;AACzB,UAAM,SAAS,eAAe,IAAI,KAAK,KAAK;AAC5C,QAAI;AAEJ,QAAI,MAAM,YAAY,MAAM,SAAS,SAAS,GAAG;AAC/C,iBAAW,KAAK,MAAM,SAAU,OAAM,KAAK,eAAe,CAAC,EAAE;AAAA,IAC/D;AAEA,QAAI,MAAM,MAAM;AACd,YAAM,WAAW,aAAa,MAAM,MAAM,MAAM;AAChD,UAAI,UAAU,MAAM;AAClB,cAAM,KAAK,eAAe,MAAM,SAAS,SAAS,SAAS,IAAI,EAAE;AAAA,MACnE,WAAW,UAAU;AACnB,eAAO;AACP,oBAAY,GAAG,MAAM,QAAQ;AAC7B,cAAM,KAAK,gBAAgB,SAAS,MAAM,SAAS,IAAI,GAAG;AAC1D,cAAM,KAAK,eAAe,MAAM,QAAQ,UAAU,QAAQ,UAAU,SAAS,CAAC,GAAG;AAAA,MACnF;AAAA,IACF;AACA,QAAI,MAAM,OAAO;AACf,YAAM,WAAW,aAAa,MAAM,OAAO,MAAM;AACjD,UAAI,UAAU,MAAM;AAClB,cAAM,KAAK,eAAe,MAAM,SAAS,UAAU,SAAS,IAAI,EAAE;AAAA,MACpE,WAAW,UAAU;AACnB,eAAO;AACP,cAAM,aAAa,GAAG,MAAM,QAAQ;AACpC,cAAM,KAAK,gBAAgB,UAAU,MAAM,SAAS,IAAI,GAAG;AAC3D,cAAM,KAAK,eAAe,MAAM,QAAQ,WAAW,QAAQ,UAAU,UAAU,CAAC,GAAG;AAAA,MACrF;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,KAAK,MAAM,MAAM,SAAS,IAAI,GAAG,OAAO,EAAE;AAChD,QAAI,UAAW,YAAW,KAAK,KAAK,KAAK,UAAU,MAAM,SAAS,CAAC,KAAK,SAAS,GAAG;AAAA,EACtF;AAEA,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,QAAkB,CAAC,wDAAwD;AACjF,MAAI,eAAe;AACjB,UAAM,YAAY,QAAQ,aAAa;AACvC,UAAM,KAAK,sBAAsB,SAAS,IAAI;AAAA,EAChD,OAAO;AACL,eAAW,OAAO,QAAQ,iBAAiB,EAAE,MAAM,KAAK,CAAC,EAAG,OAAM,KAAK,GAAG;AAAA,EAC5E;AACA,QAAM,KAAK,GAAG,WAAW;AACzB,QAAM,KAAK,EAAE;AAGb,QAAM,YAAY,oBAAI,IAAoB;AAC1C,aAAW,CAAC,GAAG,CAAC,KAAK,cAAe,WAAU,IAAI,GAAG,CAAC;AACtD,aAAW,CAAC,GAAG,CAAC,KAAK,QAAS,KAAI,CAAC,UAAU,IAAI,CAAC,EAAG,WAAU,IAAI,GAAG,CAAC;AAEvE,MAAI,UAAU,OAAO,GAAG;AACtB,UAAM,KAAK,sDAAsD;AACjE,eAAW,CAAC,GAAG,CAAC,KAAK,UAAW,OAAM,KAAK,SAAS,CAAC,MAAM,CAAC,GAAG;AAC/D,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,GAAG,KAAK;AACnB,QAAM,KAAK,2CAAsC;AACjD,QAAM,KAAK,8BAA8B;AACzC,QAAM,KAAK,GAAG,UAAU;AACxB,QAAM,KAAK,aAAa;AACxB,QAAM,KAAK,EAAE;AACb,SAAO,MAAM,KAAK,IAAI;AACxB;;;AC1YA,SAAS,SAAAC,QAAO,aAAAC,kBAAiB;AACjC,SAAS,QAAAC,aAAY;AAErB,eAAsB,UACpB,QACA,eAAe,OACf,WAAW,OACI;AACf,QAAMF,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,QAAM,UAAU,CAAC,+BAA+B,8BAA8B;AAC9E,MAAI,cAAc;AAChB,YAAQ,KAAK,2BAA2B;AAAA,EAC1C;AACA,MAAI,UAAU;AACZ,YAAQ,KAAK,6BAA6B;AAAA,EAC5C;AACA,QAAM,UAAU,CAAC,0DAA0D,GAAG,SAAS,EAAE,EAAE;AAAA,IACzF;AAAA,EACF;AACA,QAAMC,WAAUC,MAAK,QAAQ,YAAY,GAAG,SAAS,MAAM;AAC7D;;;ACpBA,SAAS,SAAAC,QAAO,aAAAC,kBAAiB;AACjC,SAAS,QAAAC,OAAM,YAAAC,iBAAgB;AAa/B,eAAsB,UACpB,OACA,QACA,WAA6B,CAAC,GACf;AACf,QAAMH,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AAEvC,QAAM,gBACJ,MAAM,SAAS,IAAI,MAAM,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,IAAI,CAAC,EAAE,KAAK,KAAK,IAAI;AAE5E,QAAM,UAAU,MACb,IAAI,CAAC,MAAM;AACV,UAAM,MAAM,YAAY,EAAE,IAAI,IAAI,KAAK,UAAU,EAAE,IAAI,IAAI,EAAE;AAC7D,UAAM,YAAY,sBAAsB,GAAG,MAAM;AACjD,WAAO,OAAO,GAAG,KAAK,SAAS;AAAA,EACjC,CAAC,EACA,KAAK,IAAI;AAEZ,QAAM,cACJ;AAEF,QAAM,mBAAmB,sBAAsB,SAAS,eAAe,IAAI;AAE3E,QAAM,UAAU;AAAA;AAAA,gCAA2F,aAAa;AAAA,EAAM,WAAW;AAAA;AAAA;AAAA,EAA8E,OAAO;AAAA;AAAA,EAAU,gBAAgB;AAAA;AAExP,QAAMC,WAAUC,MAAK,QAAQ,YAAY,GAAG,SAAS,MAAM;AAC7D;AASA,SAAS,sBAAsB,aAA+C;AAC5E,MAAI,CAAC,YAAa,QAAO;AAGzB,MAAI,YAAY,aAAa;AAC3B,WAAO;AAAA;AAAA,yCAAiH,YAAY,UAAU;AAAA;AAAA,EAChJ;AAGA,MAAI,CAAC,YAAY,cAAc,YAAY,WAAW,WAAW,EAAG,QAAO;AAE3E,QAAM,YAAY,YAAY,WAAW,IAAI,CAAC,MAAM,OAAO,EAAE,IAAI,KAAK,EAAE,IAAI,GAAG,EAAE,KAAK,IAAI;AAE1F,SAAO;AAAA;AAAA,EAAuC,SAAS;AAAA;AAAA;AACzD;AAOA,SAAS,sBAAsB,MAAsB,QAAwB;AAC3E,MAAI,aAAaC,UAAS,QAAQ,KAAK,YAAY,EAAE,QAAQ,wBAAwB,EAAE;AACvF,MAAI,CAAC,WAAW,WAAW,GAAG,GAAG;AAC/B,iBAAa,KAAK,UAAU;AAAA,EAC9B;AACA,SAAO,6BAA6B,UAAU;AAChD;AAEA,SAAS,YAAY,MAAuB;AAC1C,SAAO,CAAC,6BAA6B,KAAK,IAAI;AAChD;;;AChFA,SAAS,SAAAC,QAAO,aAAAC,kBAAiB;AACjC,SAAS,QAAAC,cAAY;AAUrB,eAAsB,WAAW,QAA2B,QAA+B;AACzF,QAAMF,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AAEvC,QAAM,UAAU,gBAAgB,MAAM;AACtC,QAAMC,WAAUC,OAAK,QAAQ,WAAW,GAAG,SAAS,MAAM;AAC5D;AAEA,SAAS,gBAAgB,QAAmC;AAC1D,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO,WAAW;AAAA,EACpB;AAEA,QAAM,UAAU,OACb,IAAI,CAAC,MAAM,KAAK,KAAK,UAAU,EAAE,IAAI,CAAC,KAAK,KAAK,UAAU,EAAE,IAAI,CAAC,GAAG,EACpE,KAAK,IAAI;AAEZ,QAAM,iBAAiB,OAAO,IAAI,CAAC,MAAM,OAAO,KAAK,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI;AAEnF,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,cAAc;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,aAAqB;AAC5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;;;AV1GA,eAAsB,SACpB,QACA,cAAiC,CAAC,GACnB;AAGf,QAAM,aAAa,OAAO,cAAc,CAAC;AACzC,MAAI,SAAS;AACb,QAAM,MAAM,uBAAuB,QAAQ,MAAM,MAAM;AACvD,MAAI,WAAW,SAAS,GAAG;AACzB,aAAS,MAAM,qBAAqB,QAAQ,YAAY,GAAG;AAAA,EAC7D;AAGA,MAAI,OAAO,OAAO;AAChB,UAAM,cAAc,OAAO;AAC3B,UAAM,QAAQ,MAAM,cAAc;AAAA,MAChC,MAAM,YAAY;AAAA,MAClB,KAAK,OAAO,QAAQ;AAAA,MACpB,aAAa,YAAY;AAAA,MACzB,uBAAuB,YAAY;AAAA,IACrC,CAAC;AAED,UAAM,cAAc,8BAA8B,MAAM;AAExD,UAAM,UAAU,OAAO,OAAO,QAAQ,QAAQ;AAAA,MAC5C,aAAa,YAAY;AAAA,MACzB;AAAA,IACF,CAAC;AACD,UAAM,UAAU,OAAO,OAAO,QAAQ,MAAM;AAAA,EAC9C;AAEA,QAAM,YAAY,OAAO,SAAS;AAClC,QAAM,eAAe,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ;AAElD,MAAI,WAAW;AACb,UAAM,WAAW,QAAQ,OAAO,QAAQ,MAAM;AAAA,EAChD;AAEA,MAAI,cAAc;AAChB,UAAM,QAAQ,QAAQ,OAAO,QAAQ,QAAQ;AAAA,MAC3C,GAAI,OAAO,SAAS,aAAa,EAAE,mBAAmB,OAAO,QAAQ,WAAW,IAAI,CAAC;AAAA,MACrF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,MAAM,UAAU,QAAQ,OAAO,QAAQ,QAAQ,OAAO,OAAO,OAAO,UAAU;AAE/F,QAAM,UAAU,OAAO,QAAQ,QAAQ,cAAc,QAAQ;AAG7D,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,aAAa,MAAM,oBAAoB,YAAY,GAAG;AAC5D,eAAW,QAAQ,YAAY;AAC7B,YAAM,OAAOC,OAAK,OAAO,QAAQ,QAAQ,KAAK,IAAI;AAClD,YAAMC,OAAMC,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,YAAMC,WAAU,MAAM,KAAK,UAAU,MAAM;AAAA,IAC7C;AAAA,EACF;AACF;;;AWvFA,SAAS,YAAY;AACrB,SAAS,SAAAC,QAAO,YAAAC,WAAU,cAAc;AACxC,SAAS,QAAAC,cAAY;AAErB,IAAM,YAAY;AAOlB,SAAS,eAAe,KAAsB;AAC5C,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWA,eAAsB,YACpB,QACkD;AAClD,QAAMF,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,QAAM,WAAWE,OAAK,QAAQ,SAAS;AAEvC,QAAM,WAAqB,EAAE,KAAK,QAAQ,KAAK,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE;AAGnF,MAAI;AACF,UAAM,KAAK,MAAM,KAAK,UAAU,IAAI;AACpC,UAAM,GAAG,UAAU,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AACnE,UAAM,GAAG,MAAM;AAAA,EACjB,SAAS,KAAc;AACrB,QAAK,IAA8B,SAAS,UAAU;AAEpD,UAAI;AACF,cAAM,MAAM,MAAMD,UAAS,UAAU,MAAM;AAC3C,cAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,YAAI,eAAe,SAAS,GAAG,EAAG,QAAO;AAEzC,cAAM,OAAO,QAAQ;AACrB,eAAO,YAAY,MAAM;AAAA,MAC3B,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,SAAS,YAAY;AACnB,UAAI;AACF,cAAM,OAAO,QAAQ;AAAA,MACvB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;;;ApB3DA,IAAM,oBAAoB;AAO1B,IAAM,gBAAyB,EAAE,OAAO,YAAY;AAAC,EAAE;AAevD,eAAsB,MAAM,QAAwB,UAAyC;AAC3F,QAAM,OAAO,MAAM,YAAY,OAAO,QAAQ,MAAM;AAEpD,MAAI,SAAS,MAAM;AAEjB,QAAI,YAAY;AAChB,QAAI;AACF,YAAM,MAAM,MAAME,UAASC,OAAK,OAAO,QAAQ,QAAQ,eAAe,GAAG,MAAM;AAC/E,YAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,UAAI,KAAK,QAAQ,OAAW,aAAY,OAAO,KAAK,GAAG;AAAA,IACzD,QAAQ;AAAA,IAER;AACA,YAAQ;AAAA,MACN,mEAA8D,SAAS,uCAAuC,OAAO,QAAQ,MAAM;AAAA,IACrI;AACA,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,gBAAgB,MAAM,sBAAsB;AAAA,MAChD,KAAK,OAAO,QAAQ;AAAA,MACpB,MAAM,OAAO,UAAU;AAAA,MACvB,GAAI,OAAO,KAAK,WAAW,EAAE,UAAU,OAAO,IAAI,SAAS,IAAI,CAAC;AAAA,IAClE,CAAC;AACD,UAAM,SAAS,QAAQ,aAAa;AAAA,EACtC,SAAS,KAAK;AAEZ,YAAQ;AAAA,MACN,gFAAgF,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAClI;AACA,QAAI;AACF,YAAM,SAAS,MAAM;AAAA,IACvB,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,MAAI;AAGJ,QAAM,YAAY,OAAO,OAAO,QAAQ;AACxC,QAAM,eAAe,SAAS,MAAMA,OAAK,OAAO,QAAQ,KAAK,SAAS,GAAG;AAAA,IACvE,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,kBAAkB,EAAE,oBAAoB,IAAI,cAAc,GAAG;AAAA,EAC/D,CAAC;AAED,WAAS,0BAAgC;AACvC,QAAI,uBAAuB,QAAW;AACpC,mBAAa,kBAAkB;AAAA,IACjC;AACA,yBAAqB,WAAW,YAAY;AAC1C,2BAAqB;AACrB,UAAI;AACF,cAAM,SAAS,MAAM;AAAA,MACvB,SAAS,KAAK;AACZ,gBAAQ;AAAA,UACN;AAAA,UACA,eAAe,QAAQ,IAAI,UAAU;AAAA,QACvC;AAAA,MACF;AACA,iBAAW;AAAA,IACb,GAAG,iBAAiB;AAAA,EACtB;AAEA,eAAa,GAAG,OAAO,uBAAuB;AAC9C,eAAa,GAAG,UAAU,uBAAuB;AACjD,eAAa,GAAG,UAAU,uBAAuB;AAGjD,MAAI;AAEJ,QAAM,mBAAmB,SAAS,MAAMA,OAAK,OAAO,QAAQ,KAAK,OAAO,UAAU,IAAI,GAAG;AAAA,IACvF,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,kBAAkB,EAAE,oBAAoB,IAAI,cAAc,GAAG;AAAA,EAC/D,CAAC;AAED,WAAS,8BAAoC;AAC3C,QAAI,2BAA2B,QAAW;AACxC,mBAAa,sBAAsB;AAAA,IACrC;AACA,6BAAyB,WAAW,YAAY;AAC9C,+BAAyB;AACzB,UAAI;AACF,cAAM,SAA4B,MAAM,sBAAsB;AAAA,UAC5D,KAAK,OAAO,QAAQ;AAAA,UACpB,MAAM,OAAO,UAAU;AAAA,UACvB,GAAI,OAAO,KAAK,WAAW,EAAE,UAAU,OAAO,IAAI,SAAS,IAAI,CAAC;AAAA,QAClE,CAAC;AAMD,cAAM,SAAS,QAAQ,MAAM;AAAA,MAC/B,SAAS,KAAK;AACZ,gBAAQ;AAAA,UACN;AAAA,UACA,eAAe,QAAQ,IAAI,UAAU;AAAA,QACvC;AAAA,MACF;AACA,iBAAW;AAAA,IACb,GAAG,OAAO,UAAU,UAAU;AAAA,EAChC;AAEA,mBAAiB,GAAG,OAAO,2BAA2B;AACtD,mBAAiB,GAAG,UAAU,2BAA2B;AACzD,mBAAiB,GAAG,UAAU,2BAA2B;AAMzD,QAAM,eAAe,SAAS,MAAMA,OAAK,OAAO,QAAQ,KAAK,OAAO,MAAM,KAAK,GAAG;AAAA,IAChF,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,kBAAkB,EAAE,oBAAoB,IAAI,cAAc,GAAG;AAAA,EAC/D,CAAC;AAED,eAAa,GAAG,OAAO,2BAA2B;AAClD,eAAa,GAAG,UAAU,2BAA2B;AACrD,eAAa,GAAG,UAAU,2BAA2B;AAErD,SAAO;AAAA,IACL,OAAO,YAAY;AACjB,UAAI,uBAAuB,QAAW;AACpC,qBAAa,kBAAkB;AAC/B,6BAAqB;AAAA,MACvB;AACA,UAAI,2BAA2B,QAAW;AACxC,qBAAa,sBAAsB;AACnC,iCAAyB;AAAA,MAC3B;AACA,YAAM,aAAa,MAAM;AACzB,YAAM,iBAAiB,MAAM;AAC7B,YAAM,aAAa,MAAM;AACzB,YAAM,KAAK,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;;;AJ9HO,IAAM,yBAAyB,OAAO,+BAA+B;AAMrE,SAAS,UAAU,SAA+B,KAAkC;AACzF,MAAI,QAAQ,YAAY,OAAW,QAAO,QAAQ;AAClD,SAAO,QAAQ;AACjB;AASO,IAAM,uBAAN,MAA8E;AAAA,EAInF,YAA6D,SAA+B;AAA/B;AAAA,EAAgC;AAAA,EAH5E,SAAS,IAAI,OAAO,eAAe;AAAA,EAC5C,UAA0B;AAAA,EAIlC,MAAM,yBAAwC;AAC5C,QAAI,CAAC,UAAU,KAAK,SAAS,QAAQ,IAAI,QAAQ,EAAG;AAEpD,UAAM,EAAE,SAAS,UAAU,KAAK,GAAG,WAAW,IAAI,KAAK;AACvD,QAAI;AACF,YAAM,SAAS,cAAc,YAAY,OAAO,QAAQ,IAAI,CAAC;AAC7D,WAAK,UAAU,MAAM,MAAM,MAAM;AACjC,WAAK,OAAO,IAAI,YAAY,OAAO,UAAU,IAAI,WAAM,OAAO,QAAQ,MAAM,EAAE;AAAA,IAChF,SAAS,KAAK;AAEZ,WAAK,OAAO;AAAA,QACV,oCAAoC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,kBAAiC;AACrC,UAAM,KAAK,SAAS,MAAM;AAC1B,SAAK,UAAU;AAAA,EACjB;AACF;AA1Ba,uBAAN;AAAA,EADN,WAAW;AAAA,EAKG,0BAAO,sBAAsB;AAAA,GAJ/B;AAkCN,IAAM,sBAAN,MAA0B;AAAA,EAC/B,OAAO,QAAQ,UAAgC,CAAC,GAAkB;AAChE,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW,CAAC,EAAE,SAAS,wBAAwB,UAAU,QAAQ,GAAG,oBAAoB;AAAA,IAC1F;AAAA,EACF;AACF;AAPa,sBAAN;AAAA,EADN,OAAO,CAAC,CAAC;AAAA,GACG;","names":["readFile","join","join","resolve","Node","Node","SyntaxKind","Node","resolve","reExportsName","sourceName","node","Node","Node","Node","Node","Node","Node","SyntaxKind","Node","SyntaxKind","resolve","join","Node","Node","firstArg","mkdir","writeFile","dirname","join","join","relative","fg","join","Node","Project","SyntaxKind","firstArg","isAbsolute","join","relative","Project","Project","join","relative","isAbsolute","mkdir","writeFile","join","mkdir","writeFile","join","relative","mkdir","writeFile","join","mkdir","writeFile","join","relative","mkdir","writeFile","join","join","mkdir","dirname","writeFile","mkdir","readFile","join","readFile","join"]}
|