@spfn/core 0.3.0-beta.28 → 0.3.0-beta.29
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/dist/codegen/index.d.ts +65 -2
- package/dist/codegen/index.js +160 -15
- package/dist/codegen/index.js.map +1 -1
- package/dist/contract/index.d.ts +1 -1
- package/dist/{error-TsUIjp_x.d.ts → error-CIZlYJlL.d.ts} +1 -1
- package/dist/ops/index.d.ts +3 -3
- package/dist/ops/index.js +15 -5
- package/dist/ops/index.js.map +1 -1
- package/dist/route/index.d.ts +2 -2
- package/dist/route/index.js +15 -5
- package/dist/route/index.js.map +1 -1
- package/dist/{router-4YoIy5fN.d.ts → router-C57y-vz1.d.ts} +12 -0
- package/dist/server/index.js +15 -5
- package/dist/server/index.js.map +1 -1
- package/dist/state/index.js +8 -3
- package/dist/state/index.js.map +1 -1
- package/dist/surface/index.d.ts +3 -3
- package/dist/surface/index.js +15 -5
- package/dist/surface/index.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen/README.md +89 -2
- package/src/state/README.md +67 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/core/orchestrator.ts","../../src/codegen/core/config-loader.ts","../../src/codegen/generators/typescript.ts","../../src/codegen/generators/contract-guard.ts","../../src/codegen/generators/router-module.ts","../../src/codegen/generators/route-map.ts","../../src/codegen/generators/contract.ts","../../src/codegen/generators/index.ts"],"names":["chokidarWatch","resolve","logger","join","generators","compiler","existsSync","target","relative","createJiti","readFileSync","dirname","genLogger","loadRouter"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Codegen Orchestrator\n *\n * Manages multiple code generators and coordinates their execution\n */\n\nimport { watch as chokidarWatch } from 'chokidar';\nimport { join, relative, sep } from 'path';\nimport mm from 'micromatch';\nimport type { Generator, GeneratorOptions, GeneratorTrigger } from './generator';\nimport { logger } from '@spfn/core/logger';\n\nconst orchestratorLogger = logger.child('@spfn/core:orchestrator');\n\nexport interface OrchestratorOptions\n{\n /** List of generators to orchestrate */\n generators: Generator[];\n\n /** Project root directory */\n cwd?: string;\n\n /** Enable debug logging */\n debug?: boolean;\n\n /**\n * Rethrow a generator failure instead of only logging it\n *\n * Off by default, which keeps watch mode alive through a half-edited file.\n * A build turns it on: a generator that refuses — a broken contract, a\n * router that will not load — has to reach the exit code, or the refusal\n * scrolls past and the build ships anyway.\n */\n throwOnError?: boolean;\n}\n\nexport class CodegenOrchestrator\n{\n private readonly generators: Generator[];\n private readonly cwd: string;\n private readonly debug: boolean;\n private readonly throwOnError: boolean;\n private isGenerating = false;\n private pendingRegenerations = new Set<string>();\n private watcher?: ReturnType<typeof chokidarWatch>;\n private watcherClosePromise?: { resolve: () => void; reject: (error: Error) => void };\n\n constructor(options: OrchestratorOptions)\n {\n this.generators = options.generators;\n this.cwd = options.cwd ?? process.cwd();\n this.debug = options.debug ?? false;\n this.throwOnError = options.throwOnError ?? false;\n }\n\n /**\n * Close watcher and cleanup resources\n */\n async close(): Promise<void>\n {\n if (this.watcher)\n {\n if (this.debug)\n {\n orchestratorLogger.info('Closing watcher');\n }\n await this.watcher.close();\n this.watcher = undefined;\n }\n\n // Resolve the watch promise if it exists\n if (this.watcherClosePromise)\n {\n this.watcherClosePromise.resolve();\n this.watcherClosePromise = undefined;\n }\n }\n\n /**\n * Check if generator should run for given trigger\n */\n private shouldRun(generator: Generator, trigger: GeneratorTrigger): boolean\n {\n const runOn = generator.runOn ?? ['watch', 'manual', 'build'];\n\n return runOn.includes(trigger);\n }\n\n /**\n * Run all generators once\n *\n * @param trigger - How the generators are being triggered\n */\n async generateAll(trigger: GeneratorTrigger = 'manual'): Promise<void>\n {\n // Always log generation start\n const activeGenerators = this.generators.filter(g => this.shouldRun(g, trigger));\n\n if (activeGenerators.length === 0)\n {\n orchestratorLogger.info('No generators to run for this trigger', { trigger });\n\n return;\n }\n\n orchestratorLogger.info(`Running ${activeGenerators.length} generator(s)`, {\n generators: activeGenerators.map(g => g.name).join(', '),\n trigger,\n });\n\n for (const generator of this.generators)\n {\n // Check if generator should run for this trigger\n if (!this.shouldRun(generator, trigger))\n {\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Skipped (runOn: ${generator.runOn?.join(', ') ?? 'default'})`);\n }\n\n continue;\n }\n\n try\n {\n const startTime = Date.now();\n\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug,\n trigger: {\n type: trigger,\n },\n };\n\n await generator.generate(genOptions);\n\n const duration = Date.now() - startTime;\n orchestratorLogger.info(`[${generator.name}] ✓ Generated successfully (${duration}ms)`);\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] ✗ Generation failed`, err);\n\n if (this.throwOnError)\n {\n throw err;\n }\n }\n }\n }\n\n /**\n * Start watch mode\n */\n async watch(): Promise<void>\n {\n // Initial generation with 'watch' trigger\n await this.generateAll('watch');\n\n // Collect all watch patterns from generators\n const allPatterns = this.generators.flatMap(g => g.watchPatterns);\n\n if (allPatterns.length === 0)\n {\n orchestratorLogger.warn('No watch patterns defined, exiting watch mode');\n\n return;\n }\n\n // Extract directories to watch from patterns\n // For pattern like \"watched/**/*.ts\", watch \"watched\" directory\n const dirsToWatch = new Set<string>();\n for (const pattern of allPatterns)\n {\n // Extract base directory from glob pattern (e.g., \"src/**/*.ts\" -> \"src\")\n const baseDir = pattern.split('**')[0].replace(/\\/$/, '') || '.';\n dirsToWatch.add(join(this.cwd, baseDir));\n }\n\n const watchDirs = Array.from(dirsToWatch);\n\n // Always log watch mode start\n orchestratorLogger.info('Watch mode started', {\n watching: watchDirs.length === 1 ? watchDirs[0] : `${watchDirs.length} directories`,\n generators: this.generators.filter(g => this.shouldRun(g, 'watch')).map(g => g.name).join(', '),\n });\n\n if (this.debug)\n {\n orchestratorLogger.info('Watch mode details', {\n patterns: allPatterns,\n watchDirs,\n cwd: this.cwd,\n });\n }\n\n this.watcher = chokidarWatch(watchDirs, {\n // Ignore dotfiles by path segments relative to cwd — matching the absolute\n // path would ignore everything when the checkout itself lives under a dot\n // directory (e.g. .claude/worktrees/<name>), leaving zero watched files\n ignored: (watchedPath: string) => relative(this.cwd, watchedPath)\n .split(sep)\n .some(segment => segment.startsWith('.') && segment !== '.' && segment !== '..'),\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50,\n },\n });\n\n const handleChange = async (absolutePath: string, event: 'add' | 'change' | 'unlink') =>\n {\n // Convert absolute path to relative path for pattern matching\n const filePath = relative(this.cwd, absolutePath);\n\n if (this.isGenerating)\n {\n this.pendingRegenerations.add(absolutePath);\n\n return;\n }\n\n this.isGenerating = true;\n this.pendingRegenerations.clear();\n\n // Always log file changes\n const eventIcon = event === 'add' ? '+' : event === 'unlink' ? '-' : '~';\n orchestratorLogger.info(`File ${eventIcon} ${filePath}`);\n\n // Find matching generators\n let regeneratedCount = 0;\n for (const generator of this.generators)\n {\n // Check if generator should run for 'watch' trigger\n if (!this.shouldRun(generator, 'watch'))\n {\n continue;\n }\n\n const matches = generator.watchPatterns.some(pattern =>\n mm.isMatch(filePath, pattern),\n );\n\n if (matches)\n {\n try\n {\n const startTime = Date.now();\n\n // Call generate() with trigger information\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug,\n trigger: {\n type: 'watch',\n changedFile: {\n path: filePath,\n event,\n },\n },\n };\n\n await generator.generate(genOptions);\n\n const duration = Date.now() - startTime;\n orchestratorLogger.info(`[${generator.name}] ✓ Regenerated (${duration}ms)`);\n regeneratedCount++;\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] ✗ Regeneration failed`, err);\n }\n }\n }\n\n if (regeneratedCount === 0 && this.debug)\n {\n orchestratorLogger.info('No generators matched this file');\n }\n\n this.isGenerating = false;\n\n // Process pending regenerations\n if (this.pendingRegenerations.size > 0)\n {\n const next = Array.from(this.pendingRegenerations)[0];\n await handleChange(next, 'change');\n }\n };\n\n this.watcher\n .on('add', (path) => handleChange(path, 'add'))\n .on('change', (path) => handleChange(path, 'change'))\n .on('unlink', (path) => handleChange(path, 'unlink'));\n\n // Return a promise that resolves when the watcher is closed\n // This allows the caller to await the watch() method and keep the process alive\n return new Promise<void>((resolve, reject) =>\n {\n this.watcherClosePromise = { resolve, reject };\n });\n }\n}\n","/**\n * Codegen Configuration Loader\n *\n * Loads codegen configuration from .spfnrc.ts, .spfnrc.json or package.json\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createJiti } from 'jiti';\nimport type { Generator } from './generator';\nimport { logger } from '@spfn/core/logger';\n\nconst configLogger = logger.child('@spfn/core:codegen-config');\n\n/**\n * Custom generator via file path\n */\ntype CustomGeneratorByPath = { path: string };\n\n/**\n * Package-based generator configuration\n */\ntype PackageGeneratorDef = { name: string; enabled?: boolean } & Record<string, any>;\n\n/**\n * Any generator configuration\n */\nexport type GeneratorConfig = CustomGeneratorByPath | PackageGeneratorDef;\n\n/**\n * Codegen configuration\n */\nexport interface CodegenConfig\n{\n generators?: GeneratorConfig[];\n}\n\n/**\n * Define a generator with type safety\n *\n * @example\n * Custom generator with type parameter:\n * ```ts\n * import { defineGenerator } from '@spfn/core/codegen';\n * import type { MyGeneratorConfig } from 'my-package';\n *\n * const customGen = defineGenerator<MyGeneratorConfig>({\n * name: 'my-package:generator',\n * myOption: 'value',\n * });\n * ```\n */\nexport function defineGenerator<T extends Record<string, any>>(config: T): T;\nexport function defineGenerator(config: PackageGeneratorDef): PackageGeneratorDef;\nexport function defineGenerator(config: CustomGeneratorByPath): CustomGeneratorByPath;\nexport function defineGenerator<T extends Record<string, any>>(config: T): T\n{\n return config;\n}\n\n/**\n * Helper function to define codegen configuration with type safety\n *\n * @example\n * With custom generator:\n * ```ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n * import type { MyGeneratorConfig } from 'my-package';\n *\n * const customGen = defineGenerator<MyGeneratorConfig>({\n * name: 'my-package:custom',\n * myOption: 'value', // Type-safe!\n * });\n *\n * export default defineConfig({\n * generators: [customGen]\n * });\n * ```\n */\nexport function defineConfig(config: CodegenConfig): CodegenConfig\n{\n return config;\n}\n\n/**\n * Load codegen configuration from .spfnrc.ts, .spfnrc.json or package.json\n */\nexport function loadCodegenConfig(cwd: string): CodegenConfig\n{\n // 1. Check .spfnrc.ts (highest priority)\n const rcTsPath = join(cwd, '.spfnrc.ts');\n if (existsSync(rcTsPath))\n {\n try\n {\n const jiti = createJiti(cwd, {\n interopDefault: true,\n moduleCache: false,\n });\n\n const module = jiti(rcTsPath);\n const config = module.default || module;\n\n if (config && typeof config === 'object')\n {\n configLogger.info('Loaded config from .spfnrc.ts');\n\n return config as CodegenConfig;\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.warn('Failed to load .spfnrc.ts', err);\n }\n }\n\n // 2. Check .spfnrc.json\n const rcPath = join(cwd, '.spfnrc.json');\n if (existsSync(rcPath))\n {\n try\n {\n const content = readFileSync(rcPath, 'utf-8');\n const config = JSON.parse(content);\n\n if (config.codegen)\n {\n configLogger.info('Loaded config from .spfnrc.json');\n\n return config.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse .spfnrc.json', error as Error);\n }\n }\n\n // 3. Check package.json\n const pkgPath = join(cwd, 'package.json');\n if (existsSync(pkgPath))\n {\n try\n {\n const content = readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n\n if (pkg.spfn?.codegen)\n {\n configLogger.info('Loaded config from package.json');\n\n return pkg.spfn.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse package.json', error as Error);\n }\n }\n\n // 4. Default configuration (empty - no generators by default)\n configLogger.info('Using default config (no generators)');\n\n return {\n generators: [],\n };\n}\n\n/**\n * Load generator from package\n *\n * Supports format: \"package:generator-name\" or \"@scope/package:generator-name\"\n */\nasync function loadGeneratorFromPackage(\n packageName: string,\n generatorName: string,\n config: Record<string, any>,\n): Promise<Generator | null>\n{\n try\n {\n // Try to load package/generators export using jiti for better module resolution\n const jiti = createJiti(import.meta.url, {\n interopDefault: true,\n moduleCache: false,\n });\n\n const generatorsModule = jiti(`${packageName}/codegen`);\n\n // Look for generator by name in registry\n if (generatorsModule.generators?.[generatorName])\n {\n const createFn = generatorsModule.generators[generatorName];\n const generator = createFn(config);\n configLogger.info(`Loaded ${packageName}:${generatorName}`);\n\n return generator;\n }\n\n // Fallback: try conventional name (createXxxGenerator)\n const conventionalName = `create${capitalize(generatorName)}Generator`;\n if (generatorsModule[conventionalName])\n {\n const createFn = generatorsModule[conventionalName];\n const generator = createFn(config);\n configLogger.info(`Loaded ${packageName}:${generatorName} (via ${conventionalName})`);\n\n return generator;\n }\n\n configLogger.warn(\n `Generator \"${generatorName}\" not found in ${packageName}/codegen. ` +\n `Expected: generators.${generatorName} or ${conventionalName}`,\n );\n\n return null;\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.warn(\n `Failed to load ${packageName}:${generatorName}. ` +\n `Make sure ${packageName} is installed. Error: ${err.message}`,\n );\n\n return null;\n }\n}\n\n/**\n * Capitalize first letter\n */\nfunction capitalize(str: string): string\n{\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Create generator instances from configuration\n */\nexport async function createGeneratorsFromConfig(config: CodegenConfig, cwd: string): Promise<Generator[]>\n{\n const generators: Generator[] = [];\n\n if (!config.generators || config.generators.length === 0)\n {\n return generators;\n }\n\n for (const generatorConfig of config.generators)\n {\n try\n {\n // Already instantiated Generator (has generate function)\n // This prevents double-loading when users accidentally call factory directly\n if ('generate' in generatorConfig && typeof (generatorConfig as any).generate === 'function')\n {\n generators.push(generatorConfig as Generator);\n configLogger.info(`Generator instance added: ${(generatorConfig as Generator).name}`);\n continue;\n }\n\n // Custom generator (via file path)\n if ('path' in generatorConfig)\n {\n const generatorPath = generatorConfig.path.startsWith('.')\n ? join(cwd, generatorConfig.path)\n : generatorConfig.path;\n\n configLogger.info(`Loading custom generator: ${generatorPath}`);\n\n let module: any;\n\n // Use jiti for .ts files, regular import for .js\n if (generatorPath.endsWith('.ts'))\n {\n const jiti = createJiti(cwd, {\n interopDefault: true,\n });\n module = jiti(generatorPath);\n }\n else\n {\n module = await import(generatorPath);\n }\n\n const createGenerator = module.default || module.createGenerator || module;\n\n if (typeof createGenerator === 'function')\n {\n const generator = createGenerator();\n generators.push(generator);\n configLogger.info(`Custom generator loaded: ${generator.name}`);\n }\n else\n {\n configLogger.warn(`Invalid generator at ${generatorPath}: expected function`);\n }\n }\n // Package-based generator: \"package:name\" or \"@scope/package:name\"\n else if ('name' in generatorConfig && generatorConfig.name.includes(':'))\n {\n if (generatorConfig.enabled !== false)\n {\n const [packageName, generatorName] = generatorConfig.name.split(':');\n const { enabled, name, ...generatorOptions } = generatorConfig;\n\n const generator = await loadGeneratorFromPackage(\n packageName,\n generatorName,\n generatorOptions,\n );\n\n if (generator)\n {\n generators.push(generator);\n }\n }\n }\n // Unknown generator name format\n else if ('name' in generatorConfig)\n {\n configLogger.warn(\n `Invalid generator name \"${generatorConfig.name}\". ` +\n `Use package:name format (e.g., \"@spfn/core:contract\")`,\n );\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.error('Failed to load generator', err);\n }\n }\n\n return generators;\n}\n","/**\n * TypeScript, loaded on first use\n *\n * Two things here read TypeScript's own parser: the `paths` a router's imports\n * resolve through, and the guard that reads `defineRouter({...})` out of the\n * router file. Both run only while a router is being read.\n *\n * `generators/index.ts` is re-exported from `@spfn/core/codegen`, so a\n * top-level `import ts from 'typescript'` loaded the whole compiler wherever\n * that entry is imported: `spfn dev` startup, the watcher child, every\n * `.spfnrc.ts` evaluation, and `spfn codegen list` — none of which resolve an\n * alias or parse a router. It cost ~0.3s and ~70MB to hand back a factory\n * function.\n *\n * `createRequire` rather than a dynamic `import()`: both callers are\n * synchronous, and the guard's whole job is to run before anything is written.\n */\n\nimport { createRequire } from 'module';\n\nlet compiler: typeof import('typescript') | undefined;\n\n/** The compiler, loaded on the first call and kept for the rest of the process. */\nexport function typescript(): typeof import('typescript')\n{\n compiler ??= createRequire(import.meta.url)('typescript') as typeof import('typescript');\n\n return compiler;\n}\n","/**\n * Router registration guard\n *\n * A route registered only behind a feature flag or an environment check makes\n * generated output depend on how the generator happened to run. The contract\n * then describes a promise nobody made, and the route map leaves out a name\n * `registerRoutes` registers in production — so `api.admin.call()` typechecks\n * and 404s wherever the flag differs.\n *\n * What it reads is the router the generator was pointed at: the export the\n * loader found the router under, and the routers that export mounts by name\n * from the same file, since a nested router's routes land in the same flat map.\n * A `defineRouter(` the file writes but the app router never reaches — a second\n * router a test harness mounts, say — registers nothing in production and is\n * not scanned.\n *\n * Reading is done with TypeScript's parser rather than a regular expression\n * over the text. A spread is a syntax node there, so a JSDoc that spells\n * `defineRouter({ ... })` in prose, a brace inside a route path, and a comment\n * holding an old router are not router source. Only a spread whose expression\n * reads a condition is refused — a ternary, `&&`, `||`, `??`. A call is\n * allowed: `...metadataRoutes(config, resource)` is how `@spfn/mcp` composes\n * its router, and loading yields exactly the routes it returns.\n *\n * Past it, by construction: a conditional spread inside an imported route\n * module, a router built by a factory, a condition hoisted to a variable\n * (`const extra = flag ? { admin } : {}` spread afterwards), and a\n * `.packages()` list assembled conditionally. `NODE_ENV` is pinned before the\n * router loads, which covers those only when the shell left it unset: the\n * generator then reads the router production gets. `spfn build` pins\n * `production` itself, so the deployed map is right. `spfn dev` sets\n * `development` before it spawns the watcher, which inherits it — a\n * `NODE_ENV === 'development'` condition hoisted to a variable therefore writes\n * a dev-only route into the map the watcher regenerates, and `spfn build` takes\n * it back out. The generated map's header names the `NODE_ENV` it was written\n * under, so that difference shows up in the diff.\n */\n\nimport type * as ts from 'typescript';\nimport { typescript } from './typescript';\n\n/** Thrown when the router registers routes conditionally. */\nexport class ConditionalRegistrationError extends Error\n{\n constructor(message: string)\n {\n super(message);\n this.name = 'ConditionalRegistrationError';\n }\n}\n\nexport interface RegistrationScan\n{\n /** Path named in the error message. */\n routerPath: string;\n\n /** Contents of the router file. */\n source: string;\n\n /** The export the loader found the router under: `appRouter`, `default`, … */\n exportName: string;\n\n /** What is being generated, named in the message: `route map`, `contract`. */\n subject: string;\n\n /**\n * The call the router is built with. `defineEventRouter` scans an event\n * router file, whose event set the contract publishes the same way.\n * @default 'defineRouter'\n */\n factory?: RouterFactory;\n}\n\nexport type RouterFactory = 'defineRouter' | 'defineEventRouter';\n\n/** What a refusal says, per kind of router: what is left out and what a client sees. */\nconst REFUSAL_WORDING: Record<RouterFactory, { noun: string; consequence: string; remedy: string }> = {\n defineRouter: {\n noun: 'routes',\n consequence: 'a route production registers is left out, and the client that addresses it by name gets a 404',\n remedy: 'Register the route unconditionally and gate its behaviour inside the handler instead.',\n },\n defineEventRouter: {\n noun: 'events',\n consequence: 'an event production streams is left out, and the client that subscribes to it by name gets a 400',\n remedy: 'Register the event unconditionally and decide who receives it with the stream\\'s authorize hook instead.',\n },\n};\n\n/**\n * Refuse a router whose route set depends on a condition.\n */\nexport function assertUnconditionalRegistration(scan: RegistrationScan): void\n{\n const compiler = typescript();\n const file = compiler.createSourceFile(\n scan.routerPath,\n scan.source,\n compiler.ScriptTarget.Latest,\n /* setParentNodes */ false,\n );\n\n const declarations = topLevelInitialisers(compiler, file);\n const routes = routesLiteral(compiler, declarations.get(scan.exportName), declarations, new Set(), factoryOf(scan));\n\n // No literal means the router is not written as `defineRouter({...})` in\n // this file — a factory, or an import. Documented as past the guard.\n if (routes)\n {\n assertLiteral(compiler, file, routes, declarations, new Set(), scan);\n }\n}\n\nfunction factoryOf(scan: RegistrationScan): RouterFactory\n{\n return scan.factory ?? 'defineRouter';\n}\n\n/**\n * What each name the loader could have found the router under is initialised\n * with: every top-level `const <name> = <expression>`, `export default\n * <expression>` under the name `default`, and a renaming export\n * (`export { r as default }`) under the name it exports.\n *\n * Top level only, because that is where a router is declared and where the\n * loader reads it from. A router built inside a function is past the guard for\n * the same reason a factory is.\n */\nfunction topLevelInitialisers(compiler: typeof ts, file: ts.SourceFile): Map<string, ts.Expression>\n{\n const found = new Map<string, ts.Expression>();\n\n for (const statement of file.statements)\n {\n if (compiler.isExportAssignment(statement) && !statement.isExportEquals)\n {\n found.set('default', statement.expression);\n }\n\n if (compiler.isVariableStatement(statement))\n {\n collectDeclarations(compiler, statement, found);\n }\n }\n\n // After the declarations, so a renamed export resolves through the name it\n // renames. `export { appRouter }` needs nothing: the declaration is the entry.\n for (const statement of file.statements)\n {\n collectRenamedExports(compiler, statement, found);\n }\n\n return found;\n}\n\nfunction collectDeclarations(\n compiler: typeof ts,\n statement: ts.VariableStatement,\n found: Map<string, ts.Expression>,\n): void\n{\n for (const declaration of statement.declarationList.declarations)\n {\n if (compiler.isIdentifier(declaration.name) && declaration.initializer)\n {\n found.set(declaration.name.text, declaration.initializer);\n }\n }\n}\n\nfunction collectRenamedExports(compiler: typeof ts, statement: ts.Statement, found: Map<string, ts.Expression>): void\n{\n if (!compiler.isExportDeclaration(statement)\n || !statement.exportClause\n || !compiler.isNamedExports(statement.exportClause))\n {\n return;\n }\n\n for (const specifier of statement.exportClause.elements)\n {\n // The local name as an expression: `routesLiteral` follows it through\n // this same map. Only a rename is recorded — mapping `x` to `x` would\n // shadow the declaration it is supposed to lead to.\n if (specifier.propertyName && !found.has(specifier.name.text))\n {\n found.set(specifier.name.text, specifier.propertyName);\n }\n }\n}\n\n/** `as const`, `satisfies`, `!` and parentheses sit between a router and its call. */\nfunction unwrap(compiler: typeof ts, expression: ts.Expression | undefined): ts.Expression | undefined\n{\n if (!expression)\n {\n return undefined;\n }\n\n if (compiler.isParenthesizedExpression(expression)\n || compiler.isAsExpression(expression)\n || compiler.isSatisfiesExpression(expression)\n || compiler.isNonNullExpression(expression)\n || compiler.isTypeAssertionExpression(expression))\n {\n return unwrap(compiler, expression.expression);\n }\n\n return expression;\n}\n\n/**\n * The object literal `defineRouter()` receives, through however the router is\n * spelled: `defineRouter({…}).packages([…]).use([…])`, a name pointing at\n * another declaration (`export default appRouter`), or the call on its own.\n *\n * `seen` stops a file whose declarations refer to each other from recursing\n * forever, and stops a router mounted twice from being scanned twice.\n */\nfunction routesLiteral(\n compiler: typeof ts,\n expression: ts.Expression | undefined,\n declarations: Map<string, ts.Expression>,\n seen: Set<string>,\n factory: RouterFactory,\n): ts.ObjectLiteralExpression | undefined\n{\n const node = unwrap(compiler, expression);\n\n if (!node)\n {\n return undefined;\n }\n\n if (compiler.isIdentifier(node))\n {\n if (seen.has(node.text))\n {\n return undefined;\n }\n\n seen.add(node.text);\n\n return routesLiteral(compiler, declarations.get(node.text), declarations, seen, factory);\n }\n\n if (!compiler.isCallExpression(node))\n {\n return undefined;\n }\n\n const callee = unwrap(compiler, node.expression);\n\n if (callee && compiler.isIdentifier(callee) && callee.text === factory)\n {\n const routes = unwrap(compiler, node.arguments[0]);\n\n return routes && compiler.isObjectLiteralExpression(routes) ? routes : undefined;\n }\n\n // A chained `.packages([...])` / `.use([...])` / `.contractVersion('1.0.0')`:\n // keep walking down to the defineRouter call the chain was built from. The\n // arguments are not followed — a package router registers its own routes,\n // which this generator neither emits nor completes.\n return callee && compiler.isPropertyAccessExpression(callee)\n ? routesLiteral(compiler, callee.expression, declarations, seen, factory)\n : undefined;\n}\n\n/**\n * Check one router's routes, and the routers it mounts by name.\n *\n * A nested router registers under its own keys into the same flat map, so a\n * condition inside one leaves out a name exactly as a condition in the app\n * router does. Being mounted is what tells it apart from a router the file\n * declares and never registers.\n */\nfunction assertLiteral(\n compiler: typeof ts,\n file: ts.SourceFile,\n literal: ts.ObjectLiteralExpression,\n declarations: Map<string, ts.Expression>,\n seen: Set<string>,\n scan: RegistrationScan,\n): void\n{\n for (const property of literal.properties)\n {\n if (compiler.isSpreadAssignment(property))\n {\n assertUnconditionalSpread(compiler, file, property.expression, scan);\n\n continue;\n }\n\n const nested = routesLiteral(compiler, mountedRouter(compiler, property), declarations, seen, factoryOf(scan));\n\n if (nested)\n {\n assertLiteral(compiler, file, nested, declarations, seen, scan);\n }\n }\n}\n\n/** What a router entry holds: the value written, or the name a shorthand stands for. */\nfunction mountedRouter(compiler: typeof ts, property: ts.ObjectLiteralElementLike): ts.Expression | undefined\n{\n if (compiler.isPropertyAssignment(property))\n {\n return property.initializer;\n }\n\n return compiler.isShorthandPropertyAssignment(property) ? property.name : undefined;\n}\n\nfunction assertUnconditionalSpread(\n compiler: typeof ts,\n file: ts.SourceFile,\n expression: ts.Expression,\n scan: RegistrationScan,\n): void\n{\n const condition = conditionKind(compiler, expression);\n\n if (!condition)\n {\n return;\n }\n\n const wording = REFUSAL_WORDING[factoryOf(scan)];\n\n throw new ConditionalRegistrationError(\n `${scan.routerPath} registers ${wording.noun} conditionally: \"...${spreadText(file, expression)}\" `\n + `(${condition}).\\n\\n`\n + `The ${scan.subject} is generated from the router as it loads, so a set of ${wording.noun} that depends on `\n + `a flag or an environment describes whichever way the generator happened to run: ${wording.consequence}.\\n`\n + wording.remedy,\n );\n}\n\n/** How the spread reads a condition, or `undefined` when it does not read one. */\nfunction conditionKind(compiler: typeof ts, expression: ts.Expression): string | undefined\n{\n const node = unwrap(compiler, expression);\n\n if (!node)\n {\n return undefined;\n }\n\n if (compiler.isConditionalExpression(node))\n {\n return 'a ternary';\n }\n\n if (!compiler.isBinaryExpression(node))\n {\n return undefined;\n }\n\n switch (node.operatorToken.kind)\n {\n case compiler.SyntaxKind.AmpersandAmpersandToken:\n return '&&';\n case compiler.SyntaxKind.BarBarToken:\n return '||';\n case compiler.SyntaxKind.QuestionQuestionToken:\n return '??';\n default:\n return undefined;\n }\n}\n\n/** The spread's source, on one line, so a multi-line ternary stays a readable message. */\nfunction spreadText(file: ts.SourceFile, expression: ts.Expression): string\n{\n return expression.getText(file).replace(/\\s+/g, ' ');\n}\n","/**\n * Loading a router for a generator\n *\n * `@spfn/core:route-map` and `@spfn/core:contract` both read the router by\n * importing it, and both need the same things settled before that import runs:\n * the environment the module observes, which otherwise follows whichever shell\n * invoked the generator, and the project's own path aliases, which jiti does not\n * read on its own.\n *\n * Both live here rather than in one generator so the two cannot drift: a\n * process-wide `NODE_ENV` pinned by whichever generator `.spfnrc.ts` happens to\n * list first would otherwise decide what the other one loads.\n */\n\nimport { existsSync, readdirSync, statSync } from 'fs';\nimport { dirname, isAbsolute, join, relative, resolve } from 'path';\nimport { createJiti } from 'jiti';\nimport type * as ts from 'typescript';\nimport type { RouteDef, Router } from '@spfn/core/route';\nimport { logger } from '@spfn/core/logger';\nimport { typescript } from './typescript';\n\nconst loadLogger = logger.child('@spfn/core:codegen');\n\n// ============================================================================\n// Environment\n// ============================================================================\n\n/**\n * Pin NODE_ENV before a router loads.\n *\n * A route module that reads the environment at import — a schema built from a\n * flag, a config module with a `development` branch — would otherwise make the\n * generated output depend on how the generator happened to be invoked. It is\n * also what stands in for the guard against a condition the guard cannot see,\n * such as one hoisted to a variable before the spread that registers it — but\n * only when the shell left NODE_ENV unset.\n *\n * The pin is process-wide and deliberately only applies when NODE_ENV is unset,\n * so calling it from both generators in one run is the same as calling it once:\n * the second call finds the value the first one set and leaves it alone.\n *\n * It is unconditional nowhere, and `spfn dev` is why: it sets `development`\n * before spawning the watcher, and a route registered only in development has\n * to be in the map the watcher writes or it 404s in `spfn dev` itself.\n * `spfn build` pins `production` and generates before it compiles, so what ships\n * is right; the cost is churn between the two, which the generated header makes\n * visible by naming the NODE_ENV the map was written under.\n */\nexport function pinNodeEnv(): void\n{\n if (process.env.NODE_ENV)\n {\n return;\n }\n\n process.env.NODE_ENV = 'production';\n loadLogger.info('NODE_ENV was unset; pinned to \"production\" so generated output does not depend on the shell');\n}\n\n// ============================================================================\n// tsconfig path aliases\n// ============================================================================\n\n/**\n * `readDirectory` is stubbed out: only `compilerOptions` is wanted here, and\n * letting TypeScript expand `include` would glob the whole project for nothing.\n */\nfunction parseHost(compiler: typeof ts): ts.ParseConfigHost\n{\n return {\n useCaseSensitiveFileNames: compiler.sys.useCaseSensitiveFileNames,\n readDirectory: () => [],\n fileExists: compiler.sys.fileExists,\n readFile: compiler.sys.readFile,\n };\n}\n\n/**\n * \"No inputs were found in config file\". The stubbed `readDirectory` produces it\n * every time and it says nothing about the config.\n */\nconst NO_INPUTS = 18003;\n\n/**\n * One tsconfig `paths` entry, as jiti resolves it.\n *\n * `from`/`to` are the alias; `pattern`, `target` and `others` are kept so that a\n * specifier which did not resolve can say which target it was tried through and\n * which ones the entry also listed — jiti holds one alias per key, so those\n * others were never tried.\n */\ninterface AliasEntry\n{\n from: string;\n to: string;\n pattern: string;\n target: string;\n others: string[];\n}\n\n/** What has to exist for a target to resolve: the directory a prefix names, or the file itself. */\nfunction targetPath(target: string, base: string): string\n{\n return resolve(base, target.endsWith('/*') ? target.slice(0, -2) : target);\n}\n\n/**\n * Codes the filesystem raises when it refuses to read a path at all.\n *\n * POSIX says EACCES; Windows and some container runtimes say EPERM for the same\n * directory. Keying on one of them would fix a developer machine and leave the\n * other platform crashing, so the guard names both.\n */\nconst UNREADABLE_CODES = new Set(['EACCES', 'EPERM']);\n\n/** Whether an error is the filesystem refusing to read a path, rather than a fault to surface. */\nfunction isUnreadable(error: unknown): boolean\n{\n // A `throw` that is not an object at all must not make the guard itself throw and\n // bury what was really raised.\n return UNREADABLE_CODES.has((error as { code?: string } | null)?.code ?? '');\n}\n\n/**\n * Whether a target can resolve anything at all.\n *\n * TypeScript and tsup substitute each target and take the first that resolves\n * the *requested module*; jiti holds one alias per key, so the nearest this can\n * get is asking whether the directory a prefix names holds anything. That is\n * the difference that matters in practice: a `dist` left behind by `rm -rf\n * dist/*`, or created empty by a tool that then failed, exists and resolves\n * nothing, and taking it ahead of `./src/*` left every import unresolved.\n *\n * A target with no wildcard names a file, and `existsSync` is the whole of the\n * question for it — it reports false for a path it cannot read rather than\n * throwing.\n *\n * The wildcard branch has to say so itself. `throwIfNoEntry: false` suppresses\n * only ENOENT: a directory the process cannot read stats fine and then makes\n * `readdirSync` throw, and an unreadable parent makes `statSync` throw too. That\n * used to reach the developer as a bare `EACCES: permission denied, scandir` from\n * inside `loadRouterModule`, before the catch that names the file and the cause.\n * A target that cannot be read resolves nothing, so it counts as unresolvable and\n * the next target in the entry is tried — which is what the caller already does\n * for a missing one. Every other error is left to throw.\n */\nfunction targetResolves(target: string, base: string): boolean\n{\n const path = targetPath(target, base);\n\n if (!target.endsWith('/*'))\n {\n return existsSync(path);\n }\n\n try\n {\n const stats = statSync(path, { throwIfNoEntry: false });\n\n return stats?.isDirectory() === true && readdirSync(path).length > 0;\n }\n catch (error)\n {\n if (!isUnreadable(error))\n {\n throw error;\n }\n\n return false;\n }\n}\n\n/** The target a `paths` entry resolves through, and the ones it passed over. */\ninterface TargetChoice\n{\n target: string;\n\n /** Targets the pattern also listed. Named in a failure, since jiti tried none of them. */\n others: string[];\n}\n\n/**\n * The target a `paths` entry resolves through.\n *\n * TypeScript tries each target in order and takes the first that resolves, and\n * so does tsup; jiti holds one alias per key. Taking the first target\n * unconditionally therefore failed a project whose first target is a build\n * output that has not been produced — an ordinary shape for a `paths` entry\n * listing `./dist/*` before `./src/*`.\n */\nfunction chooseTarget(pattern: string, targets: string[], base: string): TargetChoice | undefined\n{\n const present = targets.filter(target => targetResolves(target, base));\n const [target] = present.length > 0 ? present : targets;\n\n if (!target)\n {\n return undefined;\n }\n\n if (present.length > 1)\n {\n loadLogger.warn(\n `tsconfig \"paths\" maps ${pattern} to ${present.length} targets that could each resolve a module; `\n + `while the router loads, only the first (${target}) does`,\n );\n }\n\n if (present.length === 0 && targets.length > 1)\n {\n loadLogger.warn(\n `tsconfig \"paths\" maps ${pattern} to ${targets.length} targets and none of them exists with anything `\n + `in it; ${target} is used, and an import through it will name itself as unresolved`,\n );\n }\n\n return { target, others: targets.filter(candidate => candidate !== target) };\n}\n\n/** One `paths` entry as a jiti alias, or `undefined` when jiti cannot express it. */\nfunction toAlias(pattern: string, targets: string[], base: string): AliasEntry | undefined\n{\n const choice = chooseTarget(pattern, targets, base);\n\n if (!choice)\n {\n return undefined;\n }\n\n const { target, others } = choice;\n\n if (!pattern.includes('*'))\n {\n return { from: pattern, to: resolve(base, target), pattern, target, others };\n }\n\n // jiti matches an alias by path segment, so the only mapping it can express\n // is a prefix: \"@/*\" -> \"./src/*\" becomes \"@/\" -> \"<base>/src\".\n if (!pattern.endsWith('/*') || !target.endsWith('/*'))\n {\n loadLogger.warn(\n `tsconfig \"paths\" maps ${pattern} to ${target}, which is not a directory prefix mapping; it will not `\n + 'resolve while the router loads',\n );\n\n return undefined;\n }\n\n // The trailing slash is kept, so \"@x/*\" and \"@x\" — one entry per form, which\n // is how a package maps its own subpaths beside its entry point — become two\n // aliases instead of collapsing onto \"@x\" and losing the exact one. jiti\n // resolves \"@x/a\" through \"@x/\" either way.\n return { from: pattern.slice(0, -1), to: resolve(base, target.slice(0, -2)), pattern, target, others };\n}\n\n/** `compilerOptions` of one tsconfig, with `extends` already merged. */\nfunction readCompilerOptions(configPath: string, cwd: string): ts.CompilerOptions | undefined\n{\n if (!existsSync(configPath))\n {\n return undefined;\n }\n\n const compiler = typescript();\n const { config, error } = compiler.readConfigFile(configPath, compiler.sys.readFile);\n\n if (error || !config)\n {\n loadLogger.warn(`Could not read ${relative(cwd, configPath)}; its path aliases will not resolve`);\n\n return undefined;\n }\n\n const parsed = compiler.parseJsonConfigFileContent(config, parseHost(compiler), dirname(configPath));\n\n // An `extends` target TypeScript cannot read leaves `paths` empty rather\n // than failing, and the router then fails to load for a reason that looks\n // like a missing mapping. Reachable in ordinary CI: a base config outside\n // the package, not copied into a Docker stage.\n for (const diagnostic of parsed.errors)\n {\n if (diagnostic.code !== NO_INPUTS)\n {\n loadLogger.warn(\n `${relative(cwd, configPath)}: ${compiler.flattenDiagnosticMessageText(diagnostic.messageText, ' ')} `\n + '— path aliases it should have declared may be missing while the router loads',\n );\n }\n }\n\n return parsed.options;\n}\n\n/** Whether `directory` is `root` or below it. */\nfunction isWithin(root: string, directory: string): boolean\n{\n const step = relative(root, directory);\n\n return step === '' || (!step.startsWith('..') && !isAbsolute(step));\n}\n\n/**\n * The directories to look in, nearest first: from `startDir` up to and\n * including the project root.\n *\n * The search stops at the project root, because a tsconfig above it belongs to\n * whatever contains the project — a monorepo root, a home directory — and not\n * to the project being generated. A `startDir` outside the root contributes\n * nothing, leaving the root itself.\n */\nfunction searchDirectories(cwd: string, startDir: string): string[]\n{\n const root = resolve(cwd);\n const directories: string[] = [];\n\n for (let directory = resolve(startDir); isWithin(root, directory); directory = dirname(directory))\n {\n directories.push(directory);\n\n if (directory === root)\n {\n return directories;\n }\n }\n\n return [root];\n}\n\n/** `paths` as jiti aliases, with their targets resolved against `base`. */\nfunction aliasesOf(paths: ts.MapLike<string[]>, base: string): AliasEntry[]\n{\n const aliases = new Map<string, AliasEntry>();\n\n for (const [pattern, targets] of Object.entries(paths))\n {\n const alias = toAlias(pattern, targets, base);\n\n if (alias && !aliases.has(alias.from))\n {\n aliases.set(alias.from, alias);\n }\n }\n\n return [...aliases.values()];\n}\n\n/**\n * The project's tsconfig `paths`, as the alias map jiti resolves.\n *\n * jiti does not read tsconfig: a specifier resolves through its `alias` option\n * or not at all. Every spfn app has `@/*` in a tsconfig — `spfn init` writes it,\n * and the scaffold documents `import env from '@/server/config/env.config'` as\n * the idiom — so a generator that loads the router has to hand jiti the same\n * mappings tsc uses, or an ordinary app cannot generate anything.\n *\n * Which tsconfig: the nearest one to the router file that declares `paths`,\n * searching upward to the project root. The scaffold's aliases live in\n * `src/server/tsconfig.json` — with `baseUrl: \"../..\"` — and that is the config\n * `spfn build` compiles the server with, so a backend-only app has them nowhere\n * else. A config declaring no `paths` is passed over rather than ending the\n * search, because the same `src/server/tsconfig.json` declares none in an app\n * that keeps its aliases at the root (Next.js puts them there).\n *\n * Handled: an `extends` chain, including one that names a package; `paths`\n * targets resolved against `baseUrl`, and against the config file that declares\n * them when there is no `baseUrl`; several targets per pattern, taking the first\n * that resolves as tsc and tsup do; comments and trailing commas, because\n * TypeScript's own parser reads the file.\n *\n * Not handled, each with a warning and no alias for that entry: a pattern whose\n * `*` is not a trailing `/*` (jiti matches a prefix, not a template). A\n * `baseUrl` with no `paths` produces nothing: resolving every bare specifier\n * against a directory is not something an alias map can say.\n */\nfunction projectAliases(cwd: string, startDir: string): AliasEntry[]\n{\n for (const directory of searchDirectories(cwd, startDir))\n {\n const options = readCompilerOptions(join(directory, 'tsconfig.json'), cwd);\n\n if (options?.paths)\n {\n // A target is relative to baseUrl, and to the config that declared\n // `paths` when there is no baseUrl — TypeScript records that as\n // `pathsBasePath`, which its public typings do not carry.\n const declaredIn = (options as { pathsBasePath?: string }).pathsBasePath;\n\n return aliasesOf(options.paths, options.baseUrl ?? declaredIn ?? directory);\n }\n }\n\n return [];\n}\n\n/** The alias map jiti is handed: see `projectAliases`, of which this is the public shape. */\nexport function tsconfigAliases(cwd: string, startDir: string = cwd): Record<string, string>\n{\n return Object.fromEntries(projectAliases(cwd, startDir).map(alias => [alias.from, alias.to]));\n}\n\n// ============================================================================\n// Loading\n// ============================================================================\n\n/**\n * An import that never resolved and a module that threw are different repairs.\n *\n * The message used to advise the second for both, which sends a developer whose\n * router imports `@/server/routes` looking for a module-scope side effect that\n * is not there.\n */\nfunction describeFailure(error: unknown, subject: string, aliases: AliasEntry[]): string\n{\n const message = error instanceof Error ? error.message : String(error);\n const unresolved = /Cannot find module '([^']+)'/.exec(message);\n\n if (!unresolved)\n {\n return `${message}\\n\\n`\n + `The ${subject} is read from the loaded router, so a route module must be importable without side `\n + 'effects. Check that nothing at module scope opens a connection or reads a missing environment value.';\n }\n\n return `${message.split('\\n')[0]}\\n\\n`\n + `\"${unresolved[1]}\" did not resolve while the router was being imported. Imports resolve through Node and `\n + 'through the \"paths\" of the nearest tsconfig.json that declares them, searching from the router file up to '\n + 'the project root. Check that the specifier is mapped in one of those, and that what it points at exists: '\n + 'a workspace package resolves to a dist/ that has to have been built.'\n + describePassedOverTargets(unresolved[1], aliases);\n}\n\n/**\n * The targets the failing specifier was never tried through.\n *\n * tsc substitutes every target of a matching pattern and takes the first that\n * resolves the requested module; jiti holds one alias per key, so exactly one\n * was tried. When the pattern listed others, the import that just failed would\n * very likely have resolved through one of them, and saying so is the whole\n * repair — the alternative is a developer reading \"did not resolve\" about a\n * module that plainly exists under `./src`.\n */\nfunction describePassedOverTargets(specifier: string, aliases: AliasEntry[]): string\n{\n // Matched on either spelling: the loader names the specifier it was given\n // for an alias it has no mapping for, and the path it resolved to for one it\n // does — and it is the second that reaches here.\n const alias = aliases.find(entry => specifier.startsWith(entry.from) || specifier.startsWith(entry.to));\n\n if (!alias || alias.others.length === 0)\n {\n return '';\n }\n\n return `\\n\\nIt was resolved through \"${alias.target}\", the first target of the \"paths\" entry `\n + `\"${alias.pattern}\" that names a directory holding anything. That entry also lists `\n + `${alias.others.map(other => `\"${other}\"`).join(', ')}, which the router load never tried: one alias per `\n + 'key is all the loader can express, so the whole load goes through a single target.';\n}\n\nexport interface RouterModuleLoad\n{\n /** Project root: jiti resolves from here, and the tsconfig search stops here. */\n cwd: string;\n\n absoluteRouterPath: string;\n\n /** What is being generated, named in the failure message: `route map`. */\n subject: string;\n\n /** Wraps the message in the calling generator's own error type. */\n fail: (message: string) => Error;\n}\n\n/**\n * Import the router module, or throw the caller's error describing why not.\n */\nexport function loadRouterModule(load: RouterModuleLoad): Record<string, unknown>\n{\n const { cwd, absoluteRouterPath, subject, fail } = load;\n\n const aliases = projectAliases(cwd, dirname(absoluteRouterPath));\n\n const jiti = createJiti(cwd, {\n interopDefault: true,\n moduleCache: false,\n alias: Object.fromEntries(aliases.map(alias => [alias.from, alias.to])),\n });\n\n try\n {\n return jiti(absoluteRouterPath) as Record<string, unknown>;\n }\n catch (error)\n {\n throw fail(\n `Failed to load ${relative(cwd, absoluteRouterPath)}: ${describeFailure(error, subject, aliases)}`,\n );\n }\n}\n\nexport function isRouter(value: unknown): value is Router<Record<string, RouteDef<any> | Router<any>>>\n{\n return value !== null\n && typeof value === 'object'\n && 'routes' in value\n && '_routes' in value;\n}\n\nexport interface ResolvedRouter\n{\n router: Router<any>;\n\n /**\n * The export it was found under.\n *\n * Both generators try `appRouter`, `default` and `router` in turn, so a file\n * holding more than one router is read from whichever of those it declares.\n * The guard then reads that same one rather than every `defineRouter(` in\n * the file: a router the loader did not find is a router production never\n * mounts.\n */\n exportName: string;\n}\n\n/** The first candidate export holding a router, and the name it was found under. */\nexport function resolveRouterExport(module: Record<string, unknown>, candidates: string[]): ResolvedRouter | undefined\n{\n for (const exportName of candidates)\n {\n const candidate = module[exportName];\n\n if (isRouter(candidate))\n {\n return { router: candidate, exportName };\n }\n }\n\n return undefined;\n}\n","/**\n * Route Map Generator\n *\n * Generates a route map file containing routeName → {method, path} mappings.\n * This allows RPC proxy to resolve routes without importing the full router.\n *\n * The router is loaded and walked, not parsed from source. A source parser sees\n * the spelling rather than the router: `defineRouter({ createUser })` written on\n * one line, an aliased key `create: createUser`, and a nested router assembled by\n * a second `defineRouter(` in the same file are all ordinary ways to write a\n * router, and all of them used to leave routes out of the map. The RPC client\n * addresses a route by name, so a dropped name is a route that typechecks and\n * 404s. Walking the loaded router registers exactly what `registerRoutes`\n * registers, whatever the source looks like.\n *\n * The map carries the routes of every package router the app mounts with\n * `.packages()`, not only the app's own. A package ships a client that addresses\n * its routes by name — `authApi.login`, `monitorApi.getStats` — and the app's\n * `createRpcProxy` resolves a name in the single map it was constructed with, so\n * a package route in nobody's map is a call that resolves nowhere. The app\n * therefore merges nothing by hand: `{ ...routeMap, ...authRouteMap }` is a\n * no-op today and `{ ...routeMap }` is the whole of it. (`eventRouteMap` is the\n * exception that stays — it is a hand-written constant, not a mounted router.)\n *\n * @example\n * ```typescript\n * // .spfnrc.ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n *\n * export default defineConfig({\n * generators: [\n * defineGenerator({\n * name: '@spfn/core:route-map',\n * routerPath: './src/server/router.ts',\n * outputPath: './src/generated/route-map.ts',\n * })\n * ]\n * });\n * ```\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { join, dirname, relative } from 'path';\nimport type { HttpMethod, RouteDef, Router } from '@spfn/core/route';\nimport { logger } from '@spfn/core/logger';\nimport type { Generator, GeneratorOptions } from '../core/generator';\nimport { assertUnconditionalRegistration } from './contract-guard';\nimport { isRouter, loadRouterModule, pinNodeEnv, resolveRouterExport, type ResolvedRouter } from './router-module';\n\nconst genLogger = logger.child('@spfn/core:route-map-generator');\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface RouteMapGeneratorConfig\n{\n /**\n * Generator name (required for package-based loading)\n */\n name: '@spfn/core:route-map';\n\n /**\n * Path to the router file (relative to project root)\n * @example './src/server/router.ts'\n */\n routerPath: string;\n\n /**\n * Output path for generated route map (relative to project root)\n * @default './src/generated/route-map.ts'\n */\n outputPath?: string;\n\n /**\n * Extra file patterns to watch, for routes outside src/server/routes\n *\n * @deprecated Ignored. The map is read from the loaded router, which reaches\n * every route through its own imports wherever they live, so there is no\n * longer a set of directories to scan. Still accepted so an existing\n * `.spfnrc.ts` keeps working; the watch patterns it produced are unchanged.\n */\n additionalRouteDirs?: string[];\n}\n\n/** Thrown when the router cannot produce a route map at all. */\nexport class RouteMapGeneratorError extends Error\n{\n constructor(message: string)\n {\n super(message);\n this.name = 'RouteMapGeneratorError';\n }\n}\n\ninterface CollectedRoute\n{\n method: string;\n path: string;\n\n /** Where the route was found, for a collision message. */\n trail: string;\n\n /**\n * The definition itself, so that one route reached twice is not two routes.\n *\n * A package that exports one set of routes under two routers — a router and\n * a sub-router an app may mount beside it — hands an app that mounts both\n * the same `RouteDef` object under the same name twice. That is one route\n * with two mounts, not an ambiguity, and the app cannot resolve it by\n * renaming anything of its own. No first-party package ships that shape\n * today; the rule is keyed on object identity so that the day one does, the\n * app that mounts both still builds.\n */\n def: RouteDef<any>;\n}\n\n/** One entry of a router's `_packageRouters`, as the generated header describes it. */\ninterface PackageMount\n{\n /** The trail of the mount: `router.packages[0]`. */\n label: string;\n\n /** How many routes it contributed, which is zero for an unmapped router. */\n count: number;\n\n /** Why it contributed nothing, when it contributed nothing. */\n skipped?: string;\n\n /**\n * Where a route it holds had already been collected, if one had.\n *\n * A mount reaching only routes another mount already collected contributes\n * nothing without being skipped, so without this its header line would read\n * `— no routes` and give no reason.\n */\n sharedWith?: string;\n\n /** The first path segment of each route it contributed, for the header line. */\n prefixes: Set<string>;\n}\n\n/** Everything one walk of the router produced. */\ninterface Collection\n{\n /** The app's own routes, in walk order. */\n app: Map<string, CollectedRoute>;\n\n /** The routes of every mounted package router that publishes a map, in walk order. */\n packages: Map<string, CollectedRoute>;\n\n /** Every `.packages()` mount, contributing or not, in the order it was mounted. */\n mounts: PackageMount[];\n\n /**\n * Package routers already walked.\n *\n * `.packages()` copies a mounted router's own `_packageRouters` up to the\n * top level while leaving them in place below it, so one nested package\n * router is reachable by two trails. The second walk would collect nothing\n * either way — `addRoute`'s identity rule sees the same `RouteDef` under\n * the same name and collapses it — so this is not what keeps a router from\n * colliding with itself. It skips the work, and it is what lets the mount's\n * header line say where the routes were already reached.\n */\n visited: Map<Router<any>, string>;\n}\n\n// ============================================================================\n// Loading\n// ============================================================================\n\nfunction isRouteDef(value: unknown): value is RouteDef<any>\n{\n return value !== null\n && typeof value === 'object'\n && 'handler' in value;\n}\n\nconst ROUTER_EXPORTS = ['appRouter', 'default', 'router'];\n\nfunction loadRouter(cwd: string, absoluteRouterPath: string): ResolvedRouter\n{\n const module = loadRouterModule({\n cwd,\n absoluteRouterPath,\n subject: 'route map',\n fail: message => new RouteMapGeneratorError(message),\n });\n\n const resolved = resolveRouterExport(module, ROUTER_EXPORTS);\n\n if (resolved)\n {\n return resolved;\n }\n\n throw new RouteMapGeneratorError(\n `No router found in ${relative(cwd, absoluteRouterPath)}. `\n + `Looked for: ${ROUTER_EXPORTS.join(', ')}. `\n + 'Export the defineRouter() result under one of those names.',\n );\n}\n\n// ============================================================================\n// Collection\n// ============================================================================\n\n/**\n * Written as a record rather than a list so that a new `HttpMethod` does not\n * compile until it is named here.\n */\nconst HTTP_METHODS: Record<HttpMethod, true> = { GET: true, POST: true, PUT: true, PATCH: true, DELETE: true };\n\n/** Which map a route is collected into, and so which collision it can be part of. */\ntype Origin = 'app' | 'package';\n\nfunction duplicateNameError(\n origin: Origin,\n name: string,\n existing: CollectedRoute,\n where: string,\n): RouteMapGeneratorError\n{\n if (origin === 'app')\n {\n return new RouteMapGeneratorError(\n `Two routes are both named \"${name}\" (${existing.trail} and ${where}). `\n + 'The RPC client addresses a route by its name alone, and a nested route registers under its own '\n + 'key, so a name must be unique across the whole router.',\n );\n }\n\n return new RouteMapGeneratorError(\n `Two package routers both register a route named \"${name}\" (${existing.trail} and ${where}). `\n + 'Both are written into this app\\'s route map, which holds one entry per name, so one of the two '\n + 'packages would have its client call the other package\\'s path. Nothing of this app\\'s can be renamed '\n + 'to fix it: drop one of the two mounts, or raise the name with the package that took it second.',\n );\n}\n\n/**\n * Collect one route, or say why it is not in the map.\n *\n * Returns what was collected, which is what lets a mount count and describe\n * what it contributed without counting a route twice.\n */\nfunction addRoute(\n name: string,\n routeDef: RouteDef<any>,\n trail: string[],\n into: Map<string, CollectedRoute>,\n origin: Origin,\n): CollectedRoute | undefined\n{\n const where = trail.join('.');\n\n // Skipped rather than refused: `registerRoutes` warns and skips it too, so\n // the map that leaves it out still names every route the server answers —\n // which is the whole of what a refusal here would be protecting.\n if (!routeDef.method || !routeDef.path)\n {\n genLogger.warn(\n `Route \"${where}\" has no method or path and is left out of the map. `\n + 'The RPC client resolves a name to a method and a path, so both are required. '\n + 'A route reaches this state by being registered before .handler() was called — '\n + 'the server skips it too.',\n );\n\n return undefined;\n }\n\n // The map is typed `HttpMethod`, and `registerRoutes` lowercases whatever it\n // is given before handing it to Hono — so `method: 'get'` registers happily\n // at runtime and would emit a generated file that does not compile.\n if (!Object.hasOwn(HTTP_METHODS, routeDef.method))\n {\n throw new RouteMapGeneratorError(\n `Route \"${where}\" declares the method \"${routeDef.method}\", which is not an HttpMethod `\n + `(${Object.keys(HTTP_METHODS).join(', ')}). The generated map is typed HttpMethod, so naming it `\n + 'would write a file that does not compile.',\n );\n }\n\n const existing = into.get(name);\n if (existing)\n {\n // The same route, reached through two mounts, is one route: a package\n // that exports its routes under two routers hands both to an app that\n // mounts both, and the entry either mount writes is the same entry.\n //\n // Only for a package route. The app's own router reaches one name twice\n // by registering one route both at the top level and inside a nested\n // group, and that stays refused even though the two entries are\n // identical: it is the app's own spelling, so the app can fix it by\n // dropping one registration, and leaving it silent would hide a\n // grouping the author meant to be a second route.\n if (origin === 'package' && existing.def === routeDef)\n {\n return undefined;\n }\n\n throw duplicateNameError(origin, name, existing, where);\n }\n\n const collected: CollectedRoute = {\n method: routeDef.method,\n path: routeDef.path,\n trail: where,\n def: routeDef,\n };\n\n into.set(name, collected);\n\n return collected;\n}\n\n/** `/_auth/login` → `/_auth`: what the header line says a mount's routes live under. */\nfunction pathPrefix(path: string): string\n{\n const [, first] = path.split('/');\n\n return first ? `/${first}` : path;\n}\n\n/**\n * Every route a mounted package router registers, at any depth below it.\n *\n * These are written into the app's map beside the app's own routes. A package\n * ships a client that addresses its routes by name — `authApi.login`,\n * `monitorApi.getStats` — and the app's `createRpcProxy` resolves that name in\n * the single map it was constructed with, so a name in nobody's map resolves\n * nowhere.\n *\n * A router whose `_publishesRouteMap` is false contributes nothing, and neither\n * does anything below it: no client names those routes. That is the ops surface\n * (`createOpsRouter`), whose routes `spfn ops` invokes over the URL the manifest\n * gave it, and whose own sub-routers carry the flag too.\n *\n * The flag is read on the router being walked rather than on the mount that\n * reached it. So an unmapped router nested inside a mapped package router is\n * left out while its parent contributes, and a mapped router nested inside an\n * unmapped one is left out with it — what the flag says is whether a client\n * names these routes, which nesting does not change either way.\n */\nfunction collectPackageRoutes(\n router: Router<any>,\n trail: string[],\n mount: PackageMount,\n collection: Collection,\n): void\n{\n if (router._publishesRouteMap === false || collection.visited.has(router))\n {\n return;\n }\n\n collection.visited.set(router, trail.join('.'));\n\n for (const [name, entry] of Object.entries(router.routes))\n {\n if (isRouter(entry))\n {\n collectPackageRoutes(entry, [...trail, name], mount, collection);\n continue;\n }\n\n if (!isRouteDef(entry))\n {\n genLogger.warn(\n `Package router entry \"${[...trail, name].join('.')}\" is neither a route nor a router `\n + `(got ${typeof entry}) and is left out of the map. \\`registerRoutes\\` skips it too.`,\n );\n\n continue;\n }\n\n const collected = addRoute(name, entry, [...trail, name], collection.packages, 'package');\n\n if (collected)\n {\n mount.count += 1;\n mount.prefixes.add(pathPrefix(collected.path));\n\n continue;\n }\n\n const already = collection.packages.get(name);\n\n if (already?.def === entry)\n {\n mount.sharedWith ??= already.trail;\n }\n }\n\n for (const [index, nested] of (router._packageRouters ?? []).entries())\n {\n collectPackageRoutes(nested, [...trail, `packages[${index}]`], mount, collection);\n }\n}\n\n/** One entry of a router's `_packageRouters`, walked and described for the generated header. */\nfunction mountPackageRouter(router: Router<any>, label: string, collection: Collection): PackageMount\n{\n const mount: PackageMount = { label, count: 0, prefixes: new Set() };\n const alreadyAt = collection.visited.get(router);\n\n // Said before the walk, because the walk is what makes both true of it.\n if (router._publishesRouteMap === false)\n {\n mount.skipped = 'publishes no route map';\n }\n else if (alreadyAt)\n {\n mount.skipped = `already reached through ${alreadyAt}`;\n }\n\n collectPackageRoutes(router, [label], mount, collection);\n\n // Said after the walk, because the walk is what found the other mount.\n if (mount.count === 0 && !mount.skipped && mount.sharedWith)\n {\n mount.skipped = `every route it holds was already collected through ${mount.sharedWith}`;\n }\n\n collection.mounts.push(mount);\n\n return mount;\n}\n\n/**\n * Walk the router the way `registerRoutes` walks it.\n *\n * A nested route registers under its own key — the parent's key names the\n * grouping, not the route — so the map is flat and the trail exists only to\n * point at both sides of a collision.\n *\n * `_packageRouters` is walked into a second map rather than this one, because\n * the generated file keeps the app's own routes first and in their own order:\n * an app that mounts nothing regenerates byte-identically, and an app that\n * mounts something has the routes that are not its own written below a line\n * that says so.\n *\n * Only string keys are collected, because `Object.entries` is what the runtime\n * iterates: a symbol-keyed entry is invisible to `registerRoutes` and so has no\n * route to name in the map either.\n */\nfunction collectRoutes(router: Router<any>, trail: string[], collection: Collection): void\n{\n for (const [name, entry] of Object.entries(router.routes))\n {\n if (isRouter(entry))\n {\n collectRoutes(entry, [...trail, name], collection);\n continue;\n }\n\n // Skipped rather than refused, for the reason `addRoute` skips a route\n // with no method: the server skips it, so a map without it is complete.\n if (!isRouteDef(entry))\n {\n genLogger.warn(\n `Router entry \"${[...trail, name].join('.')}\" is neither a route nor a router (got ${typeof entry}) `\n + 'and is left out of the map. `registerRoutes` skips it too, so no name the client can call goes '\n + 'unanswered.',\n );\n\n continue;\n }\n\n addRoute(name, entry, [...trail, name], collection.app, 'app');\n }\n\n for (const [index, packageRouter] of (router._packageRouters ?? []).entries())\n {\n mountPackageRouter(packageRouter, `${trail.join('.')}.packages[${index}]`, collection);\n }\n}\n\n/**\n * Refuse an app route whose name a package router also registers.\n *\n * Both are registered at runtime, at their own paths, and both are written into\n * this one map — which holds one entry per name. The name would resolve to\n * whichever of the two the map ended up holding while the generated types still\n * describe the app's route, so every call the typed client made against the\n * app's route could go to the package's path.\n *\n * A collision with a router that publishes no map is not refused: nothing of\n * that router is written here, so the app route keeps its name and its path.\n */\nfunction assertNoPackageCollision(collection: Collection): void\n{\n for (const [name, route] of collection.packages)\n {\n const appRoute = collection.app.get(name);\n\n if (!appRoute)\n {\n continue;\n }\n\n throw new RouteMapGeneratorError(\n `The app route \"${name}\" (${appRoute.trail}) is also registered by a package router (${route.trail}). `\n + 'Both go into this app\\'s generated route map, which holds one entry per name, so one of the two '\n + 'paths becomes unreachable while the typed client still describes the app\\'s route. Rename the app '\n + 'route.',\n );\n }\n}\n\n/** The map the file is written from: the app's own routes, then its mounted packages'. */\nfunction collectRouteMap(router: Router<any>): Collection\n{\n const collection: Collection = {\n app: new Map(),\n packages: new Map(),\n mounts: [],\n visited: new Map(),\n };\n\n collectRoutes(router, ['router'], collection);\n assertNoPackageCollision(collection);\n\n return collection;\n}\n\n// ============================================================================\n// Generator\n// ============================================================================\n\n/**\n * A route name is a key in an object literal, and a key that is not an\n * identifier has to be quoted or the generated file will not parse.\n *\n * The source parser could never produce such a name — it read names off\n * `export const` — but `defineRouter({ 'get-user': getUser })` is a legal\n * router that the server registers as `get-user`, so the map has to be able to\n * spell it. `JSON.stringify` is the escaping: double quotes are what it emits,\n * and every other name is left bare so an unchanged project regenerates\n * byte-identically.\n */\nfunction toObjectKey(name: string): string\n{\n // `__proto__:` in an object literal sets the prototype instead of defining\n // an own property, and so does `\"__proto__\":` — the route would vanish from\n // Object.keys and from the proxy's spread. A computed key is the one form\n // that always defines an own property.\n if (name === '__proto__')\n {\n return `[${JSON.stringify(name)}]`;\n }\n\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);\n}\n\n/**\n * Printable ASCII, minus the two characters a single-quoted literal cannot hold.\n * Every realistic path is in here and is emitted as it always was, so an\n * unchanged project regenerates byte-identically.\n */\nconst SINGLE_QUOTABLE = /^[\\x20-\\x26\\x28-\\x5B\\x5D-\\x7E]*$/;\n\n/**\n * A path is emitted as a string literal, and a path carrying a quote, a\n * backslash or a line terminator would close it early — or end the line — and\n * leave a `DO NOT EDIT` file whose syntax error points at nothing.\n *\n * `JSON.stringify` handles all of those, so anything outside the plain ASCII a\n * single-quoted literal can hold is handed to it. U+2028 and U+2029 are the\n * exception it does not cover: they are legal in a JSON string and were a line\n * terminator in string literals before ES2019, so they are escaped by hand.\n */\nfunction toStringLiteral(value: string): string\n{\n if (SINGLE_QUOTABLE.test(value))\n {\n return `'${value}'`;\n }\n\n return JSON.stringify(value)\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\n/** One mount, as the generated header lists it. */\nfunction describeMount(mount: PackageMount): string\n{\n if (mount.count === 0)\n {\n return `${mount.label} — no routes${mount.skipped ? ` (${mount.skipped})` : ''}`;\n }\n\n const routes = `${mount.count} route${mount.count === 1 ? '' : 's'}`;\n\n return `${mount.label} — ${routes} under ${[...mount.prefixes].join(', ')}`;\n}\n\n/**\n * The header lines that say which of the entries below are not the app's.\n *\n * A package route in this file is a copy, and a copy is as old as the file: the\n * app used to import the package's own map, which an upgrade changed by itself.\n * So the header says what the copy is and names every mount it came through —\n * the diff after an upgrade then reads as an upgrade rather than as somebody\n * editing a generated file.\n *\n * Nothing is added when no package contributed, so an app that mounts nothing\n * (or mounts only routers that publish no map) regenerates byte-identically to\n * what it has committed.\n */\nfunction packageHeaderLines(collection: Collection): string[]\n{\n if (collection.packages.size === 0)\n {\n return [];\n }\n\n return [\n ' *',\n ' * The entries under the .packages() line below are not this app\\'s. They belong',\n ' * to the package routers it mounts, copied in as they were when this file was',\n ' * generated:',\n ...collection.mounts.map(mount => ` * ${describeMount(mount)}`),\n ' *',\n ' * A package upgrade reaches them only through a regeneration: `spfn build`',\n ' * regenerates before it compiles, a bare `next build` uses what is committed here.',\n ];\n}\n\n/**\n * Generate route map file content\n *\n * The environment is written into the header because it decides what the map\n * holds and nothing else records it. A route registered behind a condition the\n * guard cannot see — one hoisted to a variable, one inside an imported route\n * module — is named here only when the generator ran under the environment that\n * registers it, and `spfn build` pins `production` where `spfn dev` leaves\n * `development`. Writing the value makes that difference a line in the diff\n * instead of a route that typechecks in the editor and vanishes at build.\n */\nfunction generateRouteMapContent(collection: Collection, nodeEnv: string): string\n{\n const lines: string[] = [\n '/**',\n ' * Route Map (Auto-generated)',\n ' *',\n ' * DO NOT EDIT - This file is generated by @spfn/core:route-map generator',\n ' *',\n ` * Generated with NODE_ENV=${nodeEnv}. A route registered only under one environment is`,\n ' * named here only when the generator ran under it, so this line changing is that',\n ' * difference rather than an edit.',\n ...packageHeaderLines(collection),\n ' */',\n '',\n 'import type { HttpMethod } from \\'@spfn/core/route\\';',\n '',\n 'export interface RouteInfo',\n '{',\n ' method: HttpMethod;',\n ' path: string;',\n '}',\n '',\n 'export const routeMap: Record<string, RouteInfo> = {',\n ];\n\n for (const [name, route] of collection.app)\n {\n lines.push(entryLine(name, route));\n }\n\n if (collection.packages.size > 0)\n {\n lines.push(' // From the package routers this app mounts with .packages(), not its own:');\n\n for (const [name, route] of collection.packages)\n {\n lines.push(entryLine(name, route));\n }\n }\n\n lines.push('};');\n lines.push('');\n lines.push('export type RouteMap = typeof routeMap;');\n lines.push('');\n lines.push('export type RouteName = keyof RouteMap;');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/** One `name: { method, path },` line of the map. */\nfunction entryLine(name: string, route: CollectedRoute): string\n{\n return ` ${toObjectKey(name)}: { method: '${route.method}', path: ${toStringLiteral(route.path)} },`;\n}\n\n/**\n * Create Route Map Generator\n */\nexport function createRouteMapGenerator(config: RouteMapGeneratorConfig): Generator\n{\n const {\n routerPath,\n outputPath = './src/generated/route-map.ts',\n additionalRouteDirs = [],\n } = config;\n\n if (!routerPath)\n {\n throw new Error(\n '[@spfn/core:route-map] Missing required \"routerPath\" option.\\n\\n' +\n 'Usage:\\n' +\n ' defineGenerator<RouteMapGeneratorConfig>({\\n' +\n ' name: \\'@spfn/core:route-map\\',\\n' +\n ' routerPath: \\'./src/server/router.ts\\',\\n' +\n ' })',\n );\n }\n\n return {\n name: '@spfn/core:route-map',\n\n // Unchanged, including the deprecated dirs: what the map is *built* from\n // moved to the loaded router, but what a rebuild should be *triggered* by\n // is still every file a route can live in.\n watchPatterns: [\n routerPath,\n 'src/server/routes/**/*.ts',\n ...additionalRouteDirs.map(dir => `${dir}/**/*.ts`),\n ],\n\n runOn: ['watch', 'manual', 'build'],\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const { cwd, debug } = options;\n\n const absoluteRouterPath = join(cwd, routerPath);\n const absoluteOutputPath = join(cwd, outputPath);\n\n if (!existsSync(absoluteRouterPath))\n {\n genLogger.warn(`Router file not found: ${absoluteRouterPath}`);\n\n return;\n }\n\n if (debug)\n {\n genLogger.info('Loading router', { path: absoluteRouterPath });\n }\n\n pinNodeEnv();\n\n // Loaded before the guard reads the source, because which router the\n // guard reads is decided by which export the loader found.\n const { router, exportName } = loadRouter(cwd, absoluteRouterPath);\n\n assertUnconditionalRegistration({\n routerPath,\n source: readFileSync(absoluteRouterPath, 'utf-8'),\n exportName,\n subject: 'route map',\n });\n\n const collection = collectRouteMap(router);\n const total = collection.app.size + collection.packages.size;\n\n if (debug)\n {\n genLogger.info(`Found ${total} routes`, {\n app: [...collection.app.keys()],\n packages: [...collection.packages.keys()],\n });\n }\n\n const outputDir = dirname(absoluteOutputPath);\n if (!existsSync(outputDir))\n {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Read after `pinNodeEnv`, which is what makes it a value at all when\n // the shell left it unset.\n const nodeEnv = process.env.NODE_ENV ?? 'unset';\n\n writeFileSync(absoluteOutputPath, generateRouteMapContent(collection, nodeEnv), 'utf-8');\n\n genLogger.info(\n `Generated route map: ${relative(cwd, absoluteOutputPath)} `\n + `(${collection.app.size} app routes, ${collection.packages.size} from mounted packages)`,\n );\n },\n };\n}\n\n// ============================================================================\n// Export for package-based loading\n// ============================================================================\n\nexport default createRouteMapGenerator;\n","/**\n * Contract Generator\n *\n * Reads the router, writes `contracts/current.json`, and on a build compares it\n * against the newest released snapshot.\n *\n * It is a codegen plugin for the same reason the route map is one: hanging off\n * `spfn build` and `spfn dev` removes \"forgot to regenerate the contract\" as a\n * failure mode. On `dev` it only regenerates — refusing a half-finished route\n * mid-edit would make the feature unusable — and on `build` it also gates.\n *\n * @example\n * ```typescript\n * // .spfnrc.ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n *\n * export default defineConfig({\n * generators: [\n * defineGenerator({\n * name: '@spfn/core:contract',\n * routerPath: './src/server/router.ts',\n * eventRouterPath: './src/server/events.ts', // optional: contracted SSE events\n * outputDir: './contracts',\n * })\n * ]\n * });\n * ```\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join, relative } from 'path';\nimport { logger } from '@spfn/core/logger';\nimport {\n checkContract,\n collectContractDocument,\n formatViolations,\n writeCurrentDocument,\n} from '@spfn/core/contract';\nimport type { EventRouterDef } from '@spfn/core/event';\nimport type { Generator, GeneratorOptions } from '../core/generator';\nimport { assertUnconditionalRegistration } from './contract-guard';\nimport { loadRouterModule, pinNodeEnv, resolveRouterExport, type ResolvedRouter } from './router-module';\n\nconst genLogger = logger.child('@spfn/core:contract-generator');\n\nexport interface ContractGeneratorConfig\n{\n /**\n * Generator name (required for package-based loading)\n */\n name: '@spfn/core:contract';\n\n /**\n * Path to the router file (relative to project root)\n * @example './src/server/router.ts'\n */\n routerPath: string;\n\n /**\n * Named export holding the router.\n * @default 'appRouter', falling back to the default export\n */\n routerExport?: string;\n\n /**\n * Path to the file exporting the `defineEventRouter()` result (relative to\n * project root). When set, its contracted events are written into the\n * document's `events` section; unset, the document has none.\n * @example './src/server/events.ts'\n */\n eventRouterPath?: string;\n\n /**\n * Named export holding the event router.\n * @default 'eventRouter', falling back to the default export\n */\n eventRouterExport?: string;\n\n /**\n * Directory holding current.json, released/ and usage/ (relative to project root)\n * @default './contracts'\n */\n outputDir?: string;\n\n /**\n * Extra file patterns to watch, for routes outside src/server/routes\n */\n additionalRouteDirs?: string[];\n}\n\n/** Thrown when the build must stop. */\nexport class ContractGeneratorError extends Error\n{\n constructor(message: string)\n {\n super(message);\n this.name = 'ContractGeneratorError';\n }\n}\n\nfunction loadRouter(cwd: string, absoluteRouterPath: string, routerExport?: string): ResolvedRouter\n{\n const module = loadRouterModule({\n cwd,\n absoluteRouterPath,\n subject: 'contract',\n fail: message => new ContractGeneratorError(message),\n });\n\n const candidates = routerExport\n ? [routerExport]\n : ['appRouter', 'default', 'router'];\n\n const resolved = resolveRouterExport(module, candidates);\n\n if (resolved)\n {\n return resolved;\n }\n\n throw new ContractGeneratorError(\n `No router found in ${relative(cwd, absoluteRouterPath)}. `\n + `Looked for: ${candidates.join(', ')}. `\n + 'Set \"routerExport\" to the export holding the defineRouter() result.',\n );\n}\n\nfunction isEventRouter(value: unknown): value is EventRouterDef<any>\n{\n return value !== null\n && typeof value === 'object'\n && 'events' in value\n && 'eventNames' in value;\n}\n\ninterface ResolvedEventRouter\n{\n eventRouter: EventRouterDef<any>;\n\n /** The export it was found under, which the registration guard reads. */\n exportName: string;\n}\n\n/**\n * Load the event router through the same loader as the route router: the same\n * `NODE_ENV` pin, the same tsconfig aliases.\n */\nfunction loadEventRouter(cwd: string, absolutePath: string, eventRouterExport?: string): ResolvedEventRouter\n{\n const module = loadRouterModule({\n cwd,\n absoluteRouterPath: absolutePath,\n subject: 'contract',\n fail: message => new ContractGeneratorError(message),\n });\n\n const candidates = eventRouterExport ? [eventRouterExport] : ['eventRouter', 'default'];\n const exportName = candidates.find(candidate => isEventRouter(module[candidate]));\n\n if (exportName)\n {\n return { eventRouter: module[exportName] as EventRouterDef<any>, exportName };\n }\n\n throw new ContractGeneratorError(\n `No event router found in ${relative(cwd, absolutePath)}. `\n + `Looked for: ${candidates.join(', ')}. `\n + 'Set \"eventRouterExport\" to the export holding the defineEventRouter() result.',\n );\n}\n\n/**\n * The event router `eventRouterPath` names, or `undefined` when it is unset.\n *\n * Its source is scanned like the route router's: an event registered behind a\n * flag would make the published event set depend on how the generator ran.\n */\nfunction readEventRouter(cwd: string, eventRouterPath?: string, eventRouterExport?: string): EventRouterDef<any> | undefined\n{\n if (!eventRouterPath)\n {\n return undefined;\n }\n\n const absolutePath = join(cwd, eventRouterPath);\n\n if (!existsSync(absolutePath))\n {\n throw new ContractGeneratorError(\n `Event router file not found: ${eventRouterPath}. `\n + 'The contract generator is configured with \"eventRouterPath\" but has nothing to read there.',\n );\n }\n\n const { eventRouter, exportName } = loadEventRouter(cwd, absolutePath, eventRouterExport);\n\n assertUnconditionalRegistration({\n routerPath: eventRouterPath,\n source: readFileSync(absolutePath, 'utf-8'),\n exportName,\n subject: 'contract',\n factory: 'defineEventRouter',\n });\n\n return eventRouter;\n}\n\nexport function createContractGenerator(config: ContractGeneratorConfig): Generator\n{\n const {\n routerPath,\n routerExport,\n eventRouterPath,\n eventRouterExport,\n outputDir = './contracts',\n additionalRouteDirs = [],\n } = config;\n\n if (!routerPath)\n {\n throw new Error(\n '[@spfn/core:contract] Missing required \"routerPath\" option.\\n\\n'\n + 'Usage:\\n'\n + ' defineGenerator<ContractGeneratorConfig>({\\n'\n + ' name: \\'@spfn/core:contract\\',\\n'\n + ' routerPath: \\'./src/server/router.ts\\',\\n'\n + ' })',\n );\n }\n\n return {\n name: '@spfn/core:contract',\n\n watchPatterns: [\n routerPath,\n ...(eventRouterPath ? [eventRouterPath] : []),\n 'src/server/routes/**/*.ts',\n ...additionalRouteDirs.map(dir => `${dir}/**/*.ts`),\n ],\n\n runOn: ['watch', 'build', 'manual'],\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const { cwd } = options;\n const absoluteRouterPath = join(cwd, routerPath);\n const contractsDir = join(cwd, outputDir);\n\n if (!existsSync(absoluteRouterPath))\n {\n throw new ContractGeneratorError(\n `Router file not found: ${routerPath}. `\n + 'The contract generator is configured but has nothing to read.',\n );\n }\n\n pinNodeEnv();\n\n // Loaded before the guard reads the source, because which router the\n // guard reads is decided by which export the loader found.\n const { router, exportName } = loadRouter(cwd, absoluteRouterPath, routerExport);\n\n assertUnconditionalRegistration({\n routerPath,\n source: readFileSync(absoluteRouterPath, 'utf-8'),\n exportName,\n subject: 'contract',\n });\n\n const document = collectContractDocument(router, readEventRouter(cwd, eventRouterPath, eventRouterExport));\n\n const changed = writeCurrentDocument(contractsDir, document);\n genLogger.info(\n `${changed ? 'Wrote' : 'Verified'} ${relative(cwd, join(contractsDir, 'current.json'))} `\n + `(${document.operations.length} contracted operation(s))`,\n );\n\n if (options.trigger?.type !== 'build')\n {\n return;\n }\n\n const result = checkContract(contractsDir, document);\n\n for (const warning of result.warnings)\n {\n genLogger.warn(warning);\n }\n\n if (result.violations.length === 0)\n {\n if (result.baselineVersion)\n {\n genLogger.info(`Contract is backward compatible with released ${result.baselineVersion}`);\n }\n\n return;\n }\n\n throw new ContractGeneratorError(\n `This build breaks the contract released as ${result.baselineVersion}:\\n\\n`\n + `${formatViolations(result.violations)}\\n\\n`\n + 'A released client cannot be fixed by redeploying the server. Keep the promise, or cut a new '\n + 'contract version and let the old operation stay until no released app calls it.',\n );\n },\n };\n}\n\nexport default createContractGenerator;\n","/**\n * Built-in Generators Export\n *\n * @example\n * ```typescript\n * // .spfnrc.ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n * import type { RouteMapGeneratorConfig, ContractGeneratorConfig } from '@spfn/core/codegen';\n *\n * export default defineConfig({\n * generators: [\n * defineGenerator<RouteMapGeneratorConfig>({\n * name: '@spfn/core:route-map',\n * routerPath: './src/server/router.ts',\n * outputPath: './src/generated/route-map.ts',\n * }),\n * defineGenerator<ContractGeneratorConfig>({\n * name: '@spfn/core:contract',\n * routerPath: './src/server/router.ts',\n * outputDir: './contracts',\n * }),\n * ]\n * });\n * ```\n */\n\nimport { createRouteMapGenerator } from './route-map';\nimport { createContractGenerator } from './contract';\n\nexport type { RouteMapGeneratorConfig } from './route-map';\nexport { RouteMapGeneratorError } from './route-map';\nexport type { ContractGeneratorConfig } from './contract';\nexport { ContractGeneratorError } from './contract';\nexport { assertUnconditionalRegistration, ConditionalRegistrationError } from './contract-guard';\nexport type { RegistrationScan } from './contract-guard';\n\n/**\n * @internal\n * Registry of available generators for package-based loading.\n * DO NOT use directly - use defineGenerator({ name: '@spfn/core:route-map', ... }) instead.\n */\nexport const generators: Record<string, unknown> = {\n 'route-map': createRouteMapGenerator,\n contract: createContractGenerator,\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/core/orchestrator.ts","../../src/codegen/core/config-loader.ts","../../src/codegen/generators/typescript.ts","../../src/codegen/generators/contract-guard.ts","../../src/codegen/generators/emit.ts","../../src/codegen/generators/router-module.ts","../../src/codegen/generators/route-map.ts","../../src/codegen/generators/contract.ts","../../src/codegen/generators/states.ts","../../src/codegen/generators/index.ts"],"names":["chokidarWatch","resolve","logger","join","generators","compiler","existsSync","target","relative","createJiti","readFileSync","dirname","genLogger","loadRouter","ROUTER_EXPORTS","entryLine","mkdirSync","writeFileSync"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Codegen Orchestrator\n *\n * Manages multiple code generators and coordinates their execution\n */\n\nimport { watch as chokidarWatch } from 'chokidar';\nimport { join, relative, sep } from 'path';\nimport mm from 'micromatch';\nimport type { Generator, GeneratorOptions, GeneratorTrigger } from './generator';\nimport { logger } from '@spfn/core/logger';\n\nconst orchestratorLogger = logger.child('@spfn/core:orchestrator');\n\nexport interface OrchestratorOptions\n{\n /** List of generators to orchestrate */\n generators: Generator[];\n\n /** Project root directory */\n cwd?: string;\n\n /** Enable debug logging */\n debug?: boolean;\n\n /**\n * Rethrow a generator failure instead of only logging it\n *\n * Off by default, which keeps watch mode alive through a half-edited file.\n * A build turns it on: a generator that refuses — a broken contract, a\n * router that will not load — has to reach the exit code, or the refusal\n * scrolls past and the build ships anyway.\n */\n throwOnError?: boolean;\n}\n\nexport class CodegenOrchestrator\n{\n private readonly generators: Generator[];\n private readonly cwd: string;\n private readonly debug: boolean;\n private readonly throwOnError: boolean;\n private isGenerating = false;\n private pendingRegenerations = new Set<string>();\n private watcher?: ReturnType<typeof chokidarWatch>;\n private watcherClosePromise?: { resolve: () => void; reject: (error: Error) => void };\n\n constructor(options: OrchestratorOptions)\n {\n this.generators = options.generators;\n this.cwd = options.cwd ?? process.cwd();\n this.debug = options.debug ?? false;\n this.throwOnError = options.throwOnError ?? false;\n }\n\n /**\n * Close watcher and cleanup resources\n */\n async close(): Promise<void>\n {\n if (this.watcher)\n {\n if (this.debug)\n {\n orchestratorLogger.info('Closing watcher');\n }\n await this.watcher.close();\n this.watcher = undefined;\n }\n\n // Resolve the watch promise if it exists\n if (this.watcherClosePromise)\n {\n this.watcherClosePromise.resolve();\n this.watcherClosePromise = undefined;\n }\n }\n\n /**\n * Check if generator should run for given trigger\n */\n private shouldRun(generator: Generator, trigger: GeneratorTrigger): boolean\n {\n const runOn = generator.runOn ?? ['watch', 'manual', 'build'];\n\n return runOn.includes(trigger);\n }\n\n /**\n * Run all generators once\n *\n * @param trigger - How the generators are being triggered\n */\n async generateAll(trigger: GeneratorTrigger = 'manual'): Promise<void>\n {\n // Always log generation start\n const activeGenerators = this.generators.filter(g => this.shouldRun(g, trigger));\n\n if (activeGenerators.length === 0)\n {\n orchestratorLogger.info('No generators to run for this trigger', { trigger });\n\n return;\n }\n\n orchestratorLogger.info(`Running ${activeGenerators.length} generator(s)`, {\n generators: activeGenerators.map(g => g.name).join(', '),\n trigger,\n });\n\n for (const generator of this.generators)\n {\n // Check if generator should run for this trigger\n if (!this.shouldRun(generator, trigger))\n {\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Skipped (runOn: ${generator.runOn?.join(', ') ?? 'default'})`);\n }\n\n continue;\n }\n\n try\n {\n const startTime = Date.now();\n\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug,\n trigger: {\n type: trigger,\n },\n };\n\n await generator.generate(genOptions);\n\n const duration = Date.now() - startTime;\n orchestratorLogger.info(`[${generator.name}] ✓ Generated successfully (${duration}ms)`);\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] ✗ Generation failed`, err);\n\n if (this.throwOnError)\n {\n throw err;\n }\n }\n }\n }\n\n /**\n * Start watch mode\n */\n async watch(): Promise<void>\n {\n // Initial generation with 'watch' trigger\n await this.generateAll('watch');\n\n // Collect all watch patterns from generators\n const allPatterns = this.generators.flatMap(g => g.watchPatterns);\n\n if (allPatterns.length === 0)\n {\n orchestratorLogger.warn('No watch patterns defined, exiting watch mode');\n\n return;\n }\n\n // Extract directories to watch from patterns\n // For pattern like \"watched/**/*.ts\", watch \"watched\" directory\n const dirsToWatch = new Set<string>();\n for (const pattern of allPatterns)\n {\n // Extract base directory from glob pattern (e.g., \"src/**/*.ts\" -> \"src\")\n const baseDir = pattern.split('**')[0].replace(/\\/$/, '') || '.';\n dirsToWatch.add(join(this.cwd, baseDir));\n }\n\n const watchDirs = Array.from(dirsToWatch);\n\n // Always log watch mode start\n orchestratorLogger.info('Watch mode started', {\n watching: watchDirs.length === 1 ? watchDirs[0] : `${watchDirs.length} directories`,\n generators: this.generators.filter(g => this.shouldRun(g, 'watch')).map(g => g.name).join(', '),\n });\n\n if (this.debug)\n {\n orchestratorLogger.info('Watch mode details', {\n patterns: allPatterns,\n watchDirs,\n cwd: this.cwd,\n });\n }\n\n this.watcher = chokidarWatch(watchDirs, {\n // Ignore dotfiles by path segments relative to cwd — matching the absolute\n // path would ignore everything when the checkout itself lives under a dot\n // directory (e.g. .claude/worktrees/<name>), leaving zero watched files\n ignored: (watchedPath: string) => relative(this.cwd, watchedPath)\n .split(sep)\n .some(segment => segment.startsWith('.') && segment !== '.' && segment !== '..'),\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50,\n },\n });\n\n const handleChange = async (absolutePath: string, event: 'add' | 'change' | 'unlink') =>\n {\n // Convert absolute path to relative path for pattern matching\n const filePath = relative(this.cwd, absolutePath);\n\n if (this.isGenerating)\n {\n this.pendingRegenerations.add(absolutePath);\n\n return;\n }\n\n this.isGenerating = true;\n this.pendingRegenerations.clear();\n\n // Always log file changes\n const eventIcon = event === 'add' ? '+' : event === 'unlink' ? '-' : '~';\n orchestratorLogger.info(`File ${eventIcon} ${filePath}`);\n\n // Find matching generators\n let regeneratedCount = 0;\n for (const generator of this.generators)\n {\n // Check if generator should run for 'watch' trigger\n if (!this.shouldRun(generator, 'watch'))\n {\n continue;\n }\n\n const matches = generator.watchPatterns.some(pattern =>\n mm.isMatch(filePath, pattern),\n );\n\n if (matches)\n {\n try\n {\n const startTime = Date.now();\n\n // Call generate() with trigger information\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug,\n trigger: {\n type: 'watch',\n changedFile: {\n path: filePath,\n event,\n },\n },\n };\n\n await generator.generate(genOptions);\n\n const duration = Date.now() - startTime;\n orchestratorLogger.info(`[${generator.name}] ✓ Regenerated (${duration}ms)`);\n regeneratedCount++;\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] ✗ Regeneration failed`, err);\n }\n }\n }\n\n if (regeneratedCount === 0 && this.debug)\n {\n orchestratorLogger.info('No generators matched this file');\n }\n\n this.isGenerating = false;\n\n // Process pending regenerations\n if (this.pendingRegenerations.size > 0)\n {\n const next = Array.from(this.pendingRegenerations)[0];\n await handleChange(next, 'change');\n }\n };\n\n this.watcher\n .on('add', (path) => handleChange(path, 'add'))\n .on('change', (path) => handleChange(path, 'change'))\n .on('unlink', (path) => handleChange(path, 'unlink'));\n\n // Return a promise that resolves when the watcher is closed\n // This allows the caller to await the watch() method and keep the process alive\n return new Promise<void>((resolve, reject) =>\n {\n this.watcherClosePromise = { resolve, reject };\n });\n }\n}\n","/**\n * Codegen Configuration Loader\n *\n * Loads codegen configuration from .spfnrc.ts, .spfnrc.json or package.json\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createJiti } from 'jiti';\nimport type { Generator } from './generator';\nimport { logger } from '@spfn/core/logger';\n\nconst configLogger = logger.child('@spfn/core:codegen-config');\n\n/**\n * Custom generator via file path\n */\ntype CustomGeneratorByPath = { path: string };\n\n/**\n * Package-based generator configuration\n */\ntype PackageGeneratorDef = { name: string; enabled?: boolean } & Record<string, any>;\n\n/**\n * Any generator configuration\n */\nexport type GeneratorConfig = CustomGeneratorByPath | PackageGeneratorDef;\n\n/**\n * Codegen configuration\n */\nexport interface CodegenConfig\n{\n generators?: GeneratorConfig[];\n}\n\n/**\n * Define a generator with type safety\n *\n * @example\n * Custom generator with type parameter:\n * ```ts\n * import { defineGenerator } from '@spfn/core/codegen';\n * import type { MyGeneratorConfig } from 'my-package';\n *\n * const customGen = defineGenerator<MyGeneratorConfig>({\n * name: 'my-package:generator',\n * myOption: 'value',\n * });\n * ```\n */\nexport function defineGenerator<T extends Record<string, any>>(config: T): T;\nexport function defineGenerator(config: PackageGeneratorDef): PackageGeneratorDef;\nexport function defineGenerator(config: CustomGeneratorByPath): CustomGeneratorByPath;\nexport function defineGenerator<T extends Record<string, any>>(config: T): T\n{\n return config;\n}\n\n/**\n * Helper function to define codegen configuration with type safety\n *\n * @example\n * With custom generator:\n * ```ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n * import type { MyGeneratorConfig } from 'my-package';\n *\n * const customGen = defineGenerator<MyGeneratorConfig>({\n * name: 'my-package:custom',\n * myOption: 'value', // Type-safe!\n * });\n *\n * export default defineConfig({\n * generators: [customGen]\n * });\n * ```\n */\nexport function defineConfig(config: CodegenConfig): CodegenConfig\n{\n return config;\n}\n\n/**\n * Load codegen configuration from .spfnrc.ts, .spfnrc.json or package.json\n */\nexport function loadCodegenConfig(cwd: string): CodegenConfig\n{\n // 1. Check .spfnrc.ts (highest priority)\n const rcTsPath = join(cwd, '.spfnrc.ts');\n if (existsSync(rcTsPath))\n {\n try\n {\n const jiti = createJiti(cwd, {\n interopDefault: true,\n moduleCache: false,\n });\n\n const module = jiti(rcTsPath);\n const config = module.default || module;\n\n if (config && typeof config === 'object')\n {\n configLogger.info('Loaded config from .spfnrc.ts');\n\n return config as CodegenConfig;\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.warn('Failed to load .spfnrc.ts', err);\n }\n }\n\n // 2. Check .spfnrc.json\n const rcPath = join(cwd, '.spfnrc.json');\n if (existsSync(rcPath))\n {\n try\n {\n const content = readFileSync(rcPath, 'utf-8');\n const config = JSON.parse(content);\n\n if (config.codegen)\n {\n configLogger.info('Loaded config from .spfnrc.json');\n\n return config.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse .spfnrc.json', error as Error);\n }\n }\n\n // 3. Check package.json\n const pkgPath = join(cwd, 'package.json');\n if (existsSync(pkgPath))\n {\n try\n {\n const content = readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n\n if (pkg.spfn?.codegen)\n {\n configLogger.info('Loaded config from package.json');\n\n return pkg.spfn.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse package.json', error as Error);\n }\n }\n\n // 4. Default configuration (empty - no generators by default)\n configLogger.info('Using default config (no generators)');\n\n return {\n generators: [],\n };\n}\n\n/**\n * Load generator from package\n *\n * Supports format: \"package:generator-name\" or \"@scope/package:generator-name\"\n */\nasync function loadGeneratorFromPackage(\n packageName: string,\n generatorName: string,\n config: Record<string, any>,\n): Promise<Generator | null>\n{\n try\n {\n // Try to load package/generators export using jiti for better module resolution\n const jiti = createJiti(import.meta.url, {\n interopDefault: true,\n moduleCache: false,\n });\n\n const generatorsModule = jiti(`${packageName}/codegen`);\n\n // Look for generator by name in registry\n if (generatorsModule.generators?.[generatorName])\n {\n const createFn = generatorsModule.generators[generatorName];\n const generator = createFn(config);\n configLogger.info(`Loaded ${packageName}:${generatorName}`);\n\n return generator;\n }\n\n // Fallback: try conventional name (createXxxGenerator)\n const conventionalName = `create${capitalize(generatorName)}Generator`;\n if (generatorsModule[conventionalName])\n {\n const createFn = generatorsModule[conventionalName];\n const generator = createFn(config);\n configLogger.info(`Loaded ${packageName}:${generatorName} (via ${conventionalName})`);\n\n return generator;\n }\n\n configLogger.warn(\n `Generator \"${generatorName}\" not found in ${packageName}/codegen. ` +\n `Expected: generators.${generatorName} or ${conventionalName}`,\n );\n\n return null;\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.warn(\n `Failed to load ${packageName}:${generatorName}. ` +\n `Make sure ${packageName} is installed. Error: ${err.message}`,\n );\n\n return null;\n }\n}\n\n/**\n * Capitalize first letter\n */\nfunction capitalize(str: string): string\n{\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Create generator instances from configuration\n */\nexport async function createGeneratorsFromConfig(config: CodegenConfig, cwd: string): Promise<Generator[]>\n{\n const generators: Generator[] = [];\n\n if (!config.generators || config.generators.length === 0)\n {\n return generators;\n }\n\n for (const generatorConfig of config.generators)\n {\n try\n {\n // Already instantiated Generator (has generate function)\n // This prevents double-loading when users accidentally call factory directly\n if ('generate' in generatorConfig && typeof (generatorConfig as any).generate === 'function')\n {\n generators.push(generatorConfig as Generator);\n configLogger.info(`Generator instance added: ${(generatorConfig as Generator).name}`);\n continue;\n }\n\n // Custom generator (via file path)\n if ('path' in generatorConfig)\n {\n const generatorPath = generatorConfig.path.startsWith('.')\n ? join(cwd, generatorConfig.path)\n : generatorConfig.path;\n\n configLogger.info(`Loading custom generator: ${generatorPath}`);\n\n let module: any;\n\n // Use jiti for .ts files, regular import for .js\n if (generatorPath.endsWith('.ts'))\n {\n const jiti = createJiti(cwd, {\n interopDefault: true,\n });\n module = jiti(generatorPath);\n }\n else\n {\n module = await import(generatorPath);\n }\n\n const createGenerator = module.default || module.createGenerator || module;\n\n if (typeof createGenerator === 'function')\n {\n const generator = createGenerator();\n generators.push(generator);\n configLogger.info(`Custom generator loaded: ${generator.name}`);\n }\n else\n {\n configLogger.warn(`Invalid generator at ${generatorPath}: expected function`);\n }\n }\n // Package-based generator: \"package:name\" or \"@scope/package:name\"\n else if ('name' in generatorConfig && generatorConfig.name.includes(':'))\n {\n if (generatorConfig.enabled !== false)\n {\n const [packageName, generatorName] = generatorConfig.name.split(':');\n const { enabled, name, ...generatorOptions } = generatorConfig;\n\n const generator = await loadGeneratorFromPackage(\n packageName,\n generatorName,\n generatorOptions,\n );\n\n if (generator)\n {\n generators.push(generator);\n }\n }\n }\n // Unknown generator name format\n else if ('name' in generatorConfig)\n {\n configLogger.warn(\n `Invalid generator name \"${generatorConfig.name}\". ` +\n `Use package:name format (e.g., \"@spfn/core:contract\")`,\n );\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.error('Failed to load generator', err);\n }\n }\n\n return generators;\n}\n","/**\n * TypeScript, loaded on first use\n *\n * Two things here read TypeScript's own parser: the `paths` a router's imports\n * resolve through, and the guard that reads `defineRouter({...})` out of the\n * router file. Both run only while a router is being read.\n *\n * `generators/index.ts` is re-exported from `@spfn/core/codegen`, so a\n * top-level `import ts from 'typescript'` loaded the whole compiler wherever\n * that entry is imported: `spfn dev` startup, the watcher child, every\n * `.spfnrc.ts` evaluation, and `spfn codegen list` — none of which resolve an\n * alias or parse a router. It cost ~0.3s and ~70MB to hand back a factory\n * function.\n *\n * `createRequire` rather than a dynamic `import()`: both callers are\n * synchronous, and the guard's whole job is to run before anything is written.\n */\n\nimport { createRequire } from 'module';\n\nlet compiler: typeof import('typescript') | undefined;\n\n/** The compiler, loaded on the first call and kept for the rest of the process. */\nexport function typescript(): typeof import('typescript')\n{\n compiler ??= createRequire(import.meta.url)('typescript') as typeof import('typescript');\n\n return compiler;\n}\n","/**\n * Router registration guard\n *\n * A route registered only behind a feature flag or an environment check makes\n * generated output depend on how the generator happened to run. The contract\n * then describes a promise nobody made, and the route map leaves out a name\n * `registerRoutes` registers in production — so `api.admin.call()` typechecks\n * and 404s wherever the flag differs.\n *\n * What it reads is the router the generator was pointed at: the export the\n * loader found the router under, and the routers that export mounts by name\n * from the same file, since a nested router's routes land in the same flat map.\n * A `defineRouter(` the file writes but the app router never reaches — a second\n * router a test harness mounts, say — registers nothing in production and is\n * not scanned.\n *\n * Reading is done with TypeScript's parser rather than a regular expression\n * over the text. A spread is a syntax node there, so a JSDoc that spells\n * `defineRouter({ ... })` in prose, a brace inside a route path, and a comment\n * holding an old router are not router source. Only a spread whose expression\n * reads a condition is refused — a ternary, `&&`, `||`, `??`. A call is\n * allowed: `...metadataRoutes(config, resource)` is how `@spfn/mcp` composes\n * its router, and loading yields exactly the routes it returns.\n *\n * Past it, by construction: a conditional spread inside an imported route\n * module, a router built by a factory, a condition hoisted to a variable\n * (`const extra = flag ? { admin } : {}` spread afterwards), and a\n * `.packages()` list assembled conditionally. `NODE_ENV` is pinned before the\n * router loads, which covers those only when the shell left it unset: the\n * generator then reads the router production gets. `spfn build` pins\n * `production` itself, so the deployed map is right. `spfn dev` sets\n * `development` before it spawns the watcher, which inherits it — a\n * `NODE_ENV === 'development'` condition hoisted to a variable therefore writes\n * a dev-only route into the map the watcher regenerates, and `spfn build` takes\n * it back out. The generated map's header names the `NODE_ENV` it was written\n * under, so that difference shows up in the diff.\n */\n\nimport type * as ts from 'typescript';\nimport { typescript } from './typescript';\n\n/** Thrown when the router registers routes conditionally. */\nexport class ConditionalRegistrationError extends Error\n{\n constructor(message: string)\n {\n super(message);\n this.name = 'ConditionalRegistrationError';\n }\n}\n\nexport interface RegistrationScan\n{\n /** Path named in the error message. */\n routerPath: string;\n\n /** Contents of the router file. */\n source: string;\n\n /** The export the loader found the router under: `appRouter`, `default`, … */\n exportName: string;\n\n /** What is being generated, named in the message: `route map`, `contract`. */\n subject: string;\n\n /**\n * The call the router is built with. `defineEventRouter` scans an event\n * router file, whose event set the contract publishes the same way.\n * @default 'defineRouter'\n */\n factory?: RouterFactory;\n}\n\nexport type RouterFactory = 'defineRouter' | 'defineEventRouter';\n\n/** What a refusal says, per kind of router: what is left out and what a client sees. */\nconst REFUSAL_WORDING: Record<RouterFactory, { noun: string; consequence: string; remedy: string }> = {\n defineRouter: {\n noun: 'routes',\n consequence: 'a route production registers is left out, and the client that addresses it by name gets a 404',\n remedy: 'Register the route unconditionally and gate its behaviour inside the handler instead.',\n },\n defineEventRouter: {\n noun: 'events',\n consequence: 'an event production streams is left out, and the client that subscribes to it by name gets a 400',\n remedy: 'Register the event unconditionally and decide who receives it with the stream\\'s authorize hook instead.',\n },\n};\n\n/**\n * Refuse a router whose route set depends on a condition.\n */\nexport function assertUnconditionalRegistration(scan: RegistrationScan): void\n{\n const compiler = typescript();\n const file = compiler.createSourceFile(\n scan.routerPath,\n scan.source,\n compiler.ScriptTarget.Latest,\n /* setParentNodes */ false,\n );\n\n const declarations = topLevelInitialisers(compiler, file);\n const routes = routesLiteral(compiler, declarations.get(scan.exportName), declarations, new Set(), factoryOf(scan));\n\n // No literal means the router is not written as `defineRouter({...})` in\n // this file — a factory, or an import. Documented as past the guard.\n if (routes)\n {\n assertLiteral(compiler, file, routes, declarations, new Set(), scan);\n }\n}\n\nfunction factoryOf(scan: RegistrationScan): RouterFactory\n{\n return scan.factory ?? 'defineRouter';\n}\n\n/**\n * What each name the loader could have found the router under is initialised\n * with: every top-level `const <name> = <expression>`, `export default\n * <expression>` under the name `default`, and a renaming export\n * (`export { r as default }`) under the name it exports.\n *\n * Top level only, because that is where a router is declared and where the\n * loader reads it from. A router built inside a function is past the guard for\n * the same reason a factory is.\n */\nfunction topLevelInitialisers(compiler: typeof ts, file: ts.SourceFile): Map<string, ts.Expression>\n{\n const found = new Map<string, ts.Expression>();\n\n for (const statement of file.statements)\n {\n if (compiler.isExportAssignment(statement) && !statement.isExportEquals)\n {\n found.set('default', statement.expression);\n }\n\n if (compiler.isVariableStatement(statement))\n {\n collectDeclarations(compiler, statement, found);\n }\n }\n\n // After the declarations, so a renamed export resolves through the name it\n // renames. `export { appRouter }` needs nothing: the declaration is the entry.\n for (const statement of file.statements)\n {\n collectRenamedExports(compiler, statement, found);\n }\n\n return found;\n}\n\nfunction collectDeclarations(\n compiler: typeof ts,\n statement: ts.VariableStatement,\n found: Map<string, ts.Expression>,\n): void\n{\n for (const declaration of statement.declarationList.declarations)\n {\n if (compiler.isIdentifier(declaration.name) && declaration.initializer)\n {\n found.set(declaration.name.text, declaration.initializer);\n }\n }\n}\n\nfunction collectRenamedExports(compiler: typeof ts, statement: ts.Statement, found: Map<string, ts.Expression>): void\n{\n if (!compiler.isExportDeclaration(statement)\n || !statement.exportClause\n || !compiler.isNamedExports(statement.exportClause))\n {\n return;\n }\n\n for (const specifier of statement.exportClause.elements)\n {\n // The local name as an expression: `routesLiteral` follows it through\n // this same map. Only a rename is recorded — mapping `x` to `x` would\n // shadow the declaration it is supposed to lead to.\n if (specifier.propertyName && !found.has(specifier.name.text))\n {\n found.set(specifier.name.text, specifier.propertyName);\n }\n }\n}\n\n/** `as const`, `satisfies`, `!` and parentheses sit between a router and its call. */\nfunction unwrap(compiler: typeof ts, expression: ts.Expression | undefined): ts.Expression | undefined\n{\n if (!expression)\n {\n return undefined;\n }\n\n if (compiler.isParenthesizedExpression(expression)\n || compiler.isAsExpression(expression)\n || compiler.isSatisfiesExpression(expression)\n || compiler.isNonNullExpression(expression)\n || compiler.isTypeAssertionExpression(expression))\n {\n return unwrap(compiler, expression.expression);\n }\n\n return expression;\n}\n\n/**\n * The object literal `defineRouter()` receives, through however the router is\n * spelled: `defineRouter({…}).packages([…]).use([…])`, a name pointing at\n * another declaration (`export default appRouter`), or the call on its own.\n *\n * `seen` stops a file whose declarations refer to each other from recursing\n * forever, and stops a router mounted twice from being scanned twice.\n */\nfunction routesLiteral(\n compiler: typeof ts,\n expression: ts.Expression | undefined,\n declarations: Map<string, ts.Expression>,\n seen: Set<string>,\n factory: RouterFactory,\n): ts.ObjectLiteralExpression | undefined\n{\n const node = unwrap(compiler, expression);\n\n if (!node)\n {\n return undefined;\n }\n\n if (compiler.isIdentifier(node))\n {\n if (seen.has(node.text))\n {\n return undefined;\n }\n\n seen.add(node.text);\n\n return routesLiteral(compiler, declarations.get(node.text), declarations, seen, factory);\n }\n\n if (!compiler.isCallExpression(node))\n {\n return undefined;\n }\n\n const callee = unwrap(compiler, node.expression);\n\n if (callee && compiler.isIdentifier(callee) && callee.text === factory)\n {\n const routes = unwrap(compiler, node.arguments[0]);\n\n return routes && compiler.isObjectLiteralExpression(routes) ? routes : undefined;\n }\n\n // A chained `.packages([...])` / `.use([...])` / `.contractVersion('1.0.0')`:\n // keep walking down to the defineRouter call the chain was built from. The\n // arguments are not followed — a package router registers its own routes,\n // which this generator neither emits nor completes.\n return callee && compiler.isPropertyAccessExpression(callee)\n ? routesLiteral(compiler, callee.expression, declarations, seen, factory)\n : undefined;\n}\n\n/**\n * Check one router's routes, and the routers it mounts by name.\n *\n * A nested router registers under its own keys into the same flat map, so a\n * condition inside one leaves out a name exactly as a condition in the app\n * router does. Being mounted is what tells it apart from a router the file\n * declares and never registers.\n */\nfunction assertLiteral(\n compiler: typeof ts,\n file: ts.SourceFile,\n literal: ts.ObjectLiteralExpression,\n declarations: Map<string, ts.Expression>,\n seen: Set<string>,\n scan: RegistrationScan,\n): void\n{\n for (const property of literal.properties)\n {\n if (compiler.isSpreadAssignment(property))\n {\n assertUnconditionalSpread(compiler, file, property.expression, scan);\n\n continue;\n }\n\n const nested = routesLiteral(compiler, mountedRouter(compiler, property), declarations, seen, factoryOf(scan));\n\n if (nested)\n {\n assertLiteral(compiler, file, nested, declarations, seen, scan);\n }\n }\n}\n\n/** What a router entry holds: the value written, or the name a shorthand stands for. */\nfunction mountedRouter(compiler: typeof ts, property: ts.ObjectLiteralElementLike): ts.Expression | undefined\n{\n if (compiler.isPropertyAssignment(property))\n {\n return property.initializer;\n }\n\n return compiler.isShorthandPropertyAssignment(property) ? property.name : undefined;\n}\n\nfunction assertUnconditionalSpread(\n compiler: typeof ts,\n file: ts.SourceFile,\n expression: ts.Expression,\n scan: RegistrationScan,\n): void\n{\n const condition = conditionKind(compiler, expression);\n\n if (!condition)\n {\n return;\n }\n\n const wording = REFUSAL_WORDING[factoryOf(scan)];\n\n throw new ConditionalRegistrationError(\n `${scan.routerPath} registers ${wording.noun} conditionally: \"...${spreadText(file, expression)}\" `\n + `(${condition}).\\n\\n`\n + `The ${scan.subject} is generated from the router as it loads, so a set of ${wording.noun} that depends on `\n + `a flag or an environment describes whichever way the generator happened to run: ${wording.consequence}.\\n`\n + wording.remedy,\n );\n}\n\n/** How the spread reads a condition, or `undefined` when it does not read one. */\nfunction conditionKind(compiler: typeof ts, expression: ts.Expression): string | undefined\n{\n const node = unwrap(compiler, expression);\n\n if (!node)\n {\n return undefined;\n }\n\n if (compiler.isConditionalExpression(node))\n {\n return 'a ternary';\n }\n\n if (!compiler.isBinaryExpression(node))\n {\n return undefined;\n }\n\n switch (node.operatorToken.kind)\n {\n case compiler.SyntaxKind.AmpersandAmpersandToken:\n return '&&';\n case compiler.SyntaxKind.BarBarToken:\n return '||';\n case compiler.SyntaxKind.QuestionQuestionToken:\n return '??';\n default:\n return undefined;\n }\n}\n\n/** The spread's source, on one line, so a multi-line ternary stays a readable message. */\nfunction spreadText(file: ts.SourceFile, expression: ts.Expression): string\n{\n return expression.getText(file).replace(/\\s+/g, ' ');\n}\n","/**\n * Emit\n *\n * The literals the generators write into a generated file: an object key and a\n * string. Shared so every generated file spells a name the same way — a state\n * id and a route name reach the same `__proto__` and quoting rules.\n */\n\n/**\n * A route name is a key in an object literal, and a key that is not an\n * identifier has to be quoted or the generated file will not parse.\n *\n * The source parser could never produce such a name — it read names off\n * `export const` — but `defineRouter({ 'get-user': getUser })` is a legal\n * router that the server registers as `get-user`, so the map has to be able to\n * spell it. `JSON.stringify` is the escaping: double quotes are what it emits,\n * and every other name is left bare so an unchanged project regenerates\n * byte-identically.\n */\nexport function toObjectKey(name: string): string\n{\n // `__proto__:` in an object literal sets the prototype instead of defining\n // an own property, and so does `\"__proto__\":` — the route would vanish from\n // Object.keys and from the proxy's spread. A computed key is the one form\n // that always defines an own property.\n if (name === '__proto__')\n {\n return `[${JSON.stringify(name)}]`;\n }\n\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);\n}\n\n/**\n * Printable ASCII, minus the two characters a single-quoted literal cannot hold.\n * Every realistic path is in here and is emitted as it always was, so an\n * unchanged project regenerates byte-identically.\n */\nconst SINGLE_QUOTABLE = /^[\\x20-\\x26\\x28-\\x5B\\x5D-\\x7E]*$/;\n\n/**\n * A path is emitted as a string literal, and a path carrying a quote, a\n * backslash or a line terminator would close it early — or end the line — and\n * leave a `DO NOT EDIT` file whose syntax error points at nothing.\n *\n * `JSON.stringify` handles all of those, so anything outside the plain ASCII a\n * single-quoted literal can hold is handed to it. U+2028 and U+2029 are the\n * exception it does not cover: they are legal in a JSON string and were a line\n * terminator in string literals before ES2019, so they are escaped by hand.\n */\nexport function toStringLiteral(value: string): string\n{\n if (SINGLE_QUOTABLE.test(value))\n {\n return `'${value}'`;\n }\n\n return JSON.stringify(value)\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n","/**\n * Loading a router for a generator\n *\n * `@spfn/core:route-map` and `@spfn/core:contract` both read the router by\n * importing it, and both need the same things settled before that import runs:\n * the environment the module observes, which otherwise follows whichever shell\n * invoked the generator, and the project's own path aliases, which jiti does not\n * read on its own.\n *\n * Both live here rather than in one generator so the two cannot drift: a\n * process-wide `NODE_ENV` pinned by whichever generator `.spfnrc.ts` happens to\n * list first would otherwise decide what the other one loads.\n */\n\nimport { existsSync, readdirSync, statSync } from 'fs';\nimport { dirname, isAbsolute, join, relative, resolve } from 'path';\nimport { createJiti } from 'jiti';\nimport type * as ts from 'typescript';\nimport type { RouteDef, Router } from '@spfn/core/route';\nimport { logger } from '@spfn/core/logger';\nimport { typescript } from './typescript';\n\nconst loadLogger = logger.child('@spfn/core:codegen');\n\n// ============================================================================\n// Environment\n// ============================================================================\n\n/**\n * Pin NODE_ENV before a router loads.\n *\n * A route module that reads the environment at import — a schema built from a\n * flag, a config module with a `development` branch — would otherwise make the\n * generated output depend on how the generator happened to be invoked. It is\n * also what stands in for the guard against a condition the guard cannot see,\n * such as one hoisted to a variable before the spread that registers it — but\n * only when the shell left NODE_ENV unset.\n *\n * The pin is process-wide and deliberately only applies when NODE_ENV is unset,\n * so calling it from both generators in one run is the same as calling it once:\n * the second call finds the value the first one set and leaves it alone.\n *\n * It is unconditional nowhere, and `spfn dev` is why: it sets `development`\n * before spawning the watcher, and a route registered only in development has\n * to be in the map the watcher writes or it 404s in `spfn dev` itself.\n * `spfn build` pins `production` and generates before it compiles, so what ships\n * is right; the cost is churn between the two, which the generated header makes\n * visible by naming the NODE_ENV the map was written under.\n */\nexport function pinNodeEnv(): void\n{\n if (process.env.NODE_ENV)\n {\n return;\n }\n\n process.env.NODE_ENV = 'production';\n loadLogger.info('NODE_ENV was unset; pinned to \"production\" so generated output does not depend on the shell');\n}\n\n// ============================================================================\n// tsconfig path aliases\n// ============================================================================\n\n/**\n * `readDirectory` is stubbed out: only `compilerOptions` is wanted here, and\n * letting TypeScript expand `include` would glob the whole project for nothing.\n */\nfunction parseHost(compiler: typeof ts): ts.ParseConfigHost\n{\n return {\n useCaseSensitiveFileNames: compiler.sys.useCaseSensitiveFileNames,\n readDirectory: () => [],\n fileExists: compiler.sys.fileExists,\n readFile: compiler.sys.readFile,\n };\n}\n\n/**\n * \"No inputs were found in config file\". The stubbed `readDirectory` produces it\n * every time and it says nothing about the config.\n */\nconst NO_INPUTS = 18003;\n\n/**\n * One tsconfig `paths` entry, as jiti resolves it.\n *\n * `from`/`to` are the alias; `pattern`, `target` and `others` are kept so that a\n * specifier which did not resolve can say which target it was tried through and\n * which ones the entry also listed — jiti holds one alias per key, so those\n * others were never tried.\n */\ninterface AliasEntry\n{\n from: string;\n to: string;\n pattern: string;\n target: string;\n others: string[];\n}\n\n/** What has to exist for a target to resolve: the directory a prefix names, or the file itself. */\nfunction targetPath(target: string, base: string): string\n{\n return resolve(base, target.endsWith('/*') ? target.slice(0, -2) : target);\n}\n\n/**\n * Codes the filesystem raises when it refuses to read a path at all.\n *\n * POSIX says EACCES; Windows and some container runtimes say EPERM for the same\n * directory. Keying on one of them would fix a developer machine and leave the\n * other platform crashing, so the guard names both.\n */\nconst UNREADABLE_CODES = new Set(['EACCES', 'EPERM']);\n\n/** Whether an error is the filesystem refusing to read a path, rather than a fault to surface. */\nfunction isUnreadable(error: unknown): boolean\n{\n // A `throw` that is not an object at all must not make the guard itself throw and\n // bury what was really raised.\n return UNREADABLE_CODES.has((error as { code?: string } | null)?.code ?? '');\n}\n\n/**\n * Whether a target can resolve anything at all.\n *\n * TypeScript and tsup substitute each target and take the first that resolves\n * the *requested module*; jiti holds one alias per key, so the nearest this can\n * get is asking whether the directory a prefix names holds anything. That is\n * the difference that matters in practice: a `dist` left behind by `rm -rf\n * dist/*`, or created empty by a tool that then failed, exists and resolves\n * nothing, and taking it ahead of `./src/*` left every import unresolved.\n *\n * A target with no wildcard names a file, and `existsSync` is the whole of the\n * question for it — it reports false for a path it cannot read rather than\n * throwing.\n *\n * The wildcard branch has to say so itself. `throwIfNoEntry: false` suppresses\n * only ENOENT: a directory the process cannot read stats fine and then makes\n * `readdirSync` throw, and an unreadable parent makes `statSync` throw too. That\n * used to reach the developer as a bare `EACCES: permission denied, scandir` from\n * inside `loadRouterModule`, before the catch that names the file and the cause.\n * A target that cannot be read resolves nothing, so it counts as unresolvable and\n * the next target in the entry is tried — which is what the caller already does\n * for a missing one. Every other error is left to throw.\n */\nfunction targetResolves(target: string, base: string): boolean\n{\n const path = targetPath(target, base);\n\n if (!target.endsWith('/*'))\n {\n return existsSync(path);\n }\n\n try\n {\n const stats = statSync(path, { throwIfNoEntry: false });\n\n return stats?.isDirectory() === true && readdirSync(path).length > 0;\n }\n catch (error)\n {\n if (!isUnreadable(error))\n {\n throw error;\n }\n\n return false;\n }\n}\n\n/** The target a `paths` entry resolves through, and the ones it passed over. */\ninterface TargetChoice\n{\n target: string;\n\n /** Targets the pattern also listed. Named in a failure, since jiti tried none of them. */\n others: string[];\n}\n\n/**\n * The target a `paths` entry resolves through.\n *\n * TypeScript tries each target in order and takes the first that resolves, and\n * so does tsup; jiti holds one alias per key. Taking the first target\n * unconditionally therefore failed a project whose first target is a build\n * output that has not been produced — an ordinary shape for a `paths` entry\n * listing `./dist/*` before `./src/*`.\n */\nfunction chooseTarget(pattern: string, targets: string[], base: string): TargetChoice | undefined\n{\n const present = targets.filter(target => targetResolves(target, base));\n const [target] = present.length > 0 ? present : targets;\n\n if (!target)\n {\n return undefined;\n }\n\n if (present.length > 1)\n {\n loadLogger.warn(\n `tsconfig \"paths\" maps ${pattern} to ${present.length} targets that could each resolve a module; `\n + `while the router loads, only the first (${target}) does`,\n );\n }\n\n if (present.length === 0 && targets.length > 1)\n {\n loadLogger.warn(\n `tsconfig \"paths\" maps ${pattern} to ${targets.length} targets and none of them exists with anything `\n + `in it; ${target} is used, and an import through it will name itself as unresolved`,\n );\n }\n\n return { target, others: targets.filter(candidate => candidate !== target) };\n}\n\n/** One `paths` entry as a jiti alias, or `undefined` when jiti cannot express it. */\nfunction toAlias(pattern: string, targets: string[], base: string): AliasEntry | undefined\n{\n const choice = chooseTarget(pattern, targets, base);\n\n if (!choice)\n {\n return undefined;\n }\n\n const { target, others } = choice;\n\n if (!pattern.includes('*'))\n {\n return { from: pattern, to: resolve(base, target), pattern, target, others };\n }\n\n // jiti matches an alias by path segment, so the only mapping it can express\n // is a prefix: \"@/*\" -> \"./src/*\" becomes \"@/\" -> \"<base>/src\".\n if (!pattern.endsWith('/*') || !target.endsWith('/*'))\n {\n loadLogger.warn(\n `tsconfig \"paths\" maps ${pattern} to ${target}, which is not a directory prefix mapping; it will not `\n + 'resolve while the router loads',\n );\n\n return undefined;\n }\n\n // The trailing slash is kept, so \"@x/*\" and \"@x\" — one entry per form, which\n // is how a package maps its own subpaths beside its entry point — become two\n // aliases instead of collapsing onto \"@x\" and losing the exact one. jiti\n // resolves \"@x/a\" through \"@x/\" either way.\n return { from: pattern.slice(0, -1), to: resolve(base, target.slice(0, -2)), pattern, target, others };\n}\n\n/** `compilerOptions` of one tsconfig, with `extends` already merged. */\nfunction readCompilerOptions(configPath: string, cwd: string): ts.CompilerOptions | undefined\n{\n if (!existsSync(configPath))\n {\n return undefined;\n }\n\n const compiler = typescript();\n const { config, error } = compiler.readConfigFile(configPath, compiler.sys.readFile);\n\n if (error || !config)\n {\n loadLogger.warn(`Could not read ${relative(cwd, configPath)}; its path aliases will not resolve`);\n\n return undefined;\n }\n\n const parsed = compiler.parseJsonConfigFileContent(config, parseHost(compiler), dirname(configPath));\n\n // An `extends` target TypeScript cannot read leaves `paths` empty rather\n // than failing, and the router then fails to load for a reason that looks\n // like a missing mapping. Reachable in ordinary CI: a base config outside\n // the package, not copied into a Docker stage.\n for (const diagnostic of parsed.errors)\n {\n if (diagnostic.code !== NO_INPUTS)\n {\n loadLogger.warn(\n `${relative(cwd, configPath)}: ${compiler.flattenDiagnosticMessageText(diagnostic.messageText, ' ')} `\n + '— path aliases it should have declared may be missing while the router loads',\n );\n }\n }\n\n return parsed.options;\n}\n\n/** Whether `directory` is `root` or below it. */\nfunction isWithin(root: string, directory: string): boolean\n{\n const step = relative(root, directory);\n\n return step === '' || (!step.startsWith('..') && !isAbsolute(step));\n}\n\n/**\n * The directories to look in, nearest first: from `startDir` up to and\n * including the project root.\n *\n * The search stops at the project root, because a tsconfig above it belongs to\n * whatever contains the project — a monorepo root, a home directory — and not\n * to the project being generated. A `startDir` outside the root contributes\n * nothing, leaving the root itself.\n */\nfunction searchDirectories(cwd: string, startDir: string): string[]\n{\n const root = resolve(cwd);\n const directories: string[] = [];\n\n for (let directory = resolve(startDir); isWithin(root, directory); directory = dirname(directory))\n {\n directories.push(directory);\n\n if (directory === root)\n {\n return directories;\n }\n }\n\n return [root];\n}\n\n/** `paths` as jiti aliases, with their targets resolved against `base`. */\nfunction aliasesOf(paths: ts.MapLike<string[]>, base: string): AliasEntry[]\n{\n const aliases = new Map<string, AliasEntry>();\n\n for (const [pattern, targets] of Object.entries(paths))\n {\n const alias = toAlias(pattern, targets, base);\n\n if (alias && !aliases.has(alias.from))\n {\n aliases.set(alias.from, alias);\n }\n }\n\n return [...aliases.values()];\n}\n\n/**\n * The project's tsconfig `paths`, as the alias map jiti resolves.\n *\n * jiti does not read tsconfig: a specifier resolves through its `alias` option\n * or not at all. Every spfn app has `@/*` in a tsconfig — `spfn init` writes it,\n * and the scaffold documents `import env from '@/server/config/env.config'` as\n * the idiom — so a generator that loads the router has to hand jiti the same\n * mappings tsc uses, or an ordinary app cannot generate anything.\n *\n * Which tsconfig: the nearest one to the router file that declares `paths`,\n * searching upward to the project root. The scaffold's aliases live in\n * `src/server/tsconfig.json` — with `baseUrl: \"../..\"` — and that is the config\n * `spfn build` compiles the server with, so a backend-only app has them nowhere\n * else. A config declaring no `paths` is passed over rather than ending the\n * search, because the same `src/server/tsconfig.json` declares none in an app\n * that keeps its aliases at the root (Next.js puts them there).\n *\n * Handled: an `extends` chain, including one that names a package; `paths`\n * targets resolved against `baseUrl`, and against the config file that declares\n * them when there is no `baseUrl`; several targets per pattern, taking the first\n * that resolves as tsc and tsup do; comments and trailing commas, because\n * TypeScript's own parser reads the file.\n *\n * Not handled, each with a warning and no alias for that entry: a pattern whose\n * `*` is not a trailing `/*` (jiti matches a prefix, not a template). A\n * `baseUrl` with no `paths` produces nothing: resolving every bare specifier\n * against a directory is not something an alias map can say.\n */\nfunction projectAliases(cwd: string, startDir: string): AliasEntry[]\n{\n for (const directory of searchDirectories(cwd, startDir))\n {\n const options = readCompilerOptions(join(directory, 'tsconfig.json'), cwd);\n\n if (options?.paths)\n {\n // A target is relative to baseUrl, and to the config that declared\n // `paths` when there is no baseUrl — TypeScript records that as\n // `pathsBasePath`, which its public typings do not carry.\n const declaredIn = (options as { pathsBasePath?: string }).pathsBasePath;\n\n return aliasesOf(options.paths, options.baseUrl ?? declaredIn ?? directory);\n }\n }\n\n return [];\n}\n\n/** The alias map jiti is handed: see `projectAliases`, of which this is the public shape. */\nexport function tsconfigAliases(cwd: string, startDir: string = cwd): Record<string, string>\n{\n return Object.fromEntries(projectAliases(cwd, startDir).map(alias => [alias.from, alias.to]));\n}\n\n// ============================================================================\n// Loading\n// ============================================================================\n\n/**\n * An import that never resolved and a module that threw are different repairs.\n *\n * The message used to advise the second for both, which sends a developer whose\n * router imports `@/server/routes` looking for a module-scope side effect that\n * is not there.\n */\nfunction describeFailure(error: unknown, subject: string, aliases: AliasEntry[]): string\n{\n const message = error instanceof Error ? error.message : String(error);\n const unresolved = /Cannot find module '([^']+)'/.exec(message);\n\n if (!unresolved)\n {\n return `${message}\\n\\n`\n + `The ${subject} is read from the loaded router, so a route module must be importable without side `\n + 'effects. Check that nothing at module scope opens a connection or reads a missing environment value.';\n }\n\n return `${message.split('\\n')[0]}\\n\\n`\n + `\"${unresolved[1]}\" did not resolve while the router was being imported. Imports resolve through Node and `\n + 'through the \"paths\" of the nearest tsconfig.json that declares them, searching from the router file up to '\n + 'the project root. Check that the specifier is mapped in one of those, and that what it points at exists: '\n + 'a workspace package resolves to a dist/ that has to have been built.'\n + describePassedOverTargets(unresolved[1], aliases);\n}\n\n/**\n * The targets the failing specifier was never tried through.\n *\n * tsc substitutes every target of a matching pattern and takes the first that\n * resolves the requested module; jiti holds one alias per key, so exactly one\n * was tried. When the pattern listed others, the import that just failed would\n * very likely have resolved through one of them, and saying so is the whole\n * repair — the alternative is a developer reading \"did not resolve\" about a\n * module that plainly exists under `./src`.\n */\nfunction describePassedOverTargets(specifier: string, aliases: AliasEntry[]): string\n{\n // Matched on either spelling: the loader names the specifier it was given\n // for an alias it has no mapping for, and the path it resolved to for one it\n // does — and it is the second that reaches here.\n const alias = aliases.find(entry => specifier.startsWith(entry.from) || specifier.startsWith(entry.to));\n\n if (!alias || alias.others.length === 0)\n {\n return '';\n }\n\n return `\\n\\nIt was resolved through \"${alias.target}\", the first target of the \"paths\" entry `\n + `\"${alias.pattern}\" that names a directory holding anything. That entry also lists `\n + `${alias.others.map(other => `\"${other}\"`).join(', ')}, which the router load never tried: one alias per `\n + 'key is all the loader can express, so the whole load goes through a single target.';\n}\n\nexport interface RouterModuleLoad\n{\n /** Project root: jiti resolves from here, and the tsconfig search stops here. */\n cwd: string;\n\n absoluteRouterPath: string;\n\n /** What is being generated, named in the failure message: `route map`. */\n subject: string;\n\n /** Wraps the message in the calling generator's own error type. */\n fail: (message: string) => Error;\n}\n\n/**\n * Import the router module, or throw the caller's error describing why not.\n */\nexport function loadRouterModule(load: RouterModuleLoad): Record<string, unknown>\n{\n const { cwd, absoluteRouterPath, subject, fail } = load;\n\n const aliases = projectAliases(cwd, dirname(absoluteRouterPath));\n\n const jiti = createJiti(cwd, {\n interopDefault: true,\n moduleCache: false,\n alias: Object.fromEntries(aliases.map(alias => [alias.from, alias.to])),\n });\n\n try\n {\n return jiti(absoluteRouterPath) as Record<string, unknown>;\n }\n catch (error)\n {\n throw fail(\n `Failed to load ${relative(cwd, absoluteRouterPath)}: ${describeFailure(error, subject, aliases)}`,\n );\n }\n}\n\nexport function isRouter(value: unknown): value is Router<Record<string, RouteDef<any> | Router<any>>>\n{\n return value !== null\n && typeof value === 'object'\n && 'routes' in value\n && '_routes' in value;\n}\n\nexport interface ResolvedRouter\n{\n router: Router<any>;\n\n /**\n * The export it was found under.\n *\n * Both generators try `appRouter`, `default` and `router` in turn, so a file\n * holding more than one router is read from whichever of those it declares.\n * The guard then reads that same one rather than every `defineRouter(` in\n * the file: a router the loader did not find is a router production never\n * mounts.\n */\n exportName: string;\n}\n\n/** The first candidate export holding a router, and the name it was found under. */\nexport function resolveRouterExport(module: Record<string, unknown>, candidates: string[]): ResolvedRouter | undefined\n{\n for (const exportName of candidates)\n {\n const candidate = module[exportName];\n\n if (isRouter(candidate))\n {\n return { router: candidate, exportName };\n }\n }\n\n return undefined;\n}\n","/**\n * Route Map Generator\n *\n * Generates a route map file containing routeName → {method, path} mappings.\n * This allows RPC proxy to resolve routes without importing the full router.\n *\n * The router is loaded and walked, not parsed from source. A source parser sees\n * the spelling rather than the router: `defineRouter({ createUser })` written on\n * one line, an aliased key `create: createUser`, and a nested router assembled by\n * a second `defineRouter(` in the same file are all ordinary ways to write a\n * router, and all of them used to leave routes out of the map. The RPC client\n * addresses a route by name, so a dropped name is a route that typechecks and\n * 404s. Walking the loaded router registers exactly what `registerRoutes`\n * registers, whatever the source looks like.\n *\n * The map carries the routes of every package router the app mounts with\n * `.packages()`, not only the app's own. A package ships a client that addresses\n * its routes by name — `authApi.login`, `monitorApi.getStats` — and the app's\n * `createRpcProxy` resolves a name in the single map it was constructed with, so\n * a package route in nobody's map is a call that resolves nowhere. The app\n * therefore merges nothing by hand: `{ ...routeMap, ...authRouteMap }` is a\n * no-op today and `{ ...routeMap }` is the whole of it. (`eventRouteMap` is the\n * exception that stays — it is a hand-written constant, not a mounted router.)\n *\n * @example\n * ```typescript\n * // .spfnrc.ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n *\n * export default defineConfig({\n * generators: [\n * defineGenerator({\n * name: '@spfn/core:route-map',\n * routerPath: './src/server/router.ts',\n * outputPath: './src/generated/route-map.ts',\n * })\n * ]\n * });\n * ```\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { join, dirname, relative } from 'path';\nimport type { HttpMethod, RouteDef, Router } from '@spfn/core/route';\nimport { logger } from '@spfn/core/logger';\nimport type { Generator, GeneratorOptions } from '../core/generator';\nimport { assertUnconditionalRegistration } from './contract-guard';\nimport { toObjectKey, toStringLiteral } from './emit';\nimport { isRouter, loadRouterModule, pinNodeEnv, resolveRouterExport, type ResolvedRouter } from './router-module';\n\nconst genLogger = logger.child('@spfn/core:route-map-generator');\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface RouteMapGeneratorConfig\n{\n /**\n * Generator name (required for package-based loading)\n */\n name: '@spfn/core:route-map';\n\n /**\n * Path to the router file (relative to project root)\n * @example './src/server/router.ts'\n */\n routerPath: string;\n\n /**\n * Output path for generated route map (relative to project root)\n * @default './src/generated/route-map.ts'\n */\n outputPath?: string;\n\n /**\n * Extra file patterns to watch, for routes outside src/server/routes\n *\n * @deprecated Ignored. The map is read from the loaded router, which reaches\n * every route through its own imports wherever they live, so there is no\n * longer a set of directories to scan. Still accepted so an existing\n * `.spfnrc.ts` keeps working; the watch patterns it produced are unchanged.\n */\n additionalRouteDirs?: string[];\n}\n\n/** Thrown when the router cannot produce a route map at all. */\nexport class RouteMapGeneratorError extends Error\n{\n constructor(message: string)\n {\n super(message);\n this.name = 'RouteMapGeneratorError';\n }\n}\n\ninterface CollectedRoute\n{\n method: string;\n path: string;\n\n /** Where the route was found, for a collision message. */\n trail: string;\n\n /**\n * The definition itself, so that one route reached twice is not two routes.\n *\n * A package that exports one set of routes under two routers — a router and\n * a sub-router an app may mount beside it — hands an app that mounts both\n * the same `RouteDef` object under the same name twice. That is one route\n * with two mounts, not an ambiguity, and the app cannot resolve it by\n * renaming anything of its own. No first-party package ships that shape\n * today; the rule is keyed on object identity so that the day one does, the\n * app that mounts both still builds.\n */\n def: RouteDef<any>;\n}\n\n/** One entry of a router's `_packageRouters`, as the generated header describes it. */\ninterface PackageMount\n{\n /** The trail of the mount: `router.packages[0]`. */\n label: string;\n\n /** How many routes it contributed, which is zero for an unmapped router. */\n count: number;\n\n /** Why it contributed nothing, when it contributed nothing. */\n skipped?: string;\n\n /**\n * Where a route it holds had already been collected, if one had.\n *\n * A mount reaching only routes another mount already collected contributes\n * nothing without being skipped, so without this its header line would read\n * `— no routes` and give no reason.\n */\n sharedWith?: string;\n\n /** The first path segment of each route it contributed, for the header line. */\n prefixes: Set<string>;\n}\n\n/** Everything one walk of the router produced. */\ninterface Collection\n{\n /** The app's own routes, in walk order. */\n app: Map<string, CollectedRoute>;\n\n /** The routes of every mounted package router that publishes a map, in walk order. */\n packages: Map<string, CollectedRoute>;\n\n /** Every `.packages()` mount, contributing or not, in the order it was mounted. */\n mounts: PackageMount[];\n\n /**\n * Package routers already walked.\n *\n * `.packages()` copies a mounted router's own `_packageRouters` up to the\n * top level while leaving them in place below it, so one nested package\n * router is reachable by two trails. The second walk would collect nothing\n * either way — `addRoute`'s identity rule sees the same `RouteDef` under\n * the same name and collapses it — so this is not what keeps a router from\n * colliding with itself. It skips the work, and it is what lets the mount's\n * header line say where the routes were already reached.\n */\n visited: Map<Router<any>, string>;\n}\n\n// ============================================================================\n// Loading\n// ============================================================================\n\nfunction isRouteDef(value: unknown): value is RouteDef<any>\n{\n return value !== null\n && typeof value === 'object'\n && 'handler' in value;\n}\n\nconst ROUTER_EXPORTS = ['appRouter', 'default', 'router'];\n\nfunction loadRouter(cwd: string, absoluteRouterPath: string): ResolvedRouter\n{\n const module = loadRouterModule({\n cwd,\n absoluteRouterPath,\n subject: 'route map',\n fail: message => new RouteMapGeneratorError(message),\n });\n\n const resolved = resolveRouterExport(module, ROUTER_EXPORTS);\n\n if (resolved)\n {\n return resolved;\n }\n\n throw new RouteMapGeneratorError(\n `No router found in ${relative(cwd, absoluteRouterPath)}. `\n + `Looked for: ${ROUTER_EXPORTS.join(', ')}. `\n + 'Export the defineRouter() result under one of those names.',\n );\n}\n\n// ============================================================================\n// Collection\n// ============================================================================\n\n/**\n * Written as a record rather than a list so that a new `HttpMethod` does not\n * compile until it is named here.\n */\nconst HTTP_METHODS: Record<HttpMethod, true> = { GET: true, POST: true, PUT: true, PATCH: true, DELETE: true };\n\n/** Which map a route is collected into, and so which collision it can be part of. */\ntype Origin = 'app' | 'package';\n\nfunction duplicateNameError(\n origin: Origin,\n name: string,\n existing: CollectedRoute,\n where: string,\n): RouteMapGeneratorError\n{\n if (origin === 'app')\n {\n return new RouteMapGeneratorError(\n `Two routes are both named \"${name}\" (${existing.trail} and ${where}). `\n + 'The RPC client addresses a route by its name alone, and a nested route registers under its own '\n + 'key, so a name must be unique across the whole router.',\n );\n }\n\n return new RouteMapGeneratorError(\n `Two package routers both register a route named \"${name}\" (${existing.trail} and ${where}). `\n + 'Both are written into this app\\'s route map, which holds one entry per name, so one of the two '\n + 'packages would have its client call the other package\\'s path. Nothing of this app\\'s can be renamed '\n + 'to fix it: drop one of the two mounts, or raise the name with the package that took it second.',\n );\n}\n\n/**\n * Collect one route, or say why it is not in the map.\n *\n * Returns what was collected, which is what lets a mount count and describe\n * what it contributed without counting a route twice.\n */\nfunction addRoute(\n name: string,\n routeDef: RouteDef<any>,\n trail: string[],\n into: Map<string, CollectedRoute>,\n origin: Origin,\n): CollectedRoute | undefined\n{\n const where = trail.join('.');\n\n // Skipped rather than refused: `registerRoutes` warns and skips it too, so\n // the map that leaves it out still names every route the server answers —\n // which is the whole of what a refusal here would be protecting.\n if (!routeDef.method || !routeDef.path)\n {\n genLogger.warn(\n `Route \"${where}\" has no method or path and is left out of the map. `\n + 'The RPC client resolves a name to a method and a path, so both are required. '\n + 'A route reaches this state by being registered before .handler() was called — '\n + 'the server skips it too.',\n );\n\n return undefined;\n }\n\n // The map is typed `HttpMethod`, and `registerRoutes` lowercases whatever it\n // is given before handing it to Hono — so `method: 'get'` registers happily\n // at runtime and would emit a generated file that does not compile.\n if (!Object.hasOwn(HTTP_METHODS, routeDef.method))\n {\n throw new RouteMapGeneratorError(\n `Route \"${where}\" declares the method \"${routeDef.method}\", which is not an HttpMethod `\n + `(${Object.keys(HTTP_METHODS).join(', ')}). The generated map is typed HttpMethod, so naming it `\n + 'would write a file that does not compile.',\n );\n }\n\n const existing = into.get(name);\n if (existing)\n {\n // The same route, reached through two mounts, is one route: a package\n // that exports its routes under two routers hands both to an app that\n // mounts both, and the entry either mount writes is the same entry.\n //\n // Only for a package route. The app's own router reaches one name twice\n // by registering one route both at the top level and inside a nested\n // group, and that stays refused even though the two entries are\n // identical: it is the app's own spelling, so the app can fix it by\n // dropping one registration, and leaving it silent would hide a\n // grouping the author meant to be a second route.\n if (origin === 'package' && existing.def === routeDef)\n {\n return undefined;\n }\n\n throw duplicateNameError(origin, name, existing, where);\n }\n\n const collected: CollectedRoute = {\n method: routeDef.method,\n path: routeDef.path,\n trail: where,\n def: routeDef,\n };\n\n into.set(name, collected);\n\n return collected;\n}\n\n/** `/_auth/login` → `/_auth`: what the header line says a mount's routes live under. */\nfunction pathPrefix(path: string): string\n{\n const [, first] = path.split('/');\n\n return first ? `/${first}` : path;\n}\n\n/**\n * Every route a mounted package router registers, at any depth below it.\n *\n * These are written into the app's map beside the app's own routes. A package\n * ships a client that addresses its routes by name — `authApi.login`,\n * `monitorApi.getStats` — and the app's `createRpcProxy` resolves that name in\n * the single map it was constructed with, so a name in nobody's map resolves\n * nowhere.\n *\n * A router whose `_publishesRouteMap` is false contributes nothing, and neither\n * does anything below it: no client names those routes. That is the ops surface\n * (`createOpsRouter`), whose routes `spfn ops` invokes over the URL the manifest\n * gave it, and whose own sub-routers carry the flag too.\n *\n * The flag is read on the router being walked rather than on the mount that\n * reached it. So an unmapped router nested inside a mapped package router is\n * left out while its parent contributes, and a mapped router nested inside an\n * unmapped one is left out with it — what the flag says is whether a client\n * names these routes, which nesting does not change either way.\n */\nfunction collectPackageRoutes(\n router: Router<any>,\n trail: string[],\n mount: PackageMount,\n collection: Collection,\n): void\n{\n if (router._publishesRouteMap === false || collection.visited.has(router))\n {\n return;\n }\n\n collection.visited.set(router, trail.join('.'));\n\n for (const [name, entry] of Object.entries(router.routes))\n {\n if (isRouter(entry))\n {\n collectPackageRoutes(entry, [...trail, name], mount, collection);\n continue;\n }\n\n if (!isRouteDef(entry))\n {\n genLogger.warn(\n `Package router entry \"${[...trail, name].join('.')}\" is neither a route nor a router `\n + `(got ${typeof entry}) and is left out of the map. \\`registerRoutes\\` skips it too.`,\n );\n\n continue;\n }\n\n const collected = addRoute(name, entry, [...trail, name], collection.packages, 'package');\n\n if (collected)\n {\n mount.count += 1;\n mount.prefixes.add(pathPrefix(collected.path));\n\n continue;\n }\n\n const already = collection.packages.get(name);\n\n if (already?.def === entry)\n {\n mount.sharedWith ??= already.trail;\n }\n }\n\n for (const [index, nested] of (router._packageRouters ?? []).entries())\n {\n collectPackageRoutes(nested, [...trail, `packages[${index}]`], mount, collection);\n }\n}\n\n/** One entry of a router's `_packageRouters`, walked and described for the generated header. */\nfunction mountPackageRouter(router: Router<any>, label: string, collection: Collection): PackageMount\n{\n const mount: PackageMount = { label, count: 0, prefixes: new Set() };\n const alreadyAt = collection.visited.get(router);\n\n // Said before the walk, because the walk is what makes both true of it.\n if (router._publishesRouteMap === false)\n {\n mount.skipped = 'publishes no route map';\n }\n else if (alreadyAt)\n {\n mount.skipped = `already reached through ${alreadyAt}`;\n }\n\n collectPackageRoutes(router, [label], mount, collection);\n\n // Said after the walk, because the walk is what found the other mount.\n if (mount.count === 0 && !mount.skipped && mount.sharedWith)\n {\n mount.skipped = `every route it holds was already collected through ${mount.sharedWith}`;\n }\n\n collection.mounts.push(mount);\n\n return mount;\n}\n\n/**\n * Walk the router the way `registerRoutes` walks it.\n *\n * A nested route registers under its own key — the parent's key names the\n * grouping, not the route — so the map is flat and the trail exists only to\n * point at both sides of a collision.\n *\n * `_packageRouters` is walked into a second map rather than this one, because\n * the generated file keeps the app's own routes first and in their own order:\n * an app that mounts nothing regenerates byte-identically, and an app that\n * mounts something has the routes that are not its own written below a line\n * that says so.\n *\n * Only string keys are collected, because `Object.entries` is what the runtime\n * iterates: a symbol-keyed entry is invisible to `registerRoutes` and so has no\n * route to name in the map either.\n */\nfunction collectRoutes(router: Router<any>, trail: string[], collection: Collection): void\n{\n for (const [name, entry] of Object.entries(router.routes))\n {\n if (isRouter(entry))\n {\n collectRoutes(entry, [...trail, name], collection);\n continue;\n }\n\n // Skipped rather than refused, for the reason `addRoute` skips a route\n // with no method: the server skips it, so a map without it is complete.\n if (!isRouteDef(entry))\n {\n genLogger.warn(\n `Router entry \"${[...trail, name].join('.')}\" is neither a route nor a router (got ${typeof entry}) `\n + 'and is left out of the map. `registerRoutes` skips it too, so no name the client can call goes '\n + 'unanswered.',\n );\n\n continue;\n }\n\n addRoute(name, entry, [...trail, name], collection.app, 'app');\n }\n\n for (const [index, packageRouter] of (router._packageRouters ?? []).entries())\n {\n mountPackageRouter(packageRouter, `${trail.join('.')}.packages[${index}]`, collection);\n }\n}\n\n/**\n * Refuse an app route whose name a package router also registers.\n *\n * Both are registered at runtime, at their own paths, and both are written into\n * this one map — which holds one entry per name. The name would resolve to\n * whichever of the two the map ended up holding while the generated types still\n * describe the app's route, so every call the typed client made against the\n * app's route could go to the package's path.\n *\n * A collision with a router that publishes no map is not refused: nothing of\n * that router is written here, so the app route keeps its name and its path.\n */\nfunction assertNoPackageCollision(collection: Collection): void\n{\n for (const [name, route] of collection.packages)\n {\n const appRoute = collection.app.get(name);\n\n if (!appRoute)\n {\n continue;\n }\n\n throw new RouteMapGeneratorError(\n `The app route \"${name}\" (${appRoute.trail}) is also registered by a package router (${route.trail}). `\n + 'Both go into this app\\'s generated route map, which holds one entry per name, so one of the two '\n + 'paths becomes unreachable while the typed client still describes the app\\'s route. Rename the app '\n + 'route.',\n );\n }\n}\n\n/** The map the file is written from: the app's own routes, then its mounted packages'. */\nfunction collectRouteMap(router: Router<any>): Collection\n{\n const collection: Collection = {\n app: new Map(),\n packages: new Map(),\n mounts: [],\n visited: new Map(),\n };\n\n collectRoutes(router, ['router'], collection);\n assertNoPackageCollision(collection);\n\n return collection;\n}\n\n// ============================================================================\n// Generator\n// ============================================================================\n\n/** One mount, as the generated header lists it. */\nfunction describeMount(mount: PackageMount): string\n{\n if (mount.count === 0)\n {\n return `${mount.label} — no routes${mount.skipped ? ` (${mount.skipped})` : ''}`;\n }\n\n const routes = `${mount.count} route${mount.count === 1 ? '' : 's'}`;\n\n return `${mount.label} — ${routes} under ${[...mount.prefixes].join(', ')}`;\n}\n\n/**\n * The header lines that say which of the entries below are not the app's.\n *\n * A package route in this file is a copy, and a copy is as old as the file: the\n * app used to import the package's own map, which an upgrade changed by itself.\n * So the header says what the copy is and names every mount it came through —\n * the diff after an upgrade then reads as an upgrade rather than as somebody\n * editing a generated file.\n *\n * Nothing is added when no package contributed, so an app that mounts nothing\n * (or mounts only routers that publish no map) regenerates byte-identically to\n * what it has committed.\n */\nfunction packageHeaderLines(collection: Collection): string[]\n{\n if (collection.packages.size === 0)\n {\n return [];\n }\n\n return [\n ' *',\n ' * The entries under the .packages() line below are not this app\\'s. They belong',\n ' * to the package routers it mounts, copied in as they were when this file was',\n ' * generated:',\n ...collection.mounts.map(mount => ` * ${describeMount(mount)}`),\n ' *',\n ' * A package upgrade reaches them only through a regeneration: `spfn build`',\n ' * regenerates before it compiles, a bare `next build` uses what is committed here.',\n ];\n}\n\n/**\n * Generate route map file content\n *\n * The environment is written into the header because it decides what the map\n * holds and nothing else records it. A route registered behind a condition the\n * guard cannot see — one hoisted to a variable, one inside an imported route\n * module — is named here only when the generator ran under the environment that\n * registers it, and `spfn build` pins `production` where `spfn dev` leaves\n * `development`. Writing the value makes that difference a line in the diff\n * instead of a route that typechecks in the editor and vanishes at build.\n */\nfunction generateRouteMapContent(collection: Collection, nodeEnv: string): string\n{\n const lines: string[] = [\n '/**',\n ' * Route Map (Auto-generated)',\n ' *',\n ' * DO NOT EDIT - This file is generated by @spfn/core:route-map generator',\n ' *',\n ` * Generated with NODE_ENV=${nodeEnv}. A route registered only under one environment is`,\n ' * named here only when the generator ran under it, so this line changing is that',\n ' * difference rather than an edit.',\n ...packageHeaderLines(collection),\n ' */',\n '',\n 'import type { HttpMethod } from \\'@spfn/core/route\\';',\n '',\n 'export interface RouteInfo',\n '{',\n ' method: HttpMethod;',\n ' path: string;',\n '}',\n '',\n 'export const routeMap: Record<string, RouteInfo> = {',\n ];\n\n for (const [name, route] of collection.app)\n {\n lines.push(entryLine(name, route));\n }\n\n if (collection.packages.size > 0)\n {\n lines.push(' // From the package routers this app mounts with .packages(), not its own:');\n\n for (const [name, route] of collection.packages)\n {\n lines.push(entryLine(name, route));\n }\n }\n\n lines.push('};');\n lines.push('');\n lines.push('export type RouteMap = typeof routeMap;');\n lines.push('');\n lines.push('export type RouteName = keyof RouteMap;');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/** One `name: { method, path },` line of the map. */\nfunction entryLine(name: string, route: CollectedRoute): string\n{\n return ` ${toObjectKey(name)}: { method: '${route.method}', path: ${toStringLiteral(route.path)} },`;\n}\n\n/**\n * Create Route Map Generator\n */\nexport function createRouteMapGenerator(config: RouteMapGeneratorConfig): Generator\n{\n const {\n routerPath,\n outputPath = './src/generated/route-map.ts',\n additionalRouteDirs = [],\n } = config;\n\n if (!routerPath)\n {\n throw new Error(\n '[@spfn/core:route-map] Missing required \"routerPath\" option.\\n\\n' +\n 'Usage:\\n' +\n ' defineGenerator<RouteMapGeneratorConfig>({\\n' +\n ' name: \\'@spfn/core:route-map\\',\\n' +\n ' routerPath: \\'./src/server/router.ts\\',\\n' +\n ' })',\n );\n }\n\n return {\n name: '@spfn/core:route-map',\n\n // Unchanged, including the deprecated dirs: what the map is *built* from\n // moved to the loaded router, but what a rebuild should be *triggered* by\n // is still every file a route can live in.\n watchPatterns: [\n routerPath,\n 'src/server/routes/**/*.ts',\n ...additionalRouteDirs.map(dir => `${dir}/**/*.ts`),\n ],\n\n runOn: ['watch', 'manual', 'build'],\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const { cwd, debug } = options;\n\n const absoluteRouterPath = join(cwd, routerPath);\n const absoluteOutputPath = join(cwd, outputPath);\n\n if (!existsSync(absoluteRouterPath))\n {\n genLogger.warn(`Router file not found: ${absoluteRouterPath}`);\n\n return;\n }\n\n if (debug)\n {\n genLogger.info('Loading router', { path: absoluteRouterPath });\n }\n\n pinNodeEnv();\n\n // Loaded before the guard reads the source, because which router the\n // guard reads is decided by which export the loader found.\n const { router, exportName } = loadRouter(cwd, absoluteRouterPath);\n\n assertUnconditionalRegistration({\n routerPath,\n source: readFileSync(absoluteRouterPath, 'utf-8'),\n exportName,\n subject: 'route map',\n });\n\n const collection = collectRouteMap(router);\n const total = collection.app.size + collection.packages.size;\n\n if (debug)\n {\n genLogger.info(`Found ${total} routes`, {\n app: [...collection.app.keys()],\n packages: [...collection.packages.keys()],\n });\n }\n\n const outputDir = dirname(absoluteOutputPath);\n if (!existsSync(outputDir))\n {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Read after `pinNodeEnv`, which is what makes it a value at all when\n // the shell left it unset.\n const nodeEnv = process.env.NODE_ENV ?? 'unset';\n\n writeFileSync(absoluteOutputPath, generateRouteMapContent(collection, nodeEnv), 'utf-8');\n\n genLogger.info(\n `Generated route map: ${relative(cwd, absoluteOutputPath)} `\n + `(${collection.app.size} app routes, ${collection.packages.size} from mounted packages)`,\n );\n },\n };\n}\n\n// ============================================================================\n// Export for package-based loading\n// ============================================================================\n\nexport default createRouteMapGenerator;\n","/**\n * Contract Generator\n *\n * Reads the router, writes `contracts/current.json`, and on a build compares it\n * against the newest released snapshot.\n *\n * It is a codegen plugin for the same reason the route map is one: hanging off\n * `spfn build` and `spfn dev` removes \"forgot to regenerate the contract\" as a\n * failure mode. On `dev` it only regenerates — refusing a half-finished route\n * mid-edit would make the feature unusable — and on `build` it also gates.\n *\n * @example\n * ```typescript\n * // .spfnrc.ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n *\n * export default defineConfig({\n * generators: [\n * defineGenerator({\n * name: '@spfn/core:contract',\n * routerPath: './src/server/router.ts',\n * eventRouterPath: './src/server/events.ts', // optional: contracted SSE events\n * outputDir: './contracts',\n * })\n * ]\n * });\n * ```\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join, relative } from 'path';\nimport { logger } from '@spfn/core/logger';\nimport {\n checkContract,\n collectContractDocument,\n formatViolations,\n writeCurrentDocument,\n} from '@spfn/core/contract';\nimport type { EventRouterDef } from '@spfn/core/event';\nimport type { Generator, GeneratorOptions } from '../core/generator';\nimport { assertUnconditionalRegistration } from './contract-guard';\nimport { loadRouterModule, pinNodeEnv, resolveRouterExport, type ResolvedRouter } from './router-module';\n\nconst genLogger = logger.child('@spfn/core:contract-generator');\n\nexport interface ContractGeneratorConfig\n{\n /**\n * Generator name (required for package-based loading)\n */\n name: '@spfn/core:contract';\n\n /**\n * Path to the router file (relative to project root)\n * @example './src/server/router.ts'\n */\n routerPath: string;\n\n /**\n * Named export holding the router.\n * @default 'appRouter', falling back to the default export\n */\n routerExport?: string;\n\n /**\n * Path to the file exporting the `defineEventRouter()` result (relative to\n * project root). When set, its contracted events are written into the\n * document's `events` section; unset, the document has none.\n * @example './src/server/events.ts'\n */\n eventRouterPath?: string;\n\n /**\n * Named export holding the event router.\n * @default 'eventRouter', falling back to the default export\n */\n eventRouterExport?: string;\n\n /**\n * Directory holding current.json, released/ and usage/ (relative to project root)\n * @default './contracts'\n */\n outputDir?: string;\n\n /**\n * Extra file patterns to watch, for routes outside src/server/routes\n */\n additionalRouteDirs?: string[];\n}\n\n/** Thrown when the build must stop. */\nexport class ContractGeneratorError extends Error\n{\n constructor(message: string)\n {\n super(message);\n this.name = 'ContractGeneratorError';\n }\n}\n\nfunction loadRouter(cwd: string, absoluteRouterPath: string, routerExport?: string): ResolvedRouter\n{\n const module = loadRouterModule({\n cwd,\n absoluteRouterPath,\n subject: 'contract',\n fail: message => new ContractGeneratorError(message),\n });\n\n const candidates = routerExport\n ? [routerExport]\n : ['appRouter', 'default', 'router'];\n\n const resolved = resolveRouterExport(module, candidates);\n\n if (resolved)\n {\n return resolved;\n }\n\n throw new ContractGeneratorError(\n `No router found in ${relative(cwd, absoluteRouterPath)}. `\n + `Looked for: ${candidates.join(', ')}. `\n + 'Set \"routerExport\" to the export holding the defineRouter() result.',\n );\n}\n\nfunction isEventRouter(value: unknown): value is EventRouterDef<any>\n{\n return value !== null\n && typeof value === 'object'\n && 'events' in value\n && 'eventNames' in value;\n}\n\ninterface ResolvedEventRouter\n{\n eventRouter: EventRouterDef<any>;\n\n /** The export it was found under, which the registration guard reads. */\n exportName: string;\n}\n\n/**\n * Load the event router through the same loader as the route router: the same\n * `NODE_ENV` pin, the same tsconfig aliases.\n */\nfunction loadEventRouter(cwd: string, absolutePath: string, eventRouterExport?: string): ResolvedEventRouter\n{\n const module = loadRouterModule({\n cwd,\n absoluteRouterPath: absolutePath,\n subject: 'contract',\n fail: message => new ContractGeneratorError(message),\n });\n\n const candidates = eventRouterExport ? [eventRouterExport] : ['eventRouter', 'default'];\n const exportName = candidates.find(candidate => isEventRouter(module[candidate]));\n\n if (exportName)\n {\n return { eventRouter: module[exportName] as EventRouterDef<any>, exportName };\n }\n\n throw new ContractGeneratorError(\n `No event router found in ${relative(cwd, absolutePath)}. `\n + `Looked for: ${candidates.join(', ')}. `\n + 'Set \"eventRouterExport\" to the export holding the defineEventRouter() result.',\n );\n}\n\n/**\n * The event router `eventRouterPath` names, or `undefined` when it is unset.\n *\n * Its source is scanned like the route router's: an event registered behind a\n * flag would make the published event set depend on how the generator ran.\n */\nfunction readEventRouter(cwd: string, eventRouterPath?: string, eventRouterExport?: string): EventRouterDef<any> | undefined\n{\n if (!eventRouterPath)\n {\n return undefined;\n }\n\n const absolutePath = join(cwd, eventRouterPath);\n\n if (!existsSync(absolutePath))\n {\n throw new ContractGeneratorError(\n `Event router file not found: ${eventRouterPath}. `\n + 'The contract generator is configured with \"eventRouterPath\" but has nothing to read there.',\n );\n }\n\n const { eventRouter, exportName } = loadEventRouter(cwd, absolutePath, eventRouterExport);\n\n assertUnconditionalRegistration({\n routerPath: eventRouterPath,\n source: readFileSync(absolutePath, 'utf-8'),\n exportName,\n subject: 'contract',\n factory: 'defineEventRouter',\n });\n\n return eventRouter;\n}\n\nexport function createContractGenerator(config: ContractGeneratorConfig): Generator\n{\n const {\n routerPath,\n routerExport,\n eventRouterPath,\n eventRouterExport,\n outputDir = './contracts',\n additionalRouteDirs = [],\n } = config;\n\n if (!routerPath)\n {\n throw new Error(\n '[@spfn/core:contract] Missing required \"routerPath\" option.\\n\\n'\n + 'Usage:\\n'\n + ' defineGenerator<ContractGeneratorConfig>({\\n'\n + ' name: \\'@spfn/core:contract\\',\\n'\n + ' routerPath: \\'./src/server/router.ts\\',\\n'\n + ' })',\n );\n }\n\n return {\n name: '@spfn/core:contract',\n\n watchPatterns: [\n routerPath,\n ...(eventRouterPath ? [eventRouterPath] : []),\n 'src/server/routes/**/*.ts',\n ...additionalRouteDirs.map(dir => `${dir}/**/*.ts`),\n ],\n\n runOn: ['watch', 'build', 'manual'],\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const { cwd } = options;\n const absoluteRouterPath = join(cwd, routerPath);\n const contractsDir = join(cwd, outputDir);\n\n if (!existsSync(absoluteRouterPath))\n {\n throw new ContractGeneratorError(\n `Router file not found: ${routerPath}. `\n + 'The contract generator is configured but has nothing to read.',\n );\n }\n\n pinNodeEnv();\n\n // Loaded before the guard reads the source, because which router the\n // guard reads is decided by which export the loader found.\n const { router, exportName } = loadRouter(cwd, absoluteRouterPath, routerExport);\n\n assertUnconditionalRegistration({\n routerPath,\n source: readFileSync(absoluteRouterPath, 'utf-8'),\n exportName,\n subject: 'contract',\n });\n\n const document = collectContractDocument(router, readEventRouter(cwd, eventRouterPath, eventRouterExport));\n\n const changed = writeCurrentDocument(contractsDir, document);\n genLogger.info(\n `${changed ? 'Wrote' : 'Verified'} ${relative(cwd, join(contractsDir, 'current.json'))} `\n + `(${document.operations.length} contracted operation(s))`,\n );\n\n if (options.trigger?.type !== 'build')\n {\n return;\n }\n\n const result = checkContract(contractsDir, document);\n\n for (const warning of result.warnings)\n {\n genLogger.warn(warning);\n }\n\n if (result.violations.length === 0)\n {\n if (result.baselineVersion)\n {\n genLogger.info(`Contract is backward compatible with released ${result.baselineVersion}`);\n }\n\n return;\n }\n\n throw new ContractGeneratorError(\n `This build breaks the contract released as ${result.baselineVersion}:\\n\\n`\n + `${formatViolations(result.violations)}\\n\\n`\n + 'A released client cannot be fixed by redeploying the server. Keep the promise, or cut a new '\n + 'contract version and let the old operation stay until no released app calls it.',\n );\n },\n };\n}\n\nexport default createContractGenerator;\n","/**\n * States Generator\n *\n * Generates a file naming the states the app declared — their ids and their\n * manifest — as values a browser root or a server component can execute.\n *\n * `defineStateRouter` declares the states, and the browser reads them through\n * `createStateClient<typeof states>`: a type import, erased at build. So nothing\n * that runs in the browser says which states the app declared, and importing\n * the router to find out is not an option — each state's `read()` closes over\n * repositories and the database. A root that compares the declared ids with the\n * `manifest` of `GET /state` can report a deploy skew between the Next.js server\n * and the API before rendering, instead of a screen meeting `state.<id>` as\n * `undefined`.\n *\n * The router is loaded and walked, as the route map's is. A state router is told\n * apart by the `_stateManifest` marker `defineStateRouter` sets on the router it\n * derives — the object the snapshot route answers as `manifest` — so the ids\n * written here and the manifest the server serves come from one value.\n *\n * @example\n * ```typescript\n * // .spfnrc.ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n *\n * export default defineConfig({\n * generators: [\n * defineGenerator({\n * name: '@spfn/core:states',\n * routerPath: './src/server/router.ts',\n * outputPath: './src/generated/states.ts',\n * })\n * ]\n * });\n * ```\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { join, dirname, relative } from 'path';\nimport type { Router } from '@spfn/core/route';\nimport { logger } from '@spfn/core/logger';\nimport type { Generator, GeneratorOptions } from '../core/generator';\nimport { assertUnconditionalRegistration } from './contract-guard';\nimport { toObjectKey, toStringLiteral } from './emit';\nimport { isRouter, loadRouterModule, pinNodeEnv, resolveRouterExport, type ResolvedRouter } from './router-module';\n\nconst genLogger = logger.child('@spfn/core:states-generator');\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StatesGeneratorConfig\n{\n /**\n * Generator name (required for package-based loading)\n */\n name: '@spfn/core:states';\n\n /**\n * Path to the router file (relative to project root) — the one the route map reads\n * @example './src/server/router.ts'\n */\n routerPath: string;\n\n /**\n * Output path for the generated states file (relative to project root)\n * @default './src/generated/states.ts'\n */\n outputPath?: string;\n}\n\n/** Thrown when the router cannot produce the app's declared states. */\nexport class StatesGeneratorError extends Error\n{\n constructor(message: string)\n {\n super(message);\n this.name = 'StatesGeneratorError';\n }\n}\n\n/** One manifest entry: the state's key fields and whether it has a write. */\ninterface ManifestEntry\n{\n readonly key: readonly string[];\n readonly write: boolean;\n}\n\ninterface CollectedState\n{\n entry: ManifestEntry;\n\n /** The trail of the state router that declared it, for a collision message. */\n trail: string;\n}\n\n// ============================================================================\n// Loading\n// ============================================================================\n\nconst ROUTER_EXPORTS = ['appRouter', 'default', 'router'];\n\nfunction loadRouter(cwd: string, absoluteRouterPath: string): ResolvedRouter\n{\n const module = loadRouterModule({\n cwd,\n absoluteRouterPath,\n subject: 'state manifest',\n fail: message => new StatesGeneratorError(message),\n });\n\n const resolved = resolveRouterExport(module, ROUTER_EXPORTS);\n\n if (resolved)\n {\n return resolved;\n }\n\n throw new StatesGeneratorError(\n `No router found in ${relative(cwd, absoluteRouterPath)}. `\n + `Looked for: ${ROUTER_EXPORTS.join(', ')}. `\n + 'Export the defineRouter() result under one of those names.',\n );\n}\n\n// ============================================================================\n// Collection\n// ============================================================================\n\n/**\n * Walk the router the way the route map's `collectRoutes` walks it: every\n * nested router under `routes`, then every entry of `_packageRouters`, at any\n * depth.\n *\n * `visited` is keyed on the router object, not on the trail: `.packages()`\n * copies a mounted router's own `_packageRouters` up to the top level while\n * leaving them in place below it, so one state router is reachable by two\n * trails and must contribute its states once — a second visit would refuse the\n * router as colliding with itself.\n *\n * A nested route entry is told apart from a router by `isRouter`, as\n * `collectRoutes` does; a `RouteDef` holds no states and is passed over.\n *\n * Returns how many state routers the walk met — counted apart from the states,\n * since `defineStateRouter({})` is a state router declaring none.\n */\nfunction collectStates(\n router: Router<any>,\n trail: string[],\n visited: Set<Router<any>>,\n into: Map<string, CollectedState>,\n): number\n{\n if (visited.has(router))\n {\n return 0;\n }\n\n visited.add(router);\n\n let stateRouters = addStates(router, trail.join('.'), into) ? 1 : 0;\n\n for (const [name, entry] of Object.entries(router.routes))\n {\n if (isRouter(entry))\n {\n stateRouters += collectStates(entry, [...trail, name], visited, into);\n }\n }\n\n for (const [index, nested] of (router._packageRouters ?? []).entries())\n {\n stateRouters += collectStates(nested, [...trail, `packages[${index}]`], visited, into);\n }\n\n return stateRouters;\n}\n\n/**\n * The entries of one state router's manifest, in their declaration order.\n * Returns whether the router is a state router — whether it carries its own\n * `_stateManifest`, however many entries that holds.\n */\nfunction addStates(router: Router<any>, trail: string, into: Map<string, CollectedState>): boolean\n{\n if (!Object.hasOwn(router, '_stateManifest'))\n {\n return false;\n }\n\n for (const [id, entry] of Object.entries(router._stateManifest ?? {}))\n {\n const existing = into.get(id);\n\n if (existing)\n {\n throw new StatesGeneratorError(\n `Two state routers both declare a state \"${id}\" (${existing.trail} and ${trail}). `\n + 'The browser addresses a state by its id alone and the generated manifest holds one entry per id, '\n + 'so one of the two would be read through the other\\'s routes. Rename one of the states, or mount '\n + 'one of the two routers only.',\n );\n }\n\n into.set(id, { entry, trail });\n }\n\n return true;\n}\n\n/**\n * Every state the router mounts, at any depth, in walk order.\n *\n * Refused only when no router in the walk is a state router: the generator was\n * configured for a state router the app never mounted. A mounted state router\n * declaring no state is an app that has declared none yet, and yields an empty\n * map — the file then names no id, which is what the server serves.\n */\nfunction collectDeclaredStates(router: Router<any>, routerPath: string): Map<string, CollectedState>\n{\n const states = new Map<string, CollectedState>();\n\n if (collectStates(router, ['router'], new Set(), states) === 0)\n {\n throw new StatesGeneratorError(\n `No state router is mounted by ${routerPath}. The @spfn/core:states generator is configured, but nothing `\n + 'it reads mounts a defineStateRouter(...).router, so the file it would write could not say which states '\n + 'the app declared, and every id the server serves would read as a skew. Mount the state router — '\n + '`appRouter.packages([states.router])` — or remove the generator from .spfnrc.ts.',\n );\n }\n\n return states;\n}\n\n// ============================================================================\n// Generator\n// ============================================================================\n\n/** One `id: { key: [...], write },` line of the manifest. */\nfunction entryLine(id: string, entry: ManifestEntry): string\n{\n return ` ${toObjectKey(id)}: { key: [${entry.key.map(toStringLiteral).join(', ')}], write: ${entry.write} },`;\n}\n\n/**\n * Generate the states file content\n *\n * No import: the file is read by a browser root and a server component alike,\n * and anything it imported would reach both. The environment is written into\n * the header for the reason the route map writes it — a state router mounted\n * only under one environment is named here only when the generator ran under it.\n */\nfunction generateStatesContent(states: Map<string, CollectedState>, nodeEnv: string): string\n{\n const ids = [...states.keys()];\n\n return [\n '/**',\n ' * State Manifest (Auto-generated)',\n ' *',\n ' * DO NOT EDIT - This file is generated by @spfn/core:states generator',\n ' *',\n ` * Generated with NODE_ENV=${nodeEnv}. A state router mounted only under one environment is`,\n ' * named here only when the generator ran under it, so this line changing is that',\n ' * difference rather than an edit.',\n ' *',\n ' * Compare `stateManifest` with the `manifest` of `GET <state path>` (or of the snapshot a',\n ' * server component read): an id here that the server\\'s manifest lacks, or an entry that',\n ' * differs, is a deploy skew between this build and the API.',\n ' */',\n '',\n `export const stateIds = [${ids.map(toStringLiteral).join(', ')}] as const;`,\n '',\n 'export type StateId = (typeof stateIds)[number];',\n '',\n 'export const stateManifest: Readonly<Record<StateId, { readonly key: readonly string[]; readonly write: boolean }>> = {',\n ...ids.map(id => entryLine(id, states.get(id)!.entry)),\n '};',\n '',\n ].join('\\n');\n}\n\n/**\n * Create States Generator\n */\nexport function createStatesGenerator(config: StatesGeneratorConfig): Generator\n{\n const { routerPath, outputPath = './src/generated/states.ts' } = config;\n\n if (!routerPath)\n {\n throw new Error(\n '[@spfn/core:states] Missing required \"routerPath\" option.\\n\\n' +\n 'Usage:\\n' +\n ' defineGenerator<StatesGeneratorConfig>({\\n' +\n ' name: \\'@spfn/core:states\\',\\n' +\n ' routerPath: \\'./src/server/router.ts\\',\\n' +\n ' })',\n );\n }\n\n return {\n name: '@spfn/core:states',\n\n watchPatterns: [\n routerPath,\n 'src/server/states.ts',\n 'src/server/states/**/*.ts',\n 'src/server/routes/**/*.ts',\n ],\n\n runOn: ['watch', 'manual', 'build'],\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const { cwd, debug } = options;\n\n const absoluteRouterPath = join(cwd, routerPath);\n const absoluteOutputPath = join(cwd, outputPath);\n\n if (!existsSync(absoluteRouterPath))\n {\n genLogger.warn(`Router file not found: ${absoluteRouterPath}`);\n\n return;\n }\n\n pinNodeEnv();\n\n // Loaded before the guard reads the source, because which router the\n // guard reads is decided by which export the loader found.\n const { router, exportName } = loadRouter(cwd, absoluteRouterPath);\n\n assertUnconditionalRegistration({\n routerPath,\n source: readFileSync(absoluteRouterPath, 'utf-8'),\n exportName,\n subject: 'state manifest',\n });\n\n const states = collectDeclaredStates(router, routerPath);\n\n if (debug)\n {\n genLogger.info(`Found ${states.size} states`, { ids: [...states.keys()] });\n }\n\n mkdirSync(dirname(absoluteOutputPath), { recursive: true });\n\n // Read after `pinNodeEnv`, which is what makes it a value at all when\n // the shell left it unset.\n const nodeEnv = process.env.NODE_ENV ?? 'unset';\n\n writeFileSync(absoluteOutputPath, generateStatesContent(states, nodeEnv), 'utf-8');\n\n genLogger.info(`Generated states: ${relative(cwd, absoluteOutputPath)} (${states.size} states)`);\n },\n };\n}\n\n// ============================================================================\n// Export for package-based loading\n// ============================================================================\n\nexport default createStatesGenerator;\n","/**\n * Built-in Generators Export\n *\n * @example\n * ```typescript\n * // .spfnrc.ts\n * import { defineConfig, defineGenerator } from '@spfn/core/codegen';\n * import type { RouteMapGeneratorConfig, ContractGeneratorConfig, StatesGeneratorConfig } from '@spfn/core/codegen';\n *\n * export default defineConfig({\n * generators: [\n * defineGenerator<RouteMapGeneratorConfig>({\n * name: '@spfn/core:route-map',\n * routerPath: './src/server/router.ts',\n * outputPath: './src/generated/route-map.ts',\n * }),\n * defineGenerator<ContractGeneratorConfig>({\n * name: '@spfn/core:contract',\n * routerPath: './src/server/router.ts',\n * outputDir: './contracts',\n * }),\n * defineGenerator<StatesGeneratorConfig>({\n * name: '@spfn/core:states',\n * routerPath: './src/server/router.ts',\n * outputPath: './src/generated/states.ts',\n * }),\n * ]\n * });\n * ```\n */\n\nimport { createRouteMapGenerator } from './route-map';\nimport { createContractGenerator } from './contract';\nimport { createStatesGenerator } from './states';\n\nexport type { RouteMapGeneratorConfig } from './route-map';\nexport { RouteMapGeneratorError } from './route-map';\nexport type { ContractGeneratorConfig } from './contract';\nexport { ContractGeneratorError } from './contract';\nexport type { StatesGeneratorConfig } from './states';\nexport { StatesGeneratorError } from './states';\nexport { assertUnconditionalRegistration, ConditionalRegistrationError } from './contract-guard';\nexport type { RegistrationScan } from './contract-guard';\n\n/**\n * @internal\n * Registry of available generators for package-based loading.\n * DO NOT use directly - use defineGenerator({ name: '@spfn/core:route-map', ... }) instead.\n */\nexport const generators: Record<string, unknown> = {\n 'route-map': createRouteMapGenerator,\n contract: createContractGenerator,\n states: createStatesGenerator,\n};\n"]}
|