@blimu/codegen 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +142 -0
- package/dist/generator/typescript/templates/README.md.hbs +123 -0
- package/dist/generator/typescript/templates/client.ts.hbs +380 -0
- package/dist/generator/typescript/templates/index.ts.hbs +67 -0
- package/dist/generator/typescript/templates/package.json.hbs +48 -0
- package/dist/generator/typescript/templates/schema.ts.hbs +76 -0
- package/dist/generator/typescript/templates/schema.zod.ts.hbs +126 -0
- package/dist/generator/typescript/templates/service.ts.hbs +107 -0
- package/dist/generator/typescript/templates/tsconfig.json.hbs +28 -0
- package/dist/generator/typescript/templates/utils.ts.hbs +168 -0
- package/dist/index.d.mts +309 -0
- package/dist/index.d.ts +309 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7 -0
- package/dist/index.mjs.map +1 -0
- package/dist/main.js +8 -0
- package/dist/main.js.map +1 -0
- package/package.json +68 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
var Oe=Object.defineProperty;var l=(n,e)=>Oe(n,"name",{value:e,configurable:!0});import{z as m}from"zod";var xe=m.object({moduleName:m.string().optional(),namespace:m.string().optional(),typeNames:m.array(m.string()).optional(),outputFileName:m.string().optional()}),oe=["client.ts.hbs","index.ts.hbs","package.json.hbs","README.md.hbs","schema.ts.hbs","schema.zod.ts.hbs","service.ts.hbs","tsconfig.json.hbs","utils.ts.hbs"],je=m.object({type:m.string().min(1,"Type is required"),outDir:m.string().min(1,"OutDir is required"),name:m.string().min(1,"Name is required"),includeTags:m.array(m.string()).optional(),excludeTags:m.array(m.string()).optional(),operationIdParser:m.custom().optional(),preCommand:m.array(m.string()).optional(),postCommand:m.array(m.string()).optional(),defaultBaseURL:m.string().optional(),exclude:m.array(m.string()).optional(),typeAugmentation:xe.optional()}),Ce=je.extend({type:m.literal("typescript"),packageName:m.string().min(1,"PackageName is required"),moduleName:m.string().optional(),includeQueryKeys:m.boolean().optional(),templates:m.record(m.string(),m.string()).refine(n=>Object.keys(n).every(e=>oe.includes(e)),{message:`Template names must be one of: ${oe.join(", ")}`}).optional()}),Re=m.discriminatedUnion("type",[Ce]),se=m.object({spec:m.string().min(1,"Spec is required"),name:m.string().optional(),clients:m.array(Re).min(1,"At least one client is required")});import{Injectable as ke,Logger as $e}from"@nestjs/common";import*as ie from"fs";import*as b from"path";import{pathToFileURL as Pe}from"url";import*as U from"path";async function B(n){try{let e=U.isAbsolute(n)?n:U.resolve(n),r=await import(Pe(e).href),s=r.default||r;if(!s)throw new Error(`Config file must export a default export or named export: ${n}`);return se.parse(s)}catch(e){throw e instanceof Error?new Error(`Failed to load MJS config from ${n}: ${e.message}`):e}}l(B,"loadMjsConfig");function He(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(He,"_ts_decorate");var x=class n{static{l(this,"ConfigService")}logger=new $e(n.name);DEFAULT_CONFIG_FILE="chunkflow-codegen.config.mjs";async findDefaultConfig(){let e=process.cwd(),t=b.parse(e).root;for(;e!==t;){let r=b.join(e,this.DEFAULT_CONFIG_FILE);try{return await ie.promises.access(r),r}catch{}e=b.dirname(e)}return null}async load(e){try{let t=await B(e);return this.normalizePaths(t,e)}catch(t){throw t instanceof Error?new Error(`Failed to load config from ${e}: ${t.message}`):t}}normalizePaths(e,t){let r=b.dirname(b.resolve(t)),s=e.spec;this.isUrl(s)||b.isAbsolute(s)||(s=b.resolve(r,s));let o=e.clients.map(i=>{let a=i.outDir;return b.isAbsolute(a)||(a=b.resolve(r,a)),{...i,outDir:a}});return{...e,spec:s,clients:o}}isUrl(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}getPreCommand(e){return e.preCommand||[]}getPostCommand(e){return e.postCommand||[]}shouldExcludeFile(e,t){if(!e.exclude||e.exclude.length===0)return!1;let r;try{r=b.relative(e.outDir,t)}catch{return!1}r=b.posix.normalize(r),r==="."&&(r="");for(let s of e.exclude){let o=b.posix.normalize(s);if(r===o||o!==""&&r.startsWith(o+"/"))return!0}return!1}};x=He([ke()],x);import{Module as Ae}from"@nestjs/common";function Ie(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(Ie,"_ts_decorate");var E=class{static{l(this,"ConfigModule")}};E=Ie([Ae({providers:[x],exports:[x]})],E);function dt(n){return n}l(dt,"defineConfig");var f=(function(n){return 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})({});import{Injectable as Me,Logger as Ue}from"@nestjs/common";import{Injectable as De}from"@nestjs/common";import{Injectable as Ee}from"@nestjs/common";function ae(n){let e=n.openapi;return typeof e!="string"?"unknown":e.startsWith("3.1")?"3.1":e.startsWith("3.0")?"3.0":"unknown"}l(ae,"detectOpenAPIVersion");function ce(n){return n==="3.0"||n==="3.1"}l(ce,"isSupportedVersion");function J(n,e){if(!(!e||typeof e!="object")){if("$ref"in e&&e.$ref){let t=e.$ref;if(t.startsWith("#/components/schemas/")){let r=t.replace("#/components/schemas/","");if(n.components?.schemas?.[r]){let s=n.components.schemas[r];return"$ref"in s?J(n,s):s}}return}return e}}l(J,"getSchemaFromRef");function le(n){return n?"nullable"in n&&n.nullable===!0?!0:"type"in n&&Array.isArray(n.type)?n.type.includes("null"):!1:!1}l(le,"isSchemaNullable");function K(n){if(!(!n||!("type"in n)))return n.type}l(K,"getSchemaType");function qe(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(qe,"_ts_decorate");var j=class{static{l(this,"SchemaConverterService")}schemaRefToIR(e,t){if(!t)return{kind:f.Unknown,nullable:!1};if("$ref"in t&&t.$ref){let c=t.$ref;if(c.startsWith("#/components/schemas/")){let u=c.replace("#/components/schemas/","");return{kind:f.Ref,ref:u,nullable:!1}}let p=c.split("/");if(p.length>0){let u=p[p.length-1];if(u)return{kind:f.Ref,ref:u,nullable:!1}}return{kind:f.Unknown,nullable:!1}}let r=J(e,t);if(!r)return{kind:f.Unknown,nullable:!1};let s=le(r),o;if(r.discriminator&&(o={propertyName:r.discriminator.propertyName,mapping:r.discriminator.mapping}),r.oneOf&&r.oneOf.length>0){let c=r.oneOf.map(p=>this.schemaRefToIR(e,p));return{kind:f.OneOf,oneOf:c,nullable:s,discriminator:o}}if(r.anyOf&&r.anyOf.length>0){let c=r.anyOf.map(p=>this.schemaRefToIR(e,p));return{kind:f.AnyOf,anyOf:c,nullable:s,discriminator:o}}if(r.allOf&&r.allOf.length>0){let c=r.allOf.map(p=>this.schemaRefToIR(e,p));return{kind:f.AllOf,allOf:c,nullable:s,discriminator:o}}if(r.not){let c=this.schemaRefToIR(e,r.not);return{kind:f.Not,not:c,nullable:s,discriminator:o}}if(r.enum&&r.enum.length>0){let c=r.enum.map(u=>String(u)),p=this.inferEnumBaseKind(r);return{kind:f.Enum,enumValues:c,enumRaw:r.enum,enumBase:p,nullable:s,discriminator:o}}let i=K(r),a=Array.isArray(i)?i.filter(c=>c!=="null")[0]:i;if(a)switch(a){case"string":return{kind:f.String,nullable:s,format:r.format,discriminator:o};case"integer":return{kind:f.Integer,nullable:s,discriminator:o};case"number":return{kind:f.Number,nullable:s,discriminator:o};case"boolean":return{kind:f.Boolean,nullable:s,discriminator:o};case"array":let c=r,p=this.schemaRefToIR(e,c.items);return{kind:f.Array,items:p,nullable:s,discriminator:o};case"object":let u=[];if(r.properties){let y=Object.keys(r.properties).sort();for(let S of y){let O=r.properties[S],A=this.schemaRefToIR(e,O),F=r.required?.includes(S)||!1;u.push({name:S,type:A,required:F,annotations:this.extractAnnotations(O)})}}let g;return r.additionalProperties&&typeof r.additionalProperties=="object"&&(g=this.schemaRefToIR(e,r.additionalProperties)),{kind:f.Object,properties:u,additionalProperties:g,nullable:s,discriminator:o}}return{kind:f.Unknown,nullable:s,discriminator:o}}extractAnnotations(e){if(!e||"$ref"in e)return{};let t=e;return{title:t.title,description:t.description,deprecated:t.deprecated,readOnly:t.readOnly,writeOnly:t.writeOnly,default:t.default,examples:t.example?Array.isArray(t.example)?t.example:[t.example]:void 0}}inferEnumBaseKind(e){let t=K(e);if(t){let r=Array.isArray(t)?t.filter(s=>s!=="null")[0]:t;if(r)switch(r){case"string":return f.String;case"integer":return f.Integer;case"number":return f.Number;case"boolean":return f.Boolean}}if(e.enum&&e.enum.length>0){let r=e.enum[0];if(typeof r=="string")return f.String;if(typeof r=="number")return Number.isInteger(r)?f.Integer:f.Number;if(typeof r=="boolean")return f.Boolean}return f.Unknown}};j=qe([Ee()],j);function v(n){if(n=n.trim(),n==="")return"";let e=n.split(/[^A-Za-z0-9]+/).filter(r=>r!==""),t=[];for(let r of e){let s=Y(r);t.push(...s)}return t.filter(r=>r!=="").map(r=>r.charAt(0).toUpperCase()+r.slice(1).toLowerCase()).join("")}l(v,"toPascalCase");function I(n){let e=v(n);return e===""?"":e.charAt(0).toLowerCase()+e.slice(1)}l(I,"toCamelCase");function _(n){if(n=n.trim(),n==="")return"";let e=n.split(/[^A-Za-z0-9]+/).filter(r=>r!==""),t=[];for(let r of e){let s=Y(r);t.push(...s)}return t.filter(r=>r!=="").map(r=>r.toLowerCase()).join("_")}l(_,"toSnakeCase");function pe(n){if(n=n.trim(),n==="")return"";let e=n.split(/[^A-Za-z0-9]+/).filter(r=>r!==""),t=[];for(let r of e){let s=Y(r);t.push(...s)}return t.filter(r=>r!=="").map(r=>r.toLowerCase()).join("-")}l(pe,"toKebabCase");function Y(n){if(n==="")return[];let e=[],t="",r=Array.from(n);for(let s=0;s<r.length;s++){let o=r[s],i=!1;s>0&&Q(o)&&(Q(r[s-1])?s<r.length-1&&!Q(r[s+1])&&(i=!0):i=!0),i&&t.length>0&&(e.push(t),t=""),t+=o}return t.length>0&&e.push(t),e}l(Y,"splitCamelCase");function Q(n){return n>="A"&&n<="Z"}l(Q,"isUppercase");function Ne(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(Ne,"_ts_decorate");function fe(n,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(n,e)}l(fe,"_ts_metadata");var C=class{static{l(this,"IrBuilderService")}schemaConverter;constructor(e){this.schemaConverter=e}buildIR(e){let t=this.collectTags(e),r=this.collectSecuritySchemes(e),s=this.buildStructuredModels(e),o={};for(let a of t)o[a]=!0;let i=this.buildIRFromDoc(e,o);return i.securitySchemes=r,i.modelDefs=[...s,...i.modelDefs],i}filterIR(e,t){let r=this.compileTagFilters(t.includeTags||[]),s=this.compileTagFilters(t.excludeTags||[]),o=[];for(let a of e.services){let c=[];for(let p of a.operations)this.shouldIncludeOperation(p.originalTags,r,s)&&c.push(p);c.length>0&&o.push({...a,operations:c})}let i={services:o,models:e.models,securitySchemes:e.securitySchemes,modelDefs:e.modelDefs};return i.modelDefs=this.filterUnusedModelDefs(i,e.modelDefs),i}detectStreamingContentType(e){let t=e.toLowerCase().split(";")[0].trim();return t==="text/event-stream"?{isStreaming:!0,format:"sse"}:t==="application/x-ndjson"||t==="application/x-jsonlines"||t==="application/jsonl"?{isStreaming:!0,format:"ndjson"}:t.includes("stream")||t.includes("chunked")?{isStreaming:!0,format:"chunked"}:{isStreaming:!1}}collectTags(e){let t=new Set;if(t.add("misc"),e.paths)for(let[r,s]of Object.entries(e.paths)){if(!s)continue;let o=[s.get,s.post,s.put,s.patch,s.delete,s.options,s.head,s.trace];for(let i of o)if(!(!i||!i.tags))for(let a of i.tags)t.add(a)}return Array.from(t).sort()}compileTagFilters(e){return e.map(t=>{try{return new RegExp(t)}catch(r){throw new Error(`Invalid tag filter pattern "${t}": ${r instanceof Error?r.message:String(r)}`)}})}shouldIncludeOperation(e,t,r){let s=t.length===0;if(t.length>0)for(let o of e){for(let i of t)if(i.test(o)){s=!0;break}if(s)break}if(!s)return!1;if(r.length>0){for(let o of e)for(let i of r)if(i.test(o))return!1}return!0}buildIRFromDoc(e,t){let r={};r.misc={tag:"misc",operations:[]};let s=[],o=new Set,i=l((c,p,u,g)=>{r[c]||(r[c]={tag:c,operations:[]});let y=p.operationId||"",{pathParams:S,queryParams:O}=this.collectParams(e,p),{requestBody:A,extractedTypes:F}=this.extractRequestBodyWithTypes(e,p,c,y,u,o);s.push(...F);let{response:W,extractedTypes:z}=this.extractResponseWithTypes(e,p,c,y,u,o);s.push(...z);let q=p.tags&&p.tags.length>0?[...p.tags]:["misc"];r[c].operations.push({operationID:y,method:u,path:g,tag:c,originalTags:q,summary:p.summary||"",description:p.description||"",deprecated:p.deprecated||!1,pathParams:S,queryParams:O,requestBody:A,response:W})},"addOp");if(e.paths)for(let[c,p]of Object.entries(e.paths)){if(!p)continue;let u=[{op:p.get,method:"GET"},{op:p.post,method:"POST"},{op:p.put,method:"PUT"},{op:p.patch,method:"PATCH"},{op:p.delete,method:"DELETE"},{op:p.options,method:"OPTIONS"},{op:p.head,method:"HEAD"},{op:p.trace,method:"TRACE"}];for(let{op:g,method:y}of u){if(!g)continue;let S=this.firstAllowedTag(g.tags||[],t);S&&i(S,g,y,c)}}let a=Object.values(r);for(let c of a)c.operations.sort((p,u)=>p.path===u.path?p.method.localeCompare(u.method):p.path.localeCompare(u.path));return a.sort((c,p)=>c.tag.localeCompare(p.tag)),{services:a,models:[],securitySchemes:[],modelDefs:s}}deriveMethodName(e,t,r){if(e)return I(e);let s=r.includes("{")&&r.includes("}");switch(t){case"GET":return s?"get":"list";case"POST":return"create";case"PUT":case"PATCH":return"update";case"DELETE":return"delete";default:return t.toLowerCase()}}firstAllowedTag(e,t){for(let r of e)if(t[r])return r;return e.length===0&&t.misc?"misc":""}collectSecuritySchemes(e){if(!e.components?.securitySchemes)return[];let t=Object.keys(e.components.securitySchemes).sort(),r=[];for(let s of t){let o=e.components.securitySchemes[s];if(!o||"$ref"in o)continue;let i={key:s,type:o.type};switch(o.type){case"http":i.scheme=o.scheme,i.bearerFormat=o.bearerFormat;break;case"apiKey":i.in=o.in,i.name=o.name;break;case"oauth2":case"openIdConnect":break}r.push(i)}return r}collectParams(e,t){let r=[],s=[];if(t.parameters)for(let o of t.parameters){if(!o||"$ref"in o)continue;let i=o,a=this.schemaConverter.schemaRefToIR(e,i.schema),c={name:i.name,required:i.required||!1,schema:a,description:i.description||""};i.in==="path"?r.push(c):i.in==="query"&&s.push(c)}return r.sort((o,i)=>o.name.localeCompare(i.name)),s.sort((o,i)=>o.name.localeCompare(i.name)),{pathParams:r,queryParams:s}}extractRequestBodyWithTypes(e,t,r,s,o,i){let a=[];if(!t.requestBody||"$ref"in t.requestBody)return{requestBody:null,extractedTypes:[]};let c=t.requestBody,p=this.deriveMethodName(s,o,t.path),u=`${v(r)}${v(p)}RequestBody`;if(c.content?.["application/json"]){let y=c.content["application/json"],S=this.schemaConverter.schemaRefToIR(e,y.schema);return S.kind===f.Object&&!i.has(u)?(i.add(u),a.push({name:u,schema:S,annotations:this.schemaConverter.extractAnnotations(y.schema)}),{requestBody:{contentType:"application/json",typeTS:"",schema:{kind:f.Ref,ref:u,nullable:!1},required:c.required||!1},extractedTypes:a}):{requestBody:{contentType:"application/json",typeTS:"",schema:S,required:c.required||!1},extractedTypes:[]}}return{requestBody:this.extractRequestBody(e,t),extractedTypes:[]}}extractRequestBody(e,t){if(!t.requestBody||"$ref"in t.requestBody)return null;let r=t.requestBody;if(r.content?.["application/json"]){let s=r.content["application/json"];return{contentType:"application/json",typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,s.schema),required:r.required||!1}}if(r.content?.["application/x-www-form-urlencoded"]){let s=r.content["application/x-www-form-urlencoded"];return{contentType:"application/x-www-form-urlencoded",typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,s.schema),required:r.required||!1}}if(r.content?.["multipart/form-data"])return{contentType:"multipart/form-data",typeTS:"",schema:{kind:"unknown",nullable:!1},required:r.required||!1};if(r.content){let s=Object.keys(r.content)[0],o=r.content[s];return{contentType:s,typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,o.schema),required:r.required||!1}}return null}extractResponseWithTypes(e,t,r,s,o,i){let a=[];if(!t.responses)return{response:{typeTS:"unknown",schema:{kind:f.Unknown,nullable:!1},description:"",isStreaming:!1,contentType:""},extractedTypes:[]};let c=this.deriveMethodName(s,o,t.path),p=`${v(r)}${v(c)}Response`,u=["200","201"];for(let y of u){let S=t.responses[y];if(S&&!("$ref"in S)){let O=S;if(O.content){for(let[q,re]of Object.entries(O.content)){let ne=this.detectStreamingContentType(q),M=this.schemaConverter.schemaRefToIR(e,re.schema);if(ne.isStreaming)return{response:{typeTS:"",schema:M,description:O.description||"",isStreaming:!0,contentType:q,streamingFormat:ne.format},extractedTypes:[]};if(q==="application/json")return M.kind===f.Object&&!i.has(p)?(i.add(p),a.push({name:p,schema:M,annotations:this.schemaConverter.extractAnnotations(re.schema)}),{response:{typeTS:"",schema:{kind:f.Ref,ref:p,nullable:!1},description:O.description||"",isStreaming:!1,contentType:q},extractedTypes:a}):{response:{typeTS:"",schema:M,description:O.description||"",isStreaming:!1,contentType:q},extractedTypes:[]}}let A=Object.keys(O.content)[0],F=O.content[A],W=this.schemaConverter.schemaRefToIR(e,F.schema),z=this.detectStreamingContentType(A);return{response:{typeTS:"",schema:W,description:O.description||"",isStreaming:z.isStreaming,contentType:A,streamingFormat:z.format},extractedTypes:[]}}return{response:{typeTS:"void",schema:{kind:f.Unknown,nullable:!1},description:O.description||"",isStreaming:!1,contentType:""},extractedTypes:[]}}}return{response:this.extractResponse(e,t),extractedTypes:[]}}extractResponse(e,t){if(!t.responses)return{typeTS:"unknown",schema:{kind:f.Unknown,nullable:!1},description:"",isStreaming:!1,contentType:""};let r=["200","201"];for(let s of r){let o=t.responses[s];if(o&&!("$ref"in o)){let i=o;if(i.content){for(let[u,g]of Object.entries(i.content)){let y=this.detectStreamingContentType(u);if(y.isStreaming)return{typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,g.schema),description:i.description||"",isStreaming:!0,contentType:u,streamingFormat:y.format}}if(i.content["application/json"]){let u=i.content["application/json"];return{typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,u.schema),description:i.description||"",isStreaming:!1,contentType:"application/json"}}let a=Object.keys(i.content)[0],c=i.content[a],p=this.detectStreamingContentType(a);return{typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,c.schema),description:i.description||"",isStreaming:p.isStreaming,contentType:a,streamingFormat:p.format}}return{typeTS:"void",schema:{kind:f.Unknown,nullable:!1},description:i.description||"",isStreaming:!1,contentType:""}}}for(let[s,o]of Object.entries(t.responses))if(s.length===3&&s[0]==="2"&&o&&!("$ref"in o)){let i=o;if(s==="204")return{typeTS:"void",schema:{kind:f.Unknown,nullable:!1},description:i.description||"",isStreaming:!1,contentType:""};if(i.content){for(let[u,g]of Object.entries(i.content)){let y=this.detectStreamingContentType(u);if(y.isStreaming)return{typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,g.schema),description:i.description||"",isStreaming:!0,contentType:u,streamingFormat:y.format}}if(i.content["application/json"]){let u=i.content["application/json"];return{typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,u.schema),description:i.description||"",isStreaming:!1,contentType:"application/json"}}let a=Object.keys(i.content)[0],c=i.content[a],p=this.detectStreamingContentType(a);return{typeTS:"",schema:this.schemaConverter.schemaRefToIR(e,c.schema),description:i.description||"",isStreaming:p.isStreaming,contentType:a,streamingFormat:p.format}}}return{typeTS:"unknown",schema:{kind:f.Unknown,nullable:!1},description:"",isStreaming:!1,contentType:""}}buildStructuredModels(e){let t=[];if(!e.components?.schemas)return t;let r=Object.keys(e.components.schemas).sort(),s=new Set;for(let o of r)s.add(o);for(let o of r){let i=e.components.schemas[o],a=this.schemaConverter.schemaRefToIR(e,i);t.push({name:o,schema:a,annotations:this.schemaConverter.extractAnnotations(i)})}return t}filterUnusedModelDefs(e,t){let r=new Map;for(let a of t)r.set(a.name,a);let s=new Set,o=new Set,i=l(a=>{if(a.kind==="ref"&&a.ref){let c=a.ref;if(s.add(c),!o.has(c)){o.add(c);let p=r.get(c);p&&i(p.schema)}}if(a.items&&i(a.items),a.additionalProperties&&i(a.additionalProperties),a.oneOf)for(let c of a.oneOf)i(c);if(a.anyOf)for(let c of a.anyOf)i(c);if(a.allOf)for(let c of a.allOf)i(c);if(a.not&&i(a.not),a.properties)for(let c of a.properties)i(c.type)},"collectRefs");for(let a of e.services)for(let c of a.operations){for(let p of c.pathParams)i(p.schema);for(let p of c.queryParams)i(p.schema);c.requestBody&&i(c.requestBody.schema),i(c.response.schema)}return t.filter(a=>s.has(a.name))}};C=Ne([De(),fe("design:type",Function),fe("design:paramtypes",[typeof j>"u"?Object:j])],C);import{Injectable as Be,Logger as _e}from"@nestjs/common";import L from"@apidevtools/swagger-parser";import*as X from"fs";import*as ee from"path";function Fe(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(Fe,"_ts_decorate");var R=class n{static{l(this,"OpenApiService")}logger=new _e(n.name);async loadDocument(e){try{let t=null;try{t=new URL(e)}catch{}let r;if(t&&(t.protocol==="http:"||t.protocol==="https:"))this.logger.debug(`Loading OpenAPI spec from URL: ${e}`),r=await L.dereference(e);else{let o=ee.resolve(e);if(!X.existsSync(o))throw new Error(`OpenAPI spec file not found: ${o}`);this.logger.debug(`Loading OpenAPI spec from file: ${o}`),r=await L.dereference(o)}let s=ae(r);if(!ce(s))throw new Error(`Unsupported OpenAPI version: ${r.openapi}. Only versions 3.0.x and 3.1.0 are supported.`);return this.logger.log(`Detected OpenAPI version: ${s} (${r.openapi})`),r}catch(t){throw t instanceof Error?new Error(`Failed to load OpenAPI document from ${e}: ${t.message}`):t}}async validateDocument(e){try{let t=null;try{t=new URL(e)}catch{}if(t&&(t.protocol==="http:"||t.protocol==="https:"))await L.validate(e);else{let r=ee.resolve(e);if(!X.existsSync(r))throw new Error(`OpenAPI spec file not found: ${r}`);await L.validate(r)}}catch(t){throw t instanceof Error?new Error(`Invalid OpenAPI document: ${t.message}`):t}}};R=Fe([Be()],R);function ze(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(ze,"_ts_decorate");function ue(n,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(n,e)}l(ue,"_ts_metadata");var H=class n{static{l(this,"GeneratorService")}irBuilder;openApiService;logger=new Ue(n.name);generators=new Map;constructor(e,t){this.irBuilder=e,this.openApiService=t}register(e){this.generators.set(e.getType(),e),this.logger.debug(`Registered generator: ${e.getType()}`)}getGenerator(e){return this.generators.get(e)}getAvailableTypes(){return Array.from(this.generators.keys())}async generate(e,t){let r=this.getGenerator(t.type);if(!r)throw new Error(`Unsupported client type: ${t.type}`);let s=await this.openApiService.loadDocument(e),o=this.irBuilder.buildIR(s),i=this.irBuilder.filterIR(o,t);await r.generate(t,i)}};H=ze([Me(),ue("design:type",Function),ue("design:paramtypes",[typeof C>"u"?Object:C,typeof R>"u"?Object:R])],H);import{Module as Ye}from"@nestjs/common";import{Module as Ge}from"@nestjs/common";function Le(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(Le,"_ts_decorate");var N=class{static{l(this,"OpenApiModule")}};N=Le([Ge({providers:[R],exports:[R]})],N);import{Injectable as Je,Logger as Ke}from"@nestjs/common";import*as w from"fs";import*as T from"path";import*as h from"handlebars";import*as d from"handlebars";function me(){d.registerHelper("pascal",n=>v(n)),d.registerHelper("camel",n=>I(n)),d.registerHelper("kebab",n=>pe(n)),d.registerHelper("snake",n=>_(n)),d.registerHelper("serviceName",n=>v(n)+"Service"),d.registerHelper("serviceProp",n=>I(n)),d.registerHelper("fileBase",n=>_(n).toLowerCase()),d.registerHelper("eq",(n,e)=>n===e),d.registerHelper("ne",(n,e)=>n!==e),d.registerHelper("gt",(n,e)=>n>e),d.registerHelper("lt",(n,e)=>n<e),d.registerHelper("sub",(n,e)=>n-e),d.registerHelper("len",n=>Array.isArray(n)?n.length:0),d.registerHelper("or",function(...n){let e=n[n.length-1];return e&&e.fn?n.slice(0,-1).some(t=>t)?e.fn(this):e.inverse(this):n.slice(0,-1).some(t=>t)}),d.registerHelper("and",function(...n){let e=n[n.length-1];return e&&e.fn?n.slice(0,-1).every(t=>t)?e.fn(this):e.inverse(this):n.slice(0,-1).every(t=>t)}),d.registerHelper("replace",(n,e,t)=>typeof n!="string"?n:n.replace(new RegExp(e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),t)),d.registerHelper("index",(n,e)=>n?.[e]),d.registerHelper("getServiceName",n=>{let e=n.split(".");return e.length>1?e[1]:n}),d.registerHelper("groupByNamespace",n=>{let e={};for(let t of n){let r=t.tag.split(".");if(r.length===1)e[""]||(e[""]=[]),e[""].push(t);else{let s=r[0];e[s]||(e[s]=[]),e[s].push(t)}}return e}),d.registerHelper("getRootServices",n=>n.filter(e=>!e.tag.includes("."))),d.registerHelper("dict",()=>({})),d.registerHelper("setVar",(n,e,t)=>(t&&t.data&&t.data.root&&(t.data.root[`_${n}`]=e),"")),d.registerHelper("set",(n,e,t)=>(n&&typeof n=="object"&&(n[e]=t),"")),d.registerHelper("hasKey",(n,e)=>n&&typeof n=="object"&&e in n),d.registerHelper("lookup",(n,e)=>n&&typeof n=="object"?n[e]:void 0),d.registerHelper("reMatch",(n,e)=>{try{return new RegExp(n).test(e)}catch{return!1}})}l(me,"registerCommonHandlebarsHelpers");function k(n,e=""){let t=e+" ",r;switch(n.kind){case f.String:r="z.string()",n.format==="date"||n.format==="date-time"?r+=".datetime()":n.format==="email"?r+=".email()":n.format==="uri"||n.format==="url"?r+=".url()":n.format==="uuid"&&(r+=".uuid()");break;case f.Number:r="z.number()";break;case f.Integer:r="z.number().int()";break;case f.Boolean:r="z.boolean()";break;case f.Null:r="z.null()";break;case f.Ref:n.ref?r=`Schema.${n.ref}Schema`:r="z.unknown()";break;case f.Array:n.items?r=`z.array(${k(n.items,t)})`:r="z.array(z.unknown())";break;case f.Object:if(!n.properties||n.properties.length===0)n.additionalProperties?r=`z.record(z.string(), ${k(n.additionalProperties,t)})`:r="z.record(z.string(), z.unknown())";else{let s=[];for(let o of n.properties){let i=k(o.type,t),a=G(o.name);o.required?s.push(`${t}${a}: ${i}`):s.push(`${t}${a}: ${i}.optional()`)}if(n.additionalProperties){let o=k(n.additionalProperties,t);s.push(`${t}...z.record(z.string(), ${o}).shape`)}r=`z.object({
|
|
2
|
+
${s.join(`,
|
|
3
|
+
`)}
|
|
4
|
+
${e}})`}break;case f.Enum:n.enumValues&&n.enumValues.length>0?r=`z.enum([${n.enumValues.map(o=>o==="true"||o==="false"||/^-?[0-9]+(\.[0-9]+)?$/.test(o)?o:JSON.stringify(o)).join(", ")}])`:r="z.string()";break;case f.OneOf:n.oneOf&&n.oneOf.length>0?r=`z.union([${n.oneOf.map(o=>k(o,t)).join(", ")}])`:r="z.unknown()";break;case f.AnyOf:n.anyOf&&n.anyOf.length>0?r=`z.union([${n.anyOf.map(o=>k(o,t)).join(", ")}])`:r="z.unknown()";break;case f.AllOf:if(n.allOf&&n.allOf.length>0){let s=n.allOf.map(o=>k(o,t));r=s.join(".and(")+")".repeat(s.length-1)}else r="z.unknown()";break;default:r="z.unknown()"}return n.nullable&&r!=="z.null()"&&(r=`${r}.nullable()`),r}l(k,"schemaToZodSchema");function Ze(n){return n.replace(/"/g,'"').replace(/</g,"<").replace(/>/g,">").replace(/`/g,"`").replace(/`/g,"`").replace(/&/g,"&")}l(Ze,"decodeHtmlEntities");function P(n){let e;switch(n.kind){case f.String:n.format==="binary"?e="Blob":e="string";break;case f.Number:case f.Integer:e="number";break;case f.Boolean:e="boolean";break;case f.Null:e="null";break;case f.Ref:n.ref?e="Schema."+n.ref:e="unknown";break;case f.Array:if(n.items){let t=P(n.items);t.includes(" | ")||t.includes(" & ")?e=`Array<(${t})>`:e=`Array<${t}>`}else e="Array<unknown>";break;case f.OneOf:n.oneOf?e=n.oneOf.map(r=>P(r)).join(" | "):e="unknown";break;case f.AnyOf:n.anyOf?e=n.anyOf.map(r=>P(r)).join(" | "):e="unknown";break;case f.AllOf:n.allOf?e=n.allOf.map(r=>P(r)).join(" & "):e="unknown";break;case f.Enum:if(n.enumValues&&n.enumValues.length>0){let t=[];switch(n.enumBase){case f.Number:case f.Integer:for(let r of n.enumValues)t.push(r);break;case f.Boolean:for(let r of n.enumValues)r==="true"||r==="false"?t.push(r):t.push(`"${r}"`);break;default:for(let r of n.enumValues)t.push(`"${r}"`)}e=t.join(" | ")}else e="unknown";break;case f.Object:if(!n.properties||n.properties.length===0)e="Record<string, unknown>";else{let t=[];for(let r of n.properties){let s=P(r.type);r.required?t.push(`${r.name}: ${s}`):t.push(`${r.name}?: ${s}`)}e="{ "+t.join("; ")+" }"}break;default:e="unknown"}return n.nullable&&e!=="null"&&(e+=" | null"),Ze(e)}l(P,"schemaToTSType");function D(n){let e=n.path,t=e.includes("{")&&e.includes("}");if(n.operationID)return I(n.operationID);switch(n.method){case"GET":return t?"get":"list";case"POST":return"create";case"PUT":case"PATCH":return"update";case"DELETE":return"delete";default:return n.method.toLowerCase()}}l(D,"deriveMethodName");async function de(n,e){if(n.operationIdParser)try{let r=await n.operationIdParser(e.operationID,e.method,e.path);if(r)return I(r)}catch{}let t=Ve(e.operationID);return t?I(t):D(e)}l(de,"resolveMethodName");function Ve(n){if(!n)return"";let e=n.indexOf("Controller_");return e>=0?n.substring(e+11):n}l(Ve,"defaultParseOperationID");function he(n){let e=n.path,t="`";for(let r=0;r<e.length;r++){if(e[r]==="{"){let s=r+1;for(;s<e.length&&e[s]!=="}";)s++;if(s<e.length){let o=e.substring(r+1,s);t+=`\${encodeURIComponent(${o})}`,r=s;continue}}t+=e[r]}return t+="`",t}l(he,"buildPathTemplate");function ge(n){let t=n.path.split("/"),r=[];for(let o of t)o!==""&&(o.startsWith("{")&&o.endsWith("}")||r.push(o));return`'${r.join("/")}'`}l(ge,"buildQueryKeyBase");function Z(n){let e=[],t=new Map;for(let s=0;s<n.pathParams.length;s++)t.set(n.pathParams[s].name,s);let r=n.path;for(let s=0;s<r.length;s++)if(r[s]==="{"){let o=s+1;for(;o<r.length&&r[o]!=="}";)o++;if(o<r.length){let i=r.substring(s+1,o),a=t.get(i);a!==void 0&&e.push(n.pathParams[a]),s=o;continue}}return e}l(Z,"orderPathParams");function te(n,e){let t=[];for(let r of Z(n))t.push(`${r.name}: ${P(r.schema)}`);if(n.queryParams.length>0){let r=v(n.tag)+v(e)+"Query";t.push(`query?: Schema.${r}`)}if(n.requestBody){let r=n.requestBody.required?"":"?";t.push(`body${r}: ${P(n.requestBody.schema)}`)}return t.push('init?: Omit<RequestInit, "method" | "body">'),t}l(te,"buildMethodSignature");function ye(n){let e=[];for(let t of Z(n))e.push(t.name);return n.queryParams.length>0&&e.push("query"),n.requestBody&&e.push("body"),e}l(ye,"queryKeyArgs");function G(n){let e=!1;for(let t of n)if(!(t>="a"&&t<="z"||t>="A"&&t<="Z"||t>="0"&&t<="9"||t==="_"||t==="$")){e=!0;break}return n.length>0&&n[0]>="0"&&n[0]<="9"&&(e=!0),e?`"${n}"`:n}l(G,"quoteTSPropertyName");function be(n){return n.response.isStreaming===!0}l(be,"isStreamingOperation");function we(n){let e=n.response.schema;return e.kind===f.Array&&e.items?P(e.items):n.response.streamingFormat==="sse"?"string":P(e)}l(we,"getStreamingItemType");function We(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(We,"_ts_decorate");function Se(n,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(n,e)}l(Se,"_ts_metadata");var $=class n{static{l(this,"TypeScriptGeneratorService")}configService;logger=new Ke(n.name);constructor(e){this.configService=e}getType(){return"typescript"}async generate(e,t){let r=T.join(e.outDir,"src"),s=T.join(r,"services");await w.promises.mkdir(s,{recursive:!0});let o=await this.preprocessIR(e,t);this.registerHandlebarsHelpers(e),await this.generateClient(e,o,r),await this.generateIndex(e,o,r),await this.generateUtils(e,o,r),await this.generateServices(e,o,s),await this.generateSchema(e,o,r),await this.generateZodSchema(e,o,r),await this.generatePackageJson(e),await this.generateTsConfig(e),await this.generateReadme(e,o)}async preprocessIR(e,t){let r=await Promise.all(t.services.map(async s=>({...s,operations:await Promise.all(s.operations.map(async o=>{let i=await de(e,o);return{...o,_resolvedMethodName:i}}))})));return{...t,services:r}}registerHandlebarsHelpers(e){me(),h.registerHelper("methodName",t=>t._resolvedMethodName||D(t)),h.registerHelper("queryTypeName",t=>{let r=t._resolvedMethodName||D(t);return v(t.tag)+v(r)+"Query"}),h.registerHelper("pathTemplate",t=>{let r=he(t);return new h.SafeString(r)}),h.registerHelper("queryKeyBase",t=>ge(t)),h.registerHelper("pathParamsInOrder",t=>Z(t)),h.registerHelper("methodSignature",t=>{let r=t._resolvedMethodName||D(t);return te(t,r).map(o=>new h.SafeString(o))}),h.registerHelper("methodSignatureNoInit",t=>{let r=t._resolvedMethodName||D(t);return te(t,r).slice(0,-1)}),h.registerHelper("queryKeyArgs",t=>ye(t)),h.registerHelper("tsType",t=>t&&typeof t=="object"&&"kind"in t?P(t):"unknown"),h.registerHelper("stripSchemaNs",t=>t.replace(/^Schema\./,"")),h.registerHelper("tsTypeStripNs",t=>{if(t&&typeof t=="object"&&"kind"in t){let s=P(t).replace(/^Schema\./,"");return new h.SafeString(s)}return"unknown"}),h.registerHelper("decodeHtml",t=>typeof t!="string"?t:t.replace(/"/g,'"').replace(/</g,"<").replace(/>/g,">").replace(/`/g,"`").replace(/&/g,"&")),h.registerHelper("quotePropName",t=>G(t)),h.registerHelper("zodSchema",t=>t&&typeof t=="object"&&"kind"in t?new h.SafeString(k(t)):"z.unknown()"),h.registerHelper("isStreaming",t=>be(t)),h.registerHelper("streamingItemType",t=>new h.SafeString(we(t)))}async renderTemplate(e,t,r,s){let o=s.templates?.[e];if(o){this.logger.debug(`Using template override for ${e}: ${o}`);try{await w.promises.access(o,w.constants.R_OK);let g=await w.promises.readFile(o,"utf-8"),S=h.compile(g)(t);await w.promises.writeFile(r,S,"utf-8");return}catch(g){let y=g instanceof Error?g.message:String(g);throw this.logger.error(`Template override file not found or not readable: ${o}. Error: ${y}`),new Error(`Template override file not found or not readable: ${o}`)}}let i=[T.join(__dirname,"generator/typescript/templates",e),T.join(__dirname,"templates",e),T.join(__dirname,"../typescript/templates",e),T.join(process.cwd(),"src/generator/typescript/templates",e)],a=null;for(let g of i)try{await w.promises.access(g),a=g,this.logger.debug(`Found template at: ${a}`);break}catch{this.logger.debug(`Template not found at: ${g}`)}if(!a)throw this.logger.error(`Template not found: ${e}`),this.logger.error(`Checked paths: ${i.join(", ")}`),this.logger.error(`__dirname: ${__dirname}`),new Error(`Template not found: ${e}`);let c=await w.promises.readFile(a,"utf-8"),u=h.compile(c)(t);await w.promises.writeFile(r,u,"utf-8")}async generateClient(e,t,r){let s=T.join(r,"client.ts");if(!this.configService.shouldExcludeFile(e,s))try{await this.renderTemplate("client.ts.hbs",{Client:e,IR:t},s,e)}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.warn(`Template client.ts.hbs not found: ${i}, using placeholder`),await w.promises.writeFile(s,"// Generated client - template rendering to be implemented","utf-8")}}async generateIndex(e,t,r){let s=T.join(r,"index.ts");if(!this.configService.shouldExcludeFile(e,s))try{await this.renderTemplate("index.ts.hbs",{Client:e,IR:t},s,e)}catch{this.logger.warn("Template index.ts.hbs not found, using placeholder"),await w.promises.writeFile(s,"// Generated index - template rendering to be implemented","utf-8")}}async generateUtils(e,t,r){let s=T.join(r,"utils.ts");if(!this.configService.shouldExcludeFile(e,s))try{await this.renderTemplate("utils.ts.hbs",{Client:e,IR:t},s,e)}catch{this.logger.warn("Template utils.ts.hbs not found, using placeholder"),await w.promises.writeFile(s,"// Generated utils - template rendering to be implemented","utf-8")}}async generateServices(e,t,r){for(let s of t.services){let o=T.join(r,`${_(s.tag).toLowerCase()}.ts`);if(!this.configService.shouldExcludeFile(e,o))try{await this.renderTemplate("service.ts.hbs",{Client:e,Service:s,IR:t},o,e)}catch{this.logger.warn("Template service.ts.hbs not found, using placeholder");let a=`// Generated service ${s.tag} - template rendering to be implemented`;await w.promises.writeFile(o,a,"utf-8")}}}async generateSchema(e,t,r){let s=T.join(r,"schema.ts");if(!this.configService.shouldExcludeFile(e,s))try{await this.renderTemplate("schema.ts.hbs",{Client:e,IR:t},s,e)}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.warn(`Template schema.ts.hbs error: ${i}, using placeholder`),await w.promises.writeFile(s,"// Generated schema - template rendering to be implemented","utf-8")}}async generateZodSchema(e,t,r){let s=T.join(r,"schema.zod.ts");if(!this.configService.shouldExcludeFile(e,s))try{await this.renderTemplate("schema.zod.ts.hbs",{Client:e,IR:t},s,e)}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.warn(`Template schema.zod.ts.hbs error: ${i}, using placeholder`),await w.promises.writeFile(s,"// Generated Zod schemas - template rendering to be implemented","utf-8")}}async generatePackageJson(e){let t=T.join(e.outDir,"package.json");if(!this.configService.shouldExcludeFile(e,t))try{await this.renderTemplate("package.json.hbs",{Client:e},t,e)}catch{this.logger.warn("Template package.json.hbs not found, using fallback");let s=JSON.stringify({name:e.packageName,version:"0.0.1",main:"dist/index.js",types:"dist/index.d.ts"},null,2);await w.promises.writeFile(t,s,"utf-8")}}async generateTsConfig(e){let t=T.join(e.outDir,"tsconfig.json");if(!this.configService.shouldExcludeFile(e,t))try{await this.renderTemplate("tsconfig.json.hbs",{Client:e},t,e)}catch{this.logger.warn("Template tsconfig.json.hbs not found, using fallback");let s=JSON.stringify({compilerOptions:{target:"ES2020",module:"commonjs",lib:["ES2020"],declaration:!0,outDir:"./dist",rootDir:"./src",strict:!0,esModuleInterop:!0,skipLibCheck:!0,forceConsistentCasingInFileNames:!0},include:["src/**/*"]},null,2);await w.promises.writeFile(t,s,"utf-8")}}async generateReadme(e,t){let r=T.join(e.outDir,"README.md");if(!this.configService.shouldExcludeFile(e,r))try{await this.renderTemplate("README.md.hbs",{Client:e,IR:t},r,e)}catch{this.logger.warn("Template README.md.hbs not found, using fallback");let o=`# ${e.name}
|
|
5
|
+
|
|
6
|
+
Generated SDK from OpenAPI specification.`;await w.promises.writeFile(r,o,"utf-8")}}};$=We([Je(),Se("design:type",Function),Se("design:paramtypes",[typeof x>"u"?Object:x])],$);function Qe(n,e,t,r){var s=arguments.length,o=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,t,r);else for(var a=n.length-1;a>=0;a--)(i=n[a])&&(o=(s<3?i(o):s>3?i(e,t,o):i(e,t))||o);return s>3&&o&&Object.defineProperty(e,t,o),o}l(Qe,"_ts_decorate");function Te(n,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(n,e)}l(Te,"_ts_metadata");var V=class{static{l(this,"GeneratorModule")}generatorService;typeScriptGenerator;constructor(e,t){this.generatorService=e,this.typeScriptGenerator=t,this.generatorService.register(this.typeScriptGenerator)}};V=Qe([Ye({imports:[N,E],providers:[H,C,j,$],exports:[H,C,j]}),Te("design:type",Function),Te("design:paramtypes",[typeof H>"u"?Object:H,typeof $>"u"?Object:$])],V);import*as ve from"fs";async function qr(n,e){let t;typeof n=="string"?t=await B(n):t=n;let r=new x,s=new R,o=new j,i=new C(o),a=new H(i,s),c=new $(r);a.register(c);for(let p of t.clients)e?.client&&p.name!==e.client||(await ve.promises.mkdir(p.outDir,{recursive:!0}),await a.generate(t.spec,p))}l(qr,"generate");async function Er(n){return B(n)}l(Er,"loadConfig");export{Re as ClientSchema,E as ConfigModule,se as ConfigSchema,x as ConfigService,V as GeneratorModule,H as GeneratorService,f as IRSchemaKind,N as OpenApiModule,R as OpenApiService,oe as TYPESCRIPT_TEMPLATE_NAMES,xe as TypeAugmentationOptionsSchema,Ce as TypeScriptClientSchema,dt as defineConfig,qr as generate,Er as loadConfig,B as loadMjsConfig};
|
|
7
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +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(/"/g, '\"')\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/`/g, \"`\")\n .replace(/&/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(/"/g, '\"')\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/`/g, \"`\")\n .replace(/`/g, \"`\")\n .replace(/&/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"]}
|