@geekmidas/cli 0.6.0 → 0.6.2

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 (37) hide show
  1. package/README.md +119 -0
  2. package/dist/{OpenApiTsGenerator-0ZDYWro5.mjs → OpenApiTsGenerator-BVS4pOH7.mjs} +2 -2
  3. package/dist/{OpenApiTsGenerator-0ZDYWro5.mjs.map → OpenApiTsGenerator-BVS4pOH7.mjs.map} +1 -1
  4. package/dist/{OpenApiTsGenerator-wLwpaq_I.cjs → OpenApiTsGenerator-gPIIyppX.cjs} +2 -2
  5. package/dist/{OpenApiTsGenerator-wLwpaq_I.cjs.map → OpenApiTsGenerator-gPIIyppX.cjs.map} +1 -1
  6. package/dist/build/index.cjs +4 -4
  7. package/dist/build/index.mjs +4 -4
  8. package/dist/{build-BLriHKgm.mjs → build-Cu6Mi0Lf.mjs} +2 -2
  9. package/dist/{build-BLriHKgm.mjs.map → build-Cu6Mi0Lf.mjs.map} +1 -1
  10. package/dist/{build-Z3yGHcy2.cjs → build-wmt8ZcmA.cjs} +2 -2
  11. package/dist/{build-Z3yGHcy2.cjs.map → build-wmt8ZcmA.cjs.map} +1 -1
  12. package/dist/config-Bq72aj8e.mjs.map +1 -1
  13. package/dist/config-CFls09Ey.cjs.map +1 -1
  14. package/dist/config.d.cts +1 -1
  15. package/dist/config.d.mts +1 -1
  16. package/dist/dev/index.cjs +3 -3
  17. package/dist/dev/index.mjs +3 -3
  18. package/dist/{dev-BimlVcuk.mjs → dev-BBPWSllq.mjs} +2 -2
  19. package/dist/{dev-BimlVcuk.mjs.map → dev-BBPWSllq.mjs.map} +1 -1
  20. package/dist/{dev-Dcrb_ZSL.cjs → dev-C2lCgE53.cjs} +2 -2
  21. package/dist/{dev-Dcrb_ZSL.cjs.map → dev-C2lCgE53.cjs.map} +1 -1
  22. package/dist/generators/OpenApiTsGenerator.cjs +1 -1
  23. package/dist/generators/OpenApiTsGenerator.mjs +1 -1
  24. package/dist/index.cjs +5 -5
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.mjs +5 -5
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/{openapi-Dn9MeKg3.mjs → openapi-DA9RkPJl.mjs} +2 -2
  29. package/dist/{openapi-Dn9MeKg3.mjs.map → openapi-DA9RkPJl.mjs.map} +1 -1
  30. package/dist/{openapi-CTae4ybf.cjs → openapi-DZH6RQHk.cjs} +2 -2
  31. package/dist/{openapi-CTae4ybf.cjs.map → openapi-DZH6RQHk.cjs.map} +1 -1
  32. package/dist/openapi.cjs +2 -2
  33. package/dist/openapi.mjs +2 -2
  34. package/package.json +5 -5
  35. package/src/config.ts +1 -0
  36. package/src/dev/__tests__/index.spec.ts +6 -3
  37. package/src/generators/OpenApiTsGenerator.ts +1 -1
package/README.md CHANGED
@@ -4,6 +4,7 @@ A powerful CLI tool for building and managing TypeScript-based backend APIs with
4
4
 
5
5
  ## Features
6
6
 
7
+ - **Project Scaffolding**: Interactive `init` command to bootstrap new projects with templates
7
8
  - **Multi-Provider Support**: Generate handlers for AWS Lambda (API Gateway v1/v2) and server applications
8
9
  - **Development Server**: Hot-reload development server with file watching
9
10
  - **Telescope Integration**: Laravel-style debugging dashboard for inspecting requests, logs, and exceptions
@@ -13,6 +14,7 @@ A powerful CLI tool for building and managing TypeScript-based backend APIs with
13
14
  - **Flexible Routing**: Support for glob patterns to discover route files
14
15
  - **Environment Integration**: Seamless integration with @geekmidas/envkit for configuration
15
16
  - **Logger Integration**: Built-in logging configuration and integration
17
+ - **Monorepo Support**: Optional pnpm workspace monorepo setup with shared packages
16
18
 
17
19
  ## Installation
18
20
 
@@ -28,6 +30,18 @@ npm install -g @geekmidas/cli
28
30
 
29
31
  ## Quick Start
30
32
 
33
+ ### Option 1: Use `gkm init` (Recommended)
34
+
35
+ The fastest way to get started is with the interactive `init` command:
36
+
37
+ ```bash
38
+ npx @geekmidas/cli init my-api
39
+ ```
40
+
41
+ This will guide you through setting up a new project with your preferred options.
42
+
43
+ ### Option 2: Manual Setup
44
+
31
45
  ### 1. Create Configuration
32
46
 
33
47
  Create a `gkm.config.ts` file in your project root:
@@ -178,6 +192,111 @@ npx gkm openapi --output src/api.ts
178
192
 
179
193
  ## CLI Commands
180
194
 
195
+ ### `gkm init`
196
+
197
+ Scaffold a new project with interactive prompts.
198
+
199
+ ```bash
200
+ gkm init [name] [options]
201
+ ```
202
+
203
+ **Arguments:**
204
+ - `[name]`: Project name (optional, will prompt if not provided)
205
+
206
+ **Options:**
207
+ - `--template <template>`: Project template (`minimal`, `api`, `serverless`, `worker`)
208
+ - `--skip-install`: Skip dependency installation
209
+ - `-y, --yes`: Skip prompts, use defaults
210
+ - `--monorepo`: Setup as monorepo structure
211
+ - `--api-path <path>`: API app path in monorepo (default: `apps/api`)
212
+
213
+ **Interactive Prompts:**
214
+
215
+ When run without `--yes`, the command will ask:
216
+
217
+ 1. **Project name** - Name for your project directory
218
+ 2. **Template** - Choose from available templates:
219
+ - `minimal` - Basic health endpoint
220
+ - `api` - Full API with auth, database, services
221
+ - `serverless` - AWS Lambda handlers
222
+ - `worker` - Background job processing
223
+ 3. **Telescope** - Include debugging dashboard (default: yes)
224
+ 4. **Database** - Include Kysely database support (default: yes)
225
+ 5. **Logger** - Choose logger implementation:
226
+ - `pino` - Fast JSON logger for production (recommended)
227
+ - `console` - Simple console logger for development
228
+ 6. **Routes structure** - Choose file organization:
229
+ - `centralized-endpoints` - `src/endpoints/**/*.ts`
230
+ - `centralized-routes` - `src/routes/**/*.ts`
231
+ - `domain-based` - `src/**/routes/*.ts`
232
+ 7. **Monorepo** - Setup as pnpm workspace monorepo (default: no)
233
+ 8. **API path** - If monorepo, where to place the API app
234
+
235
+ **Examples:**
236
+
237
+ ```bash
238
+ # Interactive mode
239
+ npx @geekmidas/cli init
240
+
241
+ # With project name
242
+ npx @geekmidas/cli init my-api
243
+
244
+ # Skip prompts with defaults
245
+ npx @geekmidas/cli init my-api --yes
246
+
247
+ # Specific template
248
+ npx @geekmidas/cli init my-api --template api
249
+
250
+ # Monorepo setup
251
+ npx @geekmidas/cli init my-project --monorepo --api-path apps/backend
252
+
253
+ # Skip dependency installation
254
+ npx @geekmidas/cli init my-api --skip-install
255
+ ```
256
+
257
+ **Generated Structure (Minimal Template):**
258
+
259
+ ```
260
+ my-api/
261
+ ├── src/
262
+ │ ├── config/
263
+ │ │ ├── env.ts # Environment configuration
264
+ │ │ └── logger.ts # Logger setup
265
+ │ └── endpoints/
266
+ │ └── health.ts # Health check endpoint
267
+ ├── .env # Environment variables
268
+ ├── .env.example # Example env file
269
+ ├── .gitignore
270
+ ├── gkm.config.ts # CLI configuration
271
+ ├── package.json
272
+ ├── tsconfig.json
273
+ └── Dockerfile # Docker configuration
274
+ ```
275
+
276
+ **Generated Structure (Monorepo):**
277
+
278
+ ```
279
+ my-project/
280
+ ├── apps/
281
+ │ └── api/
282
+ │ ├── src/
283
+ │ │ ├── config/
284
+ │ │ └── endpoints/
285
+ │ ├── gkm.config.ts
286
+ │ ├── package.json
287
+ │ └── tsconfig.json
288
+ ├── packages/
289
+ │ └── models/ # Shared types/models
290
+ │ ├── src/
291
+ │ │ └── index.ts
292
+ │ ├── package.json
293
+ │ └── tsconfig.json
294
+ ├── package.json # Root workspace config
295
+ ├── pnpm-workspace.yaml
296
+ ├── tsconfig.json # Base TypeScript config
297
+ └── turbo.json # Turborepo config
298
+ ```
299
+
181
300
  ### `gkm build`
182
301
 
183
302
  Generate handlers from your endpoints.
@@ -450,7 +450,7 @@ export const apiInfo = {
450
450
  * Available security schemes for this API.
451
451
  * Maps authorizer names to OpenAPI security scheme definitions.
452
452
  */
453
- export const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/"([^"]+)":/g, "$1:")} as const satisfies Record<string, SecuritySchemeObject>;
453
+ export const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/"([a-zA-Z_$][a-zA-Z0-9_$]*)":/g, "$1:")} as const satisfies Record<string, SecuritySchemeObject>;
454
454
 
455
455
  export type SecuritySchemeId = ${schemeNames || "never"};
456
456
 
@@ -492,4 +492,4 @@ ${createApiSection}
492
492
 
493
493
  //#endregion
494
494
  export { OpenApiTsGenerator };
495
- //# sourceMappingURL=OpenApiTsGenerator-0ZDYWro5.mjs.map
495
+ //# sourceMappingURL=OpenApiTsGenerator-BVS4pOH7.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"OpenApiTsGenerator-0ZDYWro5.mjs","names":["endpoints: Endpoint<any, any, any, any, any, any>[]","options: OpenApiTsOptions","endpointInfos: EndpointInfo[]","type: string","_name: string","authMap: Record<string, string | null>","interfaces: string[]","schema: StandardSchemaV1","defaultName: string","info: EndpointInfo","str: string","name: string","collectedDefs: Map<string, JsonSchema>","schema: JsonSchema","props: string[]","s: JsonSchema","e: string","pathEntries: string[]","methodEntries: string[]","parts: string[]","params: {\n title: string;\n version: string;\n description?: string;\n securitySchemes: SecuritySchemeInfo[];\n endpointAuth: Record<string, string | null>;\n schemaInterfaces: string;\n pathsInterface: string;\n }"],"sources":["../src/generators/OpenApiTsGenerator.ts"],"sourcesContent":["import type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport {\n StandardSchemaJsonSchema,\n getSchemaMetadata,\n} from '@geekmidas/schema/conversion';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\ninterface OpenApiTsOptions {\n title?: string;\n version?: string;\n description?: string;\n}\n\n// JSON Schema type definition\ninterface JsonSchema {\n type?: string;\n properties?: Record<string, JsonSchema>;\n items?: JsonSchema;\n required?: string[];\n enum?: string[];\n $ref?: string;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n additionalProperties?: boolean | JsonSchema;\n [key: string]: unknown;\n}\n\n// Security scheme type (OpenAPI 3.1)\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\ninterface EndpointInfo {\n endpoint: string;\n route: string;\n method: string;\n authorizerName: string | null;\n /** @deprecated Use securityScheme instead */\n authorizerType: string | null;\n /** The OpenAPI security scheme definition for this endpoint's authorizer */\n securityScheme: SecuritySchemeObject | null;\n input?: {\n body?: StandardSchemaV1;\n query?: StandardSchemaV1;\n params?: StandardSchemaV1;\n };\n output?: StandardSchemaV1;\n description?: string;\n tags?: string[];\n operationId?: string;\n}\n\ninterface SecuritySchemeInfo {\n name: string;\n type: string;\n scheme: SecuritySchemeObject;\n}\n\n/**\n * Generates TypeScript OpenAPI module from endpoints.\n * Outputs:\n * - securitySchemes: typed security scheme definitions\n * - endpointAuth: runtime map of endpoints to auth requirements\n * - paths: TypeScript interface for type-safe fetcher\n * - schema interfaces: reusable TypeScript types from Zod/Valibot schemas\n */\nexport class OpenApiTsGenerator {\n async generate(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n options: OpenApiTsOptions = {},\n ): Promise<string> {\n const { title = 'API', version = '1.0.0', description } = options;\n\n // Extract endpoint info\n const endpointInfos = await this.extractEndpointInfos(endpoints);\n\n // Collect unique security schemes\n const securitySchemes = this.collectSecuritySchemes(endpointInfos);\n\n // Build endpoint auth map\n const endpointAuth = this.buildEndpointAuthMap(endpointInfos);\n\n // Generate schema interfaces\n const schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);\n\n // Generate paths interface\n const pathsInterface = await this.generatePathsInterface(endpointInfos);\n\n // Build the final TypeScript module\n return this.buildModule({\n title,\n version,\n description,\n securitySchemes,\n endpointAuth,\n schemaInterfaces,\n pathsInterface,\n });\n }\n\n private async extractEndpointInfos(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n ): Promise<EndpointInfo[]> {\n return endpoints.map((ep) => {\n const route = ep.route.replace(/:(\\w+)/g, '{$1}');\n const method = ep.method.toUpperCase();\n\n // Get security scheme from authorizer (if available)\n // This is the preferred way - the scheme is stored directly on the authorizer\n const securityScheme = ep.authorizer?.securityScheme as\n | SecuritySchemeObject\n | undefined;\n\n return {\n endpoint: `${method} ${route}`,\n route,\n method,\n authorizerName: ep.authorizer?.name ?? null,\n authorizerType: ep.authorizer?.type ?? null,\n securityScheme: securityScheme ?? null,\n input: ep.input,\n output: ep.outputSchema,\n description: ep.description,\n tags: ep.tags,\n operationId: ep.operationId,\n };\n });\n }\n\n private collectSecuritySchemes(\n endpointInfos: EndpointInfo[],\n ): SecuritySchemeInfo[] {\n const schemes = new Map<string, SecuritySchemeInfo>();\n\n for (const info of endpointInfos) {\n if (info.authorizerName && !schemes.has(info.authorizerName)) {\n // Prefer the stored security scheme (from .securitySchemes() or built-ins)\n // Fall back to inference from authorizerType for backward compatibility\n const scheme =\n info.securityScheme ??\n (info.authorizerType\n ? this.mapAuthorizerToSecurityScheme(\n info.authorizerType,\n info.authorizerName,\n )\n : null);\n\n if (scheme) {\n schemes.set(info.authorizerName, {\n name: info.authorizerName,\n type: scheme.type,\n scheme,\n });\n }\n }\n }\n\n return Array.from(schemes.values());\n }\n\n private mapAuthorizerToSecurityScheme(\n type: string,\n _name: string,\n ): SecuritySchemeObject {\n switch (type.toLowerCase()) {\n case 'jwt':\n case 'bearer':\n return {\n type: 'http',\n scheme: 'bearer',\n bearerFormat: 'JWT',\n };\n case 'iam':\n case 'aws-sigv4':\n case 'sigv4':\n return {\n type: 'apiKey',\n in: 'header',\n name: 'Authorization',\n 'x-amazon-apigateway-authtype': 'awsSigv4',\n };\n case 'apikey':\n case 'api-key':\n return {\n type: 'apiKey',\n in: 'header',\n name: 'X-API-Key',\n };\n case 'oauth2':\n return {\n type: 'oauth2',\n flows: {},\n };\n case 'oidc':\n case 'openidconnect':\n return {\n type: 'openIdConnect',\n openIdConnectUrl: '',\n };\n default:\n return {\n type: 'http',\n scheme: 'bearer',\n };\n }\n }\n\n private buildEndpointAuthMap(\n endpointInfos: EndpointInfo[],\n ): Record<string, string | null> {\n const authMap: Record<string, string | null> = {};\n\n for (const info of endpointInfos) {\n authMap[info.endpoint] = info.authorizerName;\n }\n\n return authMap;\n }\n\n private async generateSchemaInterfaces(\n endpointInfos: EndpointInfo[],\n ): Promise<string> {\n const interfaces: string[] = [];\n const generatedNames = new Set<string>();\n // Collect nested schemas with $defs (from .meta({ id: 'X' }))\n const collectedDefs = new Map<string, JsonSchema>();\n\n for (const info of endpointInfos) {\n const baseName = this.getSchemaBaseName(info);\n\n // Input body schema\n if (info.input?.body) {\n const name = await this.getSchemaName(\n info.input.body,\n `${baseName}Input`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.body,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Input params schema\n if (info.input?.params) {\n const name = await this.getSchemaName(\n info.input.params,\n `${baseName}Params`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.params,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Input query schema\n if (info.input?.query) {\n const name = await this.getSchemaName(\n info.input.query,\n `${baseName}Query`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.query,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Output schema\n if (info.output) {\n const name = await this.getSchemaName(info.output, `${baseName}Output`);\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.output,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n }\n\n // Generate interfaces for collected $defs (nested schemas with .meta({ id: 'X' }))\n for (const [defName, defSchema] of collectedDefs) {\n if (!generatedNames.has(defName)) {\n const interfaceStr = this.jsonSchemaToInterface(defSchema, defName);\n interfaces.push(interfaceStr);\n generatedNames.add(defName);\n }\n }\n\n return interfaces.join('\\n\\n');\n }\n\n /**\n * Get the name for a schema, using metadata `id` if available,\n * otherwise falling back to the provided default name.\n */\n private async getSchemaName(\n schema: StandardSchemaV1,\n defaultName: string,\n ): Promise<string> {\n try {\n const metadata = await getSchemaMetadata(schema);\n if (metadata?.id) {\n return this.pascalCase(metadata.id);\n }\n } catch {\n // Ignore metadata extraction errors\n }\n return defaultName;\n }\n\n private getSchemaBaseName(info: EndpointInfo): string {\n if (info.operationId) {\n return this.pascalCase(info.operationId);\n }\n\n // Generate name from method + route\n const routeParts = info.route\n .replace(/[{}]/g, '')\n .split('/')\n .filter(Boolean)\n .map((part) => this.pascalCase(part));\n\n return `${this.pascalCase(info.method.toLowerCase())}${routeParts.join('')}`;\n }\n\n private pascalCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, c) => c.toUpperCase())\n .replace(/^./, (c) => c.toUpperCase());\n }\n\n /**\n * Convert schema to interface while collecting $defs for nested schemas\n * with .meta({ id: 'X' }).\n */\n private async schemaToInterfaceWithDefs(\n schema: StandardSchemaV1,\n name: string,\n collectedDefs: Map<string, JsonSchema>,\n ): Promise<string | null> {\n try {\n // Get raw JSON schema with $defs intact (don't use convertStandardSchemaToJsonSchema\n // which strips $defs)\n const vendor = schema['~standard']?.vendor;\n if (!vendor || !(vendor in StandardSchemaJsonSchema)) {\n return null;\n }\n\n const toJsonSchema =\n StandardSchemaJsonSchema[\n vendor as keyof typeof StandardSchemaJsonSchema\n ];\n const jsonSchema = await toJsonSchema(schema);\n if (!jsonSchema) return null;\n\n // Extract $defs from the JSON schema (these come from .meta({ id: 'X' }))\n if (jsonSchema.$defs && typeof jsonSchema.$defs === 'object') {\n for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) {\n if (!collectedDefs.has(defName)) {\n // Remove the 'id' field from the schema as it's just metadata\n const { id, ...schemaWithoutId } = defSchema as JsonSchema & {\n id?: string;\n };\n collectedDefs.set(defName, schemaWithoutId as JsonSchema);\n }\n }\n }\n\n // Remove $defs from the schema before converting to interface\n const { $defs, ...schemaWithoutDefs } = jsonSchema;\n return this.jsonSchemaToInterface(schemaWithoutDefs, name);\n } catch {\n return null;\n }\n }\n\n private jsonSchemaToInterface(schema: JsonSchema, name: string): string {\n if (schema.type !== 'object' || !schema.properties) {\n // For non-object types, create a type alias\n const typeStr = this.jsonSchemaTypeToTs(schema);\n return `export type ${name} = ${typeStr};`;\n }\n\n const props: string[] = [];\n const required = new Set(schema.required || []);\n\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n const isRequired = required.has(propName);\n const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n const optionalMark = isRequired ? '' : '?';\n props.push(` ${propName}${optionalMark}: ${typeStr};`);\n }\n\n return `export interface ${name} {\\n${props.join('\\n')}\\n}`;\n }\n\n private jsonSchemaTypeToTs(schema: JsonSchema): string {\n if (!schema) return 'unknown';\n\n if (schema.$ref) {\n // Extract name from $ref\n const refName = schema.$ref.split('/').pop() || 'unknown';\n return refName;\n }\n\n if (schema.anyOf) {\n return schema.anyOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' | ');\n }\n\n if (schema.oneOf) {\n return schema.oneOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' | ');\n }\n\n if (schema.allOf) {\n return schema.allOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' & ');\n }\n\n switch (schema.type) {\n case 'string':\n if (schema.enum) {\n return schema.enum.map((e: string) => `'${e}'`).join(' | ');\n }\n return 'string';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'null':\n return 'null';\n case 'array':\n if (schema.items) {\n return `Array<${this.jsonSchemaTypeToTs(schema.items as JsonSchema)}>`;\n }\n return 'Array<unknown>';\n case 'object':\n if (schema.properties) {\n const props: string[] = [];\n const required = new Set(schema.required || []);\n for (const [propName, propSchema] of Object.entries(\n schema.properties,\n )) {\n const isRequired = required.has(propName);\n const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n const optionalMark = isRequired ? '' : '?';\n props.push(`${propName}${optionalMark}: ${typeStr}`);\n }\n return `{ ${props.join('; ')} }`;\n }\n if (schema.additionalProperties) {\n const valueType = this.jsonSchemaTypeToTs(\n schema.additionalProperties as JsonSchema,\n );\n return `Record<string, ${valueType}>`;\n }\n return 'Record<string, unknown>';\n default:\n return 'unknown';\n }\n }\n\n private async generatePathsInterface(\n endpointInfos: EndpointInfo[],\n ): Promise<string> {\n const pathGroups = new Map<string, EndpointInfo[]>();\n\n // Group endpoints by route\n for (const info of endpointInfos) {\n const existing = pathGroups.get(info.route) || [];\n existing.push(info);\n pathGroups.set(info.route, existing);\n }\n\n const pathEntries: string[] = [];\n\n for (const [route, infos] of pathGroups) {\n const methodEntries: string[] = [];\n\n for (const info of infos) {\n const methodDef = await this.generateMethodDefinition(info);\n methodEntries.push(` ${info.method.toLowerCase()}: ${methodDef};`);\n }\n\n // Add path parameters if present\n const firstWithParams = infos.find((i) => i.input?.params);\n let paramsEntry = '';\n if (firstWithParams?.input?.params) {\n const paramsName = await this.getSchemaName(\n firstWithParams.input.params,\n `${this.getSchemaBaseName(firstWithParams)}Params`,\n );\n paramsEntry = `\\n parameters: {\\n path: ${paramsName};\\n };`;\n }\n\n pathEntries.push(\n ` '${route}': {${paramsEntry}\\n${methodEntries.join('\\n')}\\n };`,\n );\n }\n\n return `export interface paths {\\n${pathEntries.join('\\n')}\\n}`;\n }\n\n private async generateMethodDefinition(info: EndpointInfo): Promise<string> {\n const parts: string[] = [];\n const baseName = this.getSchemaBaseName(info);\n\n // Request body\n if (info.input?.body) {\n const bodyName = await this.getSchemaName(\n info.input.body,\n `${baseName}Input`,\n );\n parts.push(`requestBody: {\n content: {\n 'application/json': ${bodyName};\n };\n }`);\n }\n\n // Query parameters\n if (info.input?.query) {\n const queryName = await this.getSchemaName(\n info.input.query,\n `${baseName}Query`,\n );\n parts.push(`parameters: {\n query: ${queryName};\n }`);\n }\n\n // Responses\n const outputName = info.output\n ? await this.getSchemaName(info.output, `${baseName}Output`)\n : 'unknown';\n parts.push(`responses: {\n 200: {\n content: {\n 'application/json': ${outputName};\n };\n };\n }`);\n\n return `{\\n ${parts.join(';\\n ')};\\n }`;\n }\n\n private buildModule(params: {\n title: string;\n version: string;\n description?: string;\n securitySchemes: SecuritySchemeInfo[];\n endpointAuth: Record<string, string | null>;\n schemaInterfaces: string;\n pathsInterface: string;\n }): string {\n const {\n title,\n version,\n description,\n securitySchemes,\n endpointAuth,\n schemaInterfaces,\n pathsInterface,\n } = params;\n\n const securitySchemesObj = securitySchemes.reduce(\n (acc, s) => {\n acc[s.name] = s.scheme;\n return acc;\n },\n {} as Record<string, SecuritySchemeObject>,\n );\n\n const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(' | ');\n\n // Generate createApi only if there are security schemes\n const hasSecuritySchemes = schemeNames.length > 0;\n\n const createApiSection = hasSecuritySchemes\n ? `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport {\n createAuthAwareFetcher,\n type AuthStrategy,\n} from '@geekmidas/client/auth-fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Auth strategies for each security scheme used in this API */\n authStrategies: Record<SecuritySchemeId, AuthStrategy>;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n /** Optional request interceptor */\n onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;\n}\n\n/**\n * Create a type-safe API client with authentication and React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * },\n * });\n *\n * // Imperative fetch\n * const user = await api('GET /users/{id}', { params: { id: '123' } });\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /users/{id}', { params: { id: '123' } });\n * const mutation = api.useMutation('POST /users');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const fetcher = createAuthAwareFetcher<paths, typeof endpointAuth, typeof securitySchemes>({\n baseURL: options.baseURL,\n endpointAuth,\n securitySchemes,\n authStrategies: options.authStrategies,\n onRequest: options.onRequest,\n });\n\n const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });\n\n return Object.assign(fetcher, hooks);\n}\n`\n : `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport { TypedFetcher, type FetcherOptions } from '@geekmidas/client/fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions extends Omit<FetcherOptions, 'baseURL'> {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n}\n\n/**\n * Create a type-safe API client with React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * });\n *\n * // Imperative fetch\n * const data = await api('GET /health');\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /health');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const { queryClient, ...fetcherOptions } = options;\n const fetcher = new TypedFetcher<paths>(fetcherOptions);\n\n const hooks = createEndpointHooks<paths>(fetcher.request.bind(fetcher), { queryClient });\n\n return Object.assign(fetcher.request.bind(fetcher), hooks);\n}\n`;\n\n return `// Auto-generated by @geekmidas/cli - DO NOT EDIT\n// Generated: ${new Date().toISOString()}\n\n// ============================================================\n// Security Scheme Type\n// ============================================================\n\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\n// ============================================================\n// API Info\n// ============================================================\n\nexport const apiInfo = {\n title: '${title}',\n version: '${version}',${description ? `\\n description: '${description.replace(/'/g, \"\\\\'\")}',` : ''}\n} as const;\n\n// ============================================================\n// Security Schemes\n// ============================================================\n\n/**\n * Available security schemes for this API.\n * Maps authorizer names to OpenAPI security scheme definitions.\n */\nexport const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/\"([^\"]+)\":/g, '$1:')} as const satisfies Record<string, SecuritySchemeObject>;\n\nexport type SecuritySchemeId = ${schemeNames || 'never'};\n\n// ============================================================\n// Endpoint Authentication Map\n// ============================================================\n\n/**\n * Runtime map of endpoints to their required authentication scheme.\n * \\`null\\` indicates a public endpoint (no auth required).\n */\nexport const endpointAuth = ${JSON.stringify(endpointAuth, null, 2).replace(/\"([^\"]+)\":/g, \"'$1':\")} as const satisfies Record<string, SecuritySchemeId | null>;\n\nexport type EndpointString = keyof typeof endpointAuth;\n\nexport type AuthenticatedEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? never : K;\n}[EndpointString];\n\nexport type PublicEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? K : never;\n}[EndpointString];\n\n// ============================================================\n// Schema Definitions\n// ============================================================\n\n${schemaInterfaces}\n\n// ============================================================\n// OpenAPI Paths\n// ============================================================\n\n${pathsInterface}\n${createApiSection}\n`;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"OpenApiTsGenerator-BVS4pOH7.mjs","names":["endpoints: Endpoint<any, any, any, any, any, any>[]","options: OpenApiTsOptions","endpointInfos: EndpointInfo[]","type: string","_name: string","authMap: Record<string, string | null>","interfaces: string[]","schema: StandardSchemaV1","defaultName: string","info: EndpointInfo","str: string","name: string","collectedDefs: Map<string, JsonSchema>","schema: JsonSchema","props: string[]","s: JsonSchema","e: string","pathEntries: string[]","methodEntries: string[]","parts: string[]","params: {\n title: string;\n version: string;\n description?: string;\n securitySchemes: SecuritySchemeInfo[];\n endpointAuth: Record<string, string | null>;\n schemaInterfaces: string;\n pathsInterface: string;\n }"],"sources":["../src/generators/OpenApiTsGenerator.ts"],"sourcesContent":["import type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport {\n StandardSchemaJsonSchema,\n getSchemaMetadata,\n} from '@geekmidas/schema/conversion';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\ninterface OpenApiTsOptions {\n title?: string;\n version?: string;\n description?: string;\n}\n\n// JSON Schema type definition\ninterface JsonSchema {\n type?: string;\n properties?: Record<string, JsonSchema>;\n items?: JsonSchema;\n required?: string[];\n enum?: string[];\n $ref?: string;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n additionalProperties?: boolean | JsonSchema;\n [key: string]: unknown;\n}\n\n// Security scheme type (OpenAPI 3.1)\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\ninterface EndpointInfo {\n endpoint: string;\n route: string;\n method: string;\n authorizerName: string | null;\n /** @deprecated Use securityScheme instead */\n authorizerType: string | null;\n /** The OpenAPI security scheme definition for this endpoint's authorizer */\n securityScheme: SecuritySchemeObject | null;\n input?: {\n body?: StandardSchemaV1;\n query?: StandardSchemaV1;\n params?: StandardSchemaV1;\n };\n output?: StandardSchemaV1;\n description?: string;\n tags?: string[];\n operationId?: string;\n}\n\ninterface SecuritySchemeInfo {\n name: string;\n type: string;\n scheme: SecuritySchemeObject;\n}\n\n/**\n * Generates TypeScript OpenAPI module from endpoints.\n * Outputs:\n * - securitySchemes: typed security scheme definitions\n * - endpointAuth: runtime map of endpoints to auth requirements\n * - paths: TypeScript interface for type-safe fetcher\n * - schema interfaces: reusable TypeScript types from Zod/Valibot schemas\n */\nexport class OpenApiTsGenerator {\n async generate(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n options: OpenApiTsOptions = {},\n ): Promise<string> {\n const { title = 'API', version = '1.0.0', description } = options;\n\n // Extract endpoint info\n const endpointInfos = await this.extractEndpointInfos(endpoints);\n\n // Collect unique security schemes\n const securitySchemes = this.collectSecuritySchemes(endpointInfos);\n\n // Build endpoint auth map\n const endpointAuth = this.buildEndpointAuthMap(endpointInfos);\n\n // Generate schema interfaces\n const schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);\n\n // Generate paths interface\n const pathsInterface = await this.generatePathsInterface(endpointInfos);\n\n // Build the final TypeScript module\n return this.buildModule({\n title,\n version,\n description,\n securitySchemes,\n endpointAuth,\n schemaInterfaces,\n pathsInterface,\n });\n }\n\n private async extractEndpointInfos(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n ): Promise<EndpointInfo[]> {\n return endpoints.map((ep) => {\n const route = ep.route.replace(/:(\\w+)/g, '{$1}');\n const method = ep.method.toUpperCase();\n\n // Get security scheme from authorizer (if available)\n // This is the preferred way - the scheme is stored directly on the authorizer\n const securityScheme = ep.authorizer?.securityScheme as\n | SecuritySchemeObject\n | undefined;\n\n return {\n endpoint: `${method} ${route}`,\n route,\n method,\n authorizerName: ep.authorizer?.name ?? null,\n authorizerType: ep.authorizer?.type ?? null,\n securityScheme: securityScheme ?? null,\n input: ep.input,\n output: ep.outputSchema,\n description: ep.description,\n tags: ep.tags,\n operationId: ep.operationId,\n };\n });\n }\n\n private collectSecuritySchemes(\n endpointInfos: EndpointInfo[],\n ): SecuritySchemeInfo[] {\n const schemes = new Map<string, SecuritySchemeInfo>();\n\n for (const info of endpointInfos) {\n if (info.authorizerName && !schemes.has(info.authorizerName)) {\n // Prefer the stored security scheme (from .securitySchemes() or built-ins)\n // Fall back to inference from authorizerType for backward compatibility\n const scheme =\n info.securityScheme ??\n (info.authorizerType\n ? this.mapAuthorizerToSecurityScheme(\n info.authorizerType,\n info.authorizerName,\n )\n : null);\n\n if (scheme) {\n schemes.set(info.authorizerName, {\n name: info.authorizerName,\n type: scheme.type,\n scheme,\n });\n }\n }\n }\n\n return Array.from(schemes.values());\n }\n\n private mapAuthorizerToSecurityScheme(\n type: string,\n _name: string,\n ): SecuritySchemeObject {\n switch (type.toLowerCase()) {\n case 'jwt':\n case 'bearer':\n return {\n type: 'http',\n scheme: 'bearer',\n bearerFormat: 'JWT',\n };\n case 'iam':\n case 'aws-sigv4':\n case 'sigv4':\n return {\n type: 'apiKey',\n in: 'header',\n name: 'Authorization',\n 'x-amazon-apigateway-authtype': 'awsSigv4',\n };\n case 'apikey':\n case 'api-key':\n return {\n type: 'apiKey',\n in: 'header',\n name: 'X-API-Key',\n };\n case 'oauth2':\n return {\n type: 'oauth2',\n flows: {},\n };\n case 'oidc':\n case 'openidconnect':\n return {\n type: 'openIdConnect',\n openIdConnectUrl: '',\n };\n default:\n return {\n type: 'http',\n scheme: 'bearer',\n };\n }\n }\n\n private buildEndpointAuthMap(\n endpointInfos: EndpointInfo[],\n ): Record<string, string | null> {\n const authMap: Record<string, string | null> = {};\n\n for (const info of endpointInfos) {\n authMap[info.endpoint] = info.authorizerName;\n }\n\n return authMap;\n }\n\n private async generateSchemaInterfaces(\n endpointInfos: EndpointInfo[],\n ): Promise<string> {\n const interfaces: string[] = [];\n const generatedNames = new Set<string>();\n // Collect nested schemas with $defs (from .meta({ id: 'X' }))\n const collectedDefs = new Map<string, JsonSchema>();\n\n for (const info of endpointInfos) {\n const baseName = this.getSchemaBaseName(info);\n\n // Input body schema\n if (info.input?.body) {\n const name = await this.getSchemaName(\n info.input.body,\n `${baseName}Input`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.body,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Input params schema\n if (info.input?.params) {\n const name = await this.getSchemaName(\n info.input.params,\n `${baseName}Params`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.params,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Input query schema\n if (info.input?.query) {\n const name = await this.getSchemaName(\n info.input.query,\n `${baseName}Query`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.query,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Output schema\n if (info.output) {\n const name = await this.getSchemaName(info.output, `${baseName}Output`);\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.output,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n }\n\n // Generate interfaces for collected $defs (nested schemas with .meta({ id: 'X' }))\n for (const [defName, defSchema] of collectedDefs) {\n if (!generatedNames.has(defName)) {\n const interfaceStr = this.jsonSchemaToInterface(defSchema, defName);\n interfaces.push(interfaceStr);\n generatedNames.add(defName);\n }\n }\n\n return interfaces.join('\\n\\n');\n }\n\n /**\n * Get the name for a schema, using metadata `id` if available,\n * otherwise falling back to the provided default name.\n */\n private async getSchemaName(\n schema: StandardSchemaV1,\n defaultName: string,\n ): Promise<string> {\n try {\n const metadata = await getSchemaMetadata(schema);\n if (metadata?.id) {\n return this.pascalCase(metadata.id);\n }\n } catch {\n // Ignore metadata extraction errors\n }\n return defaultName;\n }\n\n private getSchemaBaseName(info: EndpointInfo): string {\n if (info.operationId) {\n return this.pascalCase(info.operationId);\n }\n\n // Generate name from method + route\n const routeParts = info.route\n .replace(/[{}]/g, '')\n .split('/')\n .filter(Boolean)\n .map((part) => this.pascalCase(part));\n\n return `${this.pascalCase(info.method.toLowerCase())}${routeParts.join('')}`;\n }\n\n private pascalCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, c) => c.toUpperCase())\n .replace(/^./, (c) => c.toUpperCase());\n }\n\n /**\n * Convert schema to interface while collecting $defs for nested schemas\n * with .meta({ id: 'X' }).\n */\n private async schemaToInterfaceWithDefs(\n schema: StandardSchemaV1,\n name: string,\n collectedDefs: Map<string, JsonSchema>,\n ): Promise<string | null> {\n try {\n // Get raw JSON schema with $defs intact (don't use convertStandardSchemaToJsonSchema\n // which strips $defs)\n const vendor = schema['~standard']?.vendor;\n if (!vendor || !(vendor in StandardSchemaJsonSchema)) {\n return null;\n }\n\n const toJsonSchema =\n StandardSchemaJsonSchema[\n vendor as keyof typeof StandardSchemaJsonSchema\n ];\n const jsonSchema = await toJsonSchema(schema);\n if (!jsonSchema) return null;\n\n // Extract $defs from the JSON schema (these come from .meta({ id: 'X' }))\n if (jsonSchema.$defs && typeof jsonSchema.$defs === 'object') {\n for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) {\n if (!collectedDefs.has(defName)) {\n // Remove the 'id' field from the schema as it's just metadata\n const { id, ...schemaWithoutId } = defSchema as JsonSchema & {\n id?: string;\n };\n collectedDefs.set(defName, schemaWithoutId as JsonSchema);\n }\n }\n }\n\n // Remove $defs from the schema before converting to interface\n const { $defs, ...schemaWithoutDefs } = jsonSchema;\n return this.jsonSchemaToInterface(schemaWithoutDefs, name);\n } catch {\n return null;\n }\n }\n\n private jsonSchemaToInterface(schema: JsonSchema, name: string): string {\n if (schema.type !== 'object' || !schema.properties) {\n // For non-object types, create a type alias\n const typeStr = this.jsonSchemaTypeToTs(schema);\n return `export type ${name} = ${typeStr};`;\n }\n\n const props: string[] = [];\n const required = new Set(schema.required || []);\n\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n const isRequired = required.has(propName);\n const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n const optionalMark = isRequired ? '' : '?';\n props.push(` ${propName}${optionalMark}: ${typeStr};`);\n }\n\n return `export interface ${name} {\\n${props.join('\\n')}\\n}`;\n }\n\n private jsonSchemaTypeToTs(schema: JsonSchema): string {\n if (!schema) return 'unknown';\n\n if (schema.$ref) {\n // Extract name from $ref\n const refName = schema.$ref.split('/').pop() || 'unknown';\n return refName;\n }\n\n if (schema.anyOf) {\n return schema.anyOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' | ');\n }\n\n if (schema.oneOf) {\n return schema.oneOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' | ');\n }\n\n if (schema.allOf) {\n return schema.allOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' & ');\n }\n\n switch (schema.type) {\n case 'string':\n if (schema.enum) {\n return schema.enum.map((e: string) => `'${e}'`).join(' | ');\n }\n return 'string';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'null':\n return 'null';\n case 'array':\n if (schema.items) {\n return `Array<${this.jsonSchemaTypeToTs(schema.items as JsonSchema)}>`;\n }\n return 'Array<unknown>';\n case 'object':\n if (schema.properties) {\n const props: string[] = [];\n const required = new Set(schema.required || []);\n for (const [propName, propSchema] of Object.entries(\n schema.properties,\n )) {\n const isRequired = required.has(propName);\n const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n const optionalMark = isRequired ? '' : '?';\n props.push(`${propName}${optionalMark}: ${typeStr}`);\n }\n return `{ ${props.join('; ')} }`;\n }\n if (schema.additionalProperties) {\n const valueType = this.jsonSchemaTypeToTs(\n schema.additionalProperties as JsonSchema,\n );\n return `Record<string, ${valueType}>`;\n }\n return 'Record<string, unknown>';\n default:\n return 'unknown';\n }\n }\n\n private async generatePathsInterface(\n endpointInfos: EndpointInfo[],\n ): Promise<string> {\n const pathGroups = new Map<string, EndpointInfo[]>();\n\n // Group endpoints by route\n for (const info of endpointInfos) {\n const existing = pathGroups.get(info.route) || [];\n existing.push(info);\n pathGroups.set(info.route, existing);\n }\n\n const pathEntries: string[] = [];\n\n for (const [route, infos] of pathGroups) {\n const methodEntries: string[] = [];\n\n for (const info of infos) {\n const methodDef = await this.generateMethodDefinition(info);\n methodEntries.push(` ${info.method.toLowerCase()}: ${methodDef};`);\n }\n\n // Add path parameters if present\n const firstWithParams = infos.find((i) => i.input?.params);\n let paramsEntry = '';\n if (firstWithParams?.input?.params) {\n const paramsName = await this.getSchemaName(\n firstWithParams.input.params,\n `${this.getSchemaBaseName(firstWithParams)}Params`,\n );\n paramsEntry = `\\n parameters: {\\n path: ${paramsName};\\n };`;\n }\n\n pathEntries.push(\n ` '${route}': {${paramsEntry}\\n${methodEntries.join('\\n')}\\n };`,\n );\n }\n\n return `export interface paths {\\n${pathEntries.join('\\n')}\\n}`;\n }\n\n private async generateMethodDefinition(info: EndpointInfo): Promise<string> {\n const parts: string[] = [];\n const baseName = this.getSchemaBaseName(info);\n\n // Request body\n if (info.input?.body) {\n const bodyName = await this.getSchemaName(\n info.input.body,\n `${baseName}Input`,\n );\n parts.push(`requestBody: {\n content: {\n 'application/json': ${bodyName};\n };\n }`);\n }\n\n // Query parameters\n if (info.input?.query) {\n const queryName = await this.getSchemaName(\n info.input.query,\n `${baseName}Query`,\n );\n parts.push(`parameters: {\n query: ${queryName};\n }`);\n }\n\n // Responses\n const outputName = info.output\n ? await this.getSchemaName(info.output, `${baseName}Output`)\n : 'unknown';\n parts.push(`responses: {\n 200: {\n content: {\n 'application/json': ${outputName};\n };\n };\n }`);\n\n return `{\\n ${parts.join(';\\n ')};\\n }`;\n }\n\n private buildModule(params: {\n title: string;\n version: string;\n description?: string;\n securitySchemes: SecuritySchemeInfo[];\n endpointAuth: Record<string, string | null>;\n schemaInterfaces: string;\n pathsInterface: string;\n }): string {\n const {\n title,\n version,\n description,\n securitySchemes,\n endpointAuth,\n schemaInterfaces,\n pathsInterface,\n } = params;\n\n const securitySchemesObj = securitySchemes.reduce(\n (acc, s) => {\n acc[s.name] = s.scheme;\n return acc;\n },\n {} as Record<string, SecuritySchemeObject>,\n );\n\n const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(' | ');\n\n // Generate createApi only if there are security schemes\n const hasSecuritySchemes = schemeNames.length > 0;\n\n const createApiSection = hasSecuritySchemes\n ? `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport {\n createAuthAwareFetcher,\n type AuthStrategy,\n} from '@geekmidas/client/auth-fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Auth strategies for each security scheme used in this API */\n authStrategies: Record<SecuritySchemeId, AuthStrategy>;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n /** Optional request interceptor */\n onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;\n}\n\n/**\n * Create a type-safe API client with authentication and React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * },\n * });\n *\n * // Imperative fetch\n * const user = await api('GET /users/{id}', { params: { id: '123' } });\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /users/{id}', { params: { id: '123' } });\n * const mutation = api.useMutation('POST /users');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const fetcher = createAuthAwareFetcher<paths, typeof endpointAuth, typeof securitySchemes>({\n baseURL: options.baseURL,\n endpointAuth,\n securitySchemes,\n authStrategies: options.authStrategies,\n onRequest: options.onRequest,\n });\n\n const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });\n\n return Object.assign(fetcher, hooks);\n}\n`\n : `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport { TypedFetcher, type FetcherOptions } from '@geekmidas/client/fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions extends Omit<FetcherOptions, 'baseURL'> {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n}\n\n/**\n * Create a type-safe API client with React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * });\n *\n * // Imperative fetch\n * const data = await api('GET /health');\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /health');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const { queryClient, ...fetcherOptions } = options;\n const fetcher = new TypedFetcher<paths>(fetcherOptions);\n\n const hooks = createEndpointHooks<paths>(fetcher.request.bind(fetcher), { queryClient });\n\n return Object.assign(fetcher.request.bind(fetcher), hooks);\n}\n`;\n\n return `// Auto-generated by @geekmidas/cli - DO NOT EDIT\n// Generated: ${new Date().toISOString()}\n\n// ============================================================\n// Security Scheme Type\n// ============================================================\n\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\n// ============================================================\n// API Info\n// ============================================================\n\nexport const apiInfo = {\n title: '${title}',\n version: '${version}',${description ? `\\n description: '${description.replace(/'/g, \"\\\\'\")}',` : ''}\n} as const;\n\n// ============================================================\n// Security Schemes\n// ============================================================\n\n/**\n * Available security schemes for this API.\n * Maps authorizer names to OpenAPI security scheme definitions.\n */\nexport const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/\"([a-zA-Z_$][a-zA-Z0-9_$]*)\":/g, '$1:')} as const satisfies Record<string, SecuritySchemeObject>;\n\nexport type SecuritySchemeId = ${schemeNames || 'never'};\n\n// ============================================================\n// Endpoint Authentication Map\n// ============================================================\n\n/**\n * Runtime map of endpoints to their required authentication scheme.\n * \\`null\\` indicates a public endpoint (no auth required).\n */\nexport const endpointAuth = ${JSON.stringify(endpointAuth, null, 2).replace(/\"([^\"]+)\":/g, \"'$1':\")} as const satisfies Record<string, SecuritySchemeId | null>;\n\nexport type EndpointString = keyof typeof endpointAuth;\n\nexport type AuthenticatedEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? never : K;\n}[EndpointString];\n\nexport type PublicEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? K : never;\n}[EndpointString];\n\n// ============================================================\n// Schema Definitions\n// ============================================================\n\n${schemaInterfaces}\n\n// ============================================================\n// OpenAPI Paths\n// ============================================================\n\n${pathsInterface}\n${createApiSection}\n`;\n }\n}\n"],"mappings":"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"}
@@ -451,7 +451,7 @@ export const apiInfo = {
451
451
  * Available security schemes for this API.
452
452
  * Maps authorizer names to OpenAPI security scheme definitions.
453
453
  */
454
- export const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/"([^"]+)":/g, "$1:")} as const satisfies Record<string, SecuritySchemeObject>;
454
+ export const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/"([a-zA-Z_$][a-zA-Z0-9_$]*)":/g, "$1:")} as const satisfies Record<string, SecuritySchemeObject>;
455
455
 
456
456
  export type SecuritySchemeId = ${schemeNames || "never"};
457
457
 
@@ -498,4 +498,4 @@ Object.defineProperty(exports, 'OpenApiTsGenerator', {
498
498
  return OpenApiTsGenerator;
499
499
  }
500
500
  });
501
- //# sourceMappingURL=OpenApiTsGenerator-wLwpaq_I.cjs.map
501
+ //# sourceMappingURL=OpenApiTsGenerator-gPIIyppX.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"OpenApiTsGenerator-wLwpaq_I.cjs","names":["endpoints: Endpoint<any, any, any, any, any, any>[]","options: OpenApiTsOptions","endpointInfos: EndpointInfo[]","type: string","_name: string","authMap: Record<string, string | null>","interfaces: string[]","schema: StandardSchemaV1","defaultName: string","info: EndpointInfo","str: string","name: string","collectedDefs: Map<string, JsonSchema>","StandardSchemaJsonSchema","schema: JsonSchema","props: string[]","s: JsonSchema","e: string","pathEntries: string[]","methodEntries: string[]","parts: string[]","params: {\n title: string;\n version: string;\n description?: string;\n securitySchemes: SecuritySchemeInfo[];\n endpointAuth: Record<string, string | null>;\n schemaInterfaces: string;\n pathsInterface: string;\n }"],"sources":["../src/generators/OpenApiTsGenerator.ts"],"sourcesContent":["import type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport {\n StandardSchemaJsonSchema,\n getSchemaMetadata,\n} from '@geekmidas/schema/conversion';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\ninterface OpenApiTsOptions {\n title?: string;\n version?: string;\n description?: string;\n}\n\n// JSON Schema type definition\ninterface JsonSchema {\n type?: string;\n properties?: Record<string, JsonSchema>;\n items?: JsonSchema;\n required?: string[];\n enum?: string[];\n $ref?: string;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n additionalProperties?: boolean | JsonSchema;\n [key: string]: unknown;\n}\n\n// Security scheme type (OpenAPI 3.1)\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\ninterface EndpointInfo {\n endpoint: string;\n route: string;\n method: string;\n authorizerName: string | null;\n /** @deprecated Use securityScheme instead */\n authorizerType: string | null;\n /** The OpenAPI security scheme definition for this endpoint's authorizer */\n securityScheme: SecuritySchemeObject | null;\n input?: {\n body?: StandardSchemaV1;\n query?: StandardSchemaV1;\n params?: StandardSchemaV1;\n };\n output?: StandardSchemaV1;\n description?: string;\n tags?: string[];\n operationId?: string;\n}\n\ninterface SecuritySchemeInfo {\n name: string;\n type: string;\n scheme: SecuritySchemeObject;\n}\n\n/**\n * Generates TypeScript OpenAPI module from endpoints.\n * Outputs:\n * - securitySchemes: typed security scheme definitions\n * - endpointAuth: runtime map of endpoints to auth requirements\n * - paths: TypeScript interface for type-safe fetcher\n * - schema interfaces: reusable TypeScript types from Zod/Valibot schemas\n */\nexport class OpenApiTsGenerator {\n async generate(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n options: OpenApiTsOptions = {},\n ): Promise<string> {\n const { title = 'API', version = '1.0.0', description } = options;\n\n // Extract endpoint info\n const endpointInfos = await this.extractEndpointInfos(endpoints);\n\n // Collect unique security schemes\n const securitySchemes = this.collectSecuritySchemes(endpointInfos);\n\n // Build endpoint auth map\n const endpointAuth = this.buildEndpointAuthMap(endpointInfos);\n\n // Generate schema interfaces\n const schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);\n\n // Generate paths interface\n const pathsInterface = await this.generatePathsInterface(endpointInfos);\n\n // Build the final TypeScript module\n return this.buildModule({\n title,\n version,\n description,\n securitySchemes,\n endpointAuth,\n schemaInterfaces,\n pathsInterface,\n });\n }\n\n private async extractEndpointInfos(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n ): Promise<EndpointInfo[]> {\n return endpoints.map((ep) => {\n const route = ep.route.replace(/:(\\w+)/g, '{$1}');\n const method = ep.method.toUpperCase();\n\n // Get security scheme from authorizer (if available)\n // This is the preferred way - the scheme is stored directly on the authorizer\n const securityScheme = ep.authorizer?.securityScheme as\n | SecuritySchemeObject\n | undefined;\n\n return {\n endpoint: `${method} ${route}`,\n route,\n method,\n authorizerName: ep.authorizer?.name ?? null,\n authorizerType: ep.authorizer?.type ?? null,\n securityScheme: securityScheme ?? null,\n input: ep.input,\n output: ep.outputSchema,\n description: ep.description,\n tags: ep.tags,\n operationId: ep.operationId,\n };\n });\n }\n\n private collectSecuritySchemes(\n endpointInfos: EndpointInfo[],\n ): SecuritySchemeInfo[] {\n const schemes = new Map<string, SecuritySchemeInfo>();\n\n for (const info of endpointInfos) {\n if (info.authorizerName && !schemes.has(info.authorizerName)) {\n // Prefer the stored security scheme (from .securitySchemes() or built-ins)\n // Fall back to inference from authorizerType for backward compatibility\n const scheme =\n info.securityScheme ??\n (info.authorizerType\n ? this.mapAuthorizerToSecurityScheme(\n info.authorizerType,\n info.authorizerName,\n )\n : null);\n\n if (scheme) {\n schemes.set(info.authorizerName, {\n name: info.authorizerName,\n type: scheme.type,\n scheme,\n });\n }\n }\n }\n\n return Array.from(schemes.values());\n }\n\n private mapAuthorizerToSecurityScheme(\n type: string,\n _name: string,\n ): SecuritySchemeObject {\n switch (type.toLowerCase()) {\n case 'jwt':\n case 'bearer':\n return {\n type: 'http',\n scheme: 'bearer',\n bearerFormat: 'JWT',\n };\n case 'iam':\n case 'aws-sigv4':\n case 'sigv4':\n return {\n type: 'apiKey',\n in: 'header',\n name: 'Authorization',\n 'x-amazon-apigateway-authtype': 'awsSigv4',\n };\n case 'apikey':\n case 'api-key':\n return {\n type: 'apiKey',\n in: 'header',\n name: 'X-API-Key',\n };\n case 'oauth2':\n return {\n type: 'oauth2',\n flows: {},\n };\n case 'oidc':\n case 'openidconnect':\n return {\n type: 'openIdConnect',\n openIdConnectUrl: '',\n };\n default:\n return {\n type: 'http',\n scheme: 'bearer',\n };\n }\n }\n\n private buildEndpointAuthMap(\n endpointInfos: EndpointInfo[],\n ): Record<string, string | null> {\n const authMap: Record<string, string | null> = {};\n\n for (const info of endpointInfos) {\n authMap[info.endpoint] = info.authorizerName;\n }\n\n return authMap;\n }\n\n private async generateSchemaInterfaces(\n endpointInfos: EndpointInfo[],\n ): Promise<string> {\n const interfaces: string[] = [];\n const generatedNames = new Set<string>();\n // Collect nested schemas with $defs (from .meta({ id: 'X' }))\n const collectedDefs = new Map<string, JsonSchema>();\n\n for (const info of endpointInfos) {\n const baseName = this.getSchemaBaseName(info);\n\n // Input body schema\n if (info.input?.body) {\n const name = await this.getSchemaName(\n info.input.body,\n `${baseName}Input`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.body,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Input params schema\n if (info.input?.params) {\n const name = await this.getSchemaName(\n info.input.params,\n `${baseName}Params`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.params,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Input query schema\n if (info.input?.query) {\n const name = await this.getSchemaName(\n info.input.query,\n `${baseName}Query`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.query,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Output schema\n if (info.output) {\n const name = await this.getSchemaName(info.output, `${baseName}Output`);\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.output,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n }\n\n // Generate interfaces for collected $defs (nested schemas with .meta({ id: 'X' }))\n for (const [defName, defSchema] of collectedDefs) {\n if (!generatedNames.has(defName)) {\n const interfaceStr = this.jsonSchemaToInterface(defSchema, defName);\n interfaces.push(interfaceStr);\n generatedNames.add(defName);\n }\n }\n\n return interfaces.join('\\n\\n');\n }\n\n /**\n * Get the name for a schema, using metadata `id` if available,\n * otherwise falling back to the provided default name.\n */\n private async getSchemaName(\n schema: StandardSchemaV1,\n defaultName: string,\n ): Promise<string> {\n try {\n const metadata = await getSchemaMetadata(schema);\n if (metadata?.id) {\n return this.pascalCase(metadata.id);\n }\n } catch {\n // Ignore metadata extraction errors\n }\n return defaultName;\n }\n\n private getSchemaBaseName(info: EndpointInfo): string {\n if (info.operationId) {\n return this.pascalCase(info.operationId);\n }\n\n // Generate name from method + route\n const routeParts = info.route\n .replace(/[{}]/g, '')\n .split('/')\n .filter(Boolean)\n .map((part) => this.pascalCase(part));\n\n return `${this.pascalCase(info.method.toLowerCase())}${routeParts.join('')}`;\n }\n\n private pascalCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, c) => c.toUpperCase())\n .replace(/^./, (c) => c.toUpperCase());\n }\n\n /**\n * Convert schema to interface while collecting $defs for nested schemas\n * with .meta({ id: 'X' }).\n */\n private async schemaToInterfaceWithDefs(\n schema: StandardSchemaV1,\n name: string,\n collectedDefs: Map<string, JsonSchema>,\n ): Promise<string | null> {\n try {\n // Get raw JSON schema with $defs intact (don't use convertStandardSchemaToJsonSchema\n // which strips $defs)\n const vendor = schema['~standard']?.vendor;\n if (!vendor || !(vendor in StandardSchemaJsonSchema)) {\n return null;\n }\n\n const toJsonSchema =\n StandardSchemaJsonSchema[\n vendor as keyof typeof StandardSchemaJsonSchema\n ];\n const jsonSchema = await toJsonSchema(schema);\n if (!jsonSchema) return null;\n\n // Extract $defs from the JSON schema (these come from .meta({ id: 'X' }))\n if (jsonSchema.$defs && typeof jsonSchema.$defs === 'object') {\n for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) {\n if (!collectedDefs.has(defName)) {\n // Remove the 'id' field from the schema as it's just metadata\n const { id, ...schemaWithoutId } = defSchema as JsonSchema & {\n id?: string;\n };\n collectedDefs.set(defName, schemaWithoutId as JsonSchema);\n }\n }\n }\n\n // Remove $defs from the schema before converting to interface\n const { $defs, ...schemaWithoutDefs } = jsonSchema;\n return this.jsonSchemaToInterface(schemaWithoutDefs, name);\n } catch {\n return null;\n }\n }\n\n private jsonSchemaToInterface(schema: JsonSchema, name: string): string {\n if (schema.type !== 'object' || !schema.properties) {\n // For non-object types, create a type alias\n const typeStr = this.jsonSchemaTypeToTs(schema);\n return `export type ${name} = ${typeStr};`;\n }\n\n const props: string[] = [];\n const required = new Set(schema.required || []);\n\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n const isRequired = required.has(propName);\n const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n const optionalMark = isRequired ? '' : '?';\n props.push(` ${propName}${optionalMark}: ${typeStr};`);\n }\n\n return `export interface ${name} {\\n${props.join('\\n')}\\n}`;\n }\n\n private jsonSchemaTypeToTs(schema: JsonSchema): string {\n if (!schema) return 'unknown';\n\n if (schema.$ref) {\n // Extract name from $ref\n const refName = schema.$ref.split('/').pop() || 'unknown';\n return refName;\n }\n\n if (schema.anyOf) {\n return schema.anyOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' | ');\n }\n\n if (schema.oneOf) {\n return schema.oneOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' | ');\n }\n\n if (schema.allOf) {\n return schema.allOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' & ');\n }\n\n switch (schema.type) {\n case 'string':\n if (schema.enum) {\n return schema.enum.map((e: string) => `'${e}'`).join(' | ');\n }\n return 'string';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'null':\n return 'null';\n case 'array':\n if (schema.items) {\n return `Array<${this.jsonSchemaTypeToTs(schema.items as JsonSchema)}>`;\n }\n return 'Array<unknown>';\n case 'object':\n if (schema.properties) {\n const props: string[] = [];\n const required = new Set(schema.required || []);\n for (const [propName, propSchema] of Object.entries(\n schema.properties,\n )) {\n const isRequired = required.has(propName);\n const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n const optionalMark = isRequired ? '' : '?';\n props.push(`${propName}${optionalMark}: ${typeStr}`);\n }\n return `{ ${props.join('; ')} }`;\n }\n if (schema.additionalProperties) {\n const valueType = this.jsonSchemaTypeToTs(\n schema.additionalProperties as JsonSchema,\n );\n return `Record<string, ${valueType}>`;\n }\n return 'Record<string, unknown>';\n default:\n return 'unknown';\n }\n }\n\n private async generatePathsInterface(\n endpointInfos: EndpointInfo[],\n ): Promise<string> {\n const pathGroups = new Map<string, EndpointInfo[]>();\n\n // Group endpoints by route\n for (const info of endpointInfos) {\n const existing = pathGroups.get(info.route) || [];\n existing.push(info);\n pathGroups.set(info.route, existing);\n }\n\n const pathEntries: string[] = [];\n\n for (const [route, infos] of pathGroups) {\n const methodEntries: string[] = [];\n\n for (const info of infos) {\n const methodDef = await this.generateMethodDefinition(info);\n methodEntries.push(` ${info.method.toLowerCase()}: ${methodDef};`);\n }\n\n // Add path parameters if present\n const firstWithParams = infos.find((i) => i.input?.params);\n let paramsEntry = '';\n if (firstWithParams?.input?.params) {\n const paramsName = await this.getSchemaName(\n firstWithParams.input.params,\n `${this.getSchemaBaseName(firstWithParams)}Params`,\n );\n paramsEntry = `\\n parameters: {\\n path: ${paramsName};\\n };`;\n }\n\n pathEntries.push(\n ` '${route}': {${paramsEntry}\\n${methodEntries.join('\\n')}\\n };`,\n );\n }\n\n return `export interface paths {\\n${pathEntries.join('\\n')}\\n}`;\n }\n\n private async generateMethodDefinition(info: EndpointInfo): Promise<string> {\n const parts: string[] = [];\n const baseName = this.getSchemaBaseName(info);\n\n // Request body\n if (info.input?.body) {\n const bodyName = await this.getSchemaName(\n info.input.body,\n `${baseName}Input`,\n );\n parts.push(`requestBody: {\n content: {\n 'application/json': ${bodyName};\n };\n }`);\n }\n\n // Query parameters\n if (info.input?.query) {\n const queryName = await this.getSchemaName(\n info.input.query,\n `${baseName}Query`,\n );\n parts.push(`parameters: {\n query: ${queryName};\n }`);\n }\n\n // Responses\n const outputName = info.output\n ? await this.getSchemaName(info.output, `${baseName}Output`)\n : 'unknown';\n parts.push(`responses: {\n 200: {\n content: {\n 'application/json': ${outputName};\n };\n };\n }`);\n\n return `{\\n ${parts.join(';\\n ')};\\n }`;\n }\n\n private buildModule(params: {\n title: string;\n version: string;\n description?: string;\n securitySchemes: SecuritySchemeInfo[];\n endpointAuth: Record<string, string | null>;\n schemaInterfaces: string;\n pathsInterface: string;\n }): string {\n const {\n title,\n version,\n description,\n securitySchemes,\n endpointAuth,\n schemaInterfaces,\n pathsInterface,\n } = params;\n\n const securitySchemesObj = securitySchemes.reduce(\n (acc, s) => {\n acc[s.name] = s.scheme;\n return acc;\n },\n {} as Record<string, SecuritySchemeObject>,\n );\n\n const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(' | ');\n\n // Generate createApi only if there are security schemes\n const hasSecuritySchemes = schemeNames.length > 0;\n\n const createApiSection = hasSecuritySchemes\n ? `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport {\n createAuthAwareFetcher,\n type AuthStrategy,\n} from '@geekmidas/client/auth-fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Auth strategies for each security scheme used in this API */\n authStrategies: Record<SecuritySchemeId, AuthStrategy>;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n /** Optional request interceptor */\n onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;\n}\n\n/**\n * Create a type-safe API client with authentication and React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * },\n * });\n *\n * // Imperative fetch\n * const user = await api('GET /users/{id}', { params: { id: '123' } });\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /users/{id}', { params: { id: '123' } });\n * const mutation = api.useMutation('POST /users');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const fetcher = createAuthAwareFetcher<paths, typeof endpointAuth, typeof securitySchemes>({\n baseURL: options.baseURL,\n endpointAuth,\n securitySchemes,\n authStrategies: options.authStrategies,\n onRequest: options.onRequest,\n });\n\n const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });\n\n return Object.assign(fetcher, hooks);\n}\n`\n : `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport { TypedFetcher, type FetcherOptions } from '@geekmidas/client/fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions extends Omit<FetcherOptions, 'baseURL'> {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n}\n\n/**\n * Create a type-safe API client with React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * });\n *\n * // Imperative fetch\n * const data = await api('GET /health');\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /health');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const { queryClient, ...fetcherOptions } = options;\n const fetcher = new TypedFetcher<paths>(fetcherOptions);\n\n const hooks = createEndpointHooks<paths>(fetcher.request.bind(fetcher), { queryClient });\n\n return Object.assign(fetcher.request.bind(fetcher), hooks);\n}\n`;\n\n return `// Auto-generated by @geekmidas/cli - DO NOT EDIT\n// Generated: ${new Date().toISOString()}\n\n// ============================================================\n// Security Scheme Type\n// ============================================================\n\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\n// ============================================================\n// API Info\n// ============================================================\n\nexport const apiInfo = {\n title: '${title}',\n version: '${version}',${description ? `\\n description: '${description.replace(/'/g, \"\\\\'\")}',` : ''}\n} as const;\n\n// ============================================================\n// Security Schemes\n// ============================================================\n\n/**\n * Available security schemes for this API.\n * Maps authorizer names to OpenAPI security scheme definitions.\n */\nexport const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/\"([^\"]+)\":/g, '$1:')} as const satisfies Record<string, SecuritySchemeObject>;\n\nexport type SecuritySchemeId = ${schemeNames || 'never'};\n\n// ============================================================\n// Endpoint Authentication Map\n// ============================================================\n\n/**\n * Runtime map of endpoints to their required authentication scheme.\n * \\`null\\` indicates a public endpoint (no auth required).\n */\nexport const endpointAuth = ${JSON.stringify(endpointAuth, null, 2).replace(/\"([^\"]+)\":/g, \"'$1':\")} as const satisfies Record<string, SecuritySchemeId | null>;\n\nexport type EndpointString = keyof typeof endpointAuth;\n\nexport type AuthenticatedEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? never : K;\n}[EndpointString];\n\nexport type PublicEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? K : never;\n}[EndpointString];\n\n// ============================================================\n// Schema Definitions\n// ============================================================\n\n${schemaInterfaces}\n\n// ============================================================\n// OpenAPI Paths\n// ============================================================\n\n${pathsInterface}\n${createApiSection}\n`;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"OpenApiTsGenerator-gPIIyppX.cjs","names":["endpoints: Endpoint<any, any, any, any, any, any>[]","options: OpenApiTsOptions","endpointInfos: EndpointInfo[]","type: string","_name: string","authMap: Record<string, string | null>","interfaces: string[]","schema: StandardSchemaV1","defaultName: string","info: EndpointInfo","str: string","name: string","collectedDefs: Map<string, JsonSchema>","StandardSchemaJsonSchema","schema: JsonSchema","props: string[]","s: JsonSchema","e: string","pathEntries: string[]","methodEntries: string[]","parts: string[]","params: {\n title: string;\n version: string;\n description?: string;\n securitySchemes: SecuritySchemeInfo[];\n endpointAuth: Record<string, string | null>;\n schemaInterfaces: string;\n pathsInterface: string;\n }"],"sources":["../src/generators/OpenApiTsGenerator.ts"],"sourcesContent":["import type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport {\n StandardSchemaJsonSchema,\n getSchemaMetadata,\n} from '@geekmidas/schema/conversion';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\ninterface OpenApiTsOptions {\n title?: string;\n version?: string;\n description?: string;\n}\n\n// JSON Schema type definition\ninterface JsonSchema {\n type?: string;\n properties?: Record<string, JsonSchema>;\n items?: JsonSchema;\n required?: string[];\n enum?: string[];\n $ref?: string;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n additionalProperties?: boolean | JsonSchema;\n [key: string]: unknown;\n}\n\n// Security scheme type (OpenAPI 3.1)\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\ninterface EndpointInfo {\n endpoint: string;\n route: string;\n method: string;\n authorizerName: string | null;\n /** @deprecated Use securityScheme instead */\n authorizerType: string | null;\n /** The OpenAPI security scheme definition for this endpoint's authorizer */\n securityScheme: SecuritySchemeObject | null;\n input?: {\n body?: StandardSchemaV1;\n query?: StandardSchemaV1;\n params?: StandardSchemaV1;\n };\n output?: StandardSchemaV1;\n description?: string;\n tags?: string[];\n operationId?: string;\n}\n\ninterface SecuritySchemeInfo {\n name: string;\n type: string;\n scheme: SecuritySchemeObject;\n}\n\n/**\n * Generates TypeScript OpenAPI module from endpoints.\n * Outputs:\n * - securitySchemes: typed security scheme definitions\n * - endpointAuth: runtime map of endpoints to auth requirements\n * - paths: TypeScript interface for type-safe fetcher\n * - schema interfaces: reusable TypeScript types from Zod/Valibot schemas\n */\nexport class OpenApiTsGenerator {\n async generate(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n options: OpenApiTsOptions = {},\n ): Promise<string> {\n const { title = 'API', version = '1.0.0', description } = options;\n\n // Extract endpoint info\n const endpointInfos = await this.extractEndpointInfos(endpoints);\n\n // Collect unique security schemes\n const securitySchemes = this.collectSecuritySchemes(endpointInfos);\n\n // Build endpoint auth map\n const endpointAuth = this.buildEndpointAuthMap(endpointInfos);\n\n // Generate schema interfaces\n const schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);\n\n // Generate paths interface\n const pathsInterface = await this.generatePathsInterface(endpointInfos);\n\n // Build the final TypeScript module\n return this.buildModule({\n title,\n version,\n description,\n securitySchemes,\n endpointAuth,\n schemaInterfaces,\n pathsInterface,\n });\n }\n\n private async extractEndpointInfos(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n ): Promise<EndpointInfo[]> {\n return endpoints.map((ep) => {\n const route = ep.route.replace(/:(\\w+)/g, '{$1}');\n const method = ep.method.toUpperCase();\n\n // Get security scheme from authorizer (if available)\n // This is the preferred way - the scheme is stored directly on the authorizer\n const securityScheme = ep.authorizer?.securityScheme as\n | SecuritySchemeObject\n | undefined;\n\n return {\n endpoint: `${method} ${route}`,\n route,\n method,\n authorizerName: ep.authorizer?.name ?? null,\n authorizerType: ep.authorizer?.type ?? null,\n securityScheme: securityScheme ?? null,\n input: ep.input,\n output: ep.outputSchema,\n description: ep.description,\n tags: ep.tags,\n operationId: ep.operationId,\n };\n });\n }\n\n private collectSecuritySchemes(\n endpointInfos: EndpointInfo[],\n ): SecuritySchemeInfo[] {\n const schemes = new Map<string, SecuritySchemeInfo>();\n\n for (const info of endpointInfos) {\n if (info.authorizerName && !schemes.has(info.authorizerName)) {\n // Prefer the stored security scheme (from .securitySchemes() or built-ins)\n // Fall back to inference from authorizerType for backward compatibility\n const scheme =\n info.securityScheme ??\n (info.authorizerType\n ? this.mapAuthorizerToSecurityScheme(\n info.authorizerType,\n info.authorizerName,\n )\n : null);\n\n if (scheme) {\n schemes.set(info.authorizerName, {\n name: info.authorizerName,\n type: scheme.type,\n scheme,\n });\n }\n }\n }\n\n return Array.from(schemes.values());\n }\n\n private mapAuthorizerToSecurityScheme(\n type: string,\n _name: string,\n ): SecuritySchemeObject {\n switch (type.toLowerCase()) {\n case 'jwt':\n case 'bearer':\n return {\n type: 'http',\n scheme: 'bearer',\n bearerFormat: 'JWT',\n };\n case 'iam':\n case 'aws-sigv4':\n case 'sigv4':\n return {\n type: 'apiKey',\n in: 'header',\n name: 'Authorization',\n 'x-amazon-apigateway-authtype': 'awsSigv4',\n };\n case 'apikey':\n case 'api-key':\n return {\n type: 'apiKey',\n in: 'header',\n name: 'X-API-Key',\n };\n case 'oauth2':\n return {\n type: 'oauth2',\n flows: {},\n };\n case 'oidc':\n case 'openidconnect':\n return {\n type: 'openIdConnect',\n openIdConnectUrl: '',\n };\n default:\n return {\n type: 'http',\n scheme: 'bearer',\n };\n }\n }\n\n private buildEndpointAuthMap(\n endpointInfos: EndpointInfo[],\n ): Record<string, string | null> {\n const authMap: Record<string, string | null> = {};\n\n for (const info of endpointInfos) {\n authMap[info.endpoint] = info.authorizerName;\n }\n\n return authMap;\n }\n\n private async generateSchemaInterfaces(\n endpointInfos: EndpointInfo[],\n ): Promise<string> {\n const interfaces: string[] = [];\n const generatedNames = new Set<string>();\n // Collect nested schemas with $defs (from .meta({ id: 'X' }))\n const collectedDefs = new Map<string, JsonSchema>();\n\n for (const info of endpointInfos) {\n const baseName = this.getSchemaBaseName(info);\n\n // Input body schema\n if (info.input?.body) {\n const name = await this.getSchemaName(\n info.input.body,\n `${baseName}Input`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.body,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Input params schema\n if (info.input?.params) {\n const name = await this.getSchemaName(\n info.input.params,\n `${baseName}Params`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.params,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Input query schema\n if (info.input?.query) {\n const name = await this.getSchemaName(\n info.input.query,\n `${baseName}Query`,\n );\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.input.query,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n\n // Output schema\n if (info.output) {\n const name = await this.getSchemaName(info.output, `${baseName}Output`);\n if (!generatedNames.has(name)) {\n const schema = await this.schemaToInterfaceWithDefs(\n info.output,\n name,\n collectedDefs,\n );\n if (schema) {\n interfaces.push(schema);\n generatedNames.add(name);\n }\n }\n }\n }\n\n // Generate interfaces for collected $defs (nested schemas with .meta({ id: 'X' }))\n for (const [defName, defSchema] of collectedDefs) {\n if (!generatedNames.has(defName)) {\n const interfaceStr = this.jsonSchemaToInterface(defSchema, defName);\n interfaces.push(interfaceStr);\n generatedNames.add(defName);\n }\n }\n\n return interfaces.join('\\n\\n');\n }\n\n /**\n * Get the name for a schema, using metadata `id` if available,\n * otherwise falling back to the provided default name.\n */\n private async getSchemaName(\n schema: StandardSchemaV1,\n defaultName: string,\n ): Promise<string> {\n try {\n const metadata = await getSchemaMetadata(schema);\n if (metadata?.id) {\n return this.pascalCase(metadata.id);\n }\n } catch {\n // Ignore metadata extraction errors\n }\n return defaultName;\n }\n\n private getSchemaBaseName(info: EndpointInfo): string {\n if (info.operationId) {\n return this.pascalCase(info.operationId);\n }\n\n // Generate name from method + route\n const routeParts = info.route\n .replace(/[{}]/g, '')\n .split('/')\n .filter(Boolean)\n .map((part) => this.pascalCase(part));\n\n return `${this.pascalCase(info.method.toLowerCase())}${routeParts.join('')}`;\n }\n\n private pascalCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, c) => c.toUpperCase())\n .replace(/^./, (c) => c.toUpperCase());\n }\n\n /**\n * Convert schema to interface while collecting $defs for nested schemas\n * with .meta({ id: 'X' }).\n */\n private async schemaToInterfaceWithDefs(\n schema: StandardSchemaV1,\n name: string,\n collectedDefs: Map<string, JsonSchema>,\n ): Promise<string | null> {\n try {\n // Get raw JSON schema with $defs intact (don't use convertStandardSchemaToJsonSchema\n // which strips $defs)\n const vendor = schema['~standard']?.vendor;\n if (!vendor || !(vendor in StandardSchemaJsonSchema)) {\n return null;\n }\n\n const toJsonSchema =\n StandardSchemaJsonSchema[\n vendor as keyof typeof StandardSchemaJsonSchema\n ];\n const jsonSchema = await toJsonSchema(schema);\n if (!jsonSchema) return null;\n\n // Extract $defs from the JSON schema (these come from .meta({ id: 'X' }))\n if (jsonSchema.$defs && typeof jsonSchema.$defs === 'object') {\n for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) {\n if (!collectedDefs.has(defName)) {\n // Remove the 'id' field from the schema as it's just metadata\n const { id, ...schemaWithoutId } = defSchema as JsonSchema & {\n id?: string;\n };\n collectedDefs.set(defName, schemaWithoutId as JsonSchema);\n }\n }\n }\n\n // Remove $defs from the schema before converting to interface\n const { $defs, ...schemaWithoutDefs } = jsonSchema;\n return this.jsonSchemaToInterface(schemaWithoutDefs, name);\n } catch {\n return null;\n }\n }\n\n private jsonSchemaToInterface(schema: JsonSchema, name: string): string {\n if (schema.type !== 'object' || !schema.properties) {\n // For non-object types, create a type alias\n const typeStr = this.jsonSchemaTypeToTs(schema);\n return `export type ${name} = ${typeStr};`;\n }\n\n const props: string[] = [];\n const required = new Set(schema.required || []);\n\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n const isRequired = required.has(propName);\n const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n const optionalMark = isRequired ? '' : '?';\n props.push(` ${propName}${optionalMark}: ${typeStr};`);\n }\n\n return `export interface ${name} {\\n${props.join('\\n')}\\n}`;\n }\n\n private jsonSchemaTypeToTs(schema: JsonSchema): string {\n if (!schema) return 'unknown';\n\n if (schema.$ref) {\n // Extract name from $ref\n const refName = schema.$ref.split('/').pop() || 'unknown';\n return refName;\n }\n\n if (schema.anyOf) {\n return schema.anyOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' | ');\n }\n\n if (schema.oneOf) {\n return schema.oneOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' | ');\n }\n\n if (schema.allOf) {\n return schema.allOf\n .map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n .join(' & ');\n }\n\n switch (schema.type) {\n case 'string':\n if (schema.enum) {\n return schema.enum.map((e: string) => `'${e}'`).join(' | ');\n }\n return 'string';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'null':\n return 'null';\n case 'array':\n if (schema.items) {\n return `Array<${this.jsonSchemaTypeToTs(schema.items as JsonSchema)}>`;\n }\n return 'Array<unknown>';\n case 'object':\n if (schema.properties) {\n const props: string[] = [];\n const required = new Set(schema.required || []);\n for (const [propName, propSchema] of Object.entries(\n schema.properties,\n )) {\n const isRequired = required.has(propName);\n const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n const optionalMark = isRequired ? '' : '?';\n props.push(`${propName}${optionalMark}: ${typeStr}`);\n }\n return `{ ${props.join('; ')} }`;\n }\n if (schema.additionalProperties) {\n const valueType = this.jsonSchemaTypeToTs(\n schema.additionalProperties as JsonSchema,\n );\n return `Record<string, ${valueType}>`;\n }\n return 'Record<string, unknown>';\n default:\n return 'unknown';\n }\n }\n\n private async generatePathsInterface(\n endpointInfos: EndpointInfo[],\n ): Promise<string> {\n const pathGroups = new Map<string, EndpointInfo[]>();\n\n // Group endpoints by route\n for (const info of endpointInfos) {\n const existing = pathGroups.get(info.route) || [];\n existing.push(info);\n pathGroups.set(info.route, existing);\n }\n\n const pathEntries: string[] = [];\n\n for (const [route, infos] of pathGroups) {\n const methodEntries: string[] = [];\n\n for (const info of infos) {\n const methodDef = await this.generateMethodDefinition(info);\n methodEntries.push(` ${info.method.toLowerCase()}: ${methodDef};`);\n }\n\n // Add path parameters if present\n const firstWithParams = infos.find((i) => i.input?.params);\n let paramsEntry = '';\n if (firstWithParams?.input?.params) {\n const paramsName = await this.getSchemaName(\n firstWithParams.input.params,\n `${this.getSchemaBaseName(firstWithParams)}Params`,\n );\n paramsEntry = `\\n parameters: {\\n path: ${paramsName};\\n };`;\n }\n\n pathEntries.push(\n ` '${route}': {${paramsEntry}\\n${methodEntries.join('\\n')}\\n };`,\n );\n }\n\n return `export interface paths {\\n${pathEntries.join('\\n')}\\n}`;\n }\n\n private async generateMethodDefinition(info: EndpointInfo): Promise<string> {\n const parts: string[] = [];\n const baseName = this.getSchemaBaseName(info);\n\n // Request body\n if (info.input?.body) {\n const bodyName = await this.getSchemaName(\n info.input.body,\n `${baseName}Input`,\n );\n parts.push(`requestBody: {\n content: {\n 'application/json': ${bodyName};\n };\n }`);\n }\n\n // Query parameters\n if (info.input?.query) {\n const queryName = await this.getSchemaName(\n info.input.query,\n `${baseName}Query`,\n );\n parts.push(`parameters: {\n query: ${queryName};\n }`);\n }\n\n // Responses\n const outputName = info.output\n ? await this.getSchemaName(info.output, `${baseName}Output`)\n : 'unknown';\n parts.push(`responses: {\n 200: {\n content: {\n 'application/json': ${outputName};\n };\n };\n }`);\n\n return `{\\n ${parts.join(';\\n ')};\\n }`;\n }\n\n private buildModule(params: {\n title: string;\n version: string;\n description?: string;\n securitySchemes: SecuritySchemeInfo[];\n endpointAuth: Record<string, string | null>;\n schemaInterfaces: string;\n pathsInterface: string;\n }): string {\n const {\n title,\n version,\n description,\n securitySchemes,\n endpointAuth,\n schemaInterfaces,\n pathsInterface,\n } = params;\n\n const securitySchemesObj = securitySchemes.reduce(\n (acc, s) => {\n acc[s.name] = s.scheme;\n return acc;\n },\n {} as Record<string, SecuritySchemeObject>,\n );\n\n const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(' | ');\n\n // Generate createApi only if there are security schemes\n const hasSecuritySchemes = schemeNames.length > 0;\n\n const createApiSection = hasSecuritySchemes\n ? `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport {\n createAuthAwareFetcher,\n type AuthStrategy,\n} from '@geekmidas/client/auth-fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Auth strategies for each security scheme used in this API */\n authStrategies: Record<SecuritySchemeId, AuthStrategy>;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n /** Optional request interceptor */\n onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;\n}\n\n/**\n * Create a type-safe API client with authentication and React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * },\n * });\n *\n * // Imperative fetch\n * const user = await api('GET /users/{id}', { params: { id: '123' } });\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /users/{id}', { params: { id: '123' } });\n * const mutation = api.useMutation('POST /users');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const fetcher = createAuthAwareFetcher<paths, typeof endpointAuth, typeof securitySchemes>({\n baseURL: options.baseURL,\n endpointAuth,\n securitySchemes,\n authStrategies: options.authStrategies,\n onRequest: options.onRequest,\n });\n\n const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });\n\n return Object.assign(fetcher, hooks);\n}\n`\n : `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport { TypedFetcher, type FetcherOptions } from '@geekmidas/client/fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions extends Omit<FetcherOptions, 'baseURL'> {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n}\n\n/**\n * Create a type-safe API client with React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * });\n *\n * // Imperative fetch\n * const data = await api('GET /health');\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /health');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const { queryClient, ...fetcherOptions } = options;\n const fetcher = new TypedFetcher<paths>(fetcherOptions);\n\n const hooks = createEndpointHooks<paths>(fetcher.request.bind(fetcher), { queryClient });\n\n return Object.assign(fetcher.request.bind(fetcher), hooks);\n}\n`;\n\n return `// Auto-generated by @geekmidas/cli - DO NOT EDIT\n// Generated: ${new Date().toISOString()}\n\n// ============================================================\n// Security Scheme Type\n// ============================================================\n\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\n// ============================================================\n// API Info\n// ============================================================\n\nexport const apiInfo = {\n title: '${title}',\n version: '${version}',${description ? `\\n description: '${description.replace(/'/g, \"\\\\'\")}',` : ''}\n} as const;\n\n// ============================================================\n// Security Schemes\n// ============================================================\n\n/**\n * Available security schemes for this API.\n * Maps authorizer names to OpenAPI security scheme definitions.\n */\nexport const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/\"([a-zA-Z_$][a-zA-Z0-9_$]*)\":/g, '$1:')} as const satisfies Record<string, SecuritySchemeObject>;\n\nexport type SecuritySchemeId = ${schemeNames || 'never'};\n\n// ============================================================\n// Endpoint Authentication Map\n// ============================================================\n\n/**\n * Runtime map of endpoints to their required authentication scheme.\n * \\`null\\` indicates a public endpoint (no auth required).\n */\nexport const endpointAuth = ${JSON.stringify(endpointAuth, null, 2).replace(/\"([^\"]+)\":/g, \"'$1':\")} as const satisfies Record<string, SecuritySchemeId | null>;\n\nexport type EndpointString = keyof typeof endpointAuth;\n\nexport type AuthenticatedEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? never : K;\n}[EndpointString];\n\nexport type PublicEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? K : never;\n}[EndpointString];\n\n// ============================================================\n// Schema Definitions\n// ============================================================\n\n${schemaInterfaces}\n\n// ============================================================\n// OpenAPI Paths\n// ============================================================\n\n${pathsInterface}\n${createApiSection}\n`;\n }\n}\n"],"mappings":"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"}
@@ -6,10 +6,10 @@ require('../EndpointGenerator-npWEDoK2.cjs');
6
6
  require('../FunctionGenerator-DYTnyr4c.cjs');
7
7
  require('../SubscriberGenerator-D_zpNGFr.cjs');
8
8
  require('../generators-3IemvCLk.cjs');
9
- require('../OpenApiTsGenerator-wLwpaq_I.cjs');
10
- require('../openapi-CTae4ybf.cjs');
11
- require('../dev-Dcrb_ZSL.cjs');
9
+ require('../OpenApiTsGenerator-gPIIyppX.cjs');
10
+ require('../openapi-DZH6RQHk.cjs');
11
+ require('../dev-C2lCgE53.cjs');
12
12
  require('../manifests-D13Ej8AE.cjs');
13
- const require_build = require('../build-Z3yGHcy2.cjs');
13
+ const require_build = require('../build-wmt8ZcmA.cjs');
14
14
 
15
15
  exports.buildCommand = require_build.buildCommand;
@@ -6,10 +6,10 @@ import "../EndpointGenerator-DGivkPLT.mjs";
6
6
  import "../FunctionGenerator-CVk0h8tO.mjs";
7
7
  import "../SubscriberGenerator-DABaJXML.mjs";
8
8
  import "../generators-FNpdfN6J.mjs";
9
- import "../OpenApiTsGenerator-0ZDYWro5.mjs";
10
- import "../openapi-Dn9MeKg3.mjs";
11
- import "../dev-BimlVcuk.mjs";
9
+ import "../OpenApiTsGenerator-BVS4pOH7.mjs";
10
+ import "../openapi-DA9RkPJl.mjs";
11
+ import "../dev-BBPWSllq.mjs";
12
12
  import "../manifests-BNKG6AXf.mjs";
13
- import { buildCommand } from "../build-BLriHKgm.mjs";
13
+ import { buildCommand } from "../build-Cu6Mi0Lf.mjs";
14
14
 
15
15
  export { buildCommand };
@@ -4,7 +4,7 @@ import { CronGenerator } from "./CronGenerator-CCRYptuT.mjs";
4
4
  import { EndpointGenerator } from "./EndpointGenerator-DGivkPLT.mjs";
5
5
  import { FunctionGenerator } from "./FunctionGenerator-CVk0h8tO.mjs";
6
6
  import { SubscriberGenerator } from "./SubscriberGenerator-DABaJXML.mjs";
7
- import { normalizeTelescopeConfig } from "./dev-BimlVcuk.mjs";
7
+ import { normalizeTelescopeConfig } from "./dev-BBPWSllq.mjs";
8
8
  import { generateAwsManifest, generateServerManifest } from "./manifests-BNKG6AXf.mjs";
9
9
  import { mkdir } from "node:fs/promises";
10
10
  import { join, relative } from "node:path";
@@ -84,4 +84,4 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
84
84
 
85
85
  //#endregion
86
86
  export { buildCommand };
87
- //# sourceMappingURL=build-BLriHKgm.mjs.map
87
+ //# sourceMappingURL=build-Cu6Mi0Lf.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-BLriHKgm.mjs","names":["options: BuildOptions","buildContext: BuildContext","provider: LegacyProvider","context: BuildContext","rootOutputDir: string","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean","routeMetadata: RouteInfo[]","appInfo: ServerAppInfo"],"sources":["../src/build/index.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig, parseModuleConfig } from '../config';\nimport { normalizeTelescopeConfig } from '../dev';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n type GeneratedConstruct,\n SubscriberGenerator,\n} from '../generators';\nimport type { BuildOptions, LegacyProvider, RouteInfo } from '../types';\nimport {\n type ServerAppInfo,\n generateAwsManifest,\n generateServerManifest,\n} from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const config = await loadConfig();\n\n // Resolve providers from new config format\n const resolved = resolveProviders(config, options);\n\n logger.log(`Building with providers: ${resolved.providers.join(', ')}`);\n logger.log(`Loading routes from: ${config.routes}`);\n if (config.functions) {\n logger.log(`Loading functions from: ${config.functions}`);\n }\n if (config.crons) {\n logger.log(`Loading crons from: ${config.crons}`);\n }\n if (config.subscribers) {\n logger.log(`Loading subscribers from: ${config.subscribers}`);\n }\n logger.log(`Using envParser: ${config.envParser}`);\n\n // Parse envParser and logger configuration\n const { path: envParserPath, importPattern: envParserImportPattern } =\n parseModuleConfig(config.envParser, 'envParser');\n const { path: loggerPath, importPattern: loggerImportPattern } =\n parseModuleConfig(config.logger, 'logger');\n\n // Normalize telescope configuration\n const telescope = normalizeTelescopeConfig(config.telescope);\n if (telescope) {\n logger.log(`🔭 Telescope enabled at ${telescope.path}`);\n }\n\n const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n telescope,\n };\n\n // Initialize generators\n const endpointGenerator = new EndpointGenerator();\n const functionGenerator = new FunctionGenerator();\n const cronGenerator = new CronGenerator();\n const subscriberGenerator = new SubscriberGenerator();\n\n // Load all constructs in parallel\n const [allEndpoints, allFunctions, allCrons, allSubscribers] =\n await Promise.all([\n endpointGenerator.load(config.routes),\n config.functions ? functionGenerator.load(config.functions) : [],\n config.crons ? cronGenerator.load(config.crons) : [],\n config.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n ]);\n\n logger.log(`Found ${allEndpoints.length} endpoints`);\n logger.log(`Found ${allFunctions.length} functions`);\n logger.log(`Found ${allCrons.length} crons`);\n logger.log(`Found ${allSubscribers.length} subscribers`);\n\n if (\n allEndpoints.length === 0 &&\n allFunctions.length === 0 &&\n allCrons.length === 0 &&\n allSubscribers.length === 0\n ) {\n logger.log(\n 'No endpoints, functions, crons, or subscribers found to process',\n );\n return;\n }\n\n // Ensure .gkm directory exists\n const rootOutputDir = join(process.cwd(), '.gkm');\n await mkdir(rootOutputDir, { recursive: true });\n\n // Build for each provider and generate per-provider manifests\n for (const provider of resolved.providers) {\n await buildForProvider(\n provider,\n buildContext,\n rootOutputDir,\n endpointGenerator,\n functionGenerator,\n cronGenerator,\n subscriberGenerator,\n allEndpoints,\n allFunctions,\n allCrons,\n allSubscribers,\n resolved.enableOpenApi,\n );\n }\n}\n\nasync function buildForProvider(\n provider: LegacyProvider,\n context: BuildContext,\n rootOutputDir: string,\n endpointGenerator: EndpointGenerator,\n functionGenerator: FunctionGenerator,\n cronGenerator: CronGenerator,\n subscriberGenerator: SubscriberGenerator,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n functions: GeneratedConstruct<Function<any, any, any, any>>[],\n crons: GeneratedConstruct<Cron<any, any, any, any>>[],\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n enableOpenApi: boolean,\n): Promise<void> {\n const outputDir = join(process.cwd(), '.gkm', provider);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n logger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n // Build all constructs in parallel\n const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n [\n endpointGenerator.build(context, endpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, functions, outputDir, { provider }),\n cronGenerator.build(context, crons, outputDir, { provider }),\n subscriberGenerator.build(context, subscribers, outputDir, { provider }),\n ],\n );\n\n logger.log(\n `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n );\n\n // Generate provider-specific manifest\n if (provider === 'server') {\n // For server, collect actual route metadata from endpoint constructs\n const routeMetadata: RouteInfo[] = await Promise.all(\n endpoints.map(async ({ construct }) => ({\n path: construct._path,\n method: construct.method,\n handler: '', // Not needed for server manifest\n authorizer: construct.authorizer?.name ?? 'none',\n })),\n );\n\n const appInfo: ServerAppInfo = {\n handler: relative(process.cwd(), join(outputDir, 'app.ts')),\n endpoints: relative(process.cwd(), join(outputDir, 'endpoints.ts')),\n };\n\n await generateServerManifest(\n rootOutputDir,\n appInfo,\n routeMetadata,\n subscriberInfos,\n );\n } else {\n // For AWS providers, generate AWS manifest\n await generateAwsManifest(\n rootOutputDir,\n routes,\n functionInfos,\n cronInfos,\n subscriberInfos,\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"build-Cu6Mi0Lf.mjs","names":["options: BuildOptions","buildContext: BuildContext","provider: LegacyProvider","context: BuildContext","rootOutputDir: string","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean","routeMetadata: RouteInfo[]","appInfo: ServerAppInfo"],"sources":["../src/build/index.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig, parseModuleConfig } from '../config';\nimport { normalizeTelescopeConfig } from '../dev';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n type GeneratedConstruct,\n SubscriberGenerator,\n} from '../generators';\nimport type { BuildOptions, LegacyProvider, RouteInfo } from '../types';\nimport {\n type ServerAppInfo,\n generateAwsManifest,\n generateServerManifest,\n} from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const config = await loadConfig();\n\n // Resolve providers from new config format\n const resolved = resolveProviders(config, options);\n\n logger.log(`Building with providers: ${resolved.providers.join(', ')}`);\n logger.log(`Loading routes from: ${config.routes}`);\n if (config.functions) {\n logger.log(`Loading functions from: ${config.functions}`);\n }\n if (config.crons) {\n logger.log(`Loading crons from: ${config.crons}`);\n }\n if (config.subscribers) {\n logger.log(`Loading subscribers from: ${config.subscribers}`);\n }\n logger.log(`Using envParser: ${config.envParser}`);\n\n // Parse envParser and logger configuration\n const { path: envParserPath, importPattern: envParserImportPattern } =\n parseModuleConfig(config.envParser, 'envParser');\n const { path: loggerPath, importPattern: loggerImportPattern } =\n parseModuleConfig(config.logger, 'logger');\n\n // Normalize telescope configuration\n const telescope = normalizeTelescopeConfig(config.telescope);\n if (telescope) {\n logger.log(`🔭 Telescope enabled at ${telescope.path}`);\n }\n\n const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n telescope,\n };\n\n // Initialize generators\n const endpointGenerator = new EndpointGenerator();\n const functionGenerator = new FunctionGenerator();\n const cronGenerator = new CronGenerator();\n const subscriberGenerator = new SubscriberGenerator();\n\n // Load all constructs in parallel\n const [allEndpoints, allFunctions, allCrons, allSubscribers] =\n await Promise.all([\n endpointGenerator.load(config.routes),\n config.functions ? functionGenerator.load(config.functions) : [],\n config.crons ? cronGenerator.load(config.crons) : [],\n config.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n ]);\n\n logger.log(`Found ${allEndpoints.length} endpoints`);\n logger.log(`Found ${allFunctions.length} functions`);\n logger.log(`Found ${allCrons.length} crons`);\n logger.log(`Found ${allSubscribers.length} subscribers`);\n\n if (\n allEndpoints.length === 0 &&\n allFunctions.length === 0 &&\n allCrons.length === 0 &&\n allSubscribers.length === 0\n ) {\n logger.log(\n 'No endpoints, functions, crons, or subscribers found to process',\n );\n return;\n }\n\n // Ensure .gkm directory exists\n const rootOutputDir = join(process.cwd(), '.gkm');\n await mkdir(rootOutputDir, { recursive: true });\n\n // Build for each provider and generate per-provider manifests\n for (const provider of resolved.providers) {\n await buildForProvider(\n provider,\n buildContext,\n rootOutputDir,\n endpointGenerator,\n functionGenerator,\n cronGenerator,\n subscriberGenerator,\n allEndpoints,\n allFunctions,\n allCrons,\n allSubscribers,\n resolved.enableOpenApi,\n );\n }\n}\n\nasync function buildForProvider(\n provider: LegacyProvider,\n context: BuildContext,\n rootOutputDir: string,\n endpointGenerator: EndpointGenerator,\n functionGenerator: FunctionGenerator,\n cronGenerator: CronGenerator,\n subscriberGenerator: SubscriberGenerator,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n functions: GeneratedConstruct<Function<any, any, any, any>>[],\n crons: GeneratedConstruct<Cron<any, any, any, any>>[],\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n enableOpenApi: boolean,\n): Promise<void> {\n const outputDir = join(process.cwd(), '.gkm', provider);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n logger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n // Build all constructs in parallel\n const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n [\n endpointGenerator.build(context, endpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, functions, outputDir, { provider }),\n cronGenerator.build(context, crons, outputDir, { provider }),\n subscriberGenerator.build(context, subscribers, outputDir, { provider }),\n ],\n );\n\n logger.log(\n `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n );\n\n // Generate provider-specific manifest\n if (provider === 'server') {\n // For server, collect actual route metadata from endpoint constructs\n const routeMetadata: RouteInfo[] = await Promise.all(\n endpoints.map(async ({ construct }) => ({\n path: construct._path,\n method: construct.method,\n handler: '', // Not needed for server manifest\n authorizer: construct.authorizer?.name ?? 'none',\n })),\n );\n\n const appInfo: ServerAppInfo = {\n handler: relative(process.cwd(), join(outputDir, 'app.ts')),\n endpoints: relative(process.cwd(), join(outputDir, 'endpoints.ts')),\n };\n\n await generateServerManifest(\n rootOutputDir,\n appInfo,\n routeMetadata,\n subscriberInfos,\n );\n } else {\n // For AWS providers, generate AWS manifest\n await generateAwsManifest(\n rootOutputDir,\n routes,\n functionInfos,\n cronInfos,\n subscriberInfos,\n );\n }\n}\n"],"mappings":"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"}