@spfn/core 0.2.0-beta.1 → 0.2.0-beta.10

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.
Files changed (64) hide show
  1. package/README.md +262 -1092
  2. package/dist/{boss-D-fGtVgM.d.ts → boss-DI1r4kTS.d.ts} +68 -11
  3. package/dist/codegen/index.d.ts +55 -8
  4. package/dist/codegen/index.js +159 -5
  5. package/dist/codegen/index.js.map +1 -1
  6. package/dist/config/index.d.ts +36 -0
  7. package/dist/config/index.js +15 -6
  8. package/dist/config/index.js.map +1 -1
  9. package/dist/db/index.d.ts +13 -0
  10. package/dist/db/index.js +40 -6
  11. package/dist/db/index.js.map +1 -1
  12. package/dist/env/index.d.ts +82 -3
  13. package/dist/env/index.js +81 -14
  14. package/dist/env/index.js.map +1 -1
  15. package/dist/env/loader.d.ts +87 -0
  16. package/dist/env/loader.js +70 -0
  17. package/dist/env/loader.js.map +1 -0
  18. package/dist/event/index.d.ts +3 -70
  19. package/dist/event/index.js +10 -1
  20. package/dist/event/index.js.map +1 -1
  21. package/dist/event/sse/client.d.ts +82 -0
  22. package/dist/event/sse/client.js +115 -0
  23. package/dist/event/sse/client.js.map +1 -0
  24. package/dist/event/sse/index.d.ts +40 -0
  25. package/dist/event/sse/index.js +92 -0
  26. package/dist/event/sse/index.js.map +1 -0
  27. package/dist/job/index.d.ts +54 -8
  28. package/dist/job/index.js +61 -12
  29. package/dist/job/index.js.map +1 -1
  30. package/dist/middleware/index.d.ts +102 -11
  31. package/dist/middleware/index.js +2 -2
  32. package/dist/middleware/index.js.map +1 -1
  33. package/dist/nextjs/index.d.ts +2 -2
  34. package/dist/nextjs/index.js +36 -4
  35. package/dist/nextjs/index.js.map +1 -1
  36. package/dist/nextjs/server.d.ts +62 -15
  37. package/dist/nextjs/server.js +102 -33
  38. package/dist/nextjs/server.js.map +1 -1
  39. package/dist/route/index.d.ts +227 -15
  40. package/dist/route/index.js +307 -31
  41. package/dist/route/index.js.map +1 -1
  42. package/dist/route/types.d.ts +2 -31
  43. package/dist/router-Di7ENoah.d.ts +151 -0
  44. package/dist/server/index.d.ts +153 -6
  45. package/dist/server/index.js +216 -14
  46. package/dist/server/index.js.map +1 -1
  47. package/dist/types-B-e_f2dQ.d.ts +121 -0
  48. package/dist/{types-DRG2XMTR.d.ts → types-BOPTApC2.d.ts} +91 -3
  49. package/docs/cache.md +133 -0
  50. package/docs/codegen.md +74 -0
  51. package/docs/database.md +346 -0
  52. package/docs/entity.md +539 -0
  53. package/docs/env.md +477 -0
  54. package/docs/errors.md +319 -0
  55. package/docs/event.md +116 -0
  56. package/docs/file-upload.md +717 -0
  57. package/docs/job.md +131 -0
  58. package/docs/logger.md +108 -0
  59. package/docs/middleware.md +337 -0
  60. package/docs/nextjs.md +241 -0
  61. package/docs/repository.md +496 -0
  62. package/docs/route.md +497 -0
  63. package/docs/server.md +307 -0
  64. package/package.json +18 -3
@@ -61,11 +61,15 @@ interface JobSendOptions {
61
61
  /**
62
62
  * Job handler function type
63
63
  */
64
- type JobHandler<TInput> = TInput extends void ? () => Promise<void> : (input: TInput) => Promise<void>;
64
+ type JobHandler<TInput, TOutput = void> = TInput extends void ? () => Promise<TOutput> : (input: TInput) => Promise<TOutput>;
65
+ /**
66
+ * Compensate handler function type (for rollback)
67
+ */
68
+ type CompensateHandler<TInput, TOutput> = (input: TInput, output: TOutput) => Promise<void>;
65
69
  /**
66
70
  * Job definition interface
67
71
  */
68
- interface JobDef<TInput = void> {
72
+ interface JobDef<TInput = void, TOutput = void> {
69
73
  /**
70
74
  * Unique job name
71
75
  */
@@ -74,6 +78,10 @@ interface JobDef<TInput = void> {
74
78
  * TypeBox input schema (optional)
75
79
  */
76
80
  readonly inputSchema?: TSchema;
81
+ /**
82
+ * TypeBox output schema (optional, for workflow integration)
83
+ */
84
+ readonly outputSchema?: TSchema;
77
85
  /**
78
86
  * Cron expression for scheduled jobs
79
87
  */
@@ -97,7 +105,11 @@ interface JobDef<TInput = void> {
97
105
  /**
98
106
  * Job handler
99
107
  */
100
- readonly handler: JobHandler<TInput>;
108
+ readonly handler: JobHandler<TInput, TOutput>;
109
+ /**
110
+ * Compensate handler for rollback (optional, for workflow integration)
111
+ */
112
+ readonly compensate?: CompensateHandler<TInput, TOutput>;
101
113
  /**
102
114
  * Send job to queue (returns immediately, executes in background)
103
115
  */
@@ -105,16 +117,17 @@ interface JobDef<TInput = void> {
105
117
  /**
106
118
  * Run job synchronously (for testing/debugging)
107
119
  */
108
- run: TInput extends void ? () => Promise<void> : (input: TInput) => Promise<void>;
120
+ run: TInput extends void ? () => Promise<TOutput> : (input: TInput) => Promise<TOutput>;
109
121
  /**
110
122
  * Type inference helpers
111
123
  */
112
124
  _input: TInput;
125
+ _output: TOutput;
113
126
  }
114
127
  /**
115
128
  * Job router entry - can be a job or nested router
116
129
  */
117
- type JobRouterEntry = JobDef<any> | JobRouter<any>;
130
+ type JobRouterEntry = JobDef<any, any> | JobRouter<any>;
118
131
  /**
119
132
  * Job router interface
120
133
  */
@@ -125,7 +138,11 @@ interface JobRouter<TJobs extends Record<string, JobRouterEntry> = Record<string
125
138
  /**
126
139
  * Infer input type from JobDef
127
140
  */
128
- type InferJobInput<TJob> = TJob extends JobDef<infer TInput> ? TInput : never;
141
+ type InferJobInput<TJob> = TJob extends JobDef<infer TInput, any> ? TInput : never;
142
+ /**
143
+ * Infer output type from JobDef
144
+ */
145
+ type InferJobOutput<TJob> = TJob extends JobDef<any, infer TOutput> ? TOutput : never;
129
146
 
130
147
  /**
131
148
  * pg-boss Wrapper
@@ -134,39 +151,79 @@ type InferJobInput<TJob> = TJob extends JobDef<infer TInput> ? TInput : never;
134
151
  */
135
152
 
136
153
  /**
137
- * pg-boss configuration options
154
+ * Options for pg-boss initialization
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * await initBoss({
159
+ * connectionString: process.env.DATABASE_URL,
160
+ * schema: 'spfn_queue',
161
+ * clearOnStart: process.env.NODE_ENV === 'development',
162
+ * });
163
+ * ```
138
164
  */
139
- interface BossConfig {
165
+ interface BossOptions {
140
166
  /**
141
167
  * PostgreSQL connection string
168
+ *
169
+ * @example 'postgresql://user:password@localhost:5432/mydb'
142
170
  */
143
171
  connectionString: string;
144
172
  /**
145
173
  * Schema name for pg-boss tables
174
+ *
175
+ * pg-boss creates its own tables in this schema.
176
+ *
146
177
  * @default 'spfn_queue'
147
178
  */
148
179
  schema?: string;
149
180
  /**
150
181
  * Maintenance interval in seconds
182
+ *
183
+ * pg-boss runs maintenance tasks (cleanup, archiving) at this interval.
184
+ *
151
185
  * @default 120
152
186
  */
153
187
  maintenanceIntervalSeconds?: number;
154
188
  /**
155
189
  * Monitor state changes interval in seconds
190
+ *
191
+ * When set, pg-boss emits state change events at this interval.
192
+ *
156
193
  * @default undefined (disabled)
157
194
  */
158
195
  monitorIntervalSeconds?: number;
159
196
  /**
160
197
  * Clear all pending/scheduled jobs on startup
161
- * Useful for development mode
198
+ *
199
+ * Useful for development mode to start with a clean queue.
200
+ * Should be false in production.
201
+ *
162
202
  * @default false
163
203
  */
164
204
  clearOnStart?: boolean;
165
205
  }
206
+ /**
207
+ * @deprecated Use BossOptions instead
208
+ */
209
+ type BossConfig = BossOptions;
166
210
  /**
167
211
  * Initialize pg-boss with the given configuration
212
+ *
213
+ * Must be called before registerJobs(). Typically handled by defineServerConfig().
214
+ *
215
+ * @param options - pg-boss configuration options
216
+ * @returns The pg-boss instance
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * const boss = await initBoss({
221
+ * connectionString: process.env.DATABASE_URL!,
222
+ * schema: 'spfn_queue',
223
+ * });
224
+ * ```
168
225
  */
169
- declare function initBoss(config: BossConfig): Promise<PgBoss>;
226
+ declare function initBoss(options: BossOptions): Promise<PgBoss>;
170
227
  /**
171
228
  * Get the current pg-boss instance
172
229
  */
@@ -184,4 +241,4 @@ declare function isBossRunning(): boolean;
184
241
  */
185
242
  declare function shouldClearOnStart(): boolean;
186
243
 
187
- export { type BossConfig as B, type InferJobInput as I, type JobRouter as J, type JobOptions as a, type JobHandler as b, type JobDef as c, type JobRouterEntry as d, type JobSendOptions as e, isBossRunning as f, getBoss as g, shouldClearOnStart as h, initBoss as i, stopBoss as s };
244
+ export { type BossOptions as B, type CompensateHandler as C, type InferJobInput as I, type JobRouter as J, type JobOptions as a, type JobHandler as b, type JobDef as c, type JobRouterEntry as d, type JobSendOptions as e, type InferJobOutput as f, getBoss as g, isBossRunning as h, initBoss as i, shouldClearOnStart as j, type BossConfig as k, stopBoss as s };
@@ -270,28 +270,75 @@ interface GenerationStats {
270
270
  }
271
271
 
272
272
  /**
273
- * Built-in Generators Export
273
+ * Route Map Generator
274
+ *
275
+ * Generates a route map file containing routeName → {method, path} mappings.
276
+ * This allows RPC proxy to resolve routes without importing the full router.
277
+ *
278
+ * @example
279
+ * ```typescript
280
+ * // .spfnrc.ts
281
+ * import { defineConfig, defineGenerator } from '@spfn/core/codegen';
274
282
  *
275
- * Provides a registry of all built-in generators.
276
- * Custom generators can be added via .spfnrc.ts configuration.
283
+ * export default defineConfig({
284
+ * generators: [
285
+ * defineGenerator({
286
+ * name: '@spfn/core:route-map',
287
+ * routerPath: './src/server/router.ts',
288
+ * outputPath: './src/generated/route-map.ts',
289
+ * })
290
+ * ]
291
+ * });
292
+ * ```
293
+ */
294
+
295
+ interface RouteMapGeneratorConfig {
296
+ /**
297
+ * Generator name (required for package-based loading)
298
+ */
299
+ name: '@spfn/core:route-map';
300
+ /**
301
+ * Path to the router file (relative to project root)
302
+ * @example './src/server/router.ts'
303
+ */
304
+ routerPath: string;
305
+ /**
306
+ * Output path for generated route map (relative to project root)
307
+ * @default './src/generated/route-map.ts'
308
+ */
309
+ outputPath?: string;
310
+ /**
311
+ * Additional route directories to scan (for package routers)
312
+ */
313
+ additionalRouteDirs?: string[];
314
+ }
315
+
316
+ /**
317
+ * Built-in Generators Export
277
318
  *
278
319
  * @example
279
320
  * ```typescript
280
321
  * // .spfnrc.ts
281
322
  * import { defineConfig, defineGenerator } from '@spfn/core/codegen';
323
+ * import type { RouteMapGeneratorConfig } from '@spfn/core/codegen';
282
324
  *
283
325
  * export default defineConfig({
284
326
  * generators: [
285
- * defineGenerator({ path: './my-generator.ts' })
327
+ * defineGenerator<RouteMapGeneratorConfig>({
328
+ * name: '@spfn/core:route-map',
329
+ * routerPath: './src/server/router.ts',
330
+ * outputPath: './src/generated/route-map.ts',
331
+ * })
286
332
  * ]
287
333
  * });
288
334
  * ```
289
335
  */
336
+
290
337
  /**
291
- * Registry of available generators
292
- *
293
- * Used by package-based generator loading (e.g., "@spfn/core:my-generator")
338
+ * @internal
339
+ * Registry of available generators for package-based loading.
340
+ * DO NOT use directly - use defineGenerator({ name: '@spfn/core:route-map', ... }) instead.
294
341
  */
295
342
  declare const generators: Record<string, unknown>;
296
343
 
297
- export { type ClientGenerationOptions, type CodegenConfig, CodegenOrchestrator, type GenerationStats, type Generator, type GeneratorConfig, type GeneratorOptions, type GeneratorTrigger, type OrchestratorOptions, type ResourceRoutes, type RouteContractMapping, createGeneratorsFromConfig, defineConfig, defineGenerator, generators, loadCodegenConfig };
344
+ export { type ClientGenerationOptions, type CodegenConfig, CodegenOrchestrator, type GenerationStats, type Generator, type GeneratorConfig, type GeneratorOptions, type GeneratorTrigger, type OrchestratorOptions, type ResourceRoutes, type RouteContractMapping, type RouteMapGeneratorConfig, createGeneratorsFromConfig, defineConfig, defineGenerator, generators, loadCodegenConfig };
@@ -1,8 +1,8 @@
1
1
  import { watch } from 'chokidar';
2
- import { join, relative } from 'path';
2
+ import { join, dirname, resolve, relative } from 'path';
3
3
  import mm from 'micromatch';
4
4
  import { logger } from '@spfn/core/logger';
5
- import { existsSync, readFileSync } from 'fs';
5
+ import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
6
6
  import { createJiti } from 'jiti';
7
7
 
8
8
  // src/codegen/core/orchestrator.ts
@@ -172,8 +172,8 @@ var CodegenOrchestrator = class {
172
172
  }
173
173
  };
174
174
  this.watcher.on("add", (path) => handleChange(path, "add")).on("change", (path) => handleChange(path, "change")).on("unlink", (path) => handleChange(path, "unlink"));
175
- return new Promise((resolve, reject) => {
176
- this.watcherClosePromise = { resolve, reject };
175
+ return new Promise((resolve2, reject) => {
176
+ this.watcherClosePromise = { resolve: resolve2, reject };
177
177
  });
178
178
  }
179
179
  };
@@ -276,6 +276,11 @@ async function createGeneratorsFromConfig(config, cwd) {
276
276
  }
277
277
  for (const generatorConfig of config.generators) {
278
278
  try {
279
+ if ("generate" in generatorConfig && typeof generatorConfig.generate === "function") {
280
+ generators2.push(generatorConfig);
281
+ configLogger.info(`Generator instance added: ${generatorConfig.name}`);
282
+ continue;
283
+ }
279
284
  if ("path" in generatorConfig) {
280
285
  const generatorPath = generatorConfig.path.startsWith(".") ? join(cwd, generatorConfig.path) : generatorConfig.path;
281
286
  configLogger.info(`Loading custom generator: ${generatorPath}`);
@@ -321,9 +326,158 @@ async function createGeneratorsFromConfig(config, cwd) {
321
326
  }
322
327
  return generators2;
323
328
  }
329
+ var genLogger = logger.child("@spfn/core:route-map-generator");
330
+ function parseRouteFile(filePath) {
331
+ const routes = [];
332
+ try {
333
+ const content = readFileSync(filePath, "utf-8");
334
+ const routePattern = /export\s+const\s+(\w+)\s*=\s*route\.(get|post|put|patch|delete)\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/gi;
335
+ let match;
336
+ while ((match = routePattern.exec(content)) !== null) {
337
+ const [, name, method, path] = match;
338
+ routes.push({
339
+ name,
340
+ method: method.toUpperCase(),
341
+ path,
342
+ file: filePath
343
+ });
344
+ }
345
+ } catch (error) {
346
+ genLogger.warn(`Failed to parse route file: ${filePath}`, error);
347
+ }
348
+ return routes;
349
+ }
350
+ function parseRouterFile(routerPath) {
351
+ const importPaths = [];
352
+ const routeNames = [];
353
+ try {
354
+ const content = readFileSync(routerPath, "utf-8");
355
+ const importPattern = /import\s+\{[^}]+\}\s+from\s+['"`](\.[^'"`]+)['"`]/g;
356
+ let match;
357
+ while ((match = importPattern.exec(content)) !== null) {
358
+ const importPath = match[1];
359
+ if (importPath.includes("route")) {
360
+ importPaths.push(importPath);
361
+ }
362
+ }
363
+ const routerPattern = /defineRouter\s*\(\s*\{([^}]+)\}/s;
364
+ const routerMatch = routerPattern.exec(content);
365
+ if (routerMatch) {
366
+ const routerContent = routerMatch[1];
367
+ const namePattern = /(\w+)\s*[,}]/g;
368
+ while ((match = namePattern.exec(routerContent)) !== null) {
369
+ routeNames.push(match[1]);
370
+ }
371
+ }
372
+ } catch (error) {
373
+ genLogger.warn(`Failed to parse router file: ${routerPath}`, error);
374
+ }
375
+ return { importPaths, routeNames };
376
+ }
377
+ function generateRouteMapContent(routes) {
378
+ const lines = [
379
+ "/**",
380
+ " * Route Map (Auto-generated)",
381
+ " *",
382
+ " * DO NOT EDIT - This file is generated by @spfn/core:route-map generator",
383
+ " */",
384
+ "",
385
+ "import type { HttpMethod } from '@spfn/core/route';",
386
+ "",
387
+ "export interface RouteInfo",
388
+ "{",
389
+ " method: HttpMethod;",
390
+ " path: string;",
391
+ "}",
392
+ "",
393
+ "export const routeMap: Record<string, RouteInfo> = {"
394
+ ];
395
+ for (const route of routes) {
396
+ lines.push(` ${route.name}: { method: '${route.method}', path: '${route.path}' },`);
397
+ }
398
+ lines.push("};");
399
+ lines.push("");
400
+ lines.push("export type RouteMap = typeof routeMap;");
401
+ lines.push("");
402
+ lines.push("export type RouteName = keyof RouteMap;");
403
+ lines.push("");
404
+ return lines.join("\n");
405
+ }
406
+ function createRouteMapGenerator(config) {
407
+ const {
408
+ routerPath,
409
+ outputPath = "./src/generated/route-map.ts",
410
+ additionalRouteDirs = []
411
+ } = config;
412
+ if (!routerPath) {
413
+ throw new Error(
414
+ `[@spfn/core:route-map] Missing required "routerPath" option.
415
+
416
+ Usage:
417
+ defineGenerator<RouteMapGeneratorConfig>({
418
+ name: '@spfn/core:route-map',
419
+ routerPath: './src/server/router.ts',
420
+ })`
421
+ );
422
+ }
423
+ return {
424
+ name: "@spfn/core:route-map",
425
+ watchPatterns: [
426
+ routerPath,
427
+ // Watch route directories derived from router imports
428
+ "src/server/routes/**/*.ts",
429
+ ...additionalRouteDirs.map((dir) => `${dir}/**/*.ts`)
430
+ ],
431
+ runOn: ["watch", "build", "start", "manual"],
432
+ async generate(options) {
433
+ const { cwd, debug } = options;
434
+ const absoluteRouterPath = join(cwd, routerPath);
435
+ const absoluteOutputPath = join(cwd, outputPath);
436
+ if (!existsSync(absoluteRouterPath)) {
437
+ genLogger.warn(`Router file not found: ${absoluteRouterPath}`);
438
+ return;
439
+ }
440
+ if (debug) {
441
+ genLogger.info("Parsing router file", { path: absoluteRouterPath });
442
+ }
443
+ const { importPaths, routeNames } = parseRouterFile(absoluteRouterPath);
444
+ if (debug) {
445
+ genLogger.info("Found route imports", { count: importPaths.length, names: routeNames });
446
+ }
447
+ const routerDir = dirname(absoluteRouterPath);
448
+ const allRoutes = [];
449
+ for (const importPath of importPaths) {
450
+ let resolvedPath = resolve(routerDir, importPath);
451
+ if (!resolvedPath.endsWith(".ts")) {
452
+ resolvedPath += ".ts";
453
+ }
454
+ if (existsSync(resolvedPath)) {
455
+ const routes = parseRouteFile(resolvedPath);
456
+ allRoutes.push(...routes);
457
+ if (debug) {
458
+ genLogger.info(`Parsed ${routes.length} routes from ${relative(cwd, resolvedPath)}`);
459
+ }
460
+ }
461
+ }
462
+ const exportedRoutes = allRoutes.filter((r) => routeNames.includes(r.name));
463
+ if (debug) {
464
+ genLogger.info(`Found ${exportedRoutes.length} exported routes`);
465
+ }
466
+ const content = generateRouteMapContent(exportedRoutes);
467
+ const outputDir = dirname(absoluteOutputPath);
468
+ if (!existsSync(outputDir)) {
469
+ mkdirSync(outputDir, { recursive: true });
470
+ }
471
+ writeFileSync(absoluteOutputPath, content, "utf-8");
472
+ genLogger.info(`Generated route map: ${relative(cwd, absoluteOutputPath)} (${exportedRoutes.length} routes)`);
473
+ }
474
+ };
475
+ }
324
476
 
325
477
  // src/codegen/generators/index.ts
326
- var generators = {};
478
+ var generators = {
479
+ "route-map": createRouteMapGenerator
480
+ };
327
481
 
328
482
  export { CodegenOrchestrator, createGeneratorsFromConfig, defineConfig, defineGenerator, generators, loadCodegenConfig };
329
483
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/codegen/core/orchestrator.ts","../../src/codegen/core/config-loader.ts","../../src/codegen/generators/index.ts"],"names":["chokidarWatch","logger","join","generators"],"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 } 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\nexport class CodegenOrchestrator\n{\n private readonly generators: Generator[];\n private readonly cwd: string;\n private readonly debug: 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 }\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 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 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 }\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 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 ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\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 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 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 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 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 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 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 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 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 // 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 * Built-in Generators Export\n *\n * Provides a registry of all built-in generators.\n * Custom generators can be added via .spfnrc.ts configuration.\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({ path: './my-generator.ts' })\n * ]\n * });\n * ```\n */\n\n/**\n * Registry of available generators\n *\n * Used by package-based generator loading (e.g., \"@spfn/core:my-generator\")\n */\nexport const generators: Record<string, unknown> = {};\n"]}
1
+ {"version":3,"sources":["../../src/codegen/core/orchestrator.ts","../../src/codegen/core/config-loader.ts","../../src/codegen/generators/route-map.ts","../../src/codegen/generators/index.ts"],"names":["chokidarWatch","resolve","logger","join","generators","readFileSync","existsSync","relative"],"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 } 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\nexport class CodegenOrchestrator\n{\n private readonly generators: Generator[];\n private readonly cwd: string;\n private readonly debug: 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 }\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 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 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 }\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 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 ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\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 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 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 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 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 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 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 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 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 * 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 * @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, resolve } from 'path';\nimport type { Generator, GeneratorOptions } from '../core/generator';\nimport { logger } from '@spfn/core/logger';\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 * Additional route directories to scan (for package routers)\n */\n additionalRouteDirs?: string[];\n}\n\ninterface ParsedRoute\n{\n name: string;\n method: string;\n path: string;\n file: string;\n}\n\n// ============================================================================\n// Parser\n// ============================================================================\n\n/**\n * Parse route definitions from a route file\n *\n * Supports patterns:\n * - export const routeName = route.get('/path')...\n * - export const routeName = route.post('/path')...\n */\nfunction parseRouteFile(filePath: string): ParsedRoute[]\n{\n const routes: ParsedRoute[] = [];\n\n try\n {\n const content = readFileSync(filePath, 'utf-8');\n\n // Pattern: export const {name} = route.{method}('{path}')\n // Handles both single and double quotes\n const routePattern = /export\\s+const\\s+(\\w+)\\s*=\\s*route\\.(get|post|put|patch|delete)\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]\\s*\\)/gi;\n\n let match;\n while ((match = routePattern.exec(content)) !== null)\n {\n const [, name, method, path] = match;\n routes.push({\n name,\n method: method.toUpperCase(),\n path,\n file: filePath\n });\n }\n }\n catch (error)\n {\n genLogger.warn(`Failed to parse route file: ${filePath}`, error as Error);\n }\n\n return routes;\n}\n\n/**\n * Parse router file to find route imports and names\n *\n * Extracts:\n * - Import paths for route files\n * - Route names from defineRouter({...})\n */\nfunction parseRouterFile(routerPath: string): { importPaths: string[]; routeNames: string[] }\n{\n const importPaths: string[] = [];\n const routeNames: string[] = [];\n\n try\n {\n const content = readFileSync(routerPath, 'utf-8');\n\n // Extract import paths\n // Pattern: import { ... } from './routes/xxx'\n const importPattern = /import\\s+\\{[^}]+\\}\\s+from\\s+['\"`](\\.[^'\"`]+)['\"`]/g;\n let match;\n while ((match = importPattern.exec(content)) !== null)\n {\n const importPath = match[1];\n if (importPath.includes('route'))\n {\n importPaths.push(importPath);\n }\n }\n\n // Extract route names from defineRouter({...})\n const routerPattern = /defineRouter\\s*\\(\\s*\\{([^}]+)\\}/s;\n const routerMatch = routerPattern.exec(content);\n if (routerMatch)\n {\n const routerContent = routerMatch[1];\n // Extract identifiers (route names)\n const namePattern = /(\\w+)\\s*[,}]/g;\n while ((match = namePattern.exec(routerContent)) !== null)\n {\n routeNames.push(match[1]);\n }\n }\n }\n catch (error)\n {\n genLogger.warn(`Failed to parse router file: ${routerPath}`, error as Error);\n }\n\n return { importPaths, routeNames };\n}\n\n// ============================================================================\n// Generator\n// ============================================================================\n\n/**\n * Generate route map file content\n */\nfunction generateRouteMapContent(routes: ParsedRoute[]): 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 '',\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 route of routes)\n {\n lines.push(` ${route.name}: { method: '${route.method}', path: '${route.path}' },`);\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/**\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 watchPatterns: [\n routerPath,\n // Watch route directories derived from router imports\n 'src/server/routes/**/*.ts',\n ...additionalRouteDirs.map(dir => `${dir}/**/*.ts`)\n ],\n\n runOn: ['watch', 'build', 'start', 'manual'],\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 return;\n }\n\n if (debug)\n {\n genLogger.info('Parsing router file', { path: absoluteRouterPath });\n }\n\n // Parse router file\n const { importPaths, routeNames } = parseRouterFile(absoluteRouterPath);\n\n if (debug)\n {\n genLogger.info('Found route imports', { count: importPaths.length, names: routeNames });\n }\n\n // Resolve import paths and parse route files\n const routerDir = dirname(absoluteRouterPath);\n const allRoutes: ParsedRoute[] = [];\n\n for (const importPath of importPaths)\n {\n // Resolve .ts extension\n let resolvedPath = resolve(routerDir, importPath);\n if (!resolvedPath.endsWith('.ts'))\n {\n resolvedPath += '.ts';\n }\n\n if (existsSync(resolvedPath))\n {\n const routes = parseRouteFile(resolvedPath);\n allRoutes.push(...routes);\n\n if (debug)\n {\n genLogger.info(`Parsed ${routes.length} routes from ${relative(cwd, resolvedPath)}`);\n }\n }\n }\n\n // Filter routes that are actually exported in router\n const exportedRoutes = allRoutes.filter(r => routeNames.includes(r.name));\n\n if (debug)\n {\n genLogger.info(`Found ${exportedRoutes.length} exported routes`);\n }\n\n // Generate output\n const content = generateRouteMapContent(exportedRoutes);\n\n // Ensure output directory exists\n const outputDir = dirname(absoluteOutputPath);\n if (!existsSync(outputDir))\n {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Write file\n writeFileSync(absoluteOutputPath, content, 'utf-8');\n\n genLogger.info(`Generated route map: ${relative(cwd, absoluteOutputPath)} (${exportedRoutes.length} routes)`);\n }\n };\n}\n\n// ============================================================================\n// Export for package-based loading\n// ============================================================================\n\nexport default createRouteMapGenerator;\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 } 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 * ]\n * });\n * ```\n */\n\nimport { createRouteMapGenerator } from './route-map';\nexport type { RouteMapGeneratorConfig } from './route-map';\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};\n"]}