@blimu/codegen 0.1.0 → 0.1.1

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config/config.schema.ts","../src/config/config.service.ts","../src/config/mjs-config-loader.ts","../src/config/config.module.ts","../src/config/config-helper.ts","../src/ir/ir.types.ts","../src/generator/generator.service.ts","../src/generator/ir-builder.service.ts","../src/generator/schema-converter.service.ts","../src/openapi/openapi-version.utils.ts","../src/openapi/openapi.types.ts","../src/utils/string.utils.ts","../src/openapi/openapi.service.ts","../src/generator/generator.module.ts","../src/openapi/openapi.module.ts","../src/generator/typescript/typescript-generator.service.ts","../src/generator/handlebars-helpers.ts","../src/generator/typescript/zod-schema-converter.ts","../src/generator/typescript/helpers.ts","../src/api/generate.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Type definition for operationId parser function.\n * Transforms operationId, method, and path into a method name.\n * Can be synchronous or asynchronous.\n */\nexport type OperationIdParser = (\n operationId: string,\n method: string,\n path: string\n) => string | Promise<string>;\n\nexport const TypeAugmentationOptionsSchema = z.object({\n // ModuleName is the module name to augment (e.g., \"@blimu/backend\")\n moduleName: z.string().optional(),\n // Namespace is the namespace within the module to augment (e.g., \"Schema\")\n namespace: z.string().optional(),\n // TypeNames is a list of type names to include. If empty, all enum types are included.\n typeNames: z.array(z.string()).optional(),\n // OutputFileName is the name of the output file (defaults to packageName + \".d.ts\")\n outputFileName: z.string().optional(),\n});\n\n/**\n * Valid template names for TypeScript generator\n */\nexport const TYPESCRIPT_TEMPLATE_NAMES = [\n \"client.ts.hbs\",\n \"index.ts.hbs\",\n \"package.json.hbs\",\n \"README.md.hbs\",\n \"schema.ts.hbs\",\n \"schema.zod.ts.hbs\",\n \"service.ts.hbs\",\n \"tsconfig.json.hbs\",\n \"utils.ts.hbs\",\n] as const;\n\nexport type TypeScriptTemplateName = (typeof TYPESCRIPT_TEMPLATE_NAMES)[number];\n\n/**\n * Base client schema with common options shared across all generators\n */\nconst BaseClientSchema = z.object({\n type: z.string().min(1, \"Type is required\"),\n outDir: z.string().min(1, \"OutDir is required\"),\n name: z.string().min(1, \"Name is required\"),\n includeTags: z.array(z.string()).optional(),\n excludeTags: z.array(z.string()).optional(),\n // OperationIDParser is an optional function to transform operationId to a method name.\n // Function signature: (operationId: string, method: string, path: string) => string | Promise<string>\n // Note: Zod doesn't validate function signatures at runtime, but TypeScript will enforce the type\n operationIdParser: z.custom<OperationIdParser>().optional(),\n // PreCommand is an optional command to run before SDK generation starts.\n // Uses Docker Compose array format: [\"goimports\", \"-w\", \".\"]\n // The command will be executed in the output directory.\n preCommand: z.array(z.string()).optional(),\n // PostCommand is an optional command to run after SDK generation completes.\n // Uses Docker Compose array format: [\"goimports\", \"-w\", \".\"]\n // The command will be executed in the output directory.\n postCommand: z.array(z.string()).optional(),\n // DefaultBaseURL is the default base URL that will be used if no base URL is provided when creating a client\n defaultBaseURL: z.string().optional(),\n // ExcludeFiles is a list of file paths (relative to outDir) that should not be generated\n // Example: [\"package.json\", \"src/client.ts\"]\n exclude: z.array(z.string()).optional(),\n // TypeAugmentationOptions are options specific to type augmentation generators\n typeAugmentation: TypeAugmentationOptionsSchema.optional(),\n});\n\n/**\n * TypeScript-specific client schema\n */\nexport const TypeScriptClientSchema = BaseClientSchema.extend({\n type: z.literal(\"typescript\"),\n packageName: z.string().min(1, \"PackageName is required\"),\n moduleName: z.string().optional(),\n // IncludeQueryKeys toggles generation of __queryKeys helper methods in services\n includeQueryKeys: z.boolean().optional(),\n // Template overrides - maps valid template names to file paths\n templates: z\n .record(z.string(), z.string())\n .refine(\n (templates) => {\n // Validate that all keys are valid template names\n return Object.keys(templates).every((key) =>\n TYPESCRIPT_TEMPLATE_NAMES.includes(key as TypeScriptTemplateName)\n );\n },\n {\n message: `Template names must be one of: ${TYPESCRIPT_TEMPLATE_NAMES.join(\", \")}`,\n }\n )\n .optional(),\n});\n\n/**\n * Discriminated union of all client types\n * Add new generator types here as they are implemented\n */\nexport const ClientSchema = z.discriminatedUnion(\"type\", [\n TypeScriptClientSchema,\n // Future generators can be added here:\n // PythonClientSchema,\n // GoClientSchema,\n // etc.\n]);\n\nexport const ConfigSchema = z.object({\n spec: z.string().min(1, \"Spec is required\"),\n name: z.string().optional(),\n clients: z.array(ClientSchema).min(1, \"At least one client is required\"),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\nexport type Client = z.infer<typeof ClientSchema>;\nexport type TypeScriptClient = z.infer<typeof TypeScriptClientSchema>;\nexport type TypeAugmentationOptions = z.infer<\n typeof TypeAugmentationOptionsSchema\n>;\n","import { Injectable, Logger } from \"@nestjs/common\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { Config, ConfigSchema, Client } from \"./config.schema\";\nimport { loadMjsConfig } from \"./mjs-config-loader\";\n\n@Injectable()\nexport class ConfigService {\n private readonly logger = new Logger(ConfigService.name);\n private readonly DEFAULT_CONFIG_FILE = \"chunkflow-codegen.config.mjs\";\n\n /**\n * Find default config file in current directory and parent directories\n */\n async findDefaultConfig(): Promise<string | null> {\n let currentDir = process.cwd();\n const root = path.parse(currentDir).root;\n\n while (currentDir !== root) {\n const configPath = path.join(currentDir, this.DEFAULT_CONFIG_FILE);\n try {\n await fs.promises.access(configPath);\n return configPath;\n } catch {\n // File doesn't exist, continue searching\n }\n currentDir = path.dirname(currentDir);\n }\n\n return null;\n }\n\n /**\n * Load configuration from an MJS file\n */\n async load(configPath: string): Promise<Config> {\n try {\n // Load MJS config\n const config = await loadMjsConfig(configPath);\n\n // Normalize paths\n return this.normalizePaths(config, configPath);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to load config from ${configPath}: ${error.message}`\n );\n }\n throw error;\n }\n }\n\n /**\n * Normalize paths in the config to be absolute\n */\n private normalizePaths(config: Config, configPath: string): Config {\n const configDir = path.dirname(path.resolve(configPath));\n\n // Normalize spec path\n let spec = config.spec;\n if (!this.isUrl(spec)) {\n if (!path.isAbsolute(spec)) {\n spec = path.resolve(configDir, spec);\n }\n }\n\n // Normalize client outDir paths\n const clients = config.clients.map((client) => {\n let outDir = client.outDir;\n if (!path.isAbsolute(outDir)) {\n outDir = path.resolve(configDir, outDir);\n }\n return { ...client, outDir };\n });\n\n return {\n ...config,\n spec,\n clients,\n };\n }\n\n /**\n * Check if a string is a URL\n */\n private isUrl(str: string): boolean {\n try {\n const url = new URL(str);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n }\n\n /**\n * Get pre-command for a client\n */\n getPreCommand(client: Client): string[] {\n return client.preCommand || [];\n }\n\n /**\n * Get post-command for a client\n */\n getPostCommand(client: Client): string[] {\n return client.postCommand || [];\n }\n\n /**\n * Check if a file should be excluded based on the ExcludeFiles list.\n * targetPath should be an absolute path, and the comparison is done relative to OutDir.\n */\n shouldExcludeFile(client: Client, targetPath: string): boolean {\n if (!client.exclude || client.exclude.length === 0) {\n return false;\n }\n\n // Get relative path from OutDir to targetPath\n let relPath: string;\n try {\n relPath = path.relative(client.outDir, targetPath);\n } catch {\n // If we can't get a relative path, the file is not under OutDir, so don't exclude\n return false;\n }\n\n // Normalize the path (use forward slashes for consistency, handle . and ..)\n relPath = path.posix.normalize(relPath);\n if (relPath === \".\") {\n relPath = \"\";\n }\n\n // Check if the relative path matches any exclude pattern\n for (const excludePattern of client.exclude) {\n // Normalize exclude pattern\n const normalizedExclude = path.posix.normalize(excludePattern);\n\n // Exact match\n if (relPath === normalizedExclude) {\n return true;\n }\n\n // Check if the file is in a directory that matches the exclude pattern\n // For example, if exclude is \"src/\", then \"src/client.ts\" should match\n if (\n normalizedExclude !== \"\" &&\n relPath.startsWith(normalizedExclude + \"/\")\n ) {\n return true;\n }\n }\n\n return false;\n }\n}\n","import { pathToFileURL } from \"url\";\nimport * as path from \"path\";\nimport { Config, ConfigSchema } from \"./config.schema\";\n\n/**\n * Load configuration from an MJS (ES Module) file.\n * Supports both default export and named export patterns.\n *\n * @param configPath - Absolute or relative path to the MJS config file\n * @returns Validated configuration object\n * @throws Error if the config file cannot be loaded or validated\n */\nexport async function loadMjsConfig(configPath: string): Promise<Config> {\n try {\n // Resolve to absolute path\n const absolutePath = path.isAbsolute(configPath)\n ? configPath\n : path.resolve(configPath);\n\n // Convert to file:// URL for dynamic import\n const fileUrl = pathToFileURL(absolutePath).href;\n\n // Dynamic import the MJS file\n const configModule = await import(fileUrl);\n\n // Support both default export and named export\n const config = configModule.default || configModule;\n\n if (!config) {\n throw new Error(\n `Config file must export a default export or named export: ${configPath}`\n );\n }\n\n // Validate with Zod schema\n const validated = ConfigSchema.parse(config);\n\n return validated;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to load MJS config from ${configPath}: ${error.message}`\n );\n }\n throw error;\n }\n}\n","import { Module } from \"@nestjs/common\";\nimport { ConfigService } from \"./config.service\";\n\n@Module({\n providers: [ConfigService],\n exports: [ConfigService],\n})\nexport class ConfigModule {}\n","import { Config } from \"./config.schema\";\n\n/**\n * Helper function to define a codegen configuration with full TypeScript type inference.\n * Use this in MJS config files with `// @ts-check` for autocomplete and type checking.\n *\n * @example\n * ```javascript\n * // @ts-check\n * import { defineConfig } from '@blimu/codegen';\n *\n * export default defineConfig({\n * spec: 'http://localhost:3020/docs/backend-api/json',\n * clients: [{\n * type: 'typescript',\n * outDir: './my-sdk',\n * packageName: 'my-sdk',\n * name: 'MyClient',\n * operationIdParser: (operationId, method, path) => {\n * return operationId.replace(/Controller/g, '');\n * }\n * }]\n * });\n * ```\n */\nexport function defineConfig(config: Config): Config {\n return config;\n}\n","// Intermediate Representation types - language-agnostic representation of OpenAPI specs\n\nexport enum IRSchemaKind {\n Unknown = \"unknown\",\n String = \"string\",\n Number = \"number\",\n Integer = \"integer\",\n Boolean = \"boolean\",\n Null = \"null\",\n Array = \"array\",\n Object = \"object\",\n Enum = \"enum\",\n Ref = \"ref\",\n OneOf = \"oneOf\",\n AnyOf = \"anyOf\",\n AllOf = \"allOf\",\n Not = \"not\",\n}\n\nexport interface IROperation {\n operationID: string;\n method: string;\n path: string;\n tag: string; // The primary tag used for service grouping (first allowed tag)\n originalTags: string[]; // All original tags from the OpenAPI operation\n summary: string;\n description: string;\n deprecated: boolean;\n pathParams: IRParam[];\n queryParams: IRParam[];\n requestBody: IRRequestBody | null;\n response: IRResponse;\n}\n\nexport interface IRService {\n tag: string;\n operations: IROperation[];\n}\n\nexport interface IR {\n services: IRService[];\n models: IRModel[];\n securitySchemes: IRSecurityScheme[];\n // ModelDefs holds a language-agnostic structured representation of components schemas\n modelDefs: IRModelDef[];\n}\n\nexport interface IRParam {\n name: string;\n required: boolean;\n schema: IRSchema;\n // Description from the OpenAPI parameter\n description: string;\n}\n\nexport interface IRRequestBody {\n contentType: string;\n typeTS: string;\n required: boolean;\n schema: IRSchema;\n}\n\nexport interface IRResponse {\n typeTS: string;\n schema: IRSchema;\n // Description contains the response description chosen for this operation\n description: string;\n // Streaming support\n isStreaming: boolean;\n contentType: string;\n streamingFormat?: \"sse\" | \"ndjson\" | \"chunked\";\n}\n\n// IRModel represents a generated model (legacy, kept for compatibility)\nexport interface IRModel {\n name: string;\n decl: string;\n}\n\n// IRModelDef represents a named model (typically a component or a generated inline type)\n// with a structured schema that is language-agnostic.\nexport interface IRModelDef {\n name: string;\n schema: IRSchema;\n annotations: IRAnnotations;\n}\n\n// IRAnnotations captures non-structural metadata that some generators may render.\nexport interface IRAnnotations {\n title?: string;\n description?: string;\n deprecated?: boolean;\n readOnly?: boolean;\n writeOnly?: boolean;\n default?: any;\n examples?: any[];\n}\n\n// IRSchema models a JSON Schema (as used by OpenAPI 3.1) shape in a language-agnostic way\nexport interface IRSchema {\n kind: IRSchemaKind;\n nullable: boolean;\n format?: string;\n\n // Object\n properties?: IRField[];\n additionalProperties?: IRSchema; // typed maps; undefined when absent\n\n // Array\n items?: IRSchema;\n\n // Enum\n enumValues?: string[]; // stringified values for portability\n enumRaw?: any[]; // original values preserving type where possible\n enumBase?: IRSchemaKind; // underlying base kind: string, number, integer, boolean, unknown\n\n // Ref (component name or canonical name)\n ref?: string;\n\n // Compositions\n oneOf?: IRSchema[];\n anyOf?: IRSchema[];\n allOf?: IRSchema[];\n not?: IRSchema;\n\n // Polymorphism\n discriminator?: IRDiscriminator;\n}\n\n// IRField represents a field in an object schema\nexport interface IRField {\n name: string;\n type: IRSchema;\n required: boolean;\n // Pass-through annotations commonly used by generators\n annotations: IRAnnotations;\n}\n\n// IRDiscriminator represents polymorphism discriminator information\nexport interface IRDiscriminator {\n propertyName: string;\n mapping?: Record<string, string>;\n}\n\n// IRSecurityScheme captures a simplified view of OpenAPI security schemes\n// sufficient for SDK generation.\nexport interface IRSecurityScheme {\n // Key is the name of the security scheme in components.securitySchemes\n key: string;\n // Type is one of: http, apiKey, oauth2, openIdConnect\n type: string;\n // Scheme is used when Type is http (e.g., \"basic\", \"bearer\")\n scheme?: string;\n // In is used when Type is apiKey (e.g., \"header\", \"query\", \"cookie\")\n in?: string;\n // Name is used when Type is apiKey; it is the header/query/cookie name\n name?: string;\n // BearerFormat may be provided for bearer tokens\n bearerFormat?: string;\n}\n","import { Injectable, Logger } from \"@nestjs/common\";\nimport { IR } from \"../ir/ir.types\";\nimport { Client } from \"../config/config.schema\";\nimport { Generator } from \"./generator.interface\";\nimport { IrBuilderService } from \"./ir-builder.service\";\nimport { OpenApiService } from \"../openapi/openapi.service\";\n\n@Injectable()\nexport class GeneratorService {\n private readonly logger = new Logger(GeneratorService.name);\n private readonly generators = new Map<string, Generator>();\n\n constructor(\n private readonly irBuilder: IrBuilderService,\n private readonly openApiService: OpenApiService\n ) {}\n\n /**\n * Register a generator\n */\n register<TClient extends Client>(generator: Generator<TClient>): void {\n this.generators.set(generator.getType(), generator as Generator);\n this.logger.debug(`Registered generator: ${generator.getType()}`);\n }\n\n /**\n * Get a generator by type\n */\n getGenerator(type: string): Generator | undefined {\n return this.generators.get(type);\n }\n\n /**\n * Get all available generator types\n */\n getAvailableTypes(): string[] {\n return Array.from(this.generators.keys());\n }\n\n /**\n * Generate SDK for a client\n * TypeScript will narrow the client type based on the discriminated union\n */\n async generate(spec: string, client: Client): Promise<void> {\n const generator = this.getGenerator(client.type);\n if (!generator) {\n throw new Error(`Unsupported client type: ${client.type}`);\n }\n\n // Load OpenAPI document\n const doc = await this.openApiService.loadDocument(spec);\n // Build IR\n const fullIR = this.irBuilder.buildIR(doc);\n // Filter IR based on client configuration\n const filteredIR = this.irBuilder.filterIR(fullIR, client);\n // Generate - TypeScript will ensure type safety through the discriminated union\n // The generator's generate method will receive the correctly narrowed client type\n await generator.generate(client, filteredIR);\n }\n}\n","import { Injectable } from \"@nestjs/common\";\nimport { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\nimport {\n IR,\n IRService,\n IROperation,\n IRParam,\n IRRequestBody,\n IRResponse,\n IRSecurityScheme,\n IRModelDef,\n IRSchema,\n} from \"../ir/ir.types\";\nimport { SchemaConverterService } from \"./schema-converter.service\";\nimport { Client } from \"../config/config.schema\";\nimport { toPascalCase, toCamelCase } from \"../utils/string.utils\";\nimport { IRSchemaKind } from \"../ir/ir.types\";\nimport { OpenAPIDocument } from \"../openapi/openapi.types\";\n\n@Injectable()\nexport class IrBuilderService {\n constructor(private readonly schemaConverter: SchemaConverterService) {}\n\n /**\n * Build IR from an OpenAPI document\n * Supports both OpenAPI 3.0 and 3.1\n */\n buildIR(doc: OpenAPIDocument): IR {\n const tags = this.collectTags(doc);\n const securitySchemes = this.collectSecuritySchemes(doc);\n const modelDefs = this.buildStructuredModels(doc);\n\n // For now, include all tags - filtering will be done per client\n const allowed: Record<string, boolean> = {};\n for (const tag of tags) {\n allowed[tag] = true;\n }\n\n // Build IR with all operations (this includes extracted inline types in result.modelDefs)\n const result = this.buildIRFromDoc(doc, allowed);\n result.securitySchemes = securitySchemes;\n // Merge component schemas with extracted inline types from operations\n result.modelDefs = [...modelDefs, ...result.modelDefs];\n\n return result;\n }\n\n /**\n * Filter IR based on client configuration\n */\n filterIR(fullIR: IR, client: Client): IR {\n const include = this.compileTagFilters(client.includeTags || []);\n const exclude = this.compileTagFilters(client.excludeTags || []);\n\n // Filter services and operations based on their original tags\n const filteredServices: IRService[] = [];\n for (const service of fullIR.services) {\n const filteredOps: IROperation[] = [];\n for (const op of service.operations) {\n if (this.shouldIncludeOperation(op.originalTags, include, exclude)) {\n filteredOps.push(op);\n }\n }\n // Only include the service if it has at least one operation after filtering\n if (filteredOps.length > 0) {\n filteredServices.push({\n ...service,\n operations: filteredOps,\n });\n }\n }\n\n // Filter ModelDefs to only include those referenced by filtered operations\n const filteredIR: IR = {\n services: filteredServices,\n models: fullIR.models,\n securitySchemes: fullIR.securitySchemes,\n modelDefs: fullIR.modelDefs,\n };\n filteredIR.modelDefs = this.filterUnusedModelDefs(\n filteredIR,\n fullIR.modelDefs\n );\n\n return filteredIR;\n }\n\n /**\n * Detect if a content type indicates streaming\n */\n private detectStreamingContentType(contentType: string): {\n isStreaming: boolean;\n format?: \"sse\" | \"ndjson\" | \"chunked\";\n } {\n const normalized = contentType.toLowerCase().split(\";\")[0].trim();\n\n if (normalized === \"text/event-stream\") {\n return { isStreaming: true, format: \"sse\" };\n }\n\n if (\n normalized === \"application/x-ndjson\" ||\n normalized === \"application/x-jsonlines\" ||\n normalized === \"application/jsonl\"\n ) {\n return { isStreaming: true, format: \"ndjson\" };\n }\n\n // Check for other streaming indicators\n if (normalized.includes(\"stream\") || normalized.includes(\"chunked\")) {\n return { isStreaming: true, format: \"chunked\" };\n }\n\n return { isStreaming: false };\n }\n\n /**\n * Collect all tags from the OpenAPI document\n */\n private collectTags(doc: OpenAPIDocument): string[] {\n const uniq = new Set<string>();\n // consider untagged as \"misc\"\n uniq.add(\"misc\");\n\n if (doc.paths) {\n for (const [path, pathItem] of Object.entries(doc.paths)) {\n if (!pathItem) continue;\n const operations = [\n pathItem.get,\n pathItem.post,\n pathItem.put,\n pathItem.patch,\n pathItem.delete,\n pathItem.options,\n pathItem.head,\n pathItem.trace,\n ];\n\n for (const op of operations) {\n if (!op || !op.tags) continue;\n for (const tag of op.tags) {\n uniq.add(tag);\n }\n }\n }\n }\n\n return Array.from(uniq).sort();\n }\n\n /**\n * Compile regex patterns for tag filtering\n */\n private compileTagFilters(patterns: string[]): RegExp[] {\n return patterns.map((p) => {\n try {\n return new RegExp(p);\n } catch (error) {\n throw new Error(\n `Invalid tag filter pattern \"${p}\": ${error instanceof Error ? error.message : String(error)}`\n );\n }\n });\n }\n\n /**\n * Determine if an operation should be included based on its original tags\n */\n private shouldIncludeOperation(\n originalTags: string[],\n include: RegExp[],\n exclude: RegExp[]\n ): boolean {\n // If no include patterns, assume all tags are initially included\n let included = include.length === 0;\n\n // Check include patterns - operation is included if ANY of its tags match ANY include pattern\n if (include.length > 0) {\n for (const tag of originalTags) {\n for (const r of include) {\n if (r.test(tag)) {\n included = true;\n break;\n }\n }\n if (included) {\n break;\n }\n }\n }\n\n // If not included by include patterns, exclude it\n if (!included) {\n return false;\n }\n\n // Check exclude patterns - operation is excluded if ANY of its tags match ANY exclude pattern\n if (exclude.length > 0) {\n for (const tag of originalTags) {\n for (const r of exclude) {\n if (r.test(tag)) {\n return false;\n }\n }\n }\n }\n\n return true;\n }\n\n /**\n * Build IR structures from OpenAPI document\n */\n private buildIRFromDoc(\n doc: OpenAPIDocument,\n allowed: Record<string, boolean>\n ): IR {\n const servicesMap: Record<string, IRService> = {};\n // Always prepare misc\n servicesMap[\"misc\"] = { tag: \"misc\", operations: [] };\n\n // Collect extracted inline types from request bodies and responses\n const extractedTypes: IRModelDef[] = [];\n const seenTypeNames = new Set<string>();\n\n const addOp = (\n tag: string,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n method: string,\n path: string\n ) => {\n if (!servicesMap[tag]) {\n servicesMap[tag] = { tag, operations: [] };\n }\n const id = op.operationId || \"\";\n const { pathParams, queryParams } = this.collectParams(doc, op);\n const { requestBody: reqBody, extractedTypes: reqBodyTypes } =\n this.extractRequestBodyWithTypes(\n doc,\n op,\n tag,\n id,\n method,\n seenTypeNames\n );\n extractedTypes.push(...reqBodyTypes);\n const { response: resp, extractedTypes: respTypes } =\n this.extractResponseWithTypes(doc, op, tag, id, method, seenTypeNames);\n extractedTypes.push(...respTypes);\n\n // Copy original tags, defaulting to [\"misc\"] if no tags\n const originalTags =\n op.tags && op.tags.length > 0 ? [...op.tags] : [\"misc\"];\n\n servicesMap[tag].operations.push({\n operationID: id,\n method,\n path,\n tag,\n originalTags,\n summary: op.summary || \"\",\n description: op.description || \"\",\n deprecated: op.deprecated || false,\n pathParams,\n queryParams,\n requestBody: reqBody,\n response: resp,\n });\n };\n\n if (doc.paths) {\n for (const [path, pathItem] of Object.entries(doc.paths)) {\n if (!pathItem) continue;\n const operations = [\n { op: pathItem.get, method: \"GET\" },\n { op: pathItem.post, method: \"POST\" },\n { op: pathItem.put, method: \"PUT\" },\n { op: pathItem.patch, method: \"PATCH\" },\n { op: pathItem.delete, method: \"DELETE\" },\n { op: pathItem.options, method: \"OPTIONS\" },\n { op: pathItem.head, method: \"HEAD\" },\n { op: pathItem.trace, method: \"TRACE\" },\n ];\n\n for (const { op, method } of operations) {\n if (!op) continue;\n const t = this.firstAllowedTag(op.tags || [], allowed);\n if (t) {\n addOp(t, op, method, path);\n }\n }\n }\n }\n\n // Sort services and operations for determinism\n const services = Object.values(servicesMap);\n for (const service of services) {\n service.operations.sort((a, b) => {\n if (a.path === b.path) {\n return a.method.localeCompare(b.method);\n }\n return a.path.localeCompare(b.path);\n });\n }\n services.sort((a, b) => a.tag.localeCompare(b.tag));\n\n return {\n services,\n models: [],\n securitySchemes: [],\n modelDefs: extractedTypes,\n };\n }\n\n /**\n * Get the first allowed tag from a list\n */\n /**\n * Derive method name from operation ID, method, and path\n */\n private deriveMethodName(\n operationId: string,\n method: string,\n path: string\n ): string {\n if (operationId) {\n // Convert operationId to camelCase\n return toCamelCase(operationId);\n }\n\n // Basic REST-style heuristics\n const hasID = path.includes(\"{\") && path.includes(\"}\");\n\n switch (method) {\n case \"GET\":\n return hasID ? \"get\" : \"list\";\n case \"POST\":\n return \"create\";\n case \"PUT\":\n case \"PATCH\":\n return \"update\";\n case \"DELETE\":\n return \"delete\";\n default:\n return method.toLowerCase();\n }\n }\n\n private firstAllowedTag(\n tags: string[],\n allowed: Record<string, boolean>\n ): string {\n for (const t of tags) {\n if (allowed[t]) {\n return t;\n }\n }\n if (tags.length === 0 && allowed[\"misc\"]) {\n return \"misc\";\n }\n return \"\";\n }\n\n /**\n * Collect security schemes\n */\n private collectSecuritySchemes(doc: OpenAPIDocument): IRSecurityScheme[] {\n if (!doc.components?.securitySchemes) {\n return [];\n }\n // Deterministic order\n const names = Object.keys(doc.components.securitySchemes).sort();\n const out: IRSecurityScheme[] = [];\n for (const name of names) {\n const scheme = doc.components.securitySchemes[name];\n if (!scheme || \"$ref\" in scheme) continue;\n\n const sc: IRSecurityScheme = { key: name, type: scheme.type };\n switch (scheme.type) {\n case \"http\":\n sc.scheme = scheme.scheme;\n sc.bearerFormat = scheme.bearerFormat;\n break;\n case \"apiKey\":\n sc.in = scheme.in;\n sc.name = scheme.name;\n break;\n case \"oauth2\":\n case \"openIdConnect\":\n // Keep minimal; flows are not modeled yet\n break;\n }\n out.push(sc);\n }\n return out;\n }\n\n /**\n * Collect parameters from an operation\n */\n private collectParams(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject\n ): {\n pathParams: IRParam[];\n queryParams: IRParam[];\n } {\n const pathParams: IRParam[] = [];\n const queryParams: IRParam[] = [];\n\n if (op.parameters) {\n for (const pr of op.parameters) {\n if (!pr || \"$ref\" in pr) continue;\n const p = pr as OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject;\n const schema = this.schemaConverter.schemaRefToIR(doc, p.schema);\n const param: IRParam = {\n name: p.name,\n required: p.required || false,\n schema,\n description: p.description || \"\",\n };\n if (p.in === \"path\") {\n pathParams.push(param);\n } else if (p.in === \"query\") {\n queryParams.push(param);\n }\n }\n }\n\n // Deterministic order\n pathParams.sort((a, b) => a.name.localeCompare(b.name));\n queryParams.sort((a, b) => a.name.localeCompare(b.name));\n\n return { pathParams, queryParams };\n }\n\n /**\n * Extract request body information with inline type extraction\n */\n private extractRequestBodyWithTypes(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n tag: string,\n operationId: string,\n method: string,\n seenTypeNames: Set<string>\n ): { requestBody: IRRequestBody | null; extractedTypes: IRModelDef[] } {\n const extractedTypes: IRModelDef[] = [];\n\n if (!op.requestBody || \"$ref\" in op.requestBody) {\n return { requestBody: null, extractedTypes: [] };\n }\n const rb = op.requestBody as\n | OpenAPIV3.RequestBodyObject\n | OpenAPIV3_1.RequestBodyObject;\n\n // Generate type name: {Tag}{MethodName}RequestBody\n const methodName = this.deriveMethodName(\n operationId,\n method,\n (op as unknown as { path: string }).path\n );\n const typeName = `${toPascalCase(tag)}${toPascalCase(methodName)}RequestBody`;\n\n // Prefer application/json\n if (rb.content?.[\"application/json\"]) {\n const media = rb.content[\"application/json\"];\n const schema = this.schemaConverter.schemaRefToIR(doc, media.schema);\n\n // If schema is an inline object type, extract it\n if (schema.kind === IRSchemaKind.Object && !seenTypeNames.has(typeName)) {\n seenTypeNames.add(typeName);\n extractedTypes.push({\n name: typeName,\n schema,\n annotations: this.schemaConverter.extractAnnotations(media.schema),\n });\n return {\n requestBody: {\n contentType: \"application/json\",\n typeTS: \"\",\n schema: { kind: IRSchemaKind.Ref, ref: typeName, nullable: false },\n required: rb.required || false,\n },\n extractedTypes,\n };\n }\n\n return {\n requestBody: {\n contentType: \"application/json\",\n typeTS: \"\",\n schema,\n required: rb.required || false,\n },\n extractedTypes: [],\n };\n }\n\n // Fallback to original extractRequestBody for other content types\n const reqBody = this.extractRequestBody(doc, op);\n return { requestBody: reqBody, extractedTypes: [] };\n }\n\n /**\n * Extract request body information (legacy method, kept for fallback)\n */\n private extractRequestBody(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject\n ): IRRequestBody | null {\n if (!op.requestBody || \"$ref\" in op.requestBody) {\n return null;\n }\n const rb = op.requestBody as\n | OpenAPIV3.RequestBodyObject\n | OpenAPIV3_1.RequestBodyObject;\n // Prefer application/json\n if (rb.content?.[\"application/json\"]) {\n const media = rb.content[\"application/json\"];\n return {\n contentType: \"application/json\",\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n required: rb.required || false,\n };\n }\n if (rb.content?.[\"application/x-www-form-urlencoded\"]) {\n const media = rb.content[\"application/x-www-form-urlencoded\"];\n return {\n contentType: \"application/x-www-form-urlencoded\",\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n required: rb.required || false,\n };\n }\n if (rb.content?.[\"multipart/form-data\"]) {\n return {\n contentType: \"multipart/form-data\",\n typeTS: \"\",\n schema: { kind: \"unknown\" as any, nullable: false },\n required: rb.required || false,\n };\n }\n // Fallback to the first available media type\n if (rb.content) {\n const firstContentType = Object.keys(rb.content)[0];\n const media = rb.content[firstContentType];\n return {\n contentType: firstContentType,\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n required: rb.required || false,\n };\n }\n return null;\n }\n\n /**\n * Extract response information with inline type extraction\n */\n private extractResponseWithTypes(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n tag: string,\n operationId: string,\n method: string,\n seenTypeNames: Set<string>\n ): { response: IRResponse; extractedTypes: IRModelDef[] } {\n const extractedTypes: IRModelDef[] = [];\n\n if (!op.responses) {\n return {\n response: {\n typeTS: \"unknown\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: \"\",\n isStreaming: false,\n contentType: \"\",\n },\n extractedTypes: [],\n };\n }\n\n // Generate type name: {Tag}{MethodName}Response\n const methodName = this.deriveMethodName(\n operationId,\n method,\n (op as unknown as { path: string }).path\n );\n const typeName = `${toPascalCase(tag)}${toPascalCase(methodName)}Response`;\n\n // Choose 200, 201, or any 2xx; 204 => void\n const tryCodes = [\"200\", \"201\"];\n for (const code of tryCodes) {\n const response = op.responses[code];\n if (response && !(\"$ref\" in response)) {\n const resp = response as\n | OpenAPIV3.ResponseObject\n | OpenAPIV3_1.ResponseObject;\n\n // Check all content types for streaming\n if (resp.content) {\n for (const [contentType, media] of Object.entries(resp.content)) {\n const streaming = this.detectStreamingContentType(contentType);\n const schema = this.schemaConverter.schemaRefToIR(\n doc,\n media.schema\n );\n\n // If streaming, return immediately with streaming flags\n if (streaming.isStreaming) {\n return {\n response: {\n typeTS: \"\",\n schema,\n description: resp.description || \"\",\n isStreaming: true,\n contentType,\n streamingFormat: streaming.format,\n },\n extractedTypes: [],\n };\n }\n\n // For non-streaming JSON, check if we should extract inline types\n if (contentType === \"application/json\") {\n // If schema is an inline object type, extract it\n if (\n schema.kind === IRSchemaKind.Object &&\n !seenTypeNames.has(typeName)\n ) {\n seenTypeNames.add(typeName);\n extractedTypes.push({\n name: typeName,\n schema,\n annotations: this.schemaConverter.extractAnnotations(\n media.schema\n ),\n });\n return {\n response: {\n typeTS: \"\",\n schema: {\n kind: IRSchemaKind.Ref,\n ref: typeName,\n nullable: false,\n },\n description: resp.description || \"\",\n isStreaming: false,\n contentType,\n },\n extractedTypes,\n };\n }\n\n return {\n response: {\n typeTS: \"\",\n schema,\n description: resp.description || \"\",\n isStreaming: false,\n contentType,\n },\n extractedTypes: [],\n };\n }\n }\n\n // Fallback: use first content type\n const firstContentType = Object.keys(resp.content)[0];\n const firstMedia = resp.content[firstContentType];\n const firstSchema = this.schemaConverter.schemaRefToIR(\n doc,\n firstMedia.schema\n );\n const firstStreaming =\n this.detectStreamingContentType(firstContentType);\n\n return {\n response: {\n typeTS: \"\",\n schema: firstSchema,\n description: resp.description || \"\",\n isStreaming: firstStreaming.isStreaming,\n contentType: firstContentType,\n streamingFormat: firstStreaming.format,\n },\n extractedTypes: [],\n };\n }\n\n // No content\n return {\n response: {\n typeTS: \"void\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"\",\n },\n extractedTypes: [],\n };\n }\n }\n\n // Fallback to original extractResponse\n const resp = this.extractResponse(doc, op);\n return { response: resp, extractedTypes: [] };\n }\n\n /**\n * Extract response information (legacy method, kept for fallback)\n */\n private extractResponse(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject\n ): IRResponse {\n if (!op.responses) {\n return {\n typeTS: \"unknown\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: \"\",\n isStreaming: false,\n contentType: \"\",\n };\n }\n\n // Choose 200, 201, or any 2xx; 204 => void\n const tryCodes = [\"200\", \"201\"];\n for (const code of tryCodes) {\n const response = op.responses[code];\n if (response && !(\"$ref\" in response)) {\n const resp = response as\n | OpenAPIV3.ResponseObject\n | OpenAPIV3_1.ResponseObject;\n\n // Check for streaming content types first\n if (resp.content) {\n for (const [contentType, media] of Object.entries(resp.content)) {\n const streaming = this.detectStreamingContentType(contentType);\n if (streaming.isStreaming) {\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: true,\n contentType,\n streamingFormat: streaming.format,\n };\n }\n }\n\n // Non-streaming JSON\n if (resp.content[\"application/json\"]) {\n const media = resp.content[\"application/json\"];\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"application/json\",\n };\n }\n\n // Fallback to any content\n const firstContentType = Object.keys(resp.content)[0];\n const media = resp.content[firstContentType];\n const streaming = this.detectStreamingContentType(firstContentType);\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: streaming.isStreaming,\n contentType: firstContentType,\n streamingFormat: streaming.format,\n };\n }\n\n return {\n typeTS: \"void\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"\",\n };\n }\n }\n\n // any 2xx\n for (const [code, response] of Object.entries(op.responses)) {\n if (\n code.length === 3 &&\n code[0] === \"2\" &&\n response &&\n !(\"$ref\" in response)\n ) {\n const resp = response as\n | OpenAPIV3.ResponseObject\n | OpenAPIV3_1.ResponseObject;\n if (code === \"204\") {\n return {\n typeTS: \"void\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"\",\n };\n }\n\n if (resp.content) {\n // Check for streaming\n for (const [contentType, media] of Object.entries(resp.content)) {\n const streaming = this.detectStreamingContentType(contentType);\n if (streaming.isStreaming) {\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: true,\n contentType,\n streamingFormat: streaming.format,\n };\n }\n }\n\n // Non-streaming JSON\n if (resp.content[\"application/json\"]) {\n const media = resp.content[\"application/json\"];\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"application/json\",\n };\n }\n\n // Fallback to first content type\n const firstContentType = Object.keys(resp.content)[0];\n const media = resp.content[firstContentType];\n const streaming = this.detectStreamingContentType(firstContentType);\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: streaming.isStreaming,\n contentType: firstContentType,\n streamingFormat: streaming.format,\n };\n }\n }\n }\n\n return {\n typeTS: \"unknown\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: \"\",\n isStreaming: false,\n contentType: \"\",\n };\n }\n\n /**\n * Build structured models from components.schemas\n */\n private buildStructuredModels(doc: OpenAPIDocument): IRModelDef[] {\n const out: IRModelDef[] = [];\n if (!doc.components?.schemas) {\n return out;\n }\n const names = Object.keys(doc.components.schemas).sort();\n const seen = new Set<string>();\n\n // Pre-populate seen with component names to prevent inline duplicates\n for (const name of names) {\n seen.add(name);\n }\n\n for (const name of names) {\n const sr = doc.components.schemas[name];\n // For component schemas, use schemaRefToIR to get the actual schema without creating inline models\n const schema = this.schemaConverter.schemaRefToIR(doc, sr);\n out.push({\n name,\n schema,\n annotations: this.schemaConverter.extractAnnotations(sr),\n });\n }\n return out;\n }\n\n /**\n * Filter unused ModelDefs\n */\n private filterUnusedModelDefs(\n filteredIR: IR,\n allModelDefs: IRModelDef[]\n ): IRModelDef[] {\n // Build a map of all ModelDefs for quick lookup\n const modelDefMap = new Map<string, IRModelDef>();\n for (const md of allModelDefs) {\n modelDefMap.set(md.name, md);\n }\n\n // Collect all schema references from filtered operations\n const referenced = new Set<string>();\n const visited = new Set<string>(); // Track visited refs to avoid cycles\n\n // Helper function to collect references from a schema recursively\n const collectRefs = (schema: IRSchema) => {\n if (schema.kind === \"ref\" && schema.ref) {\n const refName = schema.ref;\n referenced.add(refName);\n // If this ref points to a ModelDef and we haven't visited it, collect its transitive references\n if (!visited.has(refName)) {\n visited.add(refName);\n const md = modelDefMap.get(refName);\n if (md) {\n collectRefs(md.schema);\n }\n }\n }\n if (schema.items) {\n collectRefs(schema.items);\n }\n if (schema.additionalProperties) {\n collectRefs(schema.additionalProperties);\n }\n if (schema.oneOf) {\n for (const sub of schema.oneOf) {\n collectRefs(sub);\n }\n }\n if (schema.anyOf) {\n for (const sub of schema.anyOf) {\n collectRefs(sub);\n }\n }\n if (schema.allOf) {\n for (const sub of schema.allOf) {\n collectRefs(sub);\n }\n }\n if (schema.not) {\n collectRefs(schema.not);\n }\n if (schema.properties) {\n for (const field of schema.properties) {\n collectRefs(field.type);\n }\n }\n };\n\n // Collect references from all operations\n for (const service of filteredIR.services) {\n for (const op of service.operations) {\n // Collect from path params\n for (const param of op.pathParams) {\n collectRefs(param.schema);\n }\n // Collect from query params\n for (const param of op.queryParams) {\n collectRefs(param.schema);\n }\n // Collect from request body\n if (op.requestBody) {\n collectRefs(op.requestBody.schema);\n }\n // Collect from response\n collectRefs(op.response.schema);\n }\n }\n\n // Filter ModelDefs to only include referenced ones\n return allModelDefs.filter((md) => referenced.has(md.name));\n }\n}\n","import { Injectable } from \"@nestjs/common\";\nimport { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\nimport {\n IRSchema,\n IRSchemaKind,\n IRField,\n IRAnnotations,\n IRDiscriminator,\n} from \"../ir/ir.types\";\nimport {\n OpenAPIDocument,\n getSchemaFromRef,\n isSchemaNullable,\n getSchemaType,\n} from \"../openapi/openapi.types\";\n\n@Injectable()\nexport class SchemaConverterService {\n /**\n * Convert an OpenAPI schema reference to IR schema\n * Supports both OpenAPI 3.0 and 3.1\n */\n schemaRefToIR(\n doc: OpenAPIDocument,\n schemaRef:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.ReferenceObject\n | OpenAPIV3_1.SchemaObject\n | undefined\n ): IRSchema {\n if (!schemaRef) {\n return { kind: IRSchemaKind.Unknown, nullable: false };\n }\n\n // Handle $ref\n if (\"$ref\" in schemaRef && schemaRef.$ref) {\n const ref = schemaRef.$ref;\n if (ref.startsWith(\"#/components/schemas/\")) {\n const name = ref.replace(\"#/components/schemas/\", \"\");\n return { kind: IRSchemaKind.Ref, ref: name, nullable: false };\n }\n // Handle other ref formats\n const parts = ref.split(\"/\");\n if (parts.length > 0) {\n const name = parts[parts.length - 1];\n if (name) {\n return { kind: IRSchemaKind.Ref, ref: name, nullable: false };\n }\n }\n return { kind: IRSchemaKind.Unknown, nullable: false };\n }\n\n const schema = getSchemaFromRef(doc, schemaRef) as\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.SchemaObject;\n if (!schema) {\n return { kind: IRSchemaKind.Unknown, nullable: false };\n }\n\n // Detect nullable (works for both 3.0 and 3.1)\n const nullable = isSchemaNullable(schema);\n\n // Polymorphism discriminator\n let discriminator: IRDiscriminator | undefined;\n if (schema.discriminator) {\n discriminator = {\n propertyName: schema.discriminator.propertyName,\n mapping: schema.discriminator.mapping,\n };\n }\n\n // Compositions\n if (schema.oneOf && schema.oneOf.length > 0) {\n const subs = schema.oneOf.map((sub) => this.schemaRefToIR(doc, sub));\n return {\n kind: IRSchemaKind.OneOf,\n oneOf: subs,\n nullable,\n discriminator,\n };\n }\n if (schema.anyOf && schema.anyOf.length > 0) {\n const subs = schema.anyOf.map((sub) => this.schemaRefToIR(doc, sub));\n return {\n kind: IRSchemaKind.AnyOf,\n anyOf: subs,\n nullable,\n discriminator,\n };\n }\n if (schema.allOf && schema.allOf.length > 0) {\n const subs = schema.allOf.map((sub) => this.schemaRefToIR(doc, sub));\n return {\n kind: IRSchemaKind.AllOf,\n allOf: subs,\n nullable,\n discriminator,\n };\n }\n if (schema.not) {\n const not = this.schemaRefToIR(doc, schema.not);\n return {\n kind: IRSchemaKind.Not,\n not,\n nullable,\n discriminator,\n };\n }\n\n // Enum\n if (schema.enum && schema.enum.length > 0) {\n const enumValues = schema.enum.map((v) => String(v));\n const enumBase = this.inferEnumBaseKind(schema);\n return {\n kind: IRSchemaKind.Enum,\n enumValues,\n enumRaw: schema.enum,\n enumBase,\n nullable,\n discriminator,\n };\n }\n\n // Primitive kinds and object/array\n // Handle both string and string[] types (3.0 vs 3.1)\n const type = getSchemaType(schema);\n const normalizedType = Array.isArray(type)\n ? type.filter((t) => t !== \"null\")[0]\n : type;\n\n if (normalizedType) {\n switch (normalizedType) {\n case \"string\":\n return {\n kind: IRSchemaKind.String,\n nullable,\n format: schema.format,\n discriminator,\n };\n case \"integer\":\n return {\n kind: IRSchemaKind.Integer,\n nullable,\n discriminator,\n };\n case \"number\":\n return {\n kind: IRSchemaKind.Number,\n nullable,\n discriminator,\n };\n case \"boolean\":\n return {\n kind: IRSchemaKind.Boolean,\n nullable,\n discriminator,\n };\n case \"array\":\n // When type is \"array\", schema has items property (required in OpenAPI spec)\n // TypeScript doesn't narrow the union type, so we use type assertion\n const arraySchema = schema as\n | (OpenAPIV3.SchemaObject & {\n items?: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject;\n })\n | (OpenAPIV3_1.SchemaObject & {\n items?: OpenAPIV3_1.SchemaObject | OpenAPIV3_1.ReferenceObject;\n });\n const items = this.schemaRefToIR(doc, arraySchema.items);\n return {\n kind: IRSchemaKind.Array,\n items,\n nullable,\n discriminator,\n };\n case \"object\":\n // Properties\n const properties: IRField[] = [];\n if (schema.properties) {\n const propNames = Object.keys(schema.properties).sort();\n for (const name of propNames) {\n const prop = schema.properties[name];\n const fieldType = this.schemaRefToIR(doc, prop);\n const required = schema.required?.includes(name) || false;\n properties.push({\n name,\n type: fieldType,\n required,\n annotations: this.extractAnnotations(prop),\n });\n }\n }\n let additionalProperties: IRSchema | undefined;\n if (schema.additionalProperties) {\n if (typeof schema.additionalProperties === \"object\") {\n additionalProperties = this.schemaRefToIR(\n doc,\n schema.additionalProperties\n );\n }\n }\n return {\n kind: IRSchemaKind.Object,\n properties,\n additionalProperties,\n nullable,\n discriminator,\n };\n }\n }\n\n return {\n kind: IRSchemaKind.Unknown,\n nullable,\n discriminator,\n };\n }\n\n /**\n * Extract annotations from a schema reference\n * Supports both OpenAPI 3.0 and 3.1\n */\n extractAnnotations(\n schemaRef:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.ReferenceObject\n | OpenAPIV3_1.SchemaObject\n | undefined\n ): IRAnnotations {\n if (!schemaRef || \"$ref\" in schemaRef) {\n return {};\n }\n const schema = schemaRef as\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.SchemaObject;\n return {\n title: schema.title,\n description: schema.description,\n deprecated: schema.deprecated,\n readOnly: schema.readOnly,\n writeOnly: schema.writeOnly,\n default: schema.default,\n examples: schema.example\n ? Array.isArray(schema.example)\n ? schema.example\n : [schema.example]\n : undefined,\n };\n }\n\n /**\n * Infer the base kind for an enum\n * Supports both OpenAPI 3.0 and 3.1\n */\n private inferEnumBaseKind(\n schema: OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject\n ): IRSchemaKind {\n // Prefer explicit type when present\n const type = getSchemaType(schema);\n if (type) {\n const normalizedType = Array.isArray(type)\n ? type.filter((t) => t !== \"null\")[0]\n : type;\n if (normalizedType) {\n switch (normalizedType) {\n case \"string\":\n return IRSchemaKind.String;\n case \"integer\":\n return IRSchemaKind.Integer;\n case \"number\":\n return IRSchemaKind.Number;\n case \"boolean\":\n return IRSchemaKind.Boolean;\n }\n }\n }\n // Fallback: inspect first enum value\n if (schema.enum && schema.enum.length > 0) {\n const first = schema.enum[0];\n if (typeof first === \"string\") {\n return IRSchemaKind.String;\n }\n if (typeof first === \"number\") {\n return Number.isInteger(first)\n ? IRSchemaKind.Integer\n : IRSchemaKind.Number;\n }\n if (typeof first === \"boolean\") {\n return IRSchemaKind.Boolean;\n }\n }\n return IRSchemaKind.Unknown;\n }\n}\n","import { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\n\nexport type OpenAPIVersion = \"3.0\" | \"3.1\" | \"unknown\";\n\nexport type OpenAPIDocument = OpenAPIV3.Document | OpenAPIV3_1.Document;\n\n/**\n * Detect OpenAPI version from a document\n */\nexport function detectOpenAPIVersion(doc: OpenAPIDocument): OpenAPIVersion {\n const version = doc.openapi;\n if (typeof version !== \"string\") {\n return \"unknown\";\n }\n\n if (version.startsWith(\"3.1\")) {\n return \"3.1\";\n }\n\n if (version.startsWith(\"3.0\")) {\n return \"3.0\";\n }\n\n return \"unknown\";\n}\n\n/**\n * Check if the OpenAPI version is supported\n */\nexport function isSupportedVersion(version: OpenAPIVersion): boolean {\n return version === \"3.0\" || version === \"3.1\";\n}\n\n/**\n * Type guard to check if document is OpenAPI 3.1\n */\nexport function isOpenAPI31(doc: OpenAPIDocument): doc is OpenAPIV3_1.Document {\n return detectOpenAPIVersion(doc) === \"3.1\";\n}\n\n/**\n * Type guard to check if document is OpenAPI 3.0\n */\nexport function isOpenAPI30(doc: OpenAPIDocument): doc is OpenAPIV3.Document {\n return detectOpenAPIVersion(doc) === \"3.0\";\n}\n","import { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\nimport {\n OpenAPIDocument,\n isOpenAPI31,\n isOpenAPI30,\n} from \"./openapi-version.utils\";\n\n// Re-export the union type and type guards for convenience\nexport type { OpenAPIDocument };\nexport { isOpenAPI31, isOpenAPI30 };\n\n/**\n * Normalized interface for accessing common OpenAPI document properties\n * regardless of version (3.0 or 3.1)\n */\nexport interface NormalizedOpenAPIDocument {\n openapi: string;\n info: OpenAPIV3.InfoObject | OpenAPIV3_1.InfoObject;\n paths: OpenAPIV3.PathsObject | OpenAPIV3_1.PathsObject | undefined;\n components?: OpenAPIV3.ComponentsObject | OpenAPIV3_1.ComponentsObject;\n servers?: (OpenAPIV3.ServerObject | OpenAPIV3_1.ServerObject)[];\n}\n\n/**\n * Normalize an OpenAPI document to a common interface\n * This allows accessing common properties without version-specific checks\n */\nexport function normalizeDocument(\n doc: OpenAPIDocument\n): NormalizedOpenAPIDocument {\n return {\n openapi: doc.openapi,\n info: doc.info,\n paths: doc.paths,\n components: doc.components,\n servers: doc.servers,\n };\n}\n\n/**\n * Get the schema object from a reference or direct schema\n * Works with both OpenAPI 3.0 and 3.1\n */\nexport function getSchemaFromRef(\n doc: OpenAPIDocument,\n schemaRef:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.ReferenceObject\n | OpenAPIV3_1.SchemaObject\n | undefined\n): OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject | undefined {\n if (!schemaRef || typeof schemaRef !== \"object\") {\n return undefined;\n }\n\n // Handle $ref\n if (\"$ref\" in schemaRef && schemaRef.$ref) {\n const ref = schemaRef.$ref;\n if (ref.startsWith(\"#/components/schemas/\")) {\n const name = ref.replace(\"#/components/schemas/\", \"\");\n if (doc.components?.schemas?.[name]) {\n const schema = doc.components.schemas[name];\n if (\"$ref\" in schema) {\n // Recursive reference\n return getSchemaFromRef(doc, schema);\n }\n return schema as OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject;\n }\n }\n return undefined;\n }\n\n return schemaRef as OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject;\n}\n\n/**\n * Check if a schema is nullable (works for both 3.0 and 3.1)\n */\nexport function isSchemaNullable(\n schema: OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject | undefined\n): boolean {\n if (!schema) {\n return false;\n }\n\n // OpenAPI 3.0: uses nullable property\n if (\"nullable\" in schema && schema.nullable === true) {\n return true;\n }\n\n // OpenAPI 3.1: uses type array with 'null'\n if (\"type\" in schema && Array.isArray(schema.type)) {\n return schema.type.includes(\"null\");\n }\n\n return false;\n}\n\n/**\n * Get the type from a schema (normalized for both versions)\n */\nexport function getSchemaType(\n schema: OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject | undefined\n): string | string[] | undefined {\n if (!schema || !(\"type\" in schema)) {\n return undefined;\n }\n\n return schema.type;\n}\n","/**\n * String utility functions for code generation\n */\n\n/**\n * Convert a string to PascalCase\n */\nexport function toPascalCase(s: string): string {\n s = s.trim();\n if (s === \"\") {\n return \"\";\n }\n\n // Split by non-alphanumeric characters\n const parts = s.split(/[^A-Za-z0-9]+/).filter((p) => p !== \"\");\n const allParts: string[] = [];\n\n for (const part of parts) {\n // Further split camelCase/PascalCase words\n const subParts = splitCamelCase(part);\n allParts.push(...subParts);\n }\n\n return allParts\n .filter((p) => p !== \"\")\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join(\"\");\n}\n\n/**\n * Convert a string to camelCase\n */\nexport function toCamelCase(s: string): string {\n const pascal = toPascalCase(s);\n if (pascal === \"\") {\n return \"\";\n }\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\n/**\n * Convert a string to snake_case\n */\nexport function toSnakeCase(s: string): string {\n s = s.trim();\n if (s === \"\") {\n return \"\";\n }\n\n // Split by non-alphanumeric characters\n const parts = s.split(/[^A-Za-z0-9]+/).filter((p) => p !== \"\");\n const allParts: string[] = [];\n\n for (const part of parts) {\n // Further split camelCase/PascalCase words\n const subParts = splitCamelCase(part);\n allParts.push(...subParts);\n }\n\n return allParts\n .filter((p) => p !== \"\")\n .map((p) => p.toLowerCase())\n .join(\"_\");\n}\n\n/**\n * Convert a string to kebab-case\n */\nexport function toKebabCase(s: string): string {\n s = s.trim();\n if (s === \"\") {\n return \"\";\n }\n\n // Split by non-alphanumeric characters\n const parts = s.split(/[^A-Za-z0-9]+/).filter((p) => p !== \"\");\n const allParts: string[] = [];\n\n for (const part of parts) {\n // Further split camelCase/PascalCase words\n const subParts = splitCamelCase(part);\n allParts.push(...subParts);\n }\n\n return allParts\n .filter((p) => p !== \"\")\n .map((p) => p.toLowerCase())\n .join(\"-\");\n}\n\n/**\n * Split a camelCase or PascalCase string into words\n */\nfunction splitCamelCase(s: string): string[] {\n if (s === \"\") {\n return [];\n }\n\n const parts: string[] = [];\n let current = \"\";\n\n const chars = Array.from(s);\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i];\n // Check if this is the start of a new word\n let isNewWord = false;\n if (i > 0 && isUppercase(char)) {\n // Current char is uppercase\n if (!isUppercase(chars[i - 1])) {\n // Previous char was lowercase, so this starts a new word\n isNewWord = true;\n } else if (i < chars.length - 1 && !isUppercase(chars[i + 1])) {\n // Previous char was uppercase, but next char is lowercase\n // This handles cases like \"XMLHttp\" -> \"XML\", \"Http\"\n isNewWord = true;\n }\n }\n\n if (isNewWord && current.length > 0) {\n parts.push(current);\n current = \"\";\n }\n\n current += char;\n }\n\n if (current.length > 0) {\n parts.push(current);\n }\n\n return parts;\n}\n\n/**\n * Check if a character is uppercase\n */\nfunction isUppercase(char: string): boolean {\n return char >= \"A\" && char <= \"Z\";\n}\n","import { Injectable, Logger } from \"@nestjs/common\";\nimport SwaggerParser from \"@apidevtools/swagger-parser\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\nimport {\n OpenAPIDocument,\n detectOpenAPIVersion,\n isSupportedVersion,\n} from \"./openapi-version.utils\";\n\n@Injectable()\nexport class OpenApiService {\n private readonly logger = new Logger(OpenApiService.name);\n\n /**\n * Load an OpenAPI document from a local file path or an HTTP(S) URL\n * Supports both OpenAPI 3.0 and 3.1\n */\n async loadDocument(input: string): Promise<OpenAPIDocument> {\n try {\n // Try to parse as URL; if it looks like http(s), fetch via URL\n let url: URL | null = null;\n try {\n url = new URL(input);\n } catch {\n // Not a URL, treat as file path\n }\n\n let api: OpenAPIDocument;\n if (url && (url.protocol === \"http:\" || url.protocol === \"https:\")) {\n // Load from URL\n this.logger.debug(`Loading OpenAPI spec from URL: ${input}`);\n api = (await SwaggerParser.dereference(input)) as OpenAPIDocument;\n } else {\n // Load from file\n const filePath = path.resolve(input);\n if (!fs.existsSync(filePath)) {\n throw new Error(`OpenAPI spec file not found: ${filePath}`);\n }\n this.logger.debug(`Loading OpenAPI spec from file: ${filePath}`);\n api = (await SwaggerParser.dereference(filePath)) as OpenAPIDocument;\n }\n\n // Detect and validate version\n const version = detectOpenAPIVersion(api);\n if (!isSupportedVersion(version)) {\n throw new Error(\n `Unsupported OpenAPI version: ${api.openapi}. Only versions 3.0.x and 3.1.0 are supported.`\n );\n }\n\n this.logger.log(`Detected OpenAPI version: ${version} (${api.openapi})`);\n return api;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to load OpenAPI document from ${input}: ${error.message}`\n );\n }\n throw error;\n }\n }\n\n /**\n * Validate an OpenAPI document\n */\n async validateDocument(input: string): Promise<void> {\n try {\n let url: URL | null = null;\n try {\n url = new URL(input);\n } catch {\n // Not a URL\n }\n\n if (url && (url.protocol === \"http:\" || url.protocol === \"https:\")) {\n await SwaggerParser.validate(input);\n } else {\n const filePath = path.resolve(input);\n if (!fs.existsSync(filePath)) {\n throw new Error(`OpenAPI spec file not found: ${filePath}`);\n }\n await SwaggerParser.validate(filePath);\n }\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Invalid OpenAPI document: ${error.message}`);\n }\n throw error;\n }\n }\n}\n","import { Module } from \"@nestjs/common\";\nimport { GeneratorService } from \"./generator.service\";\nimport { IrBuilderService } from \"./ir-builder.service\";\nimport { SchemaConverterService } from \"./schema-converter.service\";\nimport { OpenApiModule } from \"../openapi/openapi.module\";\nimport { ConfigModule } from \"../config/config.module\";\nimport { TypeScriptGeneratorService } from \"./typescript/typescript-generator.service\";\n\n@Module({\n imports: [OpenApiModule, ConfigModule],\n providers: [\n GeneratorService,\n IrBuilderService,\n SchemaConverterService,\n TypeScriptGeneratorService,\n ],\n exports: [GeneratorService, IrBuilderService, SchemaConverterService],\n})\nexport class GeneratorModule {\n constructor(\n private readonly generatorService: GeneratorService,\n private readonly typeScriptGenerator: TypeScriptGeneratorService\n ) {\n // Register default generators\n this.generatorService.register(this.typeScriptGenerator);\n }\n}\n","import { Module } from \"@nestjs/common\";\nimport { OpenApiService } from \"./openapi.service\";\n\n@Module({\n providers: [OpenApiService],\n exports: [OpenApiService],\n})\nexport class OpenApiModule {}\n","import { Injectable, Logger } from \"@nestjs/common\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as Handlebars from \"handlebars\";\nimport { IR } from \"../../ir/ir.types\";\nimport { TypeScriptClient } from \"../../config/config.schema\";\nimport { Generator } from \"../generator.interface\";\nimport { ConfigService } from \"../../config/config.service\";\nimport { registerCommonHandlebarsHelpers } from \"../handlebars-helpers\";\nimport {\n schemaToTSType,\n resolveMethodName,\n deriveMethodName,\n buildPathTemplate,\n buildQueryKeyBase,\n orderPathParams,\n buildMethodSignature,\n queryKeyArgs,\n quoteTSPropertyName,\n isStreamingOperation,\n getStreamingItemType,\n} from \"./helpers\";\nimport { schemaToZodSchema } from \"./zod-schema-converter\";\nimport { toPascalCase, toSnakeCase } from \"../../utils/string.utils\";\n\n@Injectable()\nexport class TypeScriptGeneratorService implements Generator<TypeScriptClient> {\n private readonly logger = new Logger(TypeScriptGeneratorService.name);\n\n constructor(private readonly configService: ConfigService) {}\n\n getType(): string {\n return \"typescript\";\n }\n\n async generate(client: TypeScriptClient, ir: IR): Promise<void> {\n // Ensure directories\n const srcDir = path.join(client.outDir, \"src\");\n const servicesDir = path.join(srcDir, \"services\");\n await fs.promises.mkdir(servicesDir, { recursive: true });\n\n // Pre-process operations to resolve method names (async operation)\n const processedIR = await this.preprocessIR(client, ir);\n\n // Register Handlebars helpers\n this.registerHandlebarsHelpers(client);\n\n // Generate files\n await this.generateClient(client, processedIR, srcDir);\n await this.generateIndex(client, processedIR, srcDir);\n await this.generateUtils(client, processedIR, srcDir);\n await this.generateServices(client, processedIR, servicesDir);\n await this.generateSchema(client, processedIR, srcDir);\n await this.generateZodSchema(client, processedIR, srcDir);\n await this.generatePackageJson(client);\n await this.generateTsConfig(client);\n await this.generateReadme(client, processedIR);\n }\n\n /**\n * Pre-process IR to resolve method names and add cached values\n */\n private async preprocessIR(client: TypeScriptClient, ir: IR): Promise<IR> {\n // Create a copy of IR with resolved method names\n const processedServices = await Promise.all(\n ir.services.map(async (service) => ({\n ...service,\n operations: await Promise.all(\n service.operations.map(async (op) => {\n const methodName = await resolveMethodName(client, op);\n return {\n ...op,\n _resolvedMethodName: methodName, // Cache the resolved name\n };\n })\n ),\n }))\n );\n\n return {\n ...ir,\n services: processedServices,\n };\n }\n\n private registerHandlebarsHelpers(client: TypeScriptClient): void {\n // Register common helpers shared across all generators\n registerCommonHandlebarsHelpers();\n\n // TypeScript-specific helpers\n // Use pre-resolved method names from _resolvedMethodName\n Handlebars.registerHelper(\"methodName\", (op: any) => {\n return op._resolvedMethodName || deriveMethodName(op);\n });\n Handlebars.registerHelper(\"queryTypeName\", (op: any) => {\n const methodName = op._resolvedMethodName || deriveMethodName(op);\n return toPascalCase(op.tag) + toPascalCase(methodName) + \"Query\";\n });\n Handlebars.registerHelper(\"pathTemplate\", (op: any) => {\n const result = buildPathTemplate(op);\n // Return as Handlebars.SafeString to prevent HTML escaping\n return new Handlebars.SafeString(result);\n });\n Handlebars.registerHelper(\"queryKeyBase\", (op: any) =>\n buildQueryKeyBase(op)\n );\n Handlebars.registerHelper(\"pathParamsInOrder\", (op: any) =>\n orderPathParams(op)\n );\n Handlebars.registerHelper(\"methodSignature\", (op: any) => {\n const methodName = op._resolvedMethodName || deriveMethodName(op);\n const signature = buildMethodSignature(op, methodName);\n // Return as SafeString array to prevent HTML escaping\n return signature.map((s) => new Handlebars.SafeString(s));\n });\n Handlebars.registerHelper(\"methodSignatureNoInit\", (op: any) => {\n const methodName = op._resolvedMethodName || deriveMethodName(op);\n const parts = buildMethodSignature(op, methodName);\n return parts.slice(0, -1); // Remove init parameter\n });\n Handlebars.registerHelper(\"queryKeyArgs\", (op: any) => queryKeyArgs(op));\n Handlebars.registerHelper(\"tsType\", (x: any) => {\n if (x && typeof x === \"object\" && \"kind\" in x) {\n return schemaToTSType(x);\n }\n return \"unknown\";\n });\n Handlebars.registerHelper(\"stripSchemaNs\", (s: string) =>\n s.replace(/^Schema\\./, \"\")\n );\n Handlebars.registerHelper(\"tsTypeStripNs\", (x: any) => {\n if (x && typeof x === \"object\" && \"kind\" in x) {\n const typeStr = schemaToTSType(x);\n const stripped = typeStr.replace(/^Schema\\./, \"\");\n // Return as SafeString to prevent Handlebars HTML escaping\n return new Handlebars.SafeString(stripped);\n }\n return \"unknown\";\n });\n // Decode HTML entities in strings\n Handlebars.registerHelper(\"decodeHtml\", (str: string) => {\n if (typeof str !== \"string\") return str;\n return str\n .replace(/&quot;/g, '\"')\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&#x60;/g, \"`\")\n .replace(/&amp;/g, \"&\");\n });\n Handlebars.registerHelper(\"quotePropName\", (name: string) =>\n quoteTSPropertyName(name)\n );\n Handlebars.registerHelper(\"zodSchema\", (x: any) => {\n if (x && typeof x === \"object\" && \"kind\" in x) {\n return new Handlebars.SafeString(schemaToZodSchema(x));\n }\n return \"z.unknown()\";\n });\n // Streaming helpers\n Handlebars.registerHelper(\"isStreaming\", (op: any) => {\n return isStreamingOperation(op);\n });\n Handlebars.registerHelper(\"streamingItemType\", (op: any) => {\n return new Handlebars.SafeString(getStreamingItemType(op));\n });\n }\n\n private async renderTemplate(\n templateName: string,\n data: any,\n outputPath: string,\n client: TypeScriptClient\n ): Promise<void> {\n // 1. Check for template override\n const overridePath =\n client.templates?.[templateName as keyof typeof client.templates];\n if (overridePath) {\n this.logger.debug(\n `Using template override for ${templateName}: ${overridePath}`\n );\n try {\n // Validate that override path exists and is readable\n await fs.promises.access(overridePath, fs.constants.R_OK);\n const templateContent = await fs.promises.readFile(\n overridePath,\n \"utf-8\"\n );\n const template = Handlebars.compile(templateContent);\n const rendered = template(data);\n await fs.promises.writeFile(outputPath, rendered, \"utf-8\");\n return;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.error(\n `Template override file not found or not readable: ${overridePath}. Error: ${errorMsg}`\n );\n throw new Error(\n `Template override file not found or not readable: ${overridePath}`\n );\n }\n }\n\n // 2. Fall back to default template resolution\n // Templates are now co-located with the generator\n // Try multiple possible template paths (handles both source and compiled locations)\n // Note: When bundled by tsup, __dirname will be 'dist', so we need to look for templates\n // in dist/generator/typescript/templates/\n const possiblePaths = [\n path.join(__dirname, \"generator/typescript/templates\", templateName), // Bundled: dist/generator/typescript/templates/\n path.join(__dirname, \"templates\", templateName), // If __dirname is dist/generator/typescript/\n path.join(__dirname, \"../typescript/templates\", templateName), // Fallback\n path.join(\n process.cwd(),\n \"src/generator/typescript/templates\",\n templateName\n ), // Development\n ];\n\n let templatePath: string | null = null;\n for (const possiblePath of possiblePaths) {\n try {\n await fs.promises.access(possiblePath);\n templatePath = possiblePath;\n this.logger.debug(`Found template at: ${templatePath}`);\n break;\n } catch (error) {\n this.logger.debug(`Template not found at: ${possiblePath}`);\n // Continue to next path\n }\n }\n\n if (!templatePath) {\n this.logger.error(`Template not found: ${templateName}`);\n this.logger.error(`Checked paths: ${possiblePaths.join(\", \")}`);\n this.logger.error(`__dirname: ${__dirname}`);\n throw new Error(`Template not found: ${templateName}`);\n }\n\n const templateContent = await fs.promises.readFile(templatePath, \"utf-8\");\n const template = Handlebars.compile(templateContent);\n const rendered = template(data);\n await fs.promises.writeFile(outputPath, rendered, \"utf-8\");\n }\n\n private async generateClient(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const clientPath = path.join(srcDir, \"client.ts\");\n if (this.configService.shouldExcludeFile(client, clientPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"client.ts.hbs\",\n { Client: client, IR: ir },\n clientPath,\n client\n );\n } catch (error) {\n // Fallback if template doesn't exist yet\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.warn(\n `Template client.ts.hbs not found: ${errorMsg}, using placeholder`\n );\n const content = `// Generated client - template rendering to be implemented`;\n await fs.promises.writeFile(clientPath, content, \"utf-8\");\n }\n }\n\n private async generateIndex(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const indexPath = path.join(srcDir, \"index.ts\");\n if (this.configService.shouldExcludeFile(client, indexPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"index.ts.hbs\",\n { Client: client, IR: ir },\n indexPath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template index.ts.hbs not found, using placeholder`);\n const content = `// Generated index - template rendering to be implemented`;\n await fs.promises.writeFile(indexPath, content, \"utf-8\");\n }\n }\n\n private async generateUtils(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const utilsPath = path.join(srcDir, \"utils.ts\");\n if (this.configService.shouldExcludeFile(client, utilsPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"utils.ts.hbs\",\n { Client: client, IR: ir },\n utilsPath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template utils.ts.hbs not found, using placeholder`);\n const content = `// Generated utils - template rendering to be implemented`;\n await fs.promises.writeFile(utilsPath, content, \"utf-8\");\n }\n }\n\n private async generateServices(\n client: TypeScriptClient,\n ir: IR,\n servicesDir: string\n ): Promise<void> {\n for (const service of ir.services) {\n const servicePath = path.join(\n servicesDir,\n `${toSnakeCase(service.tag).toLowerCase()}.ts`\n );\n if (this.configService.shouldExcludeFile(client, servicePath)) {\n continue;\n }\n try {\n await this.renderTemplate(\n \"service.ts.hbs\",\n { Client: client, Service: service, IR: ir },\n servicePath,\n client\n );\n } catch (error) {\n this.logger.warn(\n `Template service.ts.hbs not found, using placeholder`\n );\n const content = `// Generated service ${service.tag} - template rendering to be implemented`;\n await fs.promises.writeFile(servicePath, content, \"utf-8\");\n }\n }\n }\n\n private async generateSchema(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const schemaPath = path.join(srcDir, \"schema.ts\");\n if (this.configService.shouldExcludeFile(client, schemaPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"schema.ts.hbs\",\n { Client: client, IR: ir },\n schemaPath,\n client\n );\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.warn(\n `Template schema.ts.hbs error: ${errorMsg}, using placeholder`\n );\n const content = `// Generated schema - template rendering to be implemented`;\n await fs.promises.writeFile(schemaPath, content, \"utf-8\");\n }\n }\n\n private async generateZodSchema(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const zodSchemaPath = path.join(srcDir, \"schema.zod.ts\");\n if (this.configService.shouldExcludeFile(client, zodSchemaPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"schema.zod.ts.hbs\",\n { Client: client, IR: ir },\n zodSchemaPath,\n client\n );\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.warn(\n `Template schema.zod.ts.hbs error: ${errorMsg}, using placeholder`\n );\n const content = `// Generated Zod schemas - template rendering to be implemented`;\n await fs.promises.writeFile(zodSchemaPath, content, \"utf-8\");\n }\n }\n\n private async generatePackageJson(client: TypeScriptClient): Promise<void> {\n const packageJsonPath = path.join(client.outDir, \"package.json\");\n if (this.configService.shouldExcludeFile(client, packageJsonPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"package.json.hbs\",\n { Client: client },\n packageJsonPath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template package.json.hbs not found, using fallback`);\n const content = JSON.stringify(\n {\n name: client.packageName,\n version: \"0.0.1\",\n main: \"dist/index.js\",\n types: \"dist/index.d.ts\",\n },\n null,\n 2\n );\n await fs.promises.writeFile(packageJsonPath, content, \"utf-8\");\n }\n }\n\n private async generateTsConfig(client: TypeScriptClient): Promise<void> {\n const tsConfigPath = path.join(client.outDir, \"tsconfig.json\");\n if (this.configService.shouldExcludeFile(client, tsConfigPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"tsconfig.json.hbs\",\n { Client: client },\n tsConfigPath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template tsconfig.json.hbs not found, using fallback`);\n const content = JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2020\",\n module: \"commonjs\",\n lib: [\"ES2020\"],\n declaration: true,\n outDir: \"./dist\",\n rootDir: \"./src\",\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n },\n include: [\"src/**/*\"],\n },\n null,\n 2\n );\n await fs.promises.writeFile(tsConfigPath, content, \"utf-8\");\n }\n }\n\n private async generateReadme(\n client: TypeScriptClient,\n ir: IR\n ): Promise<void> {\n const readmePath = path.join(client.outDir, \"README.md\");\n if (this.configService.shouldExcludeFile(client, readmePath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"README.md.hbs\",\n { Client: client, IR: ir },\n readmePath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template README.md.hbs not found, using fallback`);\n const content = `# ${client.name}\\n\\nGenerated SDK from OpenAPI specification.`;\n await fs.promises.writeFile(readmePath, content, \"utf-8\");\n }\n }\n}\n","import * as Handlebars from \"handlebars\";\nimport {\n toPascalCase,\n toCamelCase,\n toSnakeCase,\n toKebabCase,\n} from \"../utils/string.utils\";\n\n/**\n * Register common Handlebars helpers that can be shared across all generators\n * These helpers are language-agnostic and work with any generator type\n */\nexport function registerCommonHandlebarsHelpers(): void {\n // String transformation helpers\n Handlebars.registerHelper(\"pascal\", (str: string) => toPascalCase(str));\n Handlebars.registerHelper(\"camel\", (str: string) => toCamelCase(str));\n Handlebars.registerHelper(\"kebab\", (str: string) => toKebabCase(str));\n Handlebars.registerHelper(\"snake\", (str: string) => toSnakeCase(str));\n Handlebars.registerHelper(\n \"serviceName\",\n (tag: string) => toPascalCase(tag) + \"Service\"\n );\n Handlebars.registerHelper(\"serviceProp\", (tag: string) => toCamelCase(tag));\n Handlebars.registerHelper(\"fileBase\", (tag: string) =>\n toSnakeCase(tag).toLowerCase()\n );\n\n // Comparison helpers\n Handlebars.registerHelper(\"eq\", (a: any, b: any) => a === b);\n Handlebars.registerHelper(\"ne\", (a: any, b: any) => a !== b);\n Handlebars.registerHelper(\"gt\", (a: any, b: any) => a > b);\n Handlebars.registerHelper(\"lt\", (a: any, b: any) => a < b);\n Handlebars.registerHelper(\"sub\", (a: number, b: number) => a - b);\n Handlebars.registerHelper(\"len\", (arr: any) =>\n Array.isArray(arr) ? arr.length : 0\n );\n Handlebars.registerHelper(\"or\", function (this: any, ...args: any[]) {\n const options = args[args.length - 1];\n if (options && options.fn) {\n // Block helper\n return args.slice(0, -1).some((a) => a)\n ? options.fn(this)\n : options.inverse(this);\n }\n // Regular helper\n return args.slice(0, -1).some((a) => a);\n });\n Handlebars.registerHelper(\"and\", function (this: any, ...args: any[]) {\n const options = args[args.length - 1];\n if (options && options.fn) {\n // Block helper\n return args.slice(0, -1).every((a) => a)\n ? options.fn(this)\n : options.inverse(this);\n }\n // Regular helper\n return args.slice(0, -1).every((a) => a);\n });\n\n // String manipulation helpers\n Handlebars.registerHelper(\n \"replace\",\n (str: string, search: string, replace: string) => {\n if (typeof str !== \"string\") return str;\n return str.replace(\n new RegExp(search.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), \"g\"),\n replace\n );\n }\n );\n Handlebars.registerHelper(\"index\", (arr: any[], idx: number) => arr?.[idx]);\n\n // Service/namespace helpers\n Handlebars.registerHelper(\"getServiceName\", (tag: string) => {\n const parts = tag.split(\".\");\n return parts.length > 1 ? parts[1] : tag;\n });\n Handlebars.registerHelper(\"groupByNamespace\", (services: any[]) => {\n const namespaces: Record<string, any[]> = {};\n for (const service of services) {\n const parts = service.tag.split(\".\");\n if (parts.length === 1) {\n if (!namespaces[\"\"]) namespaces[\"\"] = [];\n namespaces[\"\"].push(service);\n } else {\n const namespace = parts[0];\n if (!namespaces[namespace]) namespaces[namespace] = [];\n namespaces[namespace].push(service);\n }\n }\n return namespaces;\n });\n Handlebars.registerHelper(\"getRootServices\", (services: any[]) => {\n return services.filter((s) => !s.tag.includes(\".\"));\n });\n\n // Dictionary/object helpers for template state management\n Handlebars.registerHelper(\"dict\", () => ({}));\n Handlebars.registerHelper(\n \"setVar\",\n (name: string, value: any, options: any) => {\n if (options && options.data && options.data.root) {\n options.data.root[`_${name}`] = value;\n }\n return \"\";\n }\n );\n Handlebars.registerHelper(\"set\", (obj: any, key: string, value: any) => {\n if (obj && typeof obj === \"object\") {\n obj[key] = value;\n }\n return \"\";\n });\n Handlebars.registerHelper(\"hasKey\", (obj: any, key: string) => {\n return obj && typeof obj === \"object\" && key in obj;\n });\n Handlebars.registerHelper(\"lookup\", (obj: any, key: string) => {\n return obj && typeof obj === \"object\" ? obj[key] : undefined;\n });\n\n // Regex helper\n Handlebars.registerHelper(\"reMatch\", (pattern: string, str: string) => {\n try {\n const regex = new RegExp(pattern);\n return regex.test(str);\n } catch {\n return false;\n }\n });\n}\n","import { IRSchema, IRSchemaKind } from \"../../ir/ir.types\";\nimport { quoteTSPropertyName } from \"./helpers\";\n\n/**\n * Convert an IR schema to Zod schema string\n */\nexport function schemaToZodSchema(s: IRSchema, indent: string = \"\"): string {\n const nextIndent = indent + \" \";\n let zod: string;\n\n switch (s.kind) {\n case IRSchemaKind.String:\n zod = \"z.string()\";\n if (s.format === \"date\" || s.format === \"date-time\") {\n zod += \".datetime()\";\n } else if (s.format === \"email\") {\n zod += \".email()\";\n } else if (s.format === \"uri\" || s.format === \"url\") {\n zod += \".url()\";\n } else if (s.format === \"uuid\") {\n zod += \".uuid()\";\n }\n break;\n case IRSchemaKind.Number:\n zod = \"z.number()\";\n break;\n case IRSchemaKind.Integer:\n zod = \"z.number().int()\";\n break;\n case IRSchemaKind.Boolean:\n zod = \"z.boolean()\";\n break;\n case IRSchemaKind.Null:\n zod = \"z.null()\";\n break;\n case IRSchemaKind.Ref:\n if (s.ref) {\n zod = `Schema.${s.ref}Schema`;\n } else {\n zod = \"z.unknown()\";\n }\n break;\n case IRSchemaKind.Array:\n if (s.items) {\n const itemsZod = schemaToZodSchema(s.items, nextIndent);\n zod = `z.array(${itemsZod})`;\n } else {\n zod = \"z.array(z.unknown())\";\n }\n break;\n case IRSchemaKind.Object:\n if (!s.properties || s.properties.length === 0) {\n if (s.additionalProperties) {\n const valueZod = schemaToZodSchema(\n s.additionalProperties,\n nextIndent\n );\n zod = `z.record(z.string(), ${valueZod})`;\n } else {\n zod = \"z.record(z.string(), z.unknown())\";\n }\n } else {\n const props: string[] = [];\n for (const field of s.properties) {\n const fieldZod = schemaToZodSchema(field.type, nextIndent);\n const fieldName = quoteTSPropertyName(field.name);\n if (field.required) {\n props.push(`${nextIndent}${fieldName}: ${fieldZod}`);\n } else {\n props.push(`${nextIndent}${fieldName}: ${fieldZod}.optional()`);\n }\n }\n if (s.additionalProperties) {\n const valueZod = schemaToZodSchema(\n s.additionalProperties,\n nextIndent\n );\n props.push(`${nextIndent}...z.record(z.string(), ${valueZod}).shape`);\n }\n zod = `z.object({\\n${props.join(\",\\n\")}\\n${indent}})`;\n }\n break;\n case IRSchemaKind.Enum:\n if (s.enumValues && s.enumValues.length > 0) {\n // Create enum from string literals\n const enumValues = s.enumValues.map((v) => {\n // Handle boolean and number strings\n if (v === \"true\" || v === \"false\") {\n return v;\n }\n if (/^-?[0-9]+(\\.[0-9]+)?$/.test(v)) {\n return v;\n }\n return JSON.stringify(v);\n });\n zod = `z.enum([${enumValues.join(\", \")}])`;\n } else {\n zod = \"z.string()\";\n }\n break;\n case IRSchemaKind.OneOf:\n if (s.oneOf && s.oneOf.length > 0) {\n const options = s.oneOf.map((opt) =>\n schemaToZodSchema(opt, nextIndent)\n );\n zod = `z.union([${options.join(\", \")}])`;\n } else {\n zod = \"z.unknown()\";\n }\n break;\n case IRSchemaKind.AnyOf:\n if (s.anyOf && s.anyOf.length > 0) {\n const options = s.anyOf.map((opt) =>\n schemaToZodSchema(opt, nextIndent)\n );\n zod = `z.union([${options.join(\", \")}])`;\n } else {\n zod = \"z.unknown()\";\n }\n break;\n case IRSchemaKind.AllOf:\n if (s.allOf && s.allOf.length > 0) {\n const schemas = s.allOf.map((sch) =>\n schemaToZodSchema(sch, nextIndent)\n );\n // Zod doesn't have allOf, so we use intersection\n zod = schemas.join(\".and(\") + \")\".repeat(schemas.length - 1);\n } else {\n zod = \"z.unknown()\";\n }\n break;\n default:\n zod = \"z.unknown()\";\n }\n\n // Handle nullable\n if (s.nullable && zod !== \"z.null()\") {\n zod = `${zod}.nullable()`;\n }\n\n return zod;\n}\n","import { IROperation, IRSchema, IRSchemaKind } from \"../../ir/ir.types\";\nimport { Client } from \"../../config/config.schema\";\nimport { toPascalCase, toCamelCase } from \"../../utils/string.utils\";\n\n/**\n * Convert an IR schema to TypeScript type string\n */\n/**\n * Decode HTML entities in a string\n */\nfunction decodeHtmlEntities(str: string): string {\n return str\n .replace(/&quot;/g, '\"')\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&#x60;/g, \"`\")\n .replace(/&#96;/g, \"`\")\n .replace(/&amp;/g, \"&\");\n}\n\nexport function schemaToTSType(s: IRSchema): string {\n // Base type string without nullability; append null later\n let t: string;\n switch (s.kind) {\n case IRSchemaKind.String:\n if (s.format === \"binary\") {\n t = \"Blob\";\n } else {\n t = \"string\";\n }\n break;\n case IRSchemaKind.Number:\n case IRSchemaKind.Integer:\n t = \"number\";\n break;\n case IRSchemaKind.Boolean:\n t = \"boolean\";\n break;\n case IRSchemaKind.Null:\n t = \"null\";\n break;\n case IRSchemaKind.Ref:\n if (s.ref) {\n t = \"Schema.\" + s.ref;\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.Array:\n if (s.items) {\n const inner = schemaToTSType(s.items);\n // Wrap unions/intersections in parentheses inside Array<>\n if (inner.includes(\" | \") || inner.includes(\" & \")) {\n t = `Array<(${inner})>`;\n } else {\n t = `Array<${inner}>`;\n }\n } else {\n t = \"Array<unknown>\";\n }\n break;\n case IRSchemaKind.OneOf:\n if (s.oneOf) {\n const parts = s.oneOf.map((sub) => schemaToTSType(sub));\n t = parts.join(\" | \");\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.AnyOf:\n if (s.anyOf) {\n const parts = s.anyOf.map((sub) => schemaToTSType(sub));\n t = parts.join(\" | \");\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.AllOf:\n if (s.allOf) {\n const parts = s.allOf.map((sub) => schemaToTSType(sub));\n t = parts.join(\" & \");\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.Enum:\n if (s.enumValues && s.enumValues.length > 0) {\n const vals: string[] = [];\n switch (s.enumBase) {\n case IRSchemaKind.Number:\n case IRSchemaKind.Integer:\n for (const v of s.enumValues) {\n vals.push(v);\n }\n break;\n case IRSchemaKind.Boolean:\n for (const v of s.enumValues) {\n if (v === \"true\" || v === \"false\") {\n vals.push(v);\n } else {\n vals.push(`\"${v}\"`);\n }\n }\n break;\n default:\n for (const v of s.enumValues) {\n vals.push(`\"${v}\"`);\n }\n }\n t = vals.join(\" | \");\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.Object:\n if (!s.properties || s.properties.length === 0) {\n t = \"Record<string, unknown>\";\n } else {\n // Inline object shape for rare cases; nested ones should be refs\n const parts: string[] = [];\n for (const f of s.properties) {\n const ft = schemaToTSType(f.type);\n if (f.required) {\n parts.push(`${f.name}: ${ft}`);\n } else {\n parts.push(`${f.name}?: ${ft}`);\n }\n }\n t = \"{ \" + parts.join(\"; \") + \" }\";\n }\n break;\n default:\n t = \"unknown\";\n }\n if (s.nullable && t !== \"null\") {\n t += \" | null\";\n }\n // Decode any HTML entities that might be in the type string\n return decodeHtmlEntities(t);\n}\n\n/**\n * Derive method name using basic REST-style heuristics\n */\nexport function deriveMethodName(op: IROperation): string {\n // Basic REST-style heuristics\n const path = op.path;\n const hasID = path.includes(\"{\") && path.includes(\"}\");\n\n if (op.operationID) {\n return toCamelCase(op.operationID);\n }\n\n switch (op.method) {\n case \"GET\":\n return hasID ? \"get\" : \"list\";\n case \"POST\":\n return \"create\";\n case \"PUT\":\n case \"PATCH\":\n return \"update\";\n case \"DELETE\":\n return \"delete\";\n default:\n return op.method.toLowerCase();\n }\n}\n\n/**\n * Resolve method name using optional parser function, then operationId, then heuristic\n */\nexport async function resolveMethodName(\n client: Client,\n op: IROperation\n): Promise<string> {\n // Try function-based parser if provided\n if (client.operationIdParser) {\n try {\n const name = await client.operationIdParser(\n op.operationID,\n op.method,\n op.path\n );\n if (name) {\n return toCamelCase(name);\n }\n } catch {\n // Parser failed, continue with defaults\n }\n }\n\n // Default parse of operationId\n const defaultParsed = defaultParseOperationID(op.operationID);\n if (defaultParsed) {\n return toCamelCase(defaultParsed);\n }\n\n return deriveMethodName(op);\n}\n\n/**\n * Default parse operation ID\n */\nfunction defaultParseOperationID(opID: string): string {\n if (!opID) {\n return \"\";\n }\n // Strip any prefix up to and including \"Controller_\"\n const idx = opID.indexOf(\"Controller_\");\n if (idx >= 0) {\n return opID.substring(idx + \"Controller_\".length);\n }\n return opID;\n}\n\n/**\n * Build path template converts OpenAPI path to TypeScript template literal\n */\nexport function buildPathTemplate(op: IROperation): string {\n // Convert /foo/{id}/bar/{slug} -> `/foo/${encodeURIComponent(id)}/bar/${encodeURIComponent(slug)}`\n let path = op.path;\n let result = \"`\";\n for (let i = 0; i < path.length; i++) {\n if (path[i] === \"{\") {\n // read name\n let j = i + 1;\n while (j < path.length && path[j] !== \"}\") {\n j++;\n }\n if (j < path.length) {\n const name = path.substring(i + 1, j);\n result += `\\${encodeURIComponent(${name})}`;\n i = j;\n continue;\n }\n }\n result += path[i];\n }\n result += \"`\";\n return result;\n}\n\n/**\n * Build query key base returns a TS string literal for the base of a react-query key\n */\nexport function buildQueryKeyBase(op: IROperation): string {\n const path = op.path;\n // Split by '/'; skip parameter placeholders like {id}\n const parts = path.split(\"/\");\n const baseParts: string[] = [];\n for (const p of parts) {\n if (p === \"\") {\n // leading slash\n continue;\n }\n if (p.startsWith(\"{\") && p.endsWith(\"}\")) {\n continue;\n }\n baseParts.push(p);\n }\n const base = baseParts.join(\"/\");\n return `'${base}'`;\n}\n\n/**\n * Order path params extracts path parameter order as they appear in the path\n */\nexport function orderPathParams(op: IROperation) {\n const ordered: typeof op.pathParams = [];\n const index = new Map<string, number>();\n for (let i = 0; i < op.pathParams.length; i++) {\n index.set(op.pathParams[i].name, i);\n }\n const path = op.path;\n for (let i = 0; i < path.length; i++) {\n if (path[i] === \"{\") {\n let j = i + 1;\n while (j < path.length && path[j] !== \"}\") {\n j++;\n }\n if (j < path.length) {\n const name = path.substring(i + 1, j);\n const idx = index.get(name);\n if (idx !== undefined) {\n ordered.push(op.pathParams[idx]);\n }\n i = j;\n continue;\n }\n }\n }\n return ordered;\n}\n\n/**\n * Build method signature constructs the TS parameter list\n */\nexport function buildMethodSignature(\n op: IROperation,\n methodName: string\n): string[] {\n const parts: string[] = [];\n // path params as positional args\n for (const p of orderPathParams(op)) {\n parts.push(`${p.name}: ${schemaToTSType(p.schema)}`);\n }\n // query object\n if (op.queryParams.length > 0) {\n // Reference named interface defined in schema.ts\n const queryType = toPascalCase(op.tag) + toPascalCase(methodName) + \"Query\";\n parts.push(`query?: Schema.${queryType}`);\n }\n // body\n if (op.requestBody) {\n const opt = op.requestBody.required ? \"\" : \"?\";\n parts.push(`body${opt}: ${schemaToTSType(op.requestBody.schema)}`);\n }\n // init\n parts.push('init?: Omit<RequestInit, \"method\" | \"body\">');\n\n return parts;\n}\n\n/**\n * Query key args returns the parameter names (no types) in the same order as the method parameters\n */\nexport function queryKeyArgs(op: IROperation): string[] {\n const out: string[] = [];\n for (const p of orderPathParams(op)) {\n out.push(p.name);\n }\n if (op.queryParams.length > 0) {\n out.push(\"query\");\n }\n if (op.requestBody) {\n out.push(\"body\");\n }\n return out;\n}\n\n/**\n * Quote TS property name quotes TypeScript property names that contain special characters\n */\nexport function quoteTSPropertyName(name: string): string {\n // Check if the name contains characters that require quoting\n let needsQuoting = false;\n for (const char of name) {\n if (\n !(\n (char >= \"a\" && char <= \"z\") ||\n (char >= \"A\" && char <= \"Z\") ||\n (char >= \"0\" && char <= \"9\") ||\n char === \"_\" ||\n char === \"$\"\n )\n ) {\n needsQuoting = true;\n break;\n }\n }\n\n // Also quote if the name starts with a number\n if (name.length > 0 && name[0] >= \"0\" && name[0] <= \"9\") {\n needsQuoting = true;\n }\n\n if (needsQuoting) {\n return `\"${name}\"`;\n }\n return name;\n}\n\n// Re-export schemaToZodSchema from dedicated file\nexport { schemaToZodSchema } from \"./zod-schema-converter\";\n\n/**\n * Check if an operation has a streaming response\n */\nexport function isStreamingOperation(op: IROperation): boolean {\n return op.response.isStreaming === true;\n}\n\n/**\n * Get the item type for a streaming response\n * For streaming, we typically want the item type from an array schema\n */\nexport function getStreamingItemType(op: IROperation): string {\n const schema = op.response.schema;\n\n // If it's an array, return the item type\n if (schema.kind === IRSchemaKind.Array && schema.items) {\n return schemaToTSType(schema.items);\n }\n\n // For SSE, the data field is typically a string\n if (op.response.streamingFormat === \"sse\") {\n return \"string\";\n }\n\n // Default: return the schema type itself\n return schemaToTSType(schema);\n}\n","import { Config, Client } from \"../config/config.schema\";\nimport { loadMjsConfig } from \"../config/mjs-config-loader\";\nimport { ConfigService } from \"../config/config.service\";\nimport { OpenApiService } from \"../openapi/openapi.service\";\nimport { IrBuilderService } from \"../generator/ir-builder.service\";\nimport { GeneratorService } from \"../generator/generator.service\";\nimport { SchemaConverterService } from \"../generator/schema-converter.service\";\nimport { TypeScriptGeneratorService } from \"../generator/typescript/typescript-generator.service\";\nimport * as path from \"path\";\nimport * as fs from \"fs\";\n\n/**\n * Options for programmatic SDK generation\n */\nexport interface GenerateOptions {\n /**\n * Generate only the named client from config\n */\n client?: string;\n}\n\n/**\n * Standalone function to generate SDKs from a config object or config file path.\n * This function can be used programmatically without NestJS dependency injection.\n *\n * @param configOrPath - Config object or path to chunkflow-codegen.config.mjs file\n * @param options - Optional generation options\n * @returns Promise that resolves when generation is complete\n *\n * @example\n * ```typescript\n * import { generate } from '@blimu/codegen';\n *\n * // Using config object\n * await generate({\n * spec: 'http://localhost:3020/docs/backend-api/json',\n * clients: [{\n * type: 'typescript',\n * outDir: './my-sdk',\n * packageName: 'my-sdk',\n * name: 'MyClient'\n * }]\n * });\n *\n * // Using config file path\n * await generate('./chunkflow-codegen.config.mjs');\n * ```\n */\nexport async function generate(\n configOrPath: Config | string,\n options?: GenerateOptions\n): Promise<void> {\n // Load config if string path\n let config: Config;\n if (typeof configOrPath === \"string\") {\n config = await loadMjsConfig(configOrPath);\n } else {\n config = configOrPath;\n }\n\n // Initialize services (standalone, no NestJS DI)\n const configService = new ConfigService();\n const openApiService = new OpenApiService();\n const schemaConverter = new SchemaConverterService();\n const irBuilder = new IrBuilderService(schemaConverter);\n const generatorService = new GeneratorService(irBuilder, openApiService);\n\n // Register TypeScript generator\n const typeScriptGenerator = new TypeScriptGeneratorService(configService);\n generatorService.register(typeScriptGenerator);\n\n // Generate for each client\n for (const client of config.clients) {\n if (options?.client && client.name !== options.client) {\n continue;\n }\n\n // Ensure output directory exists\n await fs.promises.mkdir(client.outDir, { recursive: true });\n\n // Generate the SDK\n await generatorService.generate(config.spec, client);\n }\n}\n\n/**\n * Load a config file programmatically\n *\n * @param configPath - Path to chunkflow-codegen.config.mjs file\n * @returns Promise that resolves to the loaded config\n *\n * @example\n * ```typescript\n * import { loadConfig } from '@blimu/codegen';\n *\n * const config = await loadConfig('./chunkflow-codegen.config.mjs');\n * ```\n */\nexport async function loadConfig(configPath: string): Promise<Config> {\n return loadMjsConfig(configPath);\n}\n"],"mappings":"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","names":["z","TypeAugmentationOptionsSchema","object","moduleName","string","optional","namespace","typeNames","array","outputFileName","TYPESCRIPT_TEMPLATE_NAMES","BaseClientSchema","type","min","outDir","name","includeTags","excludeTags","operationIdParser","custom","preCommand","postCommand","defaultBaseURL","exclude","typeAugmentation","TypeScriptClientSchema","extend","literal","packageName","includeQueryKeys","boolean","templates","record","refine","Object","keys","every","key","includes","message","join","ClientSchema","discriminatedUnion","ConfigSchema","spec","clients","Injectable","Logger","fs","path","pathToFileURL","path","loadMjsConfig","configPath","absolutePath","isAbsolute","resolve","configModule","pathToFileURL","href","config","default","Error","ConfigSchema","parse","error","message","ConfigService","logger","Logger","name","DEFAULT_CONFIG_FILE","findDefaultConfig","currentDir","process","cwd","root","parse","configPath","join","promises","access","dirname","load","config","loadMjsConfig","normalizePaths","error","Error","message","configDir","resolve","spec","isUrl","isAbsolute","clients","map","client","outDir","str","url","URL","protocol","getPreCommand","preCommand","getPostCommand","postCommand","shouldExcludeFile","targetPath","exclude","length","relPath","relative","posix","normalize","excludePattern","normalizedExclude","startsWith","Module","ConfigModule","providers","ConfigService","exports","defineConfig","config","IRSchemaKind","Injectable","Logger","Injectable","Injectable","detectOpenAPIVersion","doc","version","openapi","startsWith","isSupportedVersion","getSchemaFromRef","doc","schemaRef","$ref","ref","startsWith","name","replace","components","schemas","schema","isSchemaNullable","nullable","Array","isArray","type","includes","getSchemaType","SchemaConverterService","schemaRefToIR","doc","schemaRef","kind","IRSchemaKind","Unknown","nullable","$ref","ref","startsWith","name","replace","Ref","parts","split","length","schema","getSchemaFromRef","isSchemaNullable","discriminator","propertyName","mapping","oneOf","subs","map","sub","OneOf","anyOf","AnyOf","allOf","AllOf","not","Not","enum","enumValues","v","String","enumBase","inferEnumBaseKind","Enum","enumRaw","type","getSchemaType","normalizedType","Array","isArray","filter","t","format","Integer","Number","Boolean","arraySchema","items","properties","propNames","Object","keys","sort","prop","fieldType","required","includes","push","annotations","extractAnnotations","additionalProperties","title","description","deprecated","readOnly","writeOnly","default","examples","example","undefined","first","isInteger","toPascalCase","s","trim","parts","split","filter","p","allParts","part","subParts","splitCamelCase","push","map","charAt","toUpperCase","slice","toLowerCase","join","toCamelCase","pascal","toSnakeCase","toKebabCase","current","chars","Array","from","i","length","char","isNewWord","isUppercase","IrBuilderService","schemaConverter","buildIR","doc","tags","collectTags","securitySchemes","collectSecuritySchemes","modelDefs","buildStructuredModels","allowed","tag","result","buildIRFromDoc","filterIR","fullIR","client","include","compileTagFilters","includeTags","exclude","excludeTags","filteredServices","service","services","filteredOps","op","operations","shouldIncludeOperation","originalTags","push","length","filteredIR","models","filterUnusedModelDefs","detectStreamingContentType","contentType","normalized","toLowerCase","split","trim","isStreaming","format","includes","uniq","Set","add","paths","path","pathItem","Object","entries","get","post","put","patch","delete","options","head","trace","Array","from","sort","patterns","map","p","RegExp","error","Error","message","String","included","r","test","servicesMap","extractedTypes","seenTypeNames","addOp","__name","method","id","operationId","pathParams","queryParams","collectParams","requestBody","reqBody","reqBodyTypes","extractRequestBodyWithTypes","response","resp","respTypes","extractResponseWithTypes","operationID","summary","description","deprecated","t","firstAllowedTag","values","a","b","localeCompare","deriveMethodName","toCamelCase","hasID","components","names","keys","out","name","scheme","sc","key","type","bearerFormat","in","parameters","pr","schema","schemaRefToIR","param","required","rb","methodName","typeName","toPascalCase","content","media","kind","IRSchemaKind","has","annotations","extractAnnotations","typeTS","Ref","ref","nullable","extractRequestBody","firstContentType","responses","Unknown","tryCodes","code","streaming","streamingFormat","firstMedia","firstSchema","firstStreaming","extractResponse","schemas","seen","sr","allModelDefs","modelDefMap","Map","md","set","referenced","visited","collectRefs","refName","items","additionalProperties","oneOf","sub","anyOf","allOf","not","properties","field","filter","Injectable","Logger","SwaggerParser","fs","path","OpenApiService","logger","Logger","name","loadDocument","input","url","URL","api","protocol","debug","SwaggerParser","dereference","filePath","resolve","existsSync","Error","version","detectOpenAPIVersion","isSupportedVersion","openapi","log","error","message","validateDocument","validate","GeneratorService","logger","Logger","name","generators","Map","irBuilder","openApiService","register","generator","set","getType","debug","getGenerator","type","get","getAvailableTypes","Array","from","keys","generate","spec","client","Error","doc","loadDocument","fullIR","buildIR","filteredIR","filterIR","Module","Module","OpenApiModule","providers","OpenApiService","exports","Injectable","Logger","fs","path","Handlebars","Handlebars","registerCommonHandlebarsHelpers","registerHelper","str","toPascalCase","toCamelCase","toKebabCase","toSnakeCase","tag","toLowerCase","a","b","arr","Array","isArray","length","args","options","fn","slice","some","inverse","every","search","replace","RegExp","idx","parts","split","services","namespaces","service","push","namespace","filter","s","includes","name","value","data","root","obj","key","undefined","pattern","test","schemaToZodSchema","s","indent","nextIndent","zod","kind","IRSchemaKind","String","format","Number","Integer","Boolean","Null","Ref","ref","Array","items","itemsZod","Object","properties","length","additionalProperties","valueZod","props","field","fieldZod","type","fieldName","quoteTSPropertyName","name","required","push","join","Enum","enumValues","map","v","test","JSON","stringify","OneOf","oneOf","opt","AnyOf","anyOf","AllOf","allOf","schemas","sch","repeat","nullable","decodeHtmlEntities","str","replace","schemaToTSType","s","t","kind","IRSchemaKind","String","format","Number","Integer","Boolean","Null","Ref","ref","Array","items","inner","includes","OneOf","oneOf","map","sub","join","AnyOf","anyOf","AllOf","allOf","Enum","enumValues","length","vals","enumBase","v","push","Object","properties","parts","f","ft","type","required","name","nullable","deriveMethodName","op","path","hasID","operationID","toCamelCase","method","toLowerCase","resolveMethodName","client","operationIdParser","defaultParsed","defaultParseOperationID","opID","idx","indexOf","substring","buildPathTemplate","result","i","j","buildQueryKeyBase","split","baseParts","p","startsWith","endsWith","base","orderPathParams","ordered","index","Map","pathParams","set","get","undefined","buildMethodSignature","methodName","schema","queryParams","queryType","toPascalCase","tag","requestBody","opt","queryKeyArgs","out","quoteTSPropertyName","needsQuoting","char","isStreamingOperation","response","isStreaming","getStreamingItemType","streamingFormat","TypeScriptGeneratorService","logger","Logger","name","configService","getType","generate","client","ir","srcDir","join","outDir","servicesDir","promises","mkdir","recursive","processedIR","preprocessIR","registerHandlebarsHelpers","generateClient","generateIndex","generateUtils","generateServices","generateSchema","generateZodSchema","generatePackageJson","generateTsConfig","generateReadme","processedServices","Promise","all","services","map","service","operations","op","methodName","resolveMethodName","_resolvedMethodName","registerCommonHandlebarsHelpers","registerHelper","deriveMethodName","toPascalCase","tag","result","buildPathTemplate","SafeString","buildQueryKeyBase","orderPathParams","buildMethodSignature","s","slice","queryKeyArgs","x","schemaToTSType","replace","stripped","str","quoteTSPropertyName","schemaToZodSchema","isStreamingOperation","getStreamingItemType","renderTemplate","templateName","data","outputPath","overridePath","templates","debug","access","constants","R_OK","templateContent","readFile","rendered","compile","writeFile","error","errorMsg","Error","message","String","possiblePaths","__dirname","process","cwd","templatePath","possiblePath","clientPath","shouldExcludeFile","Client","IR","warn","indexPath","utilsPath","servicePath","toSnakeCase","toLowerCase","Service","content","schemaPath","zodSchemaPath","packageJsonPath","JSON","stringify","packageName","version","main","types","tsConfigPath","compilerOptions","target","module","lib","declaration","rootDir","strict","esModuleInterop","skipLibCheck","forceConsistentCasingInFileNames","include","readmePath","GeneratorModule","generatorService","typeScriptGenerator","register","imports","OpenApiModule","ConfigModule","providers","GeneratorService","IrBuilderService","SchemaConverterService","TypeScriptGeneratorService","exports","fs","generate","configOrPath","options","config","loadMjsConfig","configService","ConfigService","openApiService","OpenApiService","schemaConverter","SchemaConverterService","irBuilder","IrBuilderService","generatorService","GeneratorService","typeScriptGenerator","TypeScriptGeneratorService","register","client","clients","name","promises","mkdir","outDir","recursive","spec","loadConfig","configPath"]}
1
+ {"version":3,"sources":["../src/config/config.schema.ts","../src/config/config.service.ts","../src/config/mjs-config-loader.ts","../src/config/config.module.ts","../src/config/config-helper.ts","../src/ir/ir.types.ts","../src/generator/generator.service.ts","../src/generator/ir-builder.service.ts","../src/generator/schema-converter.service.ts","../src/openapi/openapi-version.utils.ts","../src/openapi/openapi.types.ts","../src/utils/string.utils.ts","../src/openapi/openapi.service.ts","../src/generator/generator.module.ts","../src/openapi/openapi.module.ts","../src/generator/typescript/typescript-generator.service.ts","../src/generator/handlebars-helpers.ts","../src/generator/typescript/zod-schema-converter.ts","../src/generator/typescript/helpers.ts","../src/api/generate.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Type definition for operationId parser function.\n * Transforms operationId, method, and path into a method name.\n * Can be synchronous or asynchronous.\n */\nexport type OperationIdParser = (\n operationId: string,\n method: string,\n path: string\n) => string | Promise<string>;\n\n/**\n * Pre-defined type schema for importing types from external packages\n */\nexport const PredefinedTypeSchema = z.object({\n // Component schema name (e.g., \"ResourceType\")\n type: z.string().min(1, \"Type name is required\"),\n // Package name (e.g., \"@blimu/types\")\n package: z.string().min(1, \"Package name is required\"),\n // Optional import path (defaults to package root)\n importPath: z.string().optional(),\n});\n\nexport type PredefinedType = z.infer<typeof PredefinedTypeSchema>;\n\n/**\n * Valid template names for TypeScript generator\n */\nexport const TYPESCRIPT_TEMPLATE_NAMES = [\n \"client.ts.hbs\",\n \"index.ts.hbs\",\n \"package.json.hbs\",\n \"README.md.hbs\",\n \"schema.ts.hbs\",\n \"schema.zod.ts.hbs\",\n \"service.ts.hbs\",\n \"tsconfig.json.hbs\",\n \"utils.ts.hbs\",\n] as const;\n\nexport type TypeScriptTemplateName = (typeof TYPESCRIPT_TEMPLATE_NAMES)[number];\n\n/**\n * Base client schema with common options shared across all generators\n */\nconst BaseClientSchema = z.object({\n type: z.string().min(1, \"Type is required\"),\n outDir: z.string().min(1, \"OutDir is required\"),\n name: z.string().min(1, \"Name is required\"),\n includeTags: z.array(z.string()).optional(),\n excludeTags: z.array(z.string()).optional(),\n // OperationIDParser is an optional function to transform operationId to a method name.\n // Function signature: (operationId: string, method: string, path: string) => string | Promise<string>\n // Note: Zod doesn't validate function signatures at runtime, but TypeScript will enforce the type\n operationIdParser: z.custom<OperationIdParser>().optional(),\n // PreCommand is an optional command to run before SDK generation starts.\n // Uses Docker Compose array format: [\"goimports\", \"-w\", \".\"]\n // The command will be executed in the output directory.\n preCommand: z.array(z.string()).optional(),\n // PostCommand is an optional command to run after SDK generation completes.\n // Uses Docker Compose array format: [\"goimports\", \"-w\", \".\"]\n // The command will be executed in the output directory.\n postCommand: z.array(z.string()).optional(),\n // DefaultBaseURL is the default base URL that will be used if no base URL is provided when creating a client\n defaultBaseURL: z.string().optional(),\n // ExcludeFiles is a list of file paths (relative to outDir) that should not be generated\n // Example: [\"package.json\", \"src/client.ts\"]\n exclude: z.array(z.string()).optional(),\n});\n\n/**\n * TypeScript-specific client schema\n */\nexport const TypeScriptClientSchema = BaseClientSchema.extend({\n type: z.literal(\"typescript\"),\n packageName: z.string().min(1, \"PackageName is required\"),\n moduleName: z.string().optional(),\n // IncludeQueryKeys toggles generation of __queryKeys helper methods in services\n includeQueryKeys: z.boolean().optional(),\n // Pre-defined types to import from external packages instead of generating locally\n predefinedTypes: z.array(PredefinedTypeSchema).optional(),\n // Dependencies with explicit versions (e.g., { \"@blimu/types\": \"^0.1.0\" })\n // If not specified, predefined type packages will use \"*\" version\n dependencies: z.record(z.string(), z.string()).optional(),\n // DevDependencies with explicit versions (e.g., { \"@types/jsonwebtoken\": \"^9\" })\n devDependencies: z.record(z.string(), z.string()).optional(),\n // Template overrides - maps valid template names to file paths\n templates: z\n .record(z.string(), z.string())\n .refine(\n (templates) => {\n // Validate that all keys are valid template names\n return Object.keys(templates).every((key) =>\n TYPESCRIPT_TEMPLATE_NAMES.includes(key as TypeScriptTemplateName)\n );\n },\n {\n message: `Template names must be one of: ${TYPESCRIPT_TEMPLATE_NAMES.join(\", \")}`,\n }\n )\n .optional(),\n});\n\n/**\n * Discriminated union of all client types\n * Add new generator types here as they are implemented\n */\nexport const ClientSchema = z.discriminatedUnion(\"type\", [\n TypeScriptClientSchema,\n // Future generators can be added here:\n // PythonClientSchema,\n // GoClientSchema,\n // etc.\n]);\n\nexport const ConfigSchema = z.object({\n spec: z.string().min(1, \"Spec is required\"),\n name: z.string().optional(),\n clients: z.array(ClientSchema).min(1, \"At least one client is required\"),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\nexport type Client = z.infer<typeof ClientSchema>;\nexport type TypeScriptClient = z.infer<typeof TypeScriptClientSchema>;\n","import { Injectable, Logger } from \"@nestjs/common\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { Config, ConfigSchema, Client } from \"./config.schema\";\nimport { loadMjsConfig } from \"./mjs-config-loader\";\n\n@Injectable()\nexport class ConfigService {\n private readonly logger = new Logger(ConfigService.name);\n private readonly DEFAULT_CONFIG_FILE = \"chunkflow-codegen.config.mjs\";\n\n /**\n * Find default config file in current directory and parent directories\n */\n async findDefaultConfig(): Promise<string | null> {\n let currentDir = process.cwd();\n const root = path.parse(currentDir).root;\n\n while (currentDir !== root) {\n const configPath = path.join(currentDir, this.DEFAULT_CONFIG_FILE);\n try {\n await fs.promises.access(configPath);\n return configPath;\n } catch {\n // File doesn't exist, continue searching\n }\n currentDir = path.dirname(currentDir);\n }\n\n return null;\n }\n\n /**\n * Load configuration from an MJS file\n */\n async load(configPath: string): Promise<Config> {\n try {\n // Load MJS config\n const config = await loadMjsConfig(configPath);\n\n // Normalize paths\n return this.normalizePaths(config, configPath);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to load config from ${configPath}: ${error.message}`\n );\n }\n throw error;\n }\n }\n\n /**\n * Normalize paths in the config to be absolute\n */\n private normalizePaths(config: Config, configPath: string): Config {\n const configDir = path.dirname(path.resolve(configPath));\n\n // Normalize spec path\n let spec = config.spec;\n if (!this.isUrl(spec)) {\n if (!path.isAbsolute(spec)) {\n spec = path.resolve(configDir, spec);\n }\n }\n\n // Normalize client outDir paths\n const clients = config.clients.map((client) => {\n let outDir = client.outDir;\n if (!path.isAbsolute(outDir)) {\n outDir = path.resolve(configDir, outDir);\n }\n return { ...client, outDir };\n });\n\n return {\n ...config,\n spec,\n clients,\n };\n }\n\n /**\n * Check if a string is a URL\n */\n private isUrl(str: string): boolean {\n try {\n const url = new URL(str);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n }\n\n /**\n * Get pre-command for a client\n */\n getPreCommand(client: Client): string[] {\n return client.preCommand || [];\n }\n\n /**\n * Get post-command for a client\n */\n getPostCommand(client: Client): string[] {\n return client.postCommand || [];\n }\n\n /**\n * Check if a file should be excluded based on the ExcludeFiles list.\n * targetPath should be an absolute path, and the comparison is done relative to OutDir.\n */\n shouldExcludeFile(client: Client, targetPath: string): boolean {\n if (!client.exclude || client.exclude.length === 0) {\n return false;\n }\n\n // Get relative path from OutDir to targetPath\n let relPath: string;\n try {\n relPath = path.relative(client.outDir, targetPath);\n } catch {\n // If we can't get a relative path, the file is not under OutDir, so don't exclude\n return false;\n }\n\n // Normalize the path (use forward slashes for consistency, handle . and ..)\n relPath = path.posix.normalize(relPath);\n if (relPath === \".\") {\n relPath = \"\";\n }\n\n // Check if the relative path matches any exclude pattern\n for (const excludePattern of client.exclude) {\n // Normalize exclude pattern\n const normalizedExclude = path.posix.normalize(excludePattern);\n\n // Exact match\n if (relPath === normalizedExclude) {\n return true;\n }\n\n // Check if the file is in a directory that matches the exclude pattern\n // For example, if exclude is \"src/\", then \"src/client.ts\" should match\n if (\n normalizedExclude !== \"\" &&\n relPath.startsWith(normalizedExclude + \"/\")\n ) {\n return true;\n }\n }\n\n return false;\n }\n}\n","import { pathToFileURL } from \"url\";\nimport * as path from \"path\";\nimport { Config, ConfigSchema } from \"./config.schema\";\n\n/**\n * Load configuration from an MJS (ES Module) file.\n * Supports both default export and named export patterns.\n *\n * @param configPath - Absolute or relative path to the MJS config file\n * @returns Validated configuration object\n * @throws Error if the config file cannot be loaded or validated\n */\nexport async function loadMjsConfig(configPath: string): Promise<Config> {\n try {\n // Resolve to absolute path\n const absolutePath = path.isAbsolute(configPath)\n ? configPath\n : path.resolve(configPath);\n\n // Convert to file:// URL for dynamic import\n const fileUrl = pathToFileURL(absolutePath).href;\n\n // Dynamic import the MJS file\n const configModule = await import(fileUrl);\n\n // Support both default export and named export\n const config = configModule.default || configModule;\n\n if (!config) {\n throw new Error(\n `Config file must export a default export or named export: ${configPath}`\n );\n }\n\n // Validate with Zod schema\n const validated = ConfigSchema.parse(config);\n\n return validated;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to load MJS config from ${configPath}: ${error.message}`\n );\n }\n throw error;\n }\n}\n","import { Module } from \"@nestjs/common\";\nimport { ConfigService } from \"./config.service\";\n\n@Module({\n providers: [ConfigService],\n exports: [ConfigService],\n})\nexport class ConfigModule {}\n","import { Config, ConfigSchema } from \"./config.schema\";\n\n/**\n * Helper function to define a codegen configuration with full TypeScript type inference and runtime validation.\n * Use this in MJS config files for type safety and validation.\n *\n * This function validates the config at runtime using Zod, ensuring that:\n * - All required fields are present\n * - All field types are correct\n * - Generator-specific options are valid\n * - Template overrides use valid template names\n *\n * @example\n * ```javascript\n * import { defineConfig } from '@blimu/codegen';\n *\n * export default defineConfig({\n * spec: 'http://localhost:3020/docs/backend-api/json',\n * clients: [{\n * type: 'typescript',\n * outDir: './my-sdk',\n * packageName: 'my-sdk',\n * name: 'MyClient',\n * templates: {\n * 'client.ts.hbs': './custom/client.ts.hbs',\n * },\n * }]\n * });\n * ```\n *\n * @param config - The configuration object to validate\n * @returns The validated configuration object\n * @throws Error if the configuration is invalid\n */\nexport function defineConfig(config: Config): Config {\n // Validate the config using Zod schema\n return ConfigSchema.parse(config);\n}\n","// Intermediate Representation types - language-agnostic representation of OpenAPI specs\n\nexport enum IRSchemaKind {\n Unknown = \"unknown\",\n String = \"string\",\n Number = \"number\",\n Integer = \"integer\",\n Boolean = \"boolean\",\n Null = \"null\",\n Array = \"array\",\n Object = \"object\",\n Enum = \"enum\",\n Ref = \"ref\",\n OneOf = \"oneOf\",\n AnyOf = \"anyOf\",\n AllOf = \"allOf\",\n Not = \"not\",\n}\n\nexport interface IROperation {\n operationID: string;\n method: string;\n path: string;\n tag: string; // The primary tag used for service grouping (first allowed tag)\n originalTags: string[]; // All original tags from the OpenAPI operation\n summary: string;\n description: string;\n deprecated: boolean;\n pathParams: IRParam[];\n queryParams: IRParam[];\n requestBody: IRRequestBody | null;\n response: IRResponse;\n}\n\nexport interface IRService {\n tag: string;\n operations: IROperation[];\n}\n\nexport interface IR {\n services: IRService[];\n models: IRModel[];\n securitySchemes: IRSecurityScheme[];\n // ModelDefs holds a language-agnostic structured representation of components schemas\n modelDefs: IRModelDef[];\n // OpenAPI document used to generate this IR (optional, for saving spec to SDK package)\n openApiDocument?: any; // OpenAPIDocument type, but using any to avoid circular dependency\n}\n\nexport interface IRParam {\n name: string;\n required: boolean;\n schema: IRSchema;\n // Description from the OpenAPI parameter\n description: string;\n}\n\nexport interface IRRequestBody {\n contentType: string;\n typeTS: string;\n required: boolean;\n schema: IRSchema;\n}\n\nexport interface IRResponse {\n typeTS: string;\n schema: IRSchema;\n // Description contains the response description chosen for this operation\n description: string;\n // Streaming support\n isStreaming: boolean;\n contentType: string;\n streamingFormat?: \"sse\" | \"ndjson\" | \"chunked\";\n}\n\n// IRModel represents a generated model (legacy, kept for compatibility)\nexport interface IRModel {\n name: string;\n decl: string;\n}\n\n// IRModelDef represents a named model (typically a component or a generated inline type)\n// with a structured schema that is language-agnostic.\nexport interface IRModelDef {\n name: string;\n schema: IRSchema;\n annotations: IRAnnotations;\n}\n\n// IRAnnotations captures non-structural metadata that some generators may render.\nexport interface IRAnnotations {\n title?: string;\n description?: string;\n deprecated?: boolean;\n readOnly?: boolean;\n writeOnly?: boolean;\n default?: any;\n examples?: any[];\n}\n\n// IRSchema models a JSON Schema (as used by OpenAPI 3.1) shape in a language-agnostic way\nexport interface IRSchema {\n kind: IRSchemaKind;\n nullable: boolean;\n format?: string;\n\n // Object\n properties?: IRField[];\n additionalProperties?: IRSchema; // typed maps; undefined when absent\n\n // Array\n items?: IRSchema;\n\n // Enum\n enumValues?: string[]; // stringified values for portability\n enumRaw?: any[]; // original values preserving type where possible\n enumBase?: IRSchemaKind; // underlying base kind: string, number, integer, boolean, unknown\n\n // Ref (component name or canonical name)\n ref?: string;\n\n // Compositions\n oneOf?: IRSchema[];\n anyOf?: IRSchema[];\n allOf?: IRSchema[];\n not?: IRSchema;\n\n // Polymorphism\n discriminator?: IRDiscriminator;\n}\n\n// IRField represents a field in an object schema\nexport interface IRField {\n name: string;\n type: IRSchema;\n required: boolean;\n // Pass-through annotations commonly used by generators\n annotations: IRAnnotations;\n}\n\n// IRDiscriminator represents polymorphism discriminator information\nexport interface IRDiscriminator {\n propertyName: string;\n mapping?: Record<string, string>;\n}\n\n// IRSecurityScheme captures a simplified view of OpenAPI security schemes\n// sufficient for SDK generation.\nexport interface IRSecurityScheme {\n // Key is the name of the security scheme in components.securitySchemes\n key: string;\n // Type is one of: http, apiKey, oauth2, openIdConnect\n type: string;\n // Scheme is used when Type is http (e.g., \"basic\", \"bearer\")\n scheme?: string;\n // In is used when Type is apiKey (e.g., \"header\", \"query\", \"cookie\")\n in?: string;\n // Name is used when Type is apiKey; it is the header/query/cookie name\n name?: string;\n // BearerFormat may be provided for bearer tokens\n bearerFormat?: string;\n}\n","import { Injectable, Logger } from \"@nestjs/common\";\nimport { IR } from \"../ir/ir.types\";\nimport { Client } from \"../config/config.schema\";\nimport { Generator } from \"./generator.interface\";\nimport { IrBuilderService } from \"./ir-builder.service\";\nimport { OpenApiService } from \"../openapi/openapi.service\";\n\n@Injectable()\nexport class GeneratorService {\n private readonly logger = new Logger(GeneratorService.name);\n private readonly generators = new Map<string, Generator>();\n\n constructor(\n private readonly irBuilder: IrBuilderService,\n private readonly openApiService: OpenApiService\n ) {}\n\n /**\n * Register a generator\n */\n register<TClient extends Client>(generator: Generator<TClient>): void {\n this.generators.set(generator.getType(), generator as Generator);\n this.logger.debug(`Registered generator: ${generator.getType()}`);\n }\n\n /**\n * Get a generator by type\n */\n getGenerator(type: string): Generator | undefined {\n return this.generators.get(type);\n }\n\n /**\n * Get all available generator types\n */\n getAvailableTypes(): string[] {\n return Array.from(this.generators.keys());\n }\n\n /**\n * Generate SDK for a client\n * TypeScript will narrow the client type based on the discriminated union\n */\n async generate(spec: string, client: Client): Promise<void> {\n const generator = this.getGenerator(client.type);\n if (!generator) {\n throw new Error(`Unsupported client type: ${client.type}`);\n }\n\n // Load OpenAPI document\n const doc = await this.openApiService.loadDocument(spec);\n // Build IR\n const fullIR = this.irBuilder.buildIR(doc);\n // Filter IR based on client configuration\n const filteredIR = this.irBuilder.filterIR(fullIR, client);\n // Generate - TypeScript will ensure type safety through the discriminated union\n // The generator's generate method will receive the correctly narrowed client type\n await generator.generate(client, filteredIR);\n }\n}\n","import { Injectable } from \"@nestjs/common\";\nimport { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\nimport {\n IR,\n IRService,\n IROperation,\n IRParam,\n IRRequestBody,\n IRResponse,\n IRSecurityScheme,\n IRModelDef,\n IRSchema,\n} from \"../ir/ir.types\";\nimport { SchemaConverterService } from \"./schema-converter.service\";\nimport { Client } from \"../config/config.schema\";\nimport { toPascalCase, toCamelCase } from \"../utils/string.utils\";\nimport { IRSchemaKind } from \"../ir/ir.types\";\nimport { OpenAPIDocument } from \"../openapi/openapi.types\";\n\n@Injectable()\nexport class IrBuilderService {\n constructor(private readonly schemaConverter: SchemaConverterService) {}\n\n /**\n * Build IR from an OpenAPI document\n * Supports both OpenAPI 3.0 and 3.1\n */\n buildIR(doc: OpenAPIDocument): IR {\n const tags = this.collectTags(doc);\n const securitySchemes = this.collectSecuritySchemes(doc);\n const modelDefs = this.buildStructuredModels(doc);\n\n // For now, include all tags - filtering will be done per client\n const allowed: Record<string, boolean> = {};\n for (const tag of tags) {\n allowed[tag] = true;\n }\n\n // Build IR with all operations (this includes extracted inline types in result.modelDefs)\n const result = this.buildIRFromDoc(doc, allowed);\n result.securitySchemes = securitySchemes;\n // Merge component schemas with extracted inline types from operations\n result.modelDefs = [...modelDefs, ...result.modelDefs];\n // Store the OpenAPI document for later use (e.g., saving to SDK package)\n result.openApiDocument = doc;\n\n return result;\n }\n\n /**\n * Filter IR based on client configuration\n */\n filterIR(fullIR: IR, client: Client): IR {\n const include = this.compileTagFilters(client.includeTags || []);\n const exclude = this.compileTagFilters(client.excludeTags || []);\n\n // Filter services and operations based on their original tags\n const filteredServices: IRService[] = [];\n for (const service of fullIR.services) {\n const filteredOps: IROperation[] = [];\n for (const op of service.operations) {\n if (this.shouldIncludeOperation(op.originalTags, include, exclude)) {\n filteredOps.push(op);\n }\n }\n // Only include the service if it has at least one operation after filtering\n if (filteredOps.length > 0) {\n filteredServices.push({\n ...service,\n operations: filteredOps,\n });\n }\n }\n\n // Filter ModelDefs to only include those referenced by filtered operations\n const filteredIR: IR = {\n services: filteredServices,\n models: fullIR.models,\n securitySchemes: fullIR.securitySchemes,\n modelDefs: fullIR.modelDefs,\n openApiDocument: fullIR.openApiDocument, // Preserve OpenAPI document for spec saving\n };\n filteredIR.modelDefs = this.filterUnusedModelDefs(\n filteredIR,\n fullIR.modelDefs\n );\n\n return filteredIR;\n }\n\n /**\n * Detect if a content type indicates streaming\n */\n private detectStreamingContentType(contentType: string): {\n isStreaming: boolean;\n format?: \"sse\" | \"ndjson\" | \"chunked\";\n } {\n const normalized = contentType.toLowerCase().split(\";\")[0].trim();\n\n if (normalized === \"text/event-stream\") {\n return { isStreaming: true, format: \"sse\" };\n }\n\n if (\n normalized === \"application/x-ndjson\" ||\n normalized === \"application/x-jsonlines\" ||\n normalized === \"application/jsonl\"\n ) {\n return { isStreaming: true, format: \"ndjson\" };\n }\n\n // Check for other streaming indicators\n if (normalized.includes(\"stream\") || normalized.includes(\"chunked\")) {\n return { isStreaming: true, format: \"chunked\" };\n }\n\n return { isStreaming: false };\n }\n\n /**\n * Collect all tags from the OpenAPI document\n */\n private collectTags(doc: OpenAPIDocument): string[] {\n const uniq = new Set<string>();\n // consider untagged as \"misc\"\n uniq.add(\"misc\");\n\n if (doc.paths) {\n for (const [path, pathItem] of Object.entries(doc.paths)) {\n if (!pathItem) continue;\n const operations = [\n pathItem.get,\n pathItem.post,\n pathItem.put,\n pathItem.patch,\n pathItem.delete,\n pathItem.options,\n pathItem.head,\n pathItem.trace,\n ];\n\n for (const op of operations) {\n if (!op || !op.tags) continue;\n for (const tag of op.tags) {\n uniq.add(tag);\n }\n }\n }\n }\n\n return Array.from(uniq).sort();\n }\n\n /**\n * Compile regex patterns for tag filtering\n */\n private compileTagFilters(patterns: string[]): RegExp[] {\n return patterns.map((p) => {\n try {\n return new RegExp(p);\n } catch (error) {\n throw new Error(\n `Invalid tag filter pattern \"${p}\": ${error instanceof Error ? error.message : String(error)}`\n );\n }\n });\n }\n\n /**\n * Determine if an operation should be included based on its original tags\n */\n private shouldIncludeOperation(\n originalTags: string[],\n include: RegExp[],\n exclude: RegExp[]\n ): boolean {\n // If no include patterns, assume all tags are initially included\n let included = include.length === 0;\n\n // Check include patterns - operation is included if ANY of its tags match ANY include pattern\n if (include.length > 0) {\n for (const tag of originalTags) {\n for (const r of include) {\n if (r.test(tag)) {\n included = true;\n break;\n }\n }\n if (included) {\n break;\n }\n }\n }\n\n // If not included by include patterns, exclude it\n if (!included) {\n return false;\n }\n\n // Check exclude patterns - operation is excluded if ANY of its tags match ANY exclude pattern\n if (exclude.length > 0) {\n for (const tag of originalTags) {\n for (const r of exclude) {\n if (r.test(tag)) {\n return false;\n }\n }\n }\n }\n\n return true;\n }\n\n /**\n * Build IR structures from OpenAPI document\n */\n private buildIRFromDoc(\n doc: OpenAPIDocument,\n allowed: Record<string, boolean>\n ): IR {\n const servicesMap: Record<string, IRService> = {};\n // Always prepare misc\n servicesMap[\"misc\"] = { tag: \"misc\", operations: [] };\n\n // Collect extracted inline types from request bodies and responses\n const extractedTypes: IRModelDef[] = [];\n const seenTypeNames = new Set<string>();\n\n // Pre-populate seenTypeNames with component schema names to prevent duplicates\n if (doc.components?.schemas) {\n for (const name of Object.keys(doc.components.schemas)) {\n seenTypeNames.add(name);\n }\n }\n\n const addOp = (\n tag: string,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n method: string,\n path: string\n ) => {\n if (!servicesMap[tag]) {\n servicesMap[tag] = { tag, operations: [] };\n }\n const id = op.operationId || \"\";\n const { pathParams, queryParams } = this.collectParams(doc, op);\n const { requestBody: reqBody, extractedTypes: reqBodyTypes } =\n this.extractRequestBodyWithTypes(\n doc,\n op,\n tag,\n id,\n method,\n seenTypeNames\n );\n extractedTypes.push(...reqBodyTypes);\n const { response: resp, extractedTypes: respTypes } =\n this.extractResponseWithTypes(doc, op, tag, id, method, seenTypeNames);\n extractedTypes.push(...respTypes);\n\n // Copy original tags, defaulting to [\"misc\"] if no tags\n const originalTags =\n op.tags && op.tags.length > 0 ? [...op.tags] : [\"misc\"];\n\n servicesMap[tag].operations.push({\n operationID: id,\n method,\n path,\n tag,\n originalTags,\n summary: op.summary || \"\",\n description: op.description || \"\",\n deprecated: op.deprecated || false,\n pathParams,\n queryParams,\n requestBody: reqBody,\n response: resp,\n });\n };\n\n if (doc.paths) {\n for (const [path, pathItem] of Object.entries(doc.paths)) {\n if (!pathItem) continue;\n const operations = [\n { op: pathItem.get, method: \"GET\" },\n { op: pathItem.post, method: \"POST\" },\n { op: pathItem.put, method: \"PUT\" },\n { op: pathItem.patch, method: \"PATCH\" },\n { op: pathItem.delete, method: \"DELETE\" },\n { op: pathItem.options, method: \"OPTIONS\" },\n { op: pathItem.head, method: \"HEAD\" },\n { op: pathItem.trace, method: \"TRACE\" },\n ];\n\n for (const { op, method } of operations) {\n if (!op) continue;\n const t = this.firstAllowedTag(op.tags || [], allowed);\n if (t) {\n addOp(t, op, method, path);\n }\n }\n }\n }\n\n // Sort services and operations for determinism\n const services = Object.values(servicesMap);\n for (const service of services) {\n service.operations.sort((a, b) => {\n if (a.path === b.path) {\n return a.method.localeCompare(b.method);\n }\n return a.path.localeCompare(b.path);\n });\n }\n services.sort((a, b) => a.tag.localeCompare(b.tag));\n\n return {\n services,\n models: [],\n securitySchemes: [],\n modelDefs: extractedTypes,\n };\n }\n\n /**\n * Get the first allowed tag from a list\n */\n /**\n * Derive method name from operation ID, method, and path\n */\n private deriveMethodName(\n operationId: string,\n method: string,\n path: string\n ): string {\n if (operationId) {\n // Strip any prefix up to and including \"Controller_\"\n const idx = operationId.indexOf(\"Controller_\");\n const cleanedId =\n idx >= 0\n ? operationId.substring(idx + \"Controller_\".length)\n : operationId;\n // Convert to camelCase\n return toCamelCase(cleanedId);\n }\n\n // Basic REST-style heuristics\n const hasID = path.includes(\"{\") && path.includes(\"}\");\n\n switch (method) {\n case \"GET\":\n return hasID ? \"get\" : \"list\";\n case \"POST\":\n return \"create\";\n case \"PUT\":\n case \"PATCH\":\n return \"update\";\n case \"DELETE\":\n return \"delete\";\n default:\n return method.toLowerCase();\n }\n }\n\n private firstAllowedTag(\n tags: string[],\n allowed: Record<string, boolean>\n ): string {\n for (const t of tags) {\n if (allowed[t]) {\n return t;\n }\n }\n if (tags.length === 0 && allowed[\"misc\"]) {\n return \"misc\";\n }\n return \"\";\n }\n\n /**\n * Collect security schemes\n */\n private collectSecuritySchemes(doc: OpenAPIDocument): IRSecurityScheme[] {\n if (!doc.components?.securitySchemes) {\n return [];\n }\n // Deterministic order\n const names = Object.keys(doc.components.securitySchemes).sort();\n const out: IRSecurityScheme[] = [];\n for (const name of names) {\n const scheme = doc.components.securitySchemes[name];\n if (!scheme || \"$ref\" in scheme) continue;\n\n const sc: IRSecurityScheme = { key: name, type: scheme.type };\n switch (scheme.type) {\n case \"http\":\n sc.scheme = scheme.scheme;\n sc.bearerFormat = scheme.bearerFormat;\n break;\n case \"apiKey\":\n sc.in = scheme.in;\n sc.name = scheme.name;\n break;\n case \"oauth2\":\n case \"openIdConnect\":\n // Keep minimal; flows are not modeled yet\n break;\n }\n out.push(sc);\n }\n return out;\n }\n\n /**\n * Collect parameters from an operation\n */\n private collectParams(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject\n ): {\n pathParams: IRParam[];\n queryParams: IRParam[];\n } {\n const pathParams: IRParam[] = [];\n const queryParams: IRParam[] = [];\n\n if (op.parameters) {\n for (const pr of op.parameters) {\n if (!pr || \"$ref\" in pr) continue;\n const p = pr as OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject;\n const schema = this.schemaConverter.schemaRefToIR(doc, p.schema);\n const param: IRParam = {\n name: p.name,\n required: p.required || false,\n schema,\n description: p.description || \"\",\n };\n if (p.in === \"path\") {\n pathParams.push(param);\n } else if (p.in === \"query\") {\n queryParams.push(param);\n }\n }\n }\n\n // Deterministic order\n pathParams.sort((a, b) => a.name.localeCompare(b.name));\n queryParams.sort((a, b) => a.name.localeCompare(b.name));\n\n return { pathParams, queryParams };\n }\n\n /**\n * Extract request body information with inline type extraction\n */\n /**\n * Find if a schema matches a component schema (useful after dereferencing)\n * Returns the component schema name if found, null otherwise\n */\n private findMatchingComponentSchema(\n doc: OpenAPIDocument,\n schema:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.ReferenceObject\n | OpenAPIV3_1.SchemaObject\n | undefined\n ): string | null {\n if (!schema || !doc.components?.schemas) {\n return null;\n }\n\n // If it's still a $ref (not dereferenced), extract the name directly\n if (\"$ref\" in schema && schema.$ref) {\n const ref = schema.$ref;\n if (ref.startsWith(\"#/components/schemas/\")) {\n const name = ref.replace(\"#/components/schemas/\", \"\");\n if (doc.components.schemas[name]) {\n return name;\n }\n }\n }\n\n // After dereferencing, compare schema structures\n // Convert the schema to IR for comparison\n const schemaIR = this.schemaConverter.schemaRefToIR(doc, schema);\n\n // Compare with each component schema\n for (const [name, componentSchema] of Object.entries(\n doc.components.schemas\n )) {\n const componentIR = this.schemaConverter.schemaRefToIR(\n doc,\n componentSchema\n );\n if (this.compareSchemas(schemaIR, componentIR)) {\n return name;\n }\n }\n\n return null;\n }\n\n /**\n * Compare two IR schemas for structural equality\n */\n private compareSchemas(schema1: IRSchema, schema2: IRSchema): boolean {\n // Quick check: if kinds don't match, they're different\n if (schema1.kind !== schema2.kind) {\n return false;\n }\n\n // For refs, compare the ref name\n if (\n schema1.kind === IRSchemaKind.Ref &&\n schema2.kind === IRSchemaKind.Ref\n ) {\n return schema1.ref === schema2.ref;\n }\n\n // For objects, compare properties\n if (\n schema1.kind === IRSchemaKind.Object &&\n schema2.kind === IRSchemaKind.Object\n ) {\n const props1 = schema1.properties || [];\n const props2 = schema2.properties || [];\n\n if (props1.length !== props2.length) {\n return false;\n }\n\n // Compare each property (including required flags)\n const props1Map = new Map(\n props1.map((p) => [p.name, { type: p.type, required: p.required }])\n );\n const props2Map = new Map(\n props2.map((p) => [p.name, { type: p.type, required: p.required }])\n );\n\n if (props1Map.size !== props2Map.size) {\n return false;\n }\n\n for (const [name, prop1] of props1Map) {\n const prop2 = props2Map.get(name);\n if (\n !prop2 ||\n prop1.required !== prop2.required ||\n !this.compareSchemas(prop1.type, prop2.type)\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n // For arrays, compare items\n if (\n schema1.kind === IRSchemaKind.Array &&\n schema2.kind === IRSchemaKind.Array\n ) {\n if (!schema1.items || !schema2.items) {\n return schema1.items === schema2.items; // Both undefined or both defined\n }\n return this.compareSchemas(schema1.items, schema2.items);\n }\n\n // For other types, consider them equal if kind matches\n // (This is a simplified comparison - may need refinement)\n return true;\n }\n\n /**\n * Extract model name from schema if it's a reference, otherwise return null\n * Handles direct refs and arrays of refs\n */\n private extractModelNameFromSchema(schema: IRSchema): string | null {\n if (schema.kind === IRSchemaKind.Ref && schema.ref) {\n return schema.ref;\n }\n // Handle arrays of refs (e.g., Array<SomeModel>)\n if (schema.kind === IRSchemaKind.Array && schema.items) {\n if (schema.items.kind === IRSchemaKind.Ref && schema.items.ref) {\n return schema.items.ref;\n }\n }\n return null;\n }\n\n /**\n * Generate type name for request/response body\n * Prefers model name from schema reference, falls back to operation-based naming\n */\n private generateTypeName(\n schema: IRSchema,\n tag: string,\n operationId: string,\n method: string,\n path: string,\n suffix: \"RequestBody\" | \"Response\"\n ): string {\n // Try to use model name from schema reference first\n const modelName = this.extractModelNameFromSchema(schema);\n if (modelName) {\n return modelName;\n }\n\n // Fallback to operation-based naming for inline schemas\n const methodName = this.deriveMethodName(operationId, method, path);\n return `${toPascalCase(tag)}${toPascalCase(methodName)}${suffix}`;\n }\n\n private extractRequestBodyWithTypes(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n tag: string,\n operationId: string,\n method: string,\n seenTypeNames: Set<string>\n ): { requestBody: IRRequestBody | null; extractedTypes: IRModelDef[] } {\n const extractedTypes: IRModelDef[] = [];\n\n if (!op.requestBody || \"$ref\" in op.requestBody) {\n return { requestBody: null, extractedTypes: [] };\n }\n const rb = op.requestBody as\n | OpenAPIV3.RequestBodyObject\n | OpenAPIV3_1.RequestBodyObject;\n\n // Prefer application/json\n if (rb.content?.[\"application/json\"]) {\n const media = rb.content[\"application/json\"];\n const schema = this.schemaConverter.schemaRefToIR(doc, media.schema);\n\n // Check if this schema matches a component schema (even after dereferencing)\n const componentSchemaName = this.findMatchingComponentSchema(\n doc,\n media.schema\n );\n\n if (componentSchemaName) {\n // Use the component schema name instead of generating a new one\n return {\n requestBody: {\n contentType: \"application/json\",\n typeTS: \"\",\n schema: {\n kind: IRSchemaKind.Ref,\n ref: componentSchemaName,\n nullable: false,\n },\n required: rb.required || false,\n },\n extractedTypes: [],\n };\n }\n\n // Generate type name: prefer model name, fallback to operation-based\n const typeName = this.generateTypeName(\n schema,\n tag,\n operationId,\n method,\n (op as unknown as { path: string }).path,\n \"RequestBody\"\n );\n\n // If schema is an inline object type, extract it\n if (schema.kind === IRSchemaKind.Object && !seenTypeNames.has(typeName)) {\n seenTypeNames.add(typeName);\n extractedTypes.push({\n name: typeName,\n schema,\n annotations: this.schemaConverter.extractAnnotations(media.schema),\n });\n return {\n requestBody: {\n contentType: \"application/json\",\n typeTS: \"\",\n schema: { kind: IRSchemaKind.Ref, ref: typeName, nullable: false },\n required: rb.required || false,\n },\n extractedTypes,\n };\n }\n\n return {\n requestBody: {\n contentType: \"application/json\",\n typeTS: \"\",\n schema,\n required: rb.required || false,\n },\n extractedTypes: [],\n };\n }\n\n // Fallback to original extractRequestBody for other content types\n const reqBody = this.extractRequestBody(doc, op);\n return { requestBody: reqBody, extractedTypes: [] };\n }\n\n /**\n * Extract request body information (legacy method, kept for fallback)\n */\n private extractRequestBody(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject\n ): IRRequestBody | null {\n if (!op.requestBody || \"$ref\" in op.requestBody) {\n return null;\n }\n const rb = op.requestBody as\n | OpenAPIV3.RequestBodyObject\n | OpenAPIV3_1.RequestBodyObject;\n // Prefer application/json\n if (rb.content?.[\"application/json\"]) {\n const media = rb.content[\"application/json\"];\n return {\n contentType: \"application/json\",\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n required: rb.required || false,\n };\n }\n if (rb.content?.[\"application/x-www-form-urlencoded\"]) {\n const media = rb.content[\"application/x-www-form-urlencoded\"];\n return {\n contentType: \"application/x-www-form-urlencoded\",\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n required: rb.required || false,\n };\n }\n if (rb.content?.[\"multipart/form-data\"]) {\n return {\n contentType: \"multipart/form-data\",\n typeTS: \"\",\n schema: { kind: \"unknown\" as any, nullable: false },\n required: rb.required || false,\n };\n }\n // Fallback to the first available media type\n if (rb.content) {\n const firstContentType = Object.keys(rb.content)[0];\n const media = rb.content[firstContentType];\n return {\n contentType: firstContentType,\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n required: rb.required || false,\n };\n }\n return null;\n }\n\n /**\n * Extract response information with inline type extraction\n */\n private extractResponseWithTypes(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n tag: string,\n operationId: string,\n method: string,\n seenTypeNames: Set<string>\n ): { response: IRResponse; extractedTypes: IRModelDef[] } {\n const extractedTypes: IRModelDef[] = [];\n\n if (!op.responses) {\n return {\n response: {\n typeTS: \"unknown\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: \"\",\n isStreaming: false,\n contentType: \"\",\n },\n extractedTypes: [],\n };\n }\n\n // Choose 200, 201, or any 2xx; 204 => void\n const tryCodes = [\"200\", \"201\"];\n for (const code of tryCodes) {\n const response = op.responses[code];\n if (response && !(\"$ref\" in response)) {\n const resp = response as\n | OpenAPIV3.ResponseObject\n | OpenAPIV3_1.ResponseObject;\n\n // Check all content types for streaming\n if (resp.content) {\n for (const [contentType, media] of Object.entries(resp.content)) {\n const streaming = this.detectStreamingContentType(contentType);\n const schema = this.schemaConverter.schemaRefToIR(\n doc,\n media.schema\n );\n\n // If streaming, return immediately with streaming flags\n if (streaming.isStreaming) {\n return {\n response: {\n typeTS: \"\",\n schema,\n description: resp.description || \"\",\n isStreaming: true,\n contentType,\n streamingFormat: streaming.format,\n },\n extractedTypes: [],\n };\n }\n\n // For non-streaming JSON, check if we should extract inline types\n if (contentType === \"application/json\") {\n // Check if this schema matches a component schema (even after dereferencing)\n const componentSchemaName = this.findMatchingComponentSchema(\n doc,\n media.schema\n );\n\n if (componentSchemaName) {\n // Use the component schema name instead of generating a new one\n return {\n response: {\n typeTS: \"\",\n schema: {\n kind: IRSchemaKind.Ref,\n ref: componentSchemaName,\n nullable: false,\n },\n description: resp.description || \"\",\n isStreaming: false,\n contentType,\n },\n extractedTypes: [],\n };\n }\n\n // Generate type name: prefer model name, fallback to operation-based\n const typeName = this.generateTypeName(\n schema,\n tag,\n operationId,\n method,\n (op as unknown as { path: string }).path,\n \"Response\"\n );\n\n // If schema is an inline object type, extract it\n if (\n schema.kind === IRSchemaKind.Object &&\n !seenTypeNames.has(typeName)\n ) {\n seenTypeNames.add(typeName);\n extractedTypes.push({\n name: typeName,\n schema,\n annotations: this.schemaConverter.extractAnnotations(\n media.schema\n ),\n });\n return {\n response: {\n typeTS: \"\",\n schema: {\n kind: IRSchemaKind.Ref,\n ref: typeName,\n nullable: false,\n },\n description: resp.description || \"\",\n isStreaming: false,\n contentType,\n },\n extractedTypes,\n };\n }\n\n return {\n response: {\n typeTS: \"\",\n schema,\n description: resp.description || \"\",\n isStreaming: false,\n contentType,\n },\n extractedTypes: [],\n };\n }\n }\n\n // Fallback: use first content type\n const firstContentType = Object.keys(resp.content)[0];\n const firstMedia = resp.content[firstContentType];\n const firstSchema = this.schemaConverter.schemaRefToIR(\n doc,\n firstMedia.schema\n );\n const firstStreaming =\n this.detectStreamingContentType(firstContentType);\n\n return {\n response: {\n typeTS: \"\",\n schema: firstSchema,\n description: resp.description || \"\",\n isStreaming: firstStreaming.isStreaming,\n contentType: firstContentType,\n streamingFormat: firstStreaming.format,\n },\n extractedTypes: [],\n };\n }\n\n // No content\n return {\n response: {\n typeTS: \"void\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"\",\n },\n extractedTypes: [],\n };\n }\n }\n\n // Fallback to original extractResponse\n const resp = this.extractResponse(doc, op);\n return { response: resp, extractedTypes: [] };\n }\n\n /**\n * Extract response information (legacy method, kept for fallback)\n */\n private extractResponse(\n doc: OpenAPIDocument,\n op: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject\n ): IRResponse {\n if (!op.responses) {\n return {\n typeTS: \"unknown\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: \"\",\n isStreaming: false,\n contentType: \"\",\n };\n }\n\n // Choose 200, 201, or any 2xx; 204 => void\n const tryCodes = [\"200\", \"201\"];\n for (const code of tryCodes) {\n const response = op.responses[code];\n if (response && !(\"$ref\" in response)) {\n const resp = response as\n | OpenAPIV3.ResponseObject\n | OpenAPIV3_1.ResponseObject;\n\n // Check for streaming content types first\n if (resp.content) {\n for (const [contentType, media] of Object.entries(resp.content)) {\n const streaming = this.detectStreamingContentType(contentType);\n if (streaming.isStreaming) {\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: true,\n contentType,\n streamingFormat: streaming.format,\n };\n }\n }\n\n // Non-streaming JSON\n if (resp.content[\"application/json\"]) {\n const media = resp.content[\"application/json\"];\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"application/json\",\n };\n }\n\n // Fallback to any content\n const firstContentType = Object.keys(resp.content)[0];\n const media = resp.content[firstContentType];\n const streaming = this.detectStreamingContentType(firstContentType);\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: streaming.isStreaming,\n contentType: firstContentType,\n streamingFormat: streaming.format,\n };\n }\n\n return {\n typeTS: \"void\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"\",\n };\n }\n }\n\n // any 2xx\n for (const [code, response] of Object.entries(op.responses)) {\n if (\n code.length === 3 &&\n code[0] === \"2\" &&\n response &&\n !(\"$ref\" in response)\n ) {\n const resp = response as\n | OpenAPIV3.ResponseObject\n | OpenAPIV3_1.ResponseObject;\n if (code === \"204\") {\n return {\n typeTS: \"void\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"\",\n };\n }\n\n if (resp.content) {\n // Check for streaming\n for (const [contentType, media] of Object.entries(resp.content)) {\n const streaming = this.detectStreamingContentType(contentType);\n if (streaming.isStreaming) {\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: true,\n contentType,\n streamingFormat: streaming.format,\n };\n }\n }\n\n // Non-streaming JSON\n if (resp.content[\"application/json\"]) {\n const media = resp.content[\"application/json\"];\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: false,\n contentType: \"application/json\",\n };\n }\n\n // Fallback to first content type\n const firstContentType = Object.keys(resp.content)[0];\n const media = resp.content[firstContentType];\n const streaming = this.detectStreamingContentType(firstContentType);\n return {\n typeTS: \"\",\n schema: this.schemaConverter.schemaRefToIR(doc, media.schema),\n description: resp.description || \"\",\n isStreaming: streaming.isStreaming,\n contentType: firstContentType,\n streamingFormat: streaming.format,\n };\n }\n }\n }\n\n return {\n typeTS: \"unknown\",\n schema: { kind: IRSchemaKind.Unknown, nullable: false },\n description: \"\",\n isStreaming: false,\n contentType: \"\",\n };\n }\n\n /**\n * Build structured models from components.schemas\n */\n private buildStructuredModels(doc: OpenAPIDocument): IRModelDef[] {\n const out: IRModelDef[] = [];\n if (!doc.components?.schemas) {\n return out;\n }\n const names = Object.keys(doc.components.schemas).sort();\n const seen = new Set<string>();\n\n // Pre-populate seen with component names to prevent inline duplicates\n for (const name of names) {\n seen.add(name);\n }\n\n for (const name of names) {\n const sr = doc.components.schemas[name];\n // For component schemas, use schemaRefToIR to get the actual schema without creating inline models\n const schema = this.schemaConverter.schemaRefToIR(doc, sr);\n out.push({\n name,\n schema,\n annotations: this.schemaConverter.extractAnnotations(sr),\n });\n }\n return out;\n }\n\n /**\n * Filter unused ModelDefs\n */\n private filterUnusedModelDefs(\n filteredIR: IR,\n allModelDefs: IRModelDef[]\n ): IRModelDef[] {\n // Build a map of all ModelDefs for quick lookup\n const modelDefMap = new Map<string, IRModelDef>();\n for (const md of allModelDefs) {\n modelDefMap.set(md.name, md);\n }\n\n // Collect all schema references from filtered operations\n const referenced = new Set<string>();\n const visited = new Set<string>(); // Track visited refs to avoid cycles\n\n // Helper function to collect references from a schema recursively\n const collectRefs = (schema: IRSchema) => {\n if (schema.kind === \"ref\" && schema.ref) {\n const refName = schema.ref;\n referenced.add(refName);\n // If this ref points to a ModelDef and we haven't visited it, collect its transitive references\n if (!visited.has(refName)) {\n visited.add(refName);\n const md = modelDefMap.get(refName);\n if (md) {\n collectRefs(md.schema);\n }\n }\n }\n if (schema.items) {\n collectRefs(schema.items);\n }\n if (schema.additionalProperties) {\n collectRefs(schema.additionalProperties);\n }\n if (schema.oneOf) {\n for (const sub of schema.oneOf) {\n collectRefs(sub);\n }\n }\n if (schema.anyOf) {\n for (const sub of schema.anyOf) {\n collectRefs(sub);\n }\n }\n if (schema.allOf) {\n for (const sub of schema.allOf) {\n collectRefs(sub);\n }\n }\n if (schema.not) {\n collectRefs(schema.not);\n }\n if (schema.properties) {\n for (const field of schema.properties) {\n collectRefs(field.type);\n }\n }\n };\n\n // Collect references from all operations\n for (const service of filteredIR.services) {\n for (const op of service.operations) {\n // Collect from path params\n for (const param of op.pathParams) {\n collectRefs(param.schema);\n }\n // Collect from query params\n for (const param of op.queryParams) {\n collectRefs(param.schema);\n }\n // Collect from request body\n if (op.requestBody) {\n collectRefs(op.requestBody.schema);\n }\n // Collect from response\n collectRefs(op.response.schema);\n }\n }\n\n // Filter ModelDefs to only include referenced ones\n return allModelDefs.filter((md) => referenced.has(md.name));\n }\n}\n","import { Injectable } from \"@nestjs/common\";\nimport { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\nimport {\n IRSchema,\n IRSchemaKind,\n IRField,\n IRAnnotations,\n IRDiscriminator,\n} from \"../ir/ir.types\";\nimport {\n OpenAPIDocument,\n getSchemaFromRef,\n isSchemaNullable,\n getSchemaType,\n} from \"../openapi/openapi.types\";\n\n@Injectable()\nexport class SchemaConverterService {\n /**\n * Convert an OpenAPI schema reference to IR schema\n * Supports both OpenAPI 3.0 and 3.1\n */\n schemaRefToIR(\n doc: OpenAPIDocument,\n schemaRef:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.ReferenceObject\n | OpenAPIV3_1.SchemaObject\n | undefined\n ): IRSchema {\n if (!schemaRef) {\n return { kind: IRSchemaKind.Unknown, nullable: false };\n }\n\n // Handle $ref\n if (\"$ref\" in schemaRef && schemaRef.$ref) {\n const ref = schemaRef.$ref;\n if (ref.startsWith(\"#/components/schemas/\")) {\n const name = ref.replace(\"#/components/schemas/\", \"\");\n return { kind: IRSchemaKind.Ref, ref: name, nullable: false };\n }\n // Handle other ref formats\n const parts = ref.split(\"/\");\n if (parts.length > 0) {\n const name = parts[parts.length - 1];\n if (name) {\n return { kind: IRSchemaKind.Ref, ref: name, nullable: false };\n }\n }\n return { kind: IRSchemaKind.Unknown, nullable: false };\n }\n\n const schema = getSchemaFromRef(doc, schemaRef) as\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.SchemaObject;\n if (!schema) {\n return { kind: IRSchemaKind.Unknown, nullable: false };\n }\n\n // Detect nullable (works for both 3.0 and 3.1)\n const nullable = isSchemaNullable(schema);\n\n // Polymorphism discriminator\n let discriminator: IRDiscriminator | undefined;\n if (schema.discriminator) {\n discriminator = {\n propertyName: schema.discriminator.propertyName,\n mapping: schema.discriminator.mapping,\n };\n }\n\n // Compositions\n if (schema.oneOf && schema.oneOf.length > 0) {\n const subs = schema.oneOf.map((sub) => this.schemaRefToIR(doc, sub));\n return {\n kind: IRSchemaKind.OneOf,\n oneOf: subs,\n nullable,\n discriminator,\n };\n }\n if (schema.anyOf && schema.anyOf.length > 0) {\n const subs = schema.anyOf.map((sub) => this.schemaRefToIR(doc, sub));\n return {\n kind: IRSchemaKind.AnyOf,\n anyOf: subs,\n nullable,\n discriminator,\n };\n }\n if (schema.allOf && schema.allOf.length > 0) {\n const subs = schema.allOf.map((sub) => this.schemaRefToIR(doc, sub));\n return {\n kind: IRSchemaKind.AllOf,\n allOf: subs,\n nullable,\n discriminator,\n };\n }\n if (schema.not) {\n const not = this.schemaRefToIR(doc, schema.not);\n return {\n kind: IRSchemaKind.Not,\n not,\n nullable,\n discriminator,\n };\n }\n\n // Enum\n if (schema.enum && schema.enum.length > 0) {\n const enumValues = schema.enum.map((v) => String(v));\n const enumBase = this.inferEnumBaseKind(schema);\n return {\n kind: IRSchemaKind.Enum,\n enumValues,\n enumRaw: schema.enum,\n enumBase,\n nullable,\n discriminator,\n };\n }\n\n // Primitive kinds and object/array\n // Handle both string and string[] types (3.0 vs 3.1)\n const type = getSchemaType(schema);\n const normalizedType = Array.isArray(type)\n ? type.filter((t) => t !== \"null\")[0]\n : type;\n\n if (normalizedType) {\n switch (normalizedType) {\n case \"string\":\n return {\n kind: IRSchemaKind.String,\n nullable,\n format: schema.format,\n discriminator,\n };\n case \"integer\":\n return {\n kind: IRSchemaKind.Integer,\n nullable,\n discriminator,\n };\n case \"number\":\n return {\n kind: IRSchemaKind.Number,\n nullable,\n discriminator,\n };\n case \"boolean\":\n return {\n kind: IRSchemaKind.Boolean,\n nullable,\n discriminator,\n };\n case \"array\":\n // When type is \"array\", schema has items property (required in OpenAPI spec)\n // TypeScript doesn't narrow the union type, so we use type assertion\n const arraySchema = schema as\n | (OpenAPIV3.SchemaObject & {\n items?: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject;\n })\n | (OpenAPIV3_1.SchemaObject & {\n items?: OpenAPIV3_1.SchemaObject | OpenAPIV3_1.ReferenceObject;\n });\n const items = this.schemaRefToIR(doc, arraySchema.items);\n return {\n kind: IRSchemaKind.Array,\n items,\n nullable,\n discriminator,\n };\n case \"object\":\n // Properties\n const properties: IRField[] = [];\n if (schema.properties) {\n const propNames = Object.keys(schema.properties).sort();\n for (const name of propNames) {\n const prop = schema.properties[name];\n const fieldType = this.schemaRefToIR(doc, prop);\n const required = schema.required?.includes(name) || false;\n properties.push({\n name,\n type: fieldType,\n required,\n annotations: this.extractAnnotations(prop),\n });\n }\n }\n let additionalProperties: IRSchema | undefined;\n if (schema.additionalProperties) {\n if (typeof schema.additionalProperties === \"object\") {\n additionalProperties = this.schemaRefToIR(\n doc,\n schema.additionalProperties\n );\n }\n }\n return {\n kind: IRSchemaKind.Object,\n properties,\n additionalProperties,\n nullable,\n discriminator,\n };\n }\n }\n\n return {\n kind: IRSchemaKind.Unknown,\n nullable,\n discriminator,\n };\n }\n\n /**\n * Extract annotations from a schema reference\n * Supports both OpenAPI 3.0 and 3.1\n */\n extractAnnotations(\n schemaRef:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.ReferenceObject\n | OpenAPIV3_1.SchemaObject\n | undefined\n ): IRAnnotations {\n if (!schemaRef || \"$ref\" in schemaRef) {\n return {};\n }\n const schema = schemaRef as\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.SchemaObject;\n return {\n title: schema.title,\n description: schema.description,\n deprecated: schema.deprecated,\n readOnly: schema.readOnly,\n writeOnly: schema.writeOnly,\n default: schema.default,\n examples: schema.example\n ? Array.isArray(schema.example)\n ? schema.example\n : [schema.example]\n : undefined,\n };\n }\n\n /**\n * Infer the base kind for an enum\n * Supports both OpenAPI 3.0 and 3.1\n */\n private inferEnumBaseKind(\n schema: OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject\n ): IRSchemaKind {\n // Prefer explicit type when present\n const type = getSchemaType(schema);\n if (type) {\n const normalizedType = Array.isArray(type)\n ? type.filter((t) => t !== \"null\")[0]\n : type;\n if (normalizedType) {\n switch (normalizedType) {\n case \"string\":\n return IRSchemaKind.String;\n case \"integer\":\n return IRSchemaKind.Integer;\n case \"number\":\n return IRSchemaKind.Number;\n case \"boolean\":\n return IRSchemaKind.Boolean;\n }\n }\n }\n // Fallback: inspect first enum value\n if (schema.enum && schema.enum.length > 0) {\n const first = schema.enum[0];\n if (typeof first === \"string\") {\n return IRSchemaKind.String;\n }\n if (typeof first === \"number\") {\n return Number.isInteger(first)\n ? IRSchemaKind.Integer\n : IRSchemaKind.Number;\n }\n if (typeof first === \"boolean\") {\n return IRSchemaKind.Boolean;\n }\n }\n return IRSchemaKind.Unknown;\n }\n}\n","import { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\n\nexport type OpenAPIVersion = \"3.0\" | \"3.1\" | \"unknown\";\n\nexport type OpenAPIDocument = OpenAPIV3.Document | OpenAPIV3_1.Document;\n\n/**\n * Detect OpenAPI version from a document\n */\nexport function detectOpenAPIVersion(doc: OpenAPIDocument): OpenAPIVersion {\n const version = doc.openapi;\n if (typeof version !== \"string\") {\n return \"unknown\";\n }\n\n if (version.startsWith(\"3.1\")) {\n return \"3.1\";\n }\n\n if (version.startsWith(\"3.0\")) {\n return \"3.0\";\n }\n\n return \"unknown\";\n}\n\n/**\n * Check if the OpenAPI version is supported\n */\nexport function isSupportedVersion(version: OpenAPIVersion): boolean {\n return version === \"3.0\" || version === \"3.1\";\n}\n\n/**\n * Type guard to check if document is OpenAPI 3.1\n */\nexport function isOpenAPI31(doc: OpenAPIDocument): doc is OpenAPIV3_1.Document {\n return detectOpenAPIVersion(doc) === \"3.1\";\n}\n\n/**\n * Type guard to check if document is OpenAPI 3.0\n */\nexport function isOpenAPI30(doc: OpenAPIDocument): doc is OpenAPIV3.Document {\n return detectOpenAPIVersion(doc) === \"3.0\";\n}\n","import { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\nimport {\n OpenAPIDocument,\n isOpenAPI31,\n isOpenAPI30,\n} from \"./openapi-version.utils\";\n\n// Re-export the union type and type guards for convenience\nexport type { OpenAPIDocument };\nexport { isOpenAPI31, isOpenAPI30 };\n\n/**\n * Normalized interface for accessing common OpenAPI document properties\n * regardless of version (3.0 or 3.1)\n */\nexport interface NormalizedOpenAPIDocument {\n openapi: string;\n info: OpenAPIV3.InfoObject | OpenAPIV3_1.InfoObject;\n paths: OpenAPIV3.PathsObject | OpenAPIV3_1.PathsObject | undefined;\n components?: OpenAPIV3.ComponentsObject | OpenAPIV3_1.ComponentsObject;\n servers?: (OpenAPIV3.ServerObject | OpenAPIV3_1.ServerObject)[];\n}\n\n/**\n * Normalize an OpenAPI document to a common interface\n * This allows accessing common properties without version-specific checks\n */\nexport function normalizeDocument(\n doc: OpenAPIDocument\n): NormalizedOpenAPIDocument {\n return {\n openapi: doc.openapi,\n info: doc.info,\n paths: doc.paths,\n components: doc.components,\n servers: doc.servers,\n };\n}\n\n/**\n * Get the schema object from a reference or direct schema\n * Works with both OpenAPI 3.0 and 3.1\n */\nexport function getSchemaFromRef(\n doc: OpenAPIDocument,\n schemaRef:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject\n | OpenAPIV3_1.ReferenceObject\n | OpenAPIV3_1.SchemaObject\n | undefined\n): OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject | undefined {\n if (!schemaRef || typeof schemaRef !== \"object\") {\n return undefined;\n }\n\n // Handle $ref\n if (\"$ref\" in schemaRef && schemaRef.$ref) {\n const ref = schemaRef.$ref;\n if (ref.startsWith(\"#/components/schemas/\")) {\n const name = ref.replace(\"#/components/schemas/\", \"\");\n if (doc.components?.schemas?.[name]) {\n const schema = doc.components.schemas[name];\n if (\"$ref\" in schema) {\n // Recursive reference\n return getSchemaFromRef(doc, schema);\n }\n return schema as OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject;\n }\n }\n return undefined;\n }\n\n return schemaRef as OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject;\n}\n\n/**\n * Check if a schema is nullable (works for both 3.0 and 3.1)\n */\nexport function isSchemaNullable(\n schema: OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject | undefined\n): boolean {\n if (!schema) {\n return false;\n }\n\n // OpenAPI 3.0: uses nullable property\n if (\"nullable\" in schema && schema.nullable === true) {\n return true;\n }\n\n // OpenAPI 3.1: uses type array with 'null'\n if (\"type\" in schema && Array.isArray(schema.type)) {\n return schema.type.includes(\"null\");\n }\n\n return false;\n}\n\n/**\n * Get the type from a schema (normalized for both versions)\n */\nexport function getSchemaType(\n schema: OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject | undefined\n): string | string[] | undefined {\n if (!schema || !(\"type\" in schema)) {\n return undefined;\n }\n\n return schema.type;\n}\n","/**\n * String utility functions for code generation\n */\n\n/**\n * Convert a string to PascalCase\n */\nexport function toPascalCase(s: string): string {\n s = s.trim();\n if (s === \"\") {\n return \"\";\n }\n\n // Split by non-alphanumeric characters\n const parts = s.split(/[^A-Za-z0-9]+/).filter((p) => p !== \"\");\n const allParts: string[] = [];\n\n for (const part of parts) {\n // Further split camelCase/PascalCase words\n const subParts = splitCamelCase(part);\n allParts.push(...subParts);\n }\n\n return allParts\n .filter((p) => p !== \"\")\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join(\"\");\n}\n\n/**\n * Convert a string to camelCase\n */\nexport function toCamelCase(s: string): string {\n const pascal = toPascalCase(s);\n if (pascal === \"\") {\n return \"\";\n }\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\n/**\n * Convert a string to snake_case\n */\nexport function toSnakeCase(s: string): string {\n s = s.trim();\n if (s === \"\") {\n return \"\";\n }\n\n // Split by non-alphanumeric characters\n const parts = s.split(/[^A-Za-z0-9]+/).filter((p) => p !== \"\");\n const allParts: string[] = [];\n\n for (const part of parts) {\n // Further split camelCase/PascalCase words\n const subParts = splitCamelCase(part);\n allParts.push(...subParts);\n }\n\n return allParts\n .filter((p) => p !== \"\")\n .map((p) => p.toLowerCase())\n .join(\"_\");\n}\n\n/**\n * Convert a string to kebab-case\n */\nexport function toKebabCase(s: string): string {\n s = s.trim();\n if (s === \"\") {\n return \"\";\n }\n\n // Split by non-alphanumeric characters\n const parts = s.split(/[^A-Za-z0-9]+/).filter((p) => p !== \"\");\n const allParts: string[] = [];\n\n for (const part of parts) {\n // Further split camelCase/PascalCase words\n const subParts = splitCamelCase(part);\n allParts.push(...subParts);\n }\n\n return allParts\n .filter((p) => p !== \"\")\n .map((p) => p.toLowerCase())\n .join(\"-\");\n}\n\n/**\n * Split a camelCase or PascalCase string into words\n */\nfunction splitCamelCase(s: string): string[] {\n if (s === \"\") {\n return [];\n }\n\n const parts: string[] = [];\n let current = \"\";\n\n const chars = Array.from(s);\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i];\n // Check if this is the start of a new word\n let isNewWord = false;\n if (i > 0 && isUppercase(char)) {\n // Current char is uppercase\n if (!isUppercase(chars[i - 1])) {\n // Previous char was lowercase, so this starts a new word\n isNewWord = true;\n } else if (i < chars.length - 1 && !isUppercase(chars[i + 1])) {\n // Previous char was uppercase, but next char is lowercase\n // This handles cases like \"XMLHttp\" -> \"XML\", \"Http\"\n isNewWord = true;\n }\n }\n\n if (isNewWord && current.length > 0) {\n parts.push(current);\n current = \"\";\n }\n\n current += char;\n }\n\n if (current.length > 0) {\n parts.push(current);\n }\n\n return parts;\n}\n\n/**\n * Check if a character is uppercase\n */\nfunction isUppercase(char: string): boolean {\n return char >= \"A\" && char <= \"Z\";\n}\n","import { Injectable, Logger } from \"@nestjs/common\";\nimport SwaggerParser from \"@apidevtools/swagger-parser\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { OpenAPIV3, OpenAPIV3_1 } from \"openapi-types\";\nimport {\n OpenAPIDocument,\n detectOpenAPIVersion,\n isSupportedVersion,\n} from \"./openapi-version.utils\";\n\n@Injectable()\nexport class OpenApiService {\n private readonly logger = new Logger(OpenApiService.name);\n\n /**\n * Load an OpenAPI document from a local file path or an HTTP(S) URL\n * Supports both OpenAPI 3.0 and 3.1\n */\n async loadDocument(input: string): Promise<OpenAPIDocument> {\n try {\n // Try to parse as URL; if it looks like http(s), fetch via URL\n let url: URL | null = null;\n try {\n url = new URL(input);\n } catch {\n // Not a URL, treat as file path\n }\n\n let api: OpenAPIDocument;\n if (url && (url.protocol === \"http:\" || url.protocol === \"https:\")) {\n // Load from URL\n this.logger.debug(`Loading OpenAPI spec from URL: ${input}`);\n\n // First, fetch and parse the document\n const response = await fetch(input, {\n signal: AbortSignal.timeout(10000),\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch OpenAPI spec: HTTP ${response.status} ${response.statusText}`\n );\n }\n\n const documentText = await response.text();\n let documentJson: any;\n\n try {\n documentJson = JSON.parse(documentText);\n } catch {\n throw new Error(\"OpenAPI spec is not valid JSON\");\n }\n\n // Parse the document first to get the raw structure\n // Then use bundle on the parsed document to preserve internal $ref pointers\n // This is important for component schema references (especially simple types)\n try {\n const parsed = await SwaggerParser.parse(documentJson);\n // Bundle the parsed document to resolve external refs but preserve internal ones\n api = (await SwaggerParser.bundle(parsed)) as OpenAPIDocument;\n\n // Don't dereference - we want to preserve internal $ref pointers to component schemas\n // This allows us to correctly identify component schema references even for simple types\n // Only external $ref pointers should be resolved by bundle\n } catch (error) {\n // If bundle fails, try dereference directly\n this.logger.debug(\n `Bundle failed: ${error instanceof Error ? error.message : String(error)}`\n );\n this.logger.debug(\"Attempting dereference directly\");\n\n try {\n const parsed = await SwaggerParser.parse(documentJson);\n api = (await SwaggerParser.dereference(parsed)) as OpenAPIDocument;\n } catch (derefError) {\n throw derefError; // Throw original error\n }\n }\n } else {\n // Load from file\n const filePath = path.resolve(input);\n if (!fs.existsSync(filePath)) {\n throw new Error(`OpenAPI spec file not found: ${filePath}`);\n }\n this.logger.debug(`Loading OpenAPI spec from file: ${filePath}`);\n\n // Try bundle first (preserves internal $ref pointers)\n // If that fails, fall back to dereference\n try {\n api = (await SwaggerParser.bundle(filePath)) as OpenAPIDocument;\n // Don't dereference - we want to preserve internal $ref pointers to component schemas\n } catch (error) {\n // If bundle fails, try dereference directly\n this.logger.debug(\n `Bundle failed: ${error instanceof Error ? error.message : String(error)}`\n );\n this.logger.debug(\"Attempting dereference directly\");\n api = (await SwaggerParser.dereference(filePath)) as OpenAPIDocument;\n }\n }\n\n // Detect and validate version\n const version = detectOpenAPIVersion(api);\n if (!isSupportedVersion(version)) {\n throw new Error(\n `Unsupported OpenAPI version: ${api.openapi}. Only versions 3.0.x and 3.1.0 are supported.`\n );\n }\n\n this.logger.log(`Detected OpenAPI version: ${version} (${api.openapi})`);\n return api;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to load OpenAPI document from ${input}: ${error.message}`\n );\n }\n throw error;\n }\n }\n\n /**\n * Validate an OpenAPI document\n */\n async validateDocument(input: string): Promise<void> {\n try {\n let url: URL | null = null;\n try {\n url = new URL(input);\n } catch {\n // Not a URL\n }\n\n if (url && (url.protocol === \"http:\" || url.protocol === \"https:\")) {\n await SwaggerParser.validate(input);\n } else {\n const filePath = path.resolve(input);\n if (!fs.existsSync(filePath)) {\n throw new Error(`OpenAPI spec file not found: ${filePath}`);\n }\n await SwaggerParser.validate(filePath);\n }\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Invalid OpenAPI document: ${error.message}`);\n }\n throw error;\n }\n }\n}\n","import { Module } from \"@nestjs/common\";\nimport { GeneratorService } from \"./generator.service\";\nimport { IrBuilderService } from \"./ir-builder.service\";\nimport { SchemaConverterService } from \"./schema-converter.service\";\nimport { OpenApiModule } from \"../openapi/openapi.module\";\nimport { ConfigModule } from \"../config/config.module\";\nimport { TypeScriptGeneratorService } from \"./typescript/typescript-generator.service\";\n\n@Module({\n imports: [OpenApiModule, ConfigModule],\n providers: [\n GeneratorService,\n IrBuilderService,\n SchemaConverterService,\n TypeScriptGeneratorService,\n ],\n exports: [GeneratorService, IrBuilderService, SchemaConverterService],\n})\nexport class GeneratorModule {\n constructor(\n private readonly generatorService: GeneratorService,\n private readonly typeScriptGenerator: TypeScriptGeneratorService\n ) {\n // Register default generators\n this.generatorService.register(this.typeScriptGenerator);\n }\n}\n","import { Module } from \"@nestjs/common\";\nimport { OpenApiService } from \"./openapi.service\";\n\n@Module({\n providers: [OpenApiService],\n exports: [OpenApiService],\n})\nexport class OpenApiModule {}\n","import { Injectable, Logger } from \"@nestjs/common\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as Handlebars from \"handlebars\";\nimport { IR } from \"../../ir/ir.types\";\nimport { TypeScriptClient } from \"../../config/config.schema\";\nimport { Generator } from \"../generator.interface\";\nimport { ConfigService } from \"../../config/config.service\";\nimport { registerCommonHandlebarsHelpers } from \"../handlebars-helpers\";\nimport {\n schemaToTSType,\n resolveMethodName,\n deriveMethodName,\n buildPathTemplate,\n buildQueryKeyBase,\n orderPathParams,\n buildMethodSignature,\n collectPredefinedTypesUsedInSchema,\n queryKeyArgs,\n quoteTSPropertyName,\n isStreamingOperation,\n getStreamingItemType,\n collectPredefinedTypesUsedInService,\n} from \"./helpers\";\nimport { schemaToZodSchema } from \"./zod-schema-converter\";\nimport { toPascalCase, toSnakeCase } from \"../../utils/string.utils\";\n\n@Injectable()\nexport class TypeScriptGeneratorService implements Generator<TypeScriptClient> {\n private readonly logger = new Logger(TypeScriptGeneratorService.name);\n\n constructor(private readonly configService: ConfigService) {}\n\n getType(): string {\n return \"typescript\";\n }\n\n async generate(client: TypeScriptClient, ir: IR): Promise<void> {\n // Ensure directories\n const srcDir = path.join(client.outDir, \"src\");\n const servicesDir = path.join(srcDir, \"services\");\n await fs.promises.mkdir(servicesDir, { recursive: true });\n\n // Pre-process operations to resolve method names (async operation)\n const processedIR = await this.preprocessIR(client, ir);\n\n // Register Handlebars helpers\n this.registerHandlebarsHelpers(client);\n\n // Generate files\n await this.generateClient(client, processedIR, srcDir);\n await this.generateIndex(client, processedIR, srcDir);\n await this.generateUtils(client, processedIR, srcDir);\n await this.generateServices(client, processedIR, servicesDir);\n await this.generateSchema(client, processedIR, srcDir);\n await this.generateZodSchema(client, processedIR, srcDir);\n await this.generatePackageJson(client);\n await this.generateTsConfig(client);\n await this.generateReadme(client, processedIR);\n }\n\n /**\n * Pre-process IR to resolve method names and add cached values\n */\n private async preprocessIR(client: TypeScriptClient, ir: IR): Promise<IR> {\n // Create a copy of IR with resolved method names\n const processedServices = await Promise.all(\n ir.services.map(async (service) => ({\n ...service,\n operations: await Promise.all(\n service.operations.map(async (op) => {\n const methodName = await resolveMethodName(client, op);\n return {\n ...op,\n _resolvedMethodName: methodName, // Cache the resolved name\n };\n })\n ),\n }))\n );\n\n return {\n ...ir,\n services: processedServices,\n };\n }\n\n private registerHandlebarsHelpers(client: TypeScriptClient): void {\n // Register common helpers shared across all generators\n registerCommonHandlebarsHelpers();\n\n // TypeScript-specific helpers\n // Use pre-resolved method names from _resolvedMethodName\n Handlebars.registerHelper(\"methodName\", (op: any) => {\n return op._resolvedMethodName || deriveMethodName(op);\n });\n Handlebars.registerHelper(\"queryTypeName\", (op: any) => {\n const methodName = op._resolvedMethodName || deriveMethodName(op);\n return toPascalCase(op.tag) + toPascalCase(methodName) + \"Query\";\n });\n Handlebars.registerHelper(\"pathTemplate\", (op: any) => {\n const result = buildPathTemplate(op);\n // Return as Handlebars.SafeString to prevent HTML escaping\n return new Handlebars.SafeString(result);\n });\n Handlebars.registerHelper(\"queryKeyBase\", (op: any) => {\n const result = buildQueryKeyBase(op);\n // Return as Handlebars.SafeString to prevent HTML escaping\n return new Handlebars.SafeString(result);\n });\n Handlebars.registerHelper(\"pathParamsInOrder\", (op: any) =>\n orderPathParams(op)\n );\n Handlebars.registerHelper(\"methodSignature\", (op: any, options: any) => {\n const methodName = op._resolvedMethodName || deriveMethodName(op);\n const modelDefs = options?.data?.root?.IR?.modelDefs || [];\n const predefinedTypes = options?.data?.root?.PredefinedTypes || [];\n // Service files are not in the same file as schema.ts, so isSameFile=false\n const isSameFile = options?.data?.root?.isSameFile || false;\n const signature = buildMethodSignature(\n op,\n methodName,\n modelDefs,\n predefinedTypes,\n isSameFile\n );\n // Return as SafeString array to prevent HTML escaping\n return signature.map((s) => new Handlebars.SafeString(s));\n });\n Handlebars.registerHelper(\n \"methodSignatureNoInit\",\n (op: any, options: any) => {\n const methodName = op._resolvedMethodName || deriveMethodName(op);\n const modelDefs = options?.data?.root?.IR?.modelDefs || [];\n const predefinedTypes = options?.data?.root?.PredefinedTypes || [];\n // Service files are not in the same file as schema.ts, so isSameFile=false\n const isSameFile = options?.data?.root?.isSameFile || false;\n const parts = buildMethodSignature(\n op,\n methodName,\n modelDefs,\n predefinedTypes,\n isSameFile\n );\n return parts.slice(0, -1); // Remove init parameter\n }\n );\n Handlebars.registerHelper(\"queryKeyArgs\", (op: any) => {\n const args = queryKeyArgs(op);\n // Return as SafeString array to prevent HTML escaping\n return args.map((arg) => new Handlebars.SafeString(arg));\n });\n Handlebars.registerHelper(\"tsType\", (x: any, options: any) => {\n if (x && typeof x === \"object\" && \"kind\" in x) {\n const predefinedTypes = options?.data?.root?.PredefinedTypes || [];\n const modelDefs = options?.data?.root?.IR?.modelDefs || [];\n // When generating schema.ts, isSameFile=true; for service files, isSameFile=false\n const isSameFile = options?.data?.root?.isSameFile || false;\n return schemaToTSType(x, predefinedTypes, modelDefs, isSameFile);\n }\n return \"unknown\";\n });\n Handlebars.registerHelper(\"stripSchemaNs\", (s: string) =>\n s.replace(/^Schema\\./, \"\")\n );\n Handlebars.registerHelper(\"tsTypeStripNs\", (x: any, options: any) => {\n const predefinedTypes = options?.data?.root?.PredefinedTypes || [];\n const modelDefs = options?.data?.root?.IR?.modelDefs || [];\n // When generating schema.ts, isSameFile=true; for service files, isSameFile=false\n const isSameFile = options?.data?.root?.isSameFile || false;\n\n if (x && typeof x === \"object\" && \"kind\" in x) {\n // Use schemaToTSType with predefinedTypes and modelDefs to get correct type\n // When isSameFile=true, schemaToTSType already returns types without Schema. prefix for local types\n const typeStr = schemaToTSType(\n x,\n predefinedTypes,\n modelDefs,\n isSameFile\n );\n // Strip ALL occurrences of Schema. prefix (including nested ones in inline objects)\n // For inline objects like Array<({ type: Schema.ResourceType })>, we need to strip all Schema. references\n const stripped = typeStr.replace(/Schema\\./g, \"\");\n // Return as SafeString to prevent Handlebars HTML escaping\n return new Handlebars.SafeString(stripped);\n }\n\n // If it's a string that looks like \"Schema.TypeName\", check for predefined types\n if (typeof x === \"string\") {\n if (x.startsWith(\"Schema.\")) {\n const typeName = x.replace(/^Schema\\./, \"\");\n const predefinedType = predefinedTypes.find(\n (pt: any) => pt.type === typeName\n );\n if (predefinedType) {\n return new Handlebars.SafeString(typeName);\n }\n // Not a predefined type, return with Schema. prefix stripped (for non-predefined types)\n return new Handlebars.SafeString(typeName);\n }\n return new Handlebars.SafeString(x);\n }\n\n return \"unknown\";\n });\n // Helper to check if a type is predefined\n Handlebars.registerHelper(\n \"isPredefinedType\",\n (typeName: string, options: any) => {\n const predefinedTypes = options?.data?.root?.PredefinedTypes || [];\n return predefinedTypes.some((pt: any) => pt.type === typeName);\n }\n );\n // Helper to get predefined type info\n Handlebars.registerHelper(\n \"getPredefinedType\",\n (typeName: string, options: any) => {\n const predefinedTypes = options?.data?.root?.PredefinedTypes || [];\n return predefinedTypes.find((pt: any) => pt.type === typeName);\n }\n );\n // Helper to group predefined types by package\n Handlebars.registerHelper(\"groupByPackage\", (predefinedTypes: any[]) => {\n const grouped: Record<string, { package: string; types: string[] }> = {};\n for (const pt of predefinedTypes || []) {\n if (!grouped[pt.package]) {\n grouped[pt.package] = { package: pt.package, types: [] };\n }\n grouped[pt.package].types.push(pt.type);\n }\n return Object.values(grouped);\n });\n // Helper to get predefined types used in a service\n Handlebars.registerHelper(\n \"getServicePredefinedTypes\",\n (service: any, options: any) => {\n const predefinedTypes = options?.data?.root?.PredefinedTypes || [];\n const modelDefs = options?.data?.root?.IR?.modelDefs || [];\n return collectPredefinedTypesUsedInService(\n service,\n predefinedTypes,\n modelDefs\n );\n }\n );\n // Helper to get predefined types used in the schema file\n Handlebars.registerHelper(\"getSchemaPredefinedTypes\", (options: any) => {\n const predefinedTypes = options?.data?.root?.PredefinedTypes || [];\n const modelDefs = options?.data?.root?.IR?.modelDefs || [];\n return collectPredefinedTypesUsedInSchema(modelDefs, predefinedTypes);\n });\n // Helper to join type names with commas\n Handlebars.registerHelper(\"joinTypes\", (types: string[]) => {\n return types.join(\", \");\n });\n // Helper to get unique packages from predefined types\n Handlebars.registerHelper(\"uniquePackages\", (predefinedTypes: any[]) => {\n const packages = new Set<string>();\n for (const pt of predefinedTypes || []) {\n if (pt.package) {\n packages.add(pt.package);\n }\n }\n return Array.from(packages);\n });\n // Helper to check if a package is in predefined types\n Handlebars.registerHelper(\n \"isPredefinedPackage\",\n (packageName: string, predefinedTypes: any[]) => {\n if (!predefinedTypes) return false;\n return predefinedTypes.some((pt: any) => pt.package === packageName);\n }\n );\n // Helper to get all dependencies (predefined types + explicit dependencies)\n Handlebars.registerHelper(\n \"getAllDependencies\",\n (client: TypeScriptClient) => {\n const deps: Record<string, string> = {\n zod: \"^4.3.5\", // Always include zod\n };\n\n // Add predefined type packages\n if (client.predefinedTypes) {\n for (const pt of client.predefinedTypes) {\n if (pt.package && !deps[pt.package]) {\n // Use explicit version if provided, otherwise \"*\"\n deps[pt.package] = client.dependencies?.[pt.package] || \"*\";\n }\n }\n }\n\n // Add any other explicit dependencies (excluding zod and predefined packages)\n if (client.dependencies) {\n for (const [pkg, version] of Object.entries(client.dependencies)) {\n if (pkg !== \"zod\" && !deps[pkg]) {\n deps[pkg] = version;\n }\n }\n }\n\n return deps;\n }\n );\n // Decode HTML entities in strings\n // Note: &amp; must be replaced last to avoid double-decoding\n // Also handle cases where entities are already escaped by Handlebars (e.g., &amp;#x60;)\n Handlebars.registerHelper(\"decodeHtml\", (str: string) => {\n if (typeof str !== \"string\") return str;\n // First decode double-encoded entities (e.g., &amp;#x60; -> &#x60;)\n let decoded = str\n .replace(/&amp;#x60;/g, \"&#x60;\")\n .replace(/&amp;#96;/g, \"&#96;\")\n .replace(/&amp;quot;/g, \"&quot;\")\n .replace(/&amp;lt;/g, \"&lt;\")\n .replace(/&amp;gt;/g, \"&gt;\");\n // Then decode all HTML entities\n decoded = decoded\n .replace(/&quot;/g, '\"')\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&#x60;/g, \"`\")\n .replace(/&#96;/g, \"`\")\n .replace(/&amp;/g, \"&\");\n // Return as SafeString to prevent Handlebars from escaping it again\n return new Handlebars.SafeString(decoded);\n });\n Handlebars.registerHelper(\"quotePropName\", (name: string) =>\n quoteTSPropertyName(name)\n );\n Handlebars.registerHelper(\"zodSchema\", (x: any, options: any) => {\n if (x && typeof x === \"object\" && \"kind\" in x) {\n const modelDefs = options?.data?.root?.IR?.modelDefs || [];\n // When generating schema.zod.ts, use local SchemaTypes namespace\n // The template name is passed in the root context\n const useLocalSchemaTypes =\n options?.data?.root?._templateName === \"schema.zod.ts.hbs\";\n return new Handlebars.SafeString(\n schemaToZodSchema(x, \"\", modelDefs, useLocalSchemaTypes)\n );\n }\n return \"z.unknown()\";\n });\n // Streaming helpers\n Handlebars.registerHelper(\"isStreaming\", (op: any) => {\n return isStreamingOperation(op);\n });\n Handlebars.registerHelper(\"streamingItemType\", (op: any) => {\n return new Handlebars.SafeString(getStreamingItemType(op));\n });\n }\n\n private async renderTemplate(\n templateName: string,\n data: any,\n outputPath: string,\n client: TypeScriptClient\n ): Promise<void> {\n // 1. Check for template override\n const overridePath =\n client.templates?.[templateName as keyof typeof client.templates];\n if (overridePath) {\n this.logger.debug(\n `Using template override for ${templateName}: ${overridePath}`\n );\n try {\n // Validate that override path exists and is readable\n await fs.promises.access(overridePath, fs.constants.R_OK);\n const templateContent = await fs.promises.readFile(\n overridePath,\n \"utf-8\"\n );\n const template = Handlebars.compile(templateContent);\n // Add template name to context so helpers know which template is being rendered\n const contextWithTemplate = {\n ...data,\n _templateName: templateName,\n };\n const rendered = template(contextWithTemplate);\n await fs.promises.writeFile(outputPath, rendered, \"utf-8\");\n return;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.error(\n `Template override file not found or not readable: ${overridePath}. Error: ${errorMsg}`\n );\n throw new Error(\n `Template override file not found or not readable: ${overridePath}`\n );\n }\n }\n\n // 2. Fall back to default template resolution\n // Templates are now co-located with the generator\n // Try multiple possible template paths (handles both source and compiled locations)\n // Note: When bundled by tsup, __dirname will be 'dist', so we need to look for templates\n // in dist/generator/typescript/templates/\n const possiblePaths = [\n path.join(__dirname, \"generator/typescript/templates\", templateName), // Bundled: dist/generator/typescript/templates/\n path.join(__dirname, \"templates\", templateName), // If __dirname is dist/generator/typescript/\n path.join(__dirname, \"../typescript/templates\", templateName), // Fallback\n path.join(\n process.cwd(),\n \"src/generator/typescript/templates\",\n templateName\n ), // Development\n ];\n\n let templatePath: string | null = null;\n for (const possiblePath of possiblePaths) {\n try {\n await fs.promises.access(possiblePath);\n templatePath = possiblePath;\n this.logger.debug(`Found template at: ${templatePath}`);\n break;\n } catch (error) {\n this.logger.debug(`Template not found at: ${possiblePath}`);\n // Continue to next path\n }\n }\n\n if (!templatePath) {\n this.logger.error(`Template not found: ${templateName}`);\n this.logger.error(`Checked paths: ${possiblePaths.join(\", \")}`);\n this.logger.error(`__dirname: ${__dirname}`);\n throw new Error(`Template not found: ${templateName}`);\n }\n\n const templateContent = await fs.promises.readFile(templatePath, \"utf-8\");\n const template = Handlebars.compile(templateContent);\n // Add template name to context so helpers know which template is being rendered\n const contextWithTemplate = {\n ...data,\n _templateName: templateName,\n };\n const rendered = template(contextWithTemplate);\n await fs.promises.writeFile(outputPath, rendered, \"utf-8\");\n }\n\n private async generateClient(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const clientPath = path.join(srcDir, \"client.ts\");\n if (this.configService.shouldExcludeFile(client, clientPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"client.ts.hbs\",\n { Client: client, IR: ir },\n clientPath,\n client\n );\n } catch (error) {\n // Fallback if template doesn't exist yet\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.warn(\n `Template client.ts.hbs not found: ${errorMsg}, using placeholder`\n );\n const content = `// Generated client - template rendering to be implemented`;\n await fs.promises.writeFile(clientPath, content, \"utf-8\");\n }\n }\n\n private async generateIndex(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const indexPath = path.join(srcDir, \"index.ts\");\n if (this.configService.shouldExcludeFile(client, indexPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"index.ts.hbs\",\n { Client: client, IR: ir },\n indexPath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template index.ts.hbs not found, using placeholder`);\n const content = `// Generated index - template rendering to be implemented`;\n await fs.promises.writeFile(indexPath, content, \"utf-8\");\n }\n }\n\n private async generateUtils(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const utilsPath = path.join(srcDir, \"utils.ts\");\n if (this.configService.shouldExcludeFile(client, utilsPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"utils.ts.hbs\",\n { Client: client, IR: ir },\n utilsPath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template utils.ts.hbs not found, using placeholder`);\n const content = `// Generated utils - template rendering to be implemented`;\n await fs.promises.writeFile(utilsPath, content, \"utf-8\");\n }\n }\n\n private async generateServices(\n client: TypeScriptClient,\n ir: IR,\n servicesDir: string\n ): Promise<void> {\n for (const service of ir.services) {\n const servicePath = path.join(\n servicesDir,\n `${toSnakeCase(service.tag).toLowerCase()}.ts`\n );\n if (this.configService.shouldExcludeFile(client, servicePath)) {\n continue;\n }\n try {\n await this.renderTemplate(\n \"service.ts.hbs\",\n {\n Client: client,\n Service: service,\n IR: ir,\n PredefinedTypes: client.predefinedTypes || [],\n isSameFile: false, // Service files are separate from schema.ts\n },\n servicePath,\n client\n );\n } catch (error) {\n this.logger.warn(\n `Template service.ts.hbs not found, using placeholder`\n );\n const content = `// Generated service ${service.tag} - template rendering to be implemented`;\n await fs.promises.writeFile(servicePath, content, \"utf-8\");\n }\n }\n }\n\n private async generateSchema(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const schemaPath = path.join(srcDir, \"schema.ts\");\n if (this.configService.shouldExcludeFile(client, schemaPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"schema.ts.hbs\",\n {\n Client: client,\n IR: ir,\n PredefinedTypes: client.predefinedTypes || [],\n isSameFile: true, // Types in schema.ts are in the same file\n },\n schemaPath,\n client\n );\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.warn(\n `Template schema.ts.hbs error: ${errorMsg}, using placeholder`\n );\n const content = `// Generated schema - template rendering to be implemented`;\n await fs.promises.writeFile(schemaPath, content, \"utf-8\");\n }\n }\n\n private async generateZodSchema(\n client: TypeScriptClient,\n ir: IR,\n srcDir: string\n ): Promise<void> {\n const zodSchemaPath = path.join(srcDir, \"schema.zod.ts\");\n if (this.configService.shouldExcludeFile(client, zodSchemaPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"schema.zod.ts.hbs\",\n { Client: client, IR: ir },\n zodSchemaPath,\n client\n );\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.warn(\n `Template schema.zod.ts.hbs error: ${errorMsg}, using placeholder`\n );\n const content = `// Generated Zod schemas - template rendering to be implemented`;\n await fs.promises.writeFile(zodSchemaPath, content, \"utf-8\");\n }\n }\n\n private async generatePackageJson(client: TypeScriptClient): Promise<void> {\n const packageJsonPath = path.join(client.outDir, \"package.json\");\n if (this.configService.shouldExcludeFile(client, packageJsonPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"package.json.hbs\",\n { Client: client },\n packageJsonPath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template package.json.hbs not found, using fallback`);\n const content = JSON.stringify(\n {\n name: client.packageName,\n version: \"0.0.1\",\n main: \"dist/index.js\",\n types: \"dist/index.d.ts\",\n },\n null,\n 2\n );\n await fs.promises.writeFile(packageJsonPath, content, \"utf-8\");\n }\n }\n\n private async generateTsConfig(client: TypeScriptClient): Promise<void> {\n const tsConfigPath = path.join(client.outDir, \"tsconfig.json\");\n if (this.configService.shouldExcludeFile(client, tsConfigPath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"tsconfig.json.hbs\",\n { Client: client },\n tsConfigPath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template tsconfig.json.hbs not found, using fallback`);\n const content = JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2020\",\n module: \"commonjs\",\n lib: [\"ES2020\"],\n declaration: true,\n outDir: \"./dist\",\n rootDir: \"./src\",\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n },\n include: [\"src/**/*\"],\n },\n null,\n 2\n );\n await fs.promises.writeFile(tsConfigPath, content, \"utf-8\");\n }\n }\n\n private async generateReadme(\n client: TypeScriptClient,\n ir: IR\n ): Promise<void> {\n const readmePath = path.join(client.outDir, \"README.md\");\n if (this.configService.shouldExcludeFile(client, readmePath)) {\n return;\n }\n try {\n await this.renderTemplate(\n \"README.md.hbs\",\n { Client: client, IR: ir },\n readmePath,\n client\n );\n } catch (error) {\n this.logger.warn(`Template README.md.hbs not found, using fallback`);\n const content = `# ${client.name}\\n\\nGenerated SDK from OpenAPI specification.`;\n await fs.promises.writeFile(readmePath, content, \"utf-8\");\n }\n }\n}\n","import * as Handlebars from \"handlebars\";\nimport {\n toPascalCase,\n toCamelCase,\n toSnakeCase,\n toKebabCase,\n} from \"../utils/string.utils\";\n\n/**\n * Register common Handlebars helpers that can be shared across all generators\n * These helpers are language-agnostic and work with any generator type\n */\nexport function registerCommonHandlebarsHelpers(): void {\n // String transformation helpers\n Handlebars.registerHelper(\"pascal\", (str: string) => toPascalCase(str));\n Handlebars.registerHelper(\"camel\", (str: string) => toCamelCase(str));\n Handlebars.registerHelper(\"kebab\", (str: string) => toKebabCase(str));\n Handlebars.registerHelper(\"snake\", (str: string) => toSnakeCase(str));\n Handlebars.registerHelper(\n \"serviceName\",\n (tag: string) => toPascalCase(tag) + \"Service\"\n );\n Handlebars.registerHelper(\"serviceProp\", (tag: string) => toCamelCase(tag));\n Handlebars.registerHelper(\"fileBase\", (tag: string) =>\n toSnakeCase(tag).toLowerCase()\n );\n\n // Comparison helpers\n Handlebars.registerHelper(\"eq\", (a: any, b: any) => a === b);\n Handlebars.registerHelper(\"ne\", (a: any, b: any) => a !== b);\n Handlebars.registerHelper(\"gt\", (a: any, b: any) => a > b);\n Handlebars.registerHelper(\"lt\", (a: any, b: any) => a < b);\n Handlebars.registerHelper(\"sub\", (a: number, b: number) => a - b);\n Handlebars.registerHelper(\"len\", (arr: any) =>\n Array.isArray(arr) ? arr.length : 0\n );\n Handlebars.registerHelper(\"or\", function (this: any, ...args: any[]) {\n const options = args[args.length - 1];\n if (options && options.fn) {\n // Block helper\n return args.slice(0, -1).some((a) => a)\n ? options.fn(this)\n : options.inverse(this);\n }\n // Regular helper\n return args.slice(0, -1).some((a) => a);\n });\n Handlebars.registerHelper(\"and\", function (this: any, ...args: any[]) {\n const options = args[args.length - 1];\n if (options && options.fn) {\n // Block helper\n return args.slice(0, -1).every((a) => a)\n ? options.fn(this)\n : options.inverse(this);\n }\n // Regular helper\n return args.slice(0, -1).every((a) => a);\n });\n\n // String manipulation helpers\n Handlebars.registerHelper(\n \"replace\",\n (str: string, search: string, replace: string) => {\n if (typeof str !== \"string\") return str;\n return str.replace(\n new RegExp(search.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), \"g\"),\n replace\n );\n }\n );\n Handlebars.registerHelper(\"index\", (arr: any[], idx: number) => arr?.[idx]);\n\n // Service/namespace helpers\n Handlebars.registerHelper(\"getServiceName\", (tag: string) => {\n const parts = tag.split(\".\");\n return parts.length > 1 ? parts[1] : tag;\n });\n Handlebars.registerHelper(\"groupByNamespace\", (services: any[]) => {\n const namespaces: Record<string, any[]> = {};\n for (const service of services) {\n const parts = service.tag.split(\".\");\n if (parts.length === 1) {\n if (!namespaces[\"\"]) namespaces[\"\"] = [];\n namespaces[\"\"].push(service);\n } else {\n const namespace = parts[0];\n if (!namespaces[namespace]) namespaces[namespace] = [];\n namespaces[namespace].push(service);\n }\n }\n return namespaces;\n });\n Handlebars.registerHelper(\"getRootServices\", (services: any[]) => {\n return services.filter((s) => !s.tag.includes(\".\"));\n });\n\n // Dictionary/object helpers for template state management\n Handlebars.registerHelper(\"dict\", () => ({}));\n Handlebars.registerHelper(\n \"setVar\",\n (name: string, value: any, options: any) => {\n if (options && options.data && options.data.root) {\n options.data.root[`_${name}`] = value;\n }\n return \"\";\n }\n );\n Handlebars.registerHelper(\"getVar\", (name: string, options: any) => {\n if (options && options.data && options.data.root) {\n return options.data.root[`_${name}`] || false;\n }\n return false;\n });\n Handlebars.registerHelper(\"set\", (obj: any, key: string, value: any) => {\n if (obj && typeof obj === \"object\") {\n obj[key] = value;\n }\n return \"\";\n });\n Handlebars.registerHelper(\"hasKey\", (obj: any, key: string) => {\n return obj && typeof obj === \"object\" && key in obj;\n });\n Handlebars.registerHelper(\"lookup\", (obj: any, key: string) => {\n return obj && typeof obj === \"object\" ? obj[key] : undefined;\n });\n\n // Regex helper\n Handlebars.registerHelper(\"reMatch\", (pattern: string, str: string) => {\n try {\n const regex = new RegExp(pattern);\n return regex.test(str);\n } catch {\n return false;\n }\n });\n}\n","import { IRSchema, IRSchemaKind } from \"../../ir/ir.types\";\nimport { quoteTSPropertyName } from \"./helpers\";\n\n/**\n * Convert an IR schema to Zod schema string\n * @param modelDefs Optional array of model definitions (not used anymore, kept for compatibility)\n * @param useLocalSchemaTypes If true, use TypeNameSchema directly (for schema.zod.ts), otherwise use Schema.TypeNameSchema\n */\nexport function schemaToZodSchema(\n s: IRSchema,\n indent: string = \"\",\n modelDefs?: Array<{ name: string; schema: IRSchema }>,\n useLocalSchemaTypes: boolean = false\n): string {\n const nextIndent = indent + \" \";\n let zod: string;\n\n switch (s.kind) {\n case IRSchemaKind.String:\n zod = \"z.string()\";\n if (s.format === \"date\" || s.format === \"date-time\") {\n zod += \".datetime()\";\n } else if (s.format === \"email\") {\n zod += \".email()\";\n } else if (s.format === \"uri\" || s.format === \"url\") {\n zod += \".url()\";\n } else if (s.format === \"uuid\") {\n zod += \".uuid()\";\n }\n break;\n case IRSchemaKind.Number:\n zod = \"z.number()\";\n break;\n case IRSchemaKind.Integer:\n zod = \"z.number().int()\";\n break;\n case IRSchemaKind.Boolean:\n zod = \"z.boolean()\";\n break;\n case IRSchemaKind.Null:\n zod = \"z.null()\";\n break;\n case IRSchemaKind.Ref:\n if (s.ref) {\n // Simple types are now exported directly (not in SchemaTypes namespace)\n // In schema.zod.ts, use TypeNameSchema directly (same file)\n // Elsewhere, use Schema.TypeNameSchema\n zod = useLocalSchemaTypes ? `${s.ref}Schema` : `Schema.${s.ref}Schema`;\n } else {\n zod = \"z.unknown()\";\n }\n break;\n case IRSchemaKind.Array:\n if (s.items) {\n const itemsZod = schemaToZodSchema(\n s.items,\n nextIndent,\n modelDefs,\n useLocalSchemaTypes\n );\n zod = `z.array(${itemsZod})`;\n } else {\n zod = \"z.array(z.unknown())\";\n }\n break;\n case IRSchemaKind.Object:\n if (!s.properties || s.properties.length === 0) {\n if (s.additionalProperties) {\n const valueZod = schemaToZodSchema(\n s.additionalProperties,\n nextIndent,\n modelDefs,\n useLocalSchemaTypes\n );\n zod = `z.record(z.string(), ${valueZod})`;\n } else {\n zod = \"z.record(z.string(), z.unknown())\";\n }\n } else {\n const props: string[] = [];\n for (const field of s.properties) {\n const fieldZod = schemaToZodSchema(\n field.type,\n nextIndent,\n modelDefs,\n useLocalSchemaTypes\n );\n const fieldName = quoteTSPropertyName(field.name);\n if (field.required) {\n props.push(`${nextIndent}${fieldName}: ${fieldZod}`);\n } else {\n props.push(`${nextIndent}${fieldName}: ${fieldZod}.optional()`);\n }\n }\n const objectZod = `z.object({\\n${props.join(\",\\n\")}\\n${indent}})`;\n if (s.additionalProperties) {\n const valueZod = schemaToZodSchema(\n s.additionalProperties,\n nextIndent,\n modelDefs,\n useLocalSchemaTypes\n );\n // Use .catchall() instead of spreading .shape (which doesn't exist on ZodRecord)\n // This allows additional properties of the specified type\n zod = `${objectZod}.catchall(${valueZod})`;\n } else {\n zod = objectZod;\n }\n }\n break;\n case IRSchemaKind.Enum:\n if (s.enumValues && s.enumValues.length > 0) {\n // Create enum from string literals\n const enumValues = s.enumValues.map((v) => {\n // Handle boolean and number strings\n if (v === \"true\" || v === \"false\") {\n return v;\n }\n if (/^-?[0-9]+(\\.[0-9]+)?$/.test(v)) {\n return v;\n }\n return JSON.stringify(v);\n });\n zod = `z.enum([${enumValues.join(\", \")}])`;\n } else {\n zod = \"z.string()\";\n }\n break;\n case IRSchemaKind.OneOf:\n if (s.oneOf && s.oneOf.length > 0) {\n const options = s.oneOf.map((opt) =>\n schemaToZodSchema(opt, nextIndent, modelDefs, useLocalSchemaTypes)\n );\n zod = `z.union([${options.join(\", \")}])`;\n } else {\n zod = \"z.unknown()\";\n }\n break;\n case IRSchemaKind.AnyOf:\n if (s.anyOf && s.anyOf.length > 0) {\n const options = s.anyOf.map((opt) =>\n schemaToZodSchema(opt, nextIndent, modelDefs, useLocalSchemaTypes)\n );\n zod = `z.union([${options.join(\", \")}])`;\n } else {\n zod = \"z.unknown()\";\n }\n break;\n case IRSchemaKind.AllOf:\n if (s.allOf && s.allOf.length > 0) {\n const schemas = s.allOf.map((sch) =>\n schemaToZodSchema(sch, nextIndent, modelDefs, useLocalSchemaTypes)\n );\n // Zod doesn't have allOf, so we use intersection\n zod = schemas.join(\".and(\") + \")\".repeat(schemas.length - 1);\n } else {\n zod = \"z.unknown()\";\n }\n break;\n default:\n zod = \"z.unknown()\";\n }\n\n // Handle nullable\n if (s.nullable && zod !== \"z.null()\") {\n zod = `${zod}.nullable()`;\n }\n\n return zod;\n}\n","import { IROperation, IRSchema, IRSchemaKind } from \"../../ir/ir.types\";\nimport { Client } from \"../../config/config.schema\";\nimport { toPascalCase, toCamelCase } from \"../../utils/string.utils\";\n\n/**\n * Convert an IR schema to TypeScript type string\n */\n/**\n * Decode HTML entities in a string\n */\nfunction decodeHtmlEntities(str: string): string {\n return str\n .replace(/&quot;/g, '\"')\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&#x60;/g, \"`\")\n .replace(/&#96;/g, \"`\")\n .replace(/&amp;/g, \"&\");\n}\n\nexport function schemaToTSType(\n s: IRSchema,\n predefinedTypes?: Array<{ type: string; package: string }>,\n modelDefs?: Array<{ name: string; schema: IRSchema }>,\n isSameFile: boolean = false\n): string {\n // Base type string without nullability; append null later\n let t: string;\n switch (s.kind) {\n case IRSchemaKind.String:\n if (s.format === \"binary\") {\n t = \"Blob\";\n } else {\n t = \"string\";\n }\n break;\n case IRSchemaKind.Number:\n case IRSchemaKind.Integer:\n t = \"number\";\n break;\n case IRSchemaKind.Boolean:\n t = \"boolean\";\n break;\n case IRSchemaKind.Null:\n t = \"null\";\n break;\n case IRSchemaKind.Ref:\n if (s.ref) {\n // Check if this is a predefined type\n if (predefinedTypes?.some((pt) => pt.type === s.ref)) {\n t = s.ref; // Use type name directly for predefined types\n } else if (isSameFile && modelDefs) {\n // Only check for local types if we're in the same file (schema.ts)\n // Check if this type is defined locally in the same file\n const localType = modelDefs.find((md) => md.name === s.ref);\n if (localType) {\n // Type is defined in the same file, use it directly without Schema. prefix\n t = s.ref;\n } else {\n // Type is not defined locally, use Schema. prefix\n t = \"Schema.\" + s.ref;\n }\n } else {\n // Not in same file or no modelDefs, use Schema. prefix\n t = \"Schema.\" + s.ref;\n }\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.Array:\n if (s.items) {\n const inner = schemaToTSType(s.items, predefinedTypes, modelDefs);\n // Wrap unions/intersections in parentheses inside Array<>\n if (inner.includes(\" | \") || inner.includes(\" & \")) {\n t = `Array<(${inner})>`;\n } else {\n t = `Array<${inner}>`;\n }\n } else {\n t = \"Array<unknown>\";\n }\n break;\n case IRSchemaKind.OneOf:\n if (s.oneOf) {\n const parts = s.oneOf.map((sub) =>\n schemaToTSType(sub, predefinedTypes, modelDefs)\n );\n t = parts.join(\" | \");\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.AnyOf:\n if (s.anyOf) {\n const parts = s.anyOf.map((sub) =>\n schemaToTSType(sub, predefinedTypes, modelDefs)\n );\n t = parts.join(\" | \");\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.AllOf:\n if (s.allOf) {\n const parts = s.allOf.map((sub) =>\n schemaToTSType(sub, predefinedTypes, modelDefs)\n );\n t = parts.join(\" & \");\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.Enum:\n if (s.enumValues && s.enumValues.length > 0) {\n const vals: string[] = [];\n switch (s.enumBase) {\n case IRSchemaKind.Number:\n case IRSchemaKind.Integer:\n for (const v of s.enumValues) {\n vals.push(v);\n }\n break;\n case IRSchemaKind.Boolean:\n for (const v of s.enumValues) {\n if (v === \"true\" || v === \"false\") {\n vals.push(v);\n } else {\n vals.push(`\"${v}\"`);\n }\n }\n break;\n default:\n for (const v of s.enumValues) {\n vals.push(`\"${v}\"`);\n }\n }\n t = vals.join(\" | \");\n } else {\n t = \"unknown\";\n }\n break;\n case IRSchemaKind.Object:\n if (!s.properties || s.properties.length === 0) {\n t = \"Record<string, unknown>\";\n } else {\n // Inline object shape for rare cases; nested ones should be refs\n const parts: string[] = [];\n for (const f of s.properties) {\n const ft = schemaToTSType(\n f.type,\n predefinedTypes,\n modelDefs,\n isSameFile\n );\n if (f.required) {\n parts.push(`${f.name}: ${ft}`);\n } else {\n parts.push(`${f.name}?: ${ft}`);\n }\n }\n t = \"{ \" + parts.join(\"; \") + \" }\";\n }\n break;\n default:\n t = \"unknown\";\n }\n if (s.nullable && t !== \"null\") {\n t += \" | null\";\n }\n // Decode any HTML entities that might be in the type string\n return decodeHtmlEntities(t);\n}\n\n/**\n * Derive method name using basic REST-style heuristics\n */\nexport function deriveMethodName(op: IROperation): string {\n // Basic REST-style heuristics\n const path = op.path;\n const hasID = path.includes(\"{\") && path.includes(\"}\");\n\n if (op.operationID) {\n return toCamelCase(op.operationID);\n }\n\n switch (op.method) {\n case \"GET\":\n return hasID ? \"get\" : \"list\";\n case \"POST\":\n return \"create\";\n case \"PUT\":\n case \"PATCH\":\n return \"update\";\n case \"DELETE\":\n return \"delete\";\n default:\n return op.method.toLowerCase();\n }\n}\n\n/**\n * Resolve method name using optional parser function, then operationId, then heuristic\n */\nexport async function resolveMethodName(\n client: Client,\n op: IROperation\n): Promise<string> {\n // Try function-based parser if provided\n if (client.operationIdParser) {\n try {\n const name = await client.operationIdParser(\n op.operationID,\n op.method,\n op.path\n );\n if (name) {\n return toCamelCase(name);\n }\n } catch {\n // Parser failed, continue with defaults\n }\n }\n\n // Default parse of operationId\n const defaultParsed = defaultParseOperationID(op.operationID);\n if (defaultParsed) {\n return toCamelCase(defaultParsed);\n }\n\n return deriveMethodName(op);\n}\n\n/**\n * Default parse operation ID\n */\nfunction defaultParseOperationID(opID: string): string {\n if (!opID) {\n return \"\";\n }\n // Strip any prefix up to and including \"Controller_\"\n const idx = opID.indexOf(\"Controller_\");\n if (idx >= 0) {\n return opID.substring(idx + \"Controller_\".length);\n }\n return opID;\n}\n\n/**\n * Build path template converts OpenAPI path to TypeScript template literal\n */\nexport function buildPathTemplate(op: IROperation): string {\n // Convert /foo/{id}/bar/{slug} -> `/foo/${encodeURIComponent(id)}/bar/${encodeURIComponent(slug)}`\n let path = op.path;\n let result = \"`\";\n for (let i = 0; i < path.length; i++) {\n if (path[i] === \"{\") {\n // read name\n let j = i + 1;\n while (j < path.length && path[j] !== \"}\") {\n j++;\n }\n if (j < path.length) {\n const name = path.substring(i + 1, j);\n result += `\\${encodeURIComponent(${name})}`;\n i = j;\n continue;\n }\n }\n result += path[i];\n }\n result += \"`\";\n return result;\n}\n\n/**\n * Build query key base returns a TS string literal for the base of a react-query key\n */\nexport function buildQueryKeyBase(op: IROperation): string {\n const path = op.path;\n // Split by '/'; skip parameter placeholders like {id}\n const parts = path.split(\"/\");\n const baseParts: string[] = [];\n for (const p of parts) {\n if (p === \"\") {\n // leading slash\n continue;\n }\n if (p.startsWith(\"{\") && p.endsWith(\"}\")) {\n continue;\n }\n baseParts.push(p);\n }\n const base = baseParts.join(\"/\");\n return `'${base}'`;\n}\n\n/**\n * Order path params extracts path parameter order as they appear in the path\n */\nexport function orderPathParams(op: IROperation) {\n const ordered: typeof op.pathParams = [];\n const index = new Map<string, number>();\n for (let i = 0; i < op.pathParams.length; i++) {\n index.set(op.pathParams[i].name, i);\n }\n const path = op.path;\n for (let i = 0; i < path.length; i++) {\n if (path[i] === \"{\") {\n let j = i + 1;\n while (j < path.length && path[j] !== \"}\") {\n j++;\n }\n if (j < path.length) {\n const name = path.substring(i + 1, j);\n const idx = index.get(name);\n if (idx !== undefined) {\n ordered.push(op.pathParams[idx]);\n }\n i = j;\n continue;\n }\n }\n }\n return ordered;\n}\n\n/**\n * Build method signature constructs the TS parameter list\n */\n/**\n * Convert schema to TypeScript type, handling simple type refs\n * Simple types are now exported directly from schema.ts (not in SchemaTypes namespace)\n * So we just use Schema.TypeName for all types\n */\nexport function schemaToTSTypeWithSimpleTypes(\n s: IRSchema,\n modelDefs?: Array<{ name: string; schema: IRSchema }>,\n predefinedTypes?: Array<{ type: string; package: string }>,\n isSameFile: boolean = false\n): string {\n // Use schemaToTSType with predefined types and modelDefs\n // isSameFile should be true when generating schema.ts, false for service files\n return schemaToTSType(s, predefinedTypes, modelDefs, isSameFile);\n}\n\nexport function buildMethodSignature(\n op: IROperation,\n methodName: string,\n modelDefs?: Array<{ name: string; schema: IRSchema }>,\n predefinedTypes?: Array<{ type: string; package: string }>,\n isSameFile: boolean = false\n): string[] {\n const parts: string[] = [];\n // path params as positional args\n for (const p of orderPathParams(op)) {\n parts.push(\n `${p.name}: ${schemaToTSTypeWithSimpleTypes(p.schema, modelDefs, predefinedTypes, isSameFile)}`\n );\n }\n // query object\n if (op.queryParams.length > 0) {\n // Reference named interface defined in schema.ts\n const queryType = toPascalCase(op.tag) + toPascalCase(methodName) + \"Query\";\n parts.push(`query?: Schema.${queryType}`);\n }\n // body\n if (op.requestBody) {\n const opt = op.requestBody.required === true ? \"\" : \"?\";\n parts.push(\n `body${opt}: ${schemaToTSTypeWithSimpleTypes(op.requestBody.schema, modelDefs, predefinedTypes, isSameFile)}`\n );\n }\n // init\n parts.push('init?: Omit<RequestInit, \"method\" | \"body\">');\n\n return parts;\n}\n\n/**\n * Collect predefined types used in a schema file\n * Checks all model definitions (interfaces, types, etc.) to find which predefined types are referenced\n */\nexport function collectPredefinedTypesUsedInSchema(\n modelDefs: Array<{ name: string; schema: IRSchema }>,\n predefinedTypes?: Array<{ type: string; package: string }>\n): Array<{ type: string; package: string }> {\n if (!predefinedTypes || predefinedTypes.length === 0) {\n return [];\n }\n\n const usedTypes = new Set<string>();\n\n // Helper to resolve a ref to its actual schema\n const resolveRef = (ref: string): IRSchema | null => {\n const modelDef = modelDefs.find((md) => md.name === ref);\n return modelDef ? modelDef.schema : null;\n };\n\n // Helper to check if a schema uses a predefined type\n const checkSchema = (schema: IRSchema) => {\n if (schema.kind === \"ref\" && schema.ref) {\n // Check if the ref itself is a predefined type\n const isPredefined = predefinedTypes.some((pt) => pt.type === schema.ref);\n if (isPredefined) {\n usedTypes.add(schema.ref);\n } else {\n // Resolve the ref and check its contents\n const resolved = resolveRef(schema.ref);\n if (resolved) {\n checkSchema(resolved);\n }\n }\n } else if (schema.kind === \"array\" && schema.items) {\n checkSchema(schema.items);\n } else if (schema.kind === \"object\" && schema.properties) {\n for (const prop of schema.properties) {\n checkSchema(prop.type);\n }\n } else if (schema.kind === \"oneOf\" && schema.oneOf) {\n for (const sub of schema.oneOf) {\n checkSchema(sub);\n }\n } else if (schema.kind === \"anyOf\" && schema.anyOf) {\n for (const sub of schema.anyOf) {\n checkSchema(sub);\n }\n } else if (schema.kind === \"allOf\" && schema.allOf) {\n for (const sub of schema.allOf) {\n checkSchema(sub);\n }\n }\n };\n\n // Check all model definitions in the schema file\n for (const modelDef of modelDefs) {\n checkSchema(modelDef.schema);\n }\n\n // Return only the predefined types that were actually used\n return predefinedTypes.filter((pt) => usedTypes.has(pt.type));\n}\n\n/**\n * Collect predefined types used in a service's operations\n * Checks path parameters, query parameters, request body, and response types\n */\nexport function collectPredefinedTypesUsedInService(\n service: { operations: IROperation[] },\n predefinedTypes?: Array<{ type: string; package: string }>,\n modelDefs?: Array<{ name: string; schema: IRSchema }>\n): Array<{ type: string; package: string }> {\n if (!predefinedTypes || predefinedTypes.length === 0) {\n return [];\n }\n\n const usedTypes = new Set<string>();\n\n // Helper to resolve a ref to its actual schema\n const resolveRef = (ref: string): IRSchema | null => {\n if (!modelDefs) return null;\n const modelDef = modelDefs.find((md) => md.name === ref);\n return modelDef ? modelDef.schema : null;\n };\n\n // Helper to check if a schema uses a predefined type\n const checkSchema = (schema: IRSchema) => {\n if (schema.kind === \"ref\" && schema.ref) {\n // Check if the ref itself is a predefined type\n const isPredefined = predefinedTypes.some((pt) => pt.type === schema.ref);\n if (isPredefined) {\n usedTypes.add(schema.ref);\n } else {\n // Resolve the ref and check its contents\n const resolved = resolveRef(schema.ref);\n if (resolved) {\n checkSchema(resolved);\n }\n }\n } else if (schema.kind === \"array\" && schema.items) {\n checkSchema(schema.items);\n } else if (schema.kind === \"object\" && schema.properties) {\n for (const prop of schema.properties) {\n checkSchema(prop.type);\n }\n } else if (schema.kind === \"oneOf\" && schema.oneOf) {\n for (const sub of schema.oneOf) {\n checkSchema(sub);\n }\n } else if (schema.kind === \"anyOf\" && schema.anyOf) {\n for (const sub of schema.anyOf) {\n checkSchema(sub);\n }\n } else if (schema.kind === \"allOf\" && schema.allOf) {\n for (const sub of schema.allOf) {\n checkSchema(sub);\n }\n }\n };\n\n // Check all operations in the service\n // Note: We only check path parameters because:\n // - Query parameters use Schema.QueryType interfaces (defined in schema.ts which already imports predefined types)\n // - Request body uses Schema.BodyType interfaces (defined in schema.ts which already imports predefined types)\n // - Response uses Schema.ResponseType (defined in schema.ts which already imports predefined types)\n // Only path parameters use predefined types directly in the method signature\n for (const op of service.operations) {\n // Check path parameters (these are used directly in method signatures)\n for (const param of op.pathParams) {\n checkSchema(param.schema);\n }\n // Note: We don't check query params, request body, or response because:\n // - Query params use Schema.QueryType interfaces\n // - Request body uses Schema.BodyType interfaces\n // - Response uses Schema.ResponseType\n // These Schema types are defined in schema.ts which already imports the predefined types.\n // The service file only needs to import predefined types used directly in method signatures (path params).\n }\n\n // Return only the predefined types that were actually used\n return predefinedTypes.filter((pt) => usedTypes.has(pt.type));\n}\n\n/**\n * Query key args returns the parameter names (no types) in the same order as the method parameters\n */\nexport function queryKeyArgs(op: IROperation): string[] {\n const out: string[] = [];\n for (const p of orderPathParams(op)) {\n out.push(p.name);\n }\n if (op.queryParams.length > 0) {\n out.push(\"query\");\n }\n if (op.requestBody) {\n out.push(\"body\");\n }\n return out;\n}\n\n/**\n * Quote TS property name quotes TypeScript property names that contain special characters\n */\nexport function quoteTSPropertyName(name: string): string {\n // Check if the name contains characters that require quoting\n let needsQuoting = false;\n for (const char of name) {\n if (\n !(\n (char >= \"a\" && char <= \"z\") ||\n (char >= \"A\" && char <= \"Z\") ||\n (char >= \"0\" && char <= \"9\") ||\n char === \"_\" ||\n char === \"$\"\n )\n ) {\n needsQuoting = true;\n break;\n }\n }\n\n // Also quote if the name starts with a number\n if (name.length > 0 && name[0] >= \"0\" && name[0] <= \"9\") {\n needsQuoting = true;\n }\n\n if (needsQuoting) {\n return `\"${name}\"`;\n }\n return name;\n}\n\n// Re-export schemaToZodSchema from dedicated file\nexport { schemaToZodSchema } from \"./zod-schema-converter\";\n\n/**\n * Check if an operation has a streaming response\n */\nexport function isStreamingOperation(op: IROperation): boolean {\n return op.response.isStreaming === true;\n}\n\n/**\n * Get the item type for a streaming response\n * For streaming, we typically want the item type from an array schema\n */\nexport function getStreamingItemType(op: IROperation): string {\n const schema = op.response.schema;\n\n // If it's an array, return the item type\n if (schema.kind === IRSchemaKind.Array && schema.items) {\n return schemaToTSType(schema.items);\n }\n\n // For SSE, the data field is typically a string\n if (op.response.streamingFormat === \"sse\") {\n return \"string\";\n }\n\n // Default: return the schema type itself\n return schemaToTSType(schema);\n}\n","import { Config, Client } from \"../config/config.schema\";\nimport { loadMjsConfig } from \"../config/mjs-config-loader\";\nimport { ConfigService } from \"../config/config.service\";\nimport { OpenApiService } from \"../openapi/openapi.service\";\nimport { IrBuilderService } from \"../generator/ir-builder.service\";\nimport { GeneratorService } from \"../generator/generator.service\";\nimport { SchemaConverterService } from \"../generator/schema-converter.service\";\nimport { TypeScriptGeneratorService } from \"../generator/typescript/typescript-generator.service\";\nimport * as path from \"path\";\nimport * as fs from \"fs\";\n\n/**\n * Options for programmatic SDK generation\n */\nexport interface GenerateOptions {\n /**\n * Generate only the named client from config\n */\n client?: string;\n\n /**\n * Base directory for resolving relative outDir paths.\n * If not provided, outDir is resolved relative to process.cwd()\n */\n baseDir?: string;\n}\n\n/**\n * Standalone function to generate SDKs from a config object or config file path.\n * This function can be used programmatically without NestJS dependency injection.\n *\n * @param configOrPath - Config object or path to chunkflow-codegen.config.mjs file\n * @param options - Optional generation options\n * @returns Promise that resolves when generation is complete\n *\n * @example\n * ```typescript\n * import { generate } from '@blimu/codegen';\n *\n * // Using config object\n * await generate({\n * spec: 'http://localhost:3020/docs/backend-api/json',\n * clients: [{\n * type: 'typescript',\n * outDir: './my-sdk',\n * packageName: 'my-sdk',\n * name: 'MyClient'\n * }]\n * });\n *\n * // Using config file path\n * await generate('./chunkflow-codegen.config.mjs');\n * ```\n */\nexport async function generate(\n configOrPath: Config | string,\n options?: GenerateOptions\n): Promise<void> {\n // Load config if string path\n let config: Config;\n let baseDir: string | undefined;\n\n if (typeof configOrPath === \"string\") {\n const configPath = path.isAbsolute(configOrPath)\n ? configOrPath\n : path.resolve(configOrPath);\n config = await loadMjsConfig(configPath);\n // Use config file's directory as baseDir if not provided\n baseDir = options?.baseDir ?? path.dirname(configPath);\n } else {\n config = configOrPath;\n baseDir = options?.baseDir;\n }\n\n // Initialize services (standalone, no NestJS DI)\n const configService = new ConfigService();\n const openApiService = new OpenApiService();\n const schemaConverter = new SchemaConverterService();\n const irBuilder = new IrBuilderService(schemaConverter);\n const generatorService = new GeneratorService(irBuilder, openApiService);\n\n // Register TypeScript generator\n const typeScriptGenerator = new TypeScriptGeneratorService(configService);\n generatorService.register(typeScriptGenerator);\n\n // Generate for each client\n for (const client of config.clients) {\n if (options?.client && client.name !== options.client) {\n continue;\n }\n\n // Resolve outDir relative to baseDir if provided\n const resolvedOutDir = baseDir\n ? path.resolve(baseDir, client.outDir)\n : path.resolve(client.outDir);\n\n // Ensure output directory exists\n await fs.promises.mkdir(resolvedOutDir, { recursive: true });\n\n // Create a client copy with resolved outDir\n const clientWithResolvedPath = {\n ...client,\n outDir: resolvedOutDir,\n };\n\n // Generate the SDK\n await generatorService.generate(config.spec, clientWithResolvedPath);\n }\n}\n\n/**\n * Load a config file programmatically\n *\n * @param configPath - Path to chunkflow-codegen.config.mjs file\n * @returns Promise that resolves to the loaded config\n *\n * @example\n * ```typescript\n * import { loadConfig } from '@blimu/codegen';\n *\n * const config = await loadConfig('./chunkflow-codegen.config.mjs');\n * ```\n */\nexport async function loadConfig(configPath: string): Promise<Config> {\n return loadMjsConfig(configPath);\n}\n"],"mappings":"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","names":["z","PredefinedTypeSchema","object","type","string","min","package","importPath","optional","TYPESCRIPT_TEMPLATE_NAMES","BaseClientSchema","outDir","name","includeTags","array","excludeTags","operationIdParser","custom","preCommand","postCommand","defaultBaseURL","exclude","TypeScriptClientSchema","extend","literal","packageName","moduleName","includeQueryKeys","boolean","predefinedTypes","dependencies","record","devDependencies","templates","refine","Object","keys","every","key","includes","message","join","ClientSchema","discriminatedUnion","ConfigSchema","spec","clients","Injectable","Logger","fs","path","pathToFileURL","path","loadMjsConfig","configPath","absolutePath","isAbsolute","resolve","configModule","pathToFileURL","href","config","default","Error","ConfigSchema","parse","error","message","ConfigService","logger","Logger","name","DEFAULT_CONFIG_FILE","findDefaultConfig","currentDir","process","cwd","root","parse","configPath","join","promises","access","dirname","load","config","loadMjsConfig","normalizePaths","error","Error","message","configDir","resolve","spec","isUrl","isAbsolute","clients","map","client","outDir","str","url","URL","protocol","getPreCommand","preCommand","getPostCommand","postCommand","shouldExcludeFile","targetPath","exclude","length","relPath","relative","posix","normalize","excludePattern","normalizedExclude","startsWith","Module","ConfigModule","providers","ConfigService","exports","defineConfig","config","ConfigSchema","parse","IRSchemaKind","Injectable","Logger","Injectable","Injectable","detectOpenAPIVersion","doc","version","openapi","startsWith","isSupportedVersion","getSchemaFromRef","doc","schemaRef","$ref","ref","startsWith","name","replace","components","schemas","schema","isSchemaNullable","nullable","Array","isArray","type","includes","getSchemaType","SchemaConverterService","schemaRefToIR","doc","schemaRef","kind","IRSchemaKind","Unknown","nullable","$ref","ref","startsWith","name","replace","Ref","parts","split","length","schema","getSchemaFromRef","isSchemaNullable","discriminator","propertyName","mapping","oneOf","subs","map","sub","OneOf","anyOf","AnyOf","allOf","AllOf","not","Not","enum","enumValues","v","String","enumBase","inferEnumBaseKind","Enum","enumRaw","type","getSchemaType","normalizedType","Array","isArray","filter","t","format","Integer","Number","Boolean","arraySchema","items","properties","propNames","Object","keys","sort","prop","fieldType","required","includes","push","annotations","extractAnnotations","additionalProperties","title","description","deprecated","readOnly","writeOnly","default","examples","example","undefined","first","isInteger","toPascalCase","s","trim","parts","split","filter","p","allParts","part","subParts","splitCamelCase","push","map","charAt","toUpperCase","slice","toLowerCase","join","toCamelCase","pascal","toSnakeCase","toKebabCase","current","chars","Array","from","i","length","char","isNewWord","isUppercase","IrBuilderService","schemaConverter","buildIR","doc","tags","collectTags","securitySchemes","collectSecuritySchemes","modelDefs","buildStructuredModels","allowed","tag","result","buildIRFromDoc","openApiDocument","filterIR","fullIR","client","include","compileTagFilters","includeTags","exclude","excludeTags","filteredServices","service","services","filteredOps","op","operations","shouldIncludeOperation","originalTags","push","length","filteredIR","models","filterUnusedModelDefs","detectStreamingContentType","contentType","normalized","toLowerCase","split","trim","isStreaming","format","includes","uniq","Set","add","paths","path","pathItem","Object","entries","get","post","put","patch","delete","options","head","trace","Array","from","sort","patterns","map","p","RegExp","error","Error","message","String","included","r","test","servicesMap","extractedTypes","seenTypeNames","components","schemas","name","keys","addOp","__name","method","id","operationId","pathParams","queryParams","collectParams","requestBody","reqBody","reqBodyTypes","extractRequestBodyWithTypes","response","resp","respTypes","extractResponseWithTypes","operationID","summary","description","deprecated","t","firstAllowedTag","values","a","b","localeCompare","deriveMethodName","idx","indexOf","cleanedId","substring","toCamelCase","hasID","names","out","scheme","sc","key","type","bearerFormat","in","parameters","pr","schema","schemaRefToIR","param","required","findMatchingComponentSchema","$ref","ref","startsWith","replace","schemaIR","componentSchema","componentIR","compareSchemas","schema1","schema2","kind","IRSchemaKind","Ref","props1","properties","props2","props1Map","Map","props2Map","size","prop1","prop2","items","extractModelNameFromSchema","generateTypeName","suffix","modelName","methodName","toPascalCase","rb","content","media","componentSchemaName","typeTS","nullable","typeName","has","annotations","extractAnnotations","extractRequestBody","firstContentType","responses","Unknown","tryCodes","code","streaming","streamingFormat","firstMedia","firstSchema","firstStreaming","extractResponse","seen","sr","allModelDefs","modelDefMap","md","set","referenced","visited","collectRefs","refName","additionalProperties","oneOf","sub","anyOf","allOf","not","field","filter","Injectable","Logger","SwaggerParser","fs","path","OpenApiService","logger","Logger","name","loadDocument","input","url","URL","api","protocol","debug","response","fetch","signal","AbortSignal","timeout","ok","Error","status","statusText","documentText","text","documentJson","JSON","parse","parsed","SwaggerParser","bundle","error","message","String","dereference","derefError","filePath","resolve","existsSync","version","detectOpenAPIVersion","isSupportedVersion","openapi","log","validateDocument","validate","GeneratorService","logger","Logger","name","generators","Map","irBuilder","openApiService","register","generator","set","getType","debug","getGenerator","type","get","getAvailableTypes","Array","from","keys","generate","spec","client","Error","doc","loadDocument","fullIR","buildIR","filteredIR","filterIR","Module","Module","OpenApiModule","providers","OpenApiService","exports","Injectable","Logger","fs","path","Handlebars","Handlebars","registerCommonHandlebarsHelpers","registerHelper","str","toPascalCase","toCamelCase","toKebabCase","toSnakeCase","tag","toLowerCase","a","b","arr","Array","isArray","length","args","options","fn","slice","some","inverse","every","search","replace","RegExp","idx","parts","split","services","namespaces","service","push","namespace","filter","s","includes","name","value","data","root","obj","key","undefined","pattern","test","schemaToZodSchema","s","indent","modelDefs","useLocalSchemaTypes","nextIndent","zod","kind","IRSchemaKind","String","format","Number","Integer","Boolean","Null","Ref","ref","Array","items","itemsZod","Object","properties","length","additionalProperties","valueZod","props","field","fieldZod","type","fieldName","quoteTSPropertyName","name","required","push","objectZod","join","Enum","enumValues","map","v","test","JSON","stringify","OneOf","oneOf","opt","AnyOf","anyOf","AllOf","allOf","schemas","sch","repeat","nullable","decodeHtmlEntities","str","replace","schemaToTSType","s","predefinedTypes","modelDefs","isSameFile","t","kind","IRSchemaKind","String","format","Number","Integer","Boolean","Null","Ref","ref","some","pt","type","find","md","name","Array","items","inner","includes","OneOf","oneOf","map","sub","join","AnyOf","anyOf","AllOf","allOf","Enum","enumValues","length","vals","enumBase","v","push","Object","properties","parts","f","ft","required","nullable","deriveMethodName","op","path","hasID","operationID","toCamelCase","method","toLowerCase","resolveMethodName","client","operationIdParser","defaultParsed","defaultParseOperationID","opID","idx","indexOf","substring","buildPathTemplate","result","i","j","buildQueryKeyBase","split","baseParts","p","startsWith","endsWith","base","orderPathParams","ordered","index","Map","pathParams","set","get","undefined","schemaToTSTypeWithSimpleTypes","buildMethodSignature","methodName","schema","queryParams","queryType","toPascalCase","tag","requestBody","opt","collectPredefinedTypesUsedInSchema","usedTypes","Set","resolveRef","__name","modelDef","checkSchema","add","resolved","prop","filter","has","collectPredefinedTypesUsedInService","service","operations","param","queryKeyArgs","out","quoteTSPropertyName","needsQuoting","char","isStreamingOperation","response","isStreaming","getStreamingItemType","streamingFormat","TypeScriptGeneratorService","logger","Logger","name","configService","getType","generate","client","ir","srcDir","join","outDir","servicesDir","promises","mkdir","recursive","processedIR","preprocessIR","registerHandlebarsHelpers","generateClient","generateIndex","generateUtils","generateServices","generateSchema","generateZodSchema","generatePackageJson","generateTsConfig","generateReadme","processedServices","Promise","all","services","map","service","operations","op","methodName","resolveMethodName","_resolvedMethodName","registerCommonHandlebarsHelpers","registerHelper","deriveMethodName","toPascalCase","tag","result","buildPathTemplate","SafeString","buildQueryKeyBase","orderPathParams","options","modelDefs","data","root","IR","predefinedTypes","PredefinedTypes","isSameFile","buildMethodSignature","s","slice","queryKeyArgs","arg","x","schemaToTSType","replace","stripped","startsWith","typeName","find","pt","type","some","grouped","package","types","push","Object","values","collectPredefinedTypesUsedInService","collectPredefinedTypesUsedInSchema","packages","Set","add","Array","from","packageName","deps","zod","dependencies","pkg","version","entries","str","decoded","quoteTSPropertyName","useLocalSchemaTypes","_templateName","schemaToZodSchema","isStreamingOperation","getStreamingItemType","renderTemplate","templateName","outputPath","overridePath","templates","debug","access","constants","R_OK","templateContent","readFile","template","compile","contextWithTemplate","rendered","writeFile","error","errorMsg","Error","message","String","possiblePaths","__dirname","process","cwd","templatePath","possiblePath","clientPath","shouldExcludeFile","Client","warn","indexPath","utilsPath","servicePath","toSnakeCase","toLowerCase","Service","content","schemaPath","zodSchemaPath","packageJsonPath","JSON","stringify","main","tsConfigPath","compilerOptions","target","module","lib","declaration","rootDir","strict","esModuleInterop","skipLibCheck","forceConsistentCasingInFileNames","include","readmePath","GeneratorModule","generatorService","typeScriptGenerator","register","imports","OpenApiModule","ConfigModule","providers","GeneratorService","IrBuilderService","SchemaConverterService","TypeScriptGeneratorService","exports","path","fs","generate","configOrPath","options","config","baseDir","configPath","isAbsolute","resolve","loadMjsConfig","dirname","configService","ConfigService","openApiService","OpenApiService","schemaConverter","SchemaConverterService","irBuilder","IrBuilderService","generatorService","GeneratorService","typeScriptGenerator","TypeScriptGeneratorService","register","client","clients","name","resolvedOutDir","outDir","promises","mkdir","recursive","clientWithResolvedPath","spec","loadConfig"]}