@ahoo-wang/fetcher-generator 2.11.3 → 2.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("commander"),a=require("./index.cjs");require("@ahoo-wang/fetcher");require("yaml");require("fs");require("path");class f{getTimestamp(){return new Date().toTimeString().slice(0,8)}info(e,...t){const o=this.getTimestamp();t.length>0?console.log(`[${o}] ℹ️ ${e}`,...t):console.log(`[${o}] ℹ️ ${e}`)}success(e,...t){const o=this.getTimestamp();t.length>0?console.log(`[${o}] ✅ ${e}`,...t):console.log(`[${o}] ✅ ${e}`)}error(e,...t){const o=this.getTimestamp();t.length>0?console.error(`[${o}] ❌ ${e}`,...t):console.error(`[${o}] ❌ ${e}`)}progress(e,t=0,...o){const i=this.getTimestamp(),r=" ".repeat(t);o.length>0?console.log(`[${i}] 🔄 ${r}${e}`,...o):console.log(`[${i}] 🔄 ${r}${e}`)}progressWithCount(e,t,o,i=0,...r){const s=this.getTimestamp(),p=" ".repeat(i),l=`[${e}/${t}]`;r.length>0?console.log(`[${s}] 🔄 ${p}${l} ${o}`,...r):console.log(`[${s}] 🔄 ${p}${l} ${o}`)}}function h(n){if(!n)return!1;try{const e=new URL(n);return e.protocol==="http:"||e.protocol==="https:"}catch{return n.length>0}}async function $(n){const e=new f;process.on("SIGINT",()=>{e.error("Generation interrupted by user"),process.exit(130)}),h(n.input)||(e.error("Invalid input: must be a valid file path or HTTP/HTTPS URL"),process.exit(2));try{e.info("Starting code generation...");const t={inputPath:n.input,outputDir:n.output,configPath:n.config,tsConfigFilePath:n.tsConfigFilePath,logger:e};await new a.CodeGenerator(t).generate(),e.success(`Code generation completed successfully! Files generated in: ${n.output}`)}catch(t){e.error(`Error during code generation: ${t}`),process.exit(1)}}const d="2.11.3",m={version:d};function u(){return c.program.name("fetcher-generator").description("OpenAPI Specification TypeScript code generator for Wow").version(m.version,"-v, --version"),c.program.command("generate").description("Generate TypeScript code from OpenAPI specification").requiredOption("-i, --input <file>","Input OpenAPI specification file path or URL (http/https)").option("-o, --output <path>","Output directory path","src/generated").option("-c, --config <file>","Configuration file path",a.DEFAULT_CONFIG_PATH).option("-t, --ts-config-file-path <file>","TypeScript configuration file path").action($),c.program}function g(){u().parse()}g();exports.runCLI=g;exports.setupCLI=u;
2
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("commander"),a=require("./index.cjs");require("@ahoo-wang/fetcher");require("yaml");require("fs");require("path");class f{getTimestamp(){return new Date().toTimeString().slice(0,8)}info(e,...t){const o=this.getTimestamp();t.length>0?console.log(`[${o}] ℹ️ ${e}`,...t):console.log(`[${o}] ℹ️ ${e}`)}success(e,...t){const o=this.getTimestamp();t.length>0?console.log(`[${o}] ✅ ${e}`,...t):console.log(`[${o}] ✅ ${e}`)}error(e,...t){const o=this.getTimestamp();t.length>0?console.error(`[${o}] ❌ ${e}`,...t):console.error(`[${o}] ❌ ${e}`)}progress(e,t=0,...o){const i=this.getTimestamp(),r=" ".repeat(t);o.length>0?console.log(`[${i}] 🔄 ${r}${e}`,...o):console.log(`[${i}] 🔄 ${r}${e}`)}progressWithCount(e,t,o,i=0,...r){const s=this.getTimestamp(),p=" ".repeat(i),l=`[${e}/${t}]`;r.length>0?console.log(`[${s}] 🔄 ${p}${l} ${o}`,...r):console.log(`[${s}] 🔄 ${p}${l} ${o}`)}}function h(n){if(!n)return!1;try{const e=new URL(n);return e.protocol==="http:"||e.protocol==="https:"}catch{return n.length>0}}async function $(n){const e=new f;process.on("SIGINT",()=>{e.error("Generation interrupted by user"),process.exit(130)}),h(n.input)||(e.error("Invalid input: must be a valid file path or HTTP/HTTPS URL"),process.exit(2));try{e.info("Starting code generation...");const t={inputPath:n.input,outputDir:n.output,configPath:n.config,tsConfigFilePath:n.tsConfigFilePath,logger:e};await new a.CodeGenerator(t).generate(),e.success(`Code generation completed successfully! Files generated in: ${n.output}`)}catch(t){e.error(`Error during code generation: ${t}`),process.exit(1)}}const d="2.12.1",m={version:d};function u(){return c.program.name("fetcher-generator").description("OpenAPI Specification TypeScript code generator for Wow").version(m.version,"-v, --version"),c.program.command("generate").description("Generate TypeScript code from OpenAPI specification").requiredOption("-i, --input <file>","Input OpenAPI specification file path or URL (http/https)").option("-o, --output <path>","Output directory path","src/generated").option("-c, --config <file>","Configuration file path",a.DEFAULT_CONFIG_PATH).option("-t, --ts-config-file-path <file>","TypeScript configuration file path").action($),c.program}function g(){u().parse()}g();exports.runCLI=g;exports.setupCLI=u;
3
3
  //# sourceMappingURL=cli.cjs.map
package/dist/cli.js CHANGED
@@ -63,7 +63,7 @@ async function h(n) {
63
63
  e.error(`Error during code generation: ${t}`), process.exit(1);
64
64
  }
65
65
  }
66
- const $ = "2.11.3", m = {
66
+ const $ = "2.12.1", m = {
67
67
  version: $
68
68
  };
69
69
  function d() {
package/dist/index.cjs CHANGED
@@ -1,12 +1,21 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("ts-morph"),h=require("@ahoo-wang/fetcher"),G=require("@ahoo-wang/fetcher-wow"),J=require("yaml"),pe=require("fs"),W=require("path");function T(o){return o.$ref.split("/").pop()}function v(o,e){const t=T(o);return e.schemas?.[t]}function V(o,e){const t=T(o);return e.requestBodies?.[t]}function H(o,e){const t=T(o);return e.parameters?.[t]}function E(o,e){return{key:T(o),schema:v(o,e)}}const me=/[-_\s.]+/;function O(o){return o.split(me)}function K(o){return Array.isArray(o)?o.flatMap(e=>L(O(e))):L(O(o))}function L(o){return o.flatMap(e=>{if(e.length===0)return[];const t=[];let n="";for(let r=0;r<e.length;r++){const i=e[r],s=/[A-Z]/.test(i),a=r>0&&/[a-z]/.test(e[r-1]);s&&a&&n?(t.push(n),n=i):n+=i}return n&&t.push(n),t})}function C(o){return o===""||o.length===0?"":K(o).filter(t=>t.length>0).map(t=>{const n=t.charAt(0),r=t.slice(1);return(/[a-zA-Z]/.test(n)?n.toUpperCase():n)+r.toLowerCase()}).join("")}function y(o){const e=C(o);return e.charAt(0).toLowerCase()+e.slice(1)}function de(o){return o===""||Array.isArray(o)&&o.length===0?"":K(o).filter(t=>t.length>0).map(t=>t.toUpperCase()).join("_")}function g(o){return!!(o&&typeof o=="object"&&"$ref"in o)}function M(o,e){if(e&&!g(e)&&e.content)return e.content[o]?.schema}function Y(o){return M(h.ContentTypeValues.APPLICATION_JSON,o)}function fe(o){return M(h.ContentTypeValues.TEXT_EVENT_STREAM,o)}function he(o){return M("*/*",o)}const ye=["string","number","integer","boolean","null"];function j(o){return Array.isArray(o)?!0:ye.includes(o)}function N(o){return o.type==="array"}function xe(o){return Array.isArray(o.enum)&&o.enum.length>0}function X(o){return Array.isArray(o.anyOf)&&o.anyOf.length>0}function Z(o){return Array.isArray(o.oneOf)&&o.oneOf.length>0}function Ae(o){return X(o)||Z(o)}function Ce(o){return Array.isArray(o.allOf)&&o.allOf.length>0}function z(o){return X(o)||Z(o)||Ce(o)}function U(o){return o.includes("|")||o.includes("&")?`(${o})[]`:`${o}[]`}function Pe(o){return o.type!=="object"?!1:o.properties?Object.keys(o.properties).length===0:!0}function P(o){if(Array.isArray(o))return o.map(e=>P(e)).join(" | ");switch(o){case"string":return"string";case"number":case"integer":return"number";case"boolean":return"boolean";case"null":return"null";default:return"any"}}function D(o){return[{method:"get",operation:o.get},{method:"put",operation:o.put},{method:"post",operation:o.post},{method:"delete",operation:o.delete},{method:"options",operation:o.options},{method:"head",operation:o.head},{method:"patch",operation:o.patch},{method:"trace",operation:o.trace}].filter(({operation:e})=>e!==void 0)}function _(o){return o.responses[200]}function k(o){const e=_(o);return Y(e)}function $e(o,e){return o.parameters?o.parameters.map(t=>g(t)?H(t,e):t).filter(t=>t.in==="path"):[]}const Ie="string";function ee(o){return!o.schema||g(o.schema)||!o.schema.type||!j(o.schema.type)?Ie:P(o.schema.type)}function te(o){return o.startsWith("http://")||o.startsWith("https://")?Te(o):Ee(o)}async function Te(o){return await(await fetch(o)).text()}function Ee(o){return new Promise((e,t)=>{pe.readFile(o,"utf-8",(n,r)=>{n?t(n):e(r)})})}async function Se(o){const e=await te(o);switch(ne(e)){case"json":return JSON.parse(e);case"yaml":return J.parse(e);default:throw new Error(`Unsupported file format: ${o}`)}}async function ve(o){const e=await te(o);switch(ne(e)){case"json":return JSON.parse(e);case"yaml":return J.parse(e);default:throw new Error(`Unsupported file format: ${o}`)}}function ne(o){const e=o.trimStart();if(e.startsWith("{")||e.startsWith("["))return"json";if(e.startsWith("-")||e.startsWith("%YAML"))return"yaml";try{return JSON.parse(e),"json"}catch{if(e.length>0)return"yaml"}throw new Error("Unable to infer file format")}const oe="types.ts",Re="@";function we(o){return h.combineURLs(o.path,oe)}function re(o,e,t){const n=h.combineURLs(e,t),r=o.getSourceFile(n);return r||o.createSourceFile(n,"",{overwrite:!0})}function $(o,e,t){let n=o.getImportDeclaration(r=>r.getModuleSpecifierValue()===e);n||(n=o.addImportDeclaration({moduleSpecifier:e})),t.forEach(r=>{n.getNamedImports().some(s=>s.getName()===r)||n.addNamedImport(r)})}function f(o,e,t){if(t.path.startsWith(Re)){$(o,t.path,[t.name]);return}const n=o.getDirectoryPath(),r=W.join(e,t.path,oe);let i=W.relative(n,r);i=i.replace(/\.ts$/,""),i.startsWith(".")||(i="./"+i),$(o,i,[t.name])}function S(o,e,t,n){o.path!==n.path&&f(e,t,n)}function Oe(o){if(!Array.isArray(o))return;const e=o.filter(t=>typeof t=="string"&&t.length>0);return e.length>0?e.join(`
2
- `):void 0}function R(o,e){const t=Oe(e);t&&o.addJsDoc(t)}function w(o,e){const t=[e.title,e.description];e.format&&t.push(`- format: ${e.format}`),B(t,e,"default"),B(t,e,"example"),Ne(t,e),De(t,e),be(t,e),R(o,t)}function B(o,e,t){const n=e[t];if(n){if(typeof n!="object"){o.push(`- ${t}: \`${n}\``);return}o.push(`- ${t}: `),o.push("```json"),o.push(JSON.stringify(n)),o.push("```")}}function Ne(o,e){const t=["- Numeric Constraints"];e.minimum!==void 0&&t.push(` - minimum: ${e.minimum}`),e.maximum!==void 0&&t.push(` - maximum: ${e.maximum}`),e.exclusiveMinimum!==void 0&&t.push(` - exclusiveMinimum: ${e.exclusiveMinimum}`),e.exclusiveMaximum!==void 0&&t.push(` - exclusiveMaximum: ${e.exclusiveMaximum}`),e.multipleOf!==void 0&&t.push(` - multipleOf: ${e.multipleOf}`),t.length!==1&&o.push(...t)}function De(o,e){const t=["- String Constraints"];e.minLength!==void 0&&t.push(` - minLength: ${e.minLength}`),e.maxLength!==void 0&&t.push(` - maxLength: ${e.maxLength}`),e.pattern!==void 0&&t.push(` - pattern: ${e.pattern}`),t.length!==1&&o.push(...t)}function be(o,e){const t=["- Array Constraints"];e.minItems!==void 0&&t.push(` - minItems: ${e.minItems}`),e.maxItems!==void 0&&t.push(` - maxItems: ${e.maxItems}`),e.uniqueItems!==void 0&&t.push(` - uniqueItems: ${e.uniqueItems}`),t.length!==1&&o.push(...t)}function qe(o){const e=o.split(".");return e.length!=2||e[0].length===0||e[1].length===0?null:e}function Me(o){const e=qe(o.name);return e?{tag:o,contextAlias:e[0],aggregateName:e[1]}:null}function je(o){const e=o?.map(n=>Me(n)).filter(n=>n!==null);if(!e)return new Map;const t=new Map;return e.forEach(n=>{t.set(n.tag.name,{aggregate:n,commands:new Map,events:new Map})}),t}function _e(o){if(!o)return null;const e=o.split(".");return e.length!=3?null:e[2]}const Fe="#/components/responses/wow.CommandOk",Ge="#/components/parameters/wow.id";class We{constructor(e){this.openAPI=e,this.aggregates=je(e.tags),this.build()}aggregates;build(){for(const[e,t]of Object.entries(this.openAPI.paths)){const n=D(t);for(const r of n)this.commands(e,r),this.state(r.operation),this.events(r.operation),this.fields(r.operation)}}resolve(){const e=new Map;for(const t of this.aggregates.values()){if(!t.state||!t.fields)continue;const n=t.aggregate.contextAlias;let r=e.get(n);r||(r=new Set,e.set(n,r)),r.add(t)}return e}commands(e,t){const n=t.operation;if(n.operationId==="wow.command.send")return;const r=_e(n.operationId);if(!r)return;const i=_(n);if(!i||!g(i)||i.$ref!==Fe||!n.requestBody)return;const s=n.parameters??[],a=s.filter(m=>g(m)&&m.$ref===Ge).at(0),c=s.filter(m=>!g(m)&&m.in==="path");if(a){const m=H(a,this.openAPI.components);c.push(m)}const l=n.requestBody.content[h.ContentTypeValues.APPLICATION_JSON].schema,p=E(l,this.openAPI.components);p.schema.title=p.schema.title||n.summary,p.schema.description=p.schema.description||n.description;const le={name:r,method:t.method,path:e,pathParameters:c,summary:n.summary,description:n.description,schema:p,operation:n};n.tags?.forEach(m=>{const F=this.aggregates.get(m);F&&F.commands.set(r,le)})}state(e){if(!e.operationId?.endsWith(".snapshot_state.single"))return;const t=k(e);if(!g(t))return;const n=E(t,this.openAPI.components);e.tags?.forEach(r=>{const i=this.aggregates.get(r);i&&(i.state=n)})}events(e){if(!this.openAPI.components||!e.operationId?.endsWith(".event.list_query"))return;const t=k(e);if(g(t))return;const n=t?.items;if(!g(n))return;const i=v(n,this.openAPI.components).properties.body.items.anyOf.map(s=>{const a=s.title,c=s.properties.name.const,u=s.properties.body,l=E(u,this.openAPI.components);return l.schema.title=l.schema.title||s.title,{title:a,name:c,schema:l}});e.tags?.forEach(s=>{const a=this.aggregates.get(s);a&&i.forEach(c=>{a.events.set(c.name,c)})})}fields(e){if(!this.openAPI.components||!e.operationId?.endsWith(".snapshot.count"))return;const n=V(e.requestBody,this.openAPI.components).content[h.ContentTypeValues.APPLICATION_JSON].schema,i=v(n,this.openAPI.components).properties?.field,s=E(i,this.openAPI.components);e.tags?.forEach(a=>{const c=this.aggregates.get(a);c&&(c.fields=s)})}}const I="@ahoo-wang/fetcher-wow",Le={"wow.command.CommandResult":"CommandResult","wow.command.CommandResultArray":"CommandResultArray","wow.MessageHeaderSqlType":"MessageHeaderSqlType","wow.api.BindingError":"BindingError","wow.api.DefaultErrorInfo":"ErrorInfo","wow.api.RecoverableType":"RecoverableType","wow.api.command.DefaultDeleteAggregate":"DeleteAggregate","wow.api.command.DefaultRecoverAggregate":"RecoverAggregate","wow.api.messaging.FunctionInfoData":"FunctionInfo","wow.api.messaging.FunctionKind":"FunctionKind","wow.api.modeling.AggregateId":"AggregateId","wow.api.query.Condition":"Condition","wow.api.query.ConditionOptions":"ConditionOptions","wow.api.query.ListQuery":"ListQuery","wow.api.query.Operator":"Operator","wow.api.query.PagedQuery":"PagedQuery","wow.api.query.Pagination":"Pagination","wow.api.query.Projection":"Projection","wow.api.query.Sort":"FieldSort","wow.api.query.Sort.Direction":"SortDirection","wow.command.CommandStage":"CommandStage","wow.command.SimpleWaitSignal":"WaitSignal","wow.configuration.Aggregate":"Aggregate","wow.configuration.BoundedContext":"BoundedContext","wow.configuration.WowMetadata":"WowMetadata","wow.modeling.DomainEvent":"DomainEvent","wow.openapi.BatchResult":"BatchResult","wow.messaging.CompensationTarget":"CompensationTarget"};function d(o){if(!o)return{name:"",path:"/"};const e=Le[o];if(e)return{name:e,path:I};const t=o.split(".");let n=-1;for(let c=0;c<t.length;c++)if(t[c]&&/^[A-Z]/.test(t[c])){n=c;break}const r=t.slice(0,n),i=r.length>0?`/${r.join("/")}`:"/",s=t.slice(n);return{name:C(s),path:i}}function x(o){const e=T(o);return d(e)}class ze{constructor(e){this.context=e}getOrCreateSourceFile(e){const t=we(e);return this.context.getOrCreateSourceFile(t)}generate(){const e=this.context.openAPI.components?.schemas;if(!e){this.context.logger.info("No schemas found in OpenAPI specification");return}const t=this.stateAggregatedTypeNames(),n=this.filterSchemas(e,t);this.context.logger.progress(`Generating models for ${n.length} schemas`),n.forEach((r,i)=>{this.context.logger.progressWithCount(i+1,n.length,`Processing schema: ${r.key}`,2),this.generateKeyedSchema(r)}),this.context.logger.success("Model generation completed")}filterSchemas(e,t){return Object.entries(e).map(([n,r])=>({key:n,schema:r})).filter(n=>!this.isWowSchema(n.key,t))}isWowSchema(e,t){if(e!=="wow.api.query.PagedList"&&e.startsWith("wow.api.query.")&&e.endsWith("PagedList"))return!1;if(e.startsWith("wow.")||e.endsWith("AggregatedCondition")||e.endsWith("AggregatedDomainEventStream")||e.endsWith("AggregatedDomainEventStreamPagedList")||e.endsWith("AggregatedDomainEventStreamServerSentEventNonNullData")||e.endsWith("AggregatedListQuery")||e.endsWith("AggregatedPagedQuery")||e.endsWith("AggregatedSingleQuery"))return!0;const n=d(e);return t.has(n.name)}aggregatedSchemaSuffix=["MaterializedSnapshot","MaterializedSnapshotPagedList","MaterializedSnapshotServerSentEventNonNullData","PagedList","ServerSentEventNonNullData","Snapshot","StateEvent"];stateAggregatedTypeNames(){const e=new Set;for(const t of this.context.contextAggregates.values())for(const n of t)this.aggregatedSchemaSuffix.forEach(r=>{const i=d(n.state.key),s=C(i.name)+r;e.add(s)});return e}generateKeyedSchema({key:e,schema:t}){const n=d(e),r=this.getOrCreateSourceFile(n),i=this.process(n,r,t);i&&w(i,t)}process(e,t,n){if(xe(n))return t.addEnum({name:e.name,isExported:!0,members:n.enum.filter(i=>typeof i=="string"&&i.length>0).map(i=>({name:de(i),initializer:`'${i}'`}))});if(N(n)&&g(n.items)){const i=x(n.items);return S(e,t,this.context.outputDir,i),t.addTypeAlias({name:e.name,type:U(i.name),isExported:!0})}const r=t.addInterface({name:e.name,isExported:!0});return n.type==="object"&&n.properties?this.processInterface(t,e,n,r):(z(n)&&(n.anyOf||n.oneOf||n.allOf).forEach(s=>{if(g(s)){const a=x(s);S(e,t,this.context.outputDir,a),r.addExtends(a.name);return}this.processInterface(t,e,s,r)}),r)}processObject(e,t,n){const r=e.addInterface({name:t.name,isExported:!0});return this.processInterface(e,t,n,r)}processInterface(e,t,n,r){for(const[i,s]of Object.entries(n.properties)){const a=this.resolvePropertyType(t,e,i,s);let c=r.getProperty(i);c?c.setType(a):c=r.addProperty({name:i,type:a}),g(s)||w(c,s)}return r}resolvePropertyType(e,t,n,r){if(g(r)){const i=x(r);return S(e,t,this.context.outputDir,i),i.name}if(r.const)return`'${r.const}'`;if(N(r)){const i=this.resolvePropertyType(e,t,n,r.items);return U(i)}if(r.type&&j(r.type))return P(r.type);if(z(r))return this.resolvePropertyCompositionType(e,t,r);if(r.type==="object"&&r.properties){const i={path:e.path,name:`${e.name}${C(n)}`},s=this.processObject(t,i,r);return w(s,r),i.name}return"any"}resolvePropertyCompositionType(e,t,n){const r=n.anyOf||n.oneOf||n.allOf,i=new Set;r.forEach(a=>{if(g(a)){const c=x(a);S(e,t,this.context.outputDir,c),i.add(c.name);return}i.add(P(a.type??"string"))});const s=Ae(n)?"|":"&";return Array.from(i).join(s)}}const Ue="@ahoo-wang/fetcher-decorator",ke=["type ApiMetadata","type ApiMetadataCapable","type ParameterRequest","api","get","post","put","patch","del","request","attribute","path","autoGeneratedError"],Be={type:"Promise<Response>",metadata:"{resultExtractor: ResultExtractors.Response }"},Q={type:"Promise<string>",metadata:"{resultExtractor: ResultExtractors.Text }"},b=`{
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x=require("ts-morph"),h=require("@ahoo-wang/fetcher"),_=require("@ahoo-wang/fetcher-wow"),J=require("yaml"),de=require("fs"),G=require("path");function C(n){return n.$ref.split("/").pop()}function I(n,e){const t=C(n);return e.schemas?.[t]}function V(n,e){const t=C(n);return e.requestBodies?.[t]}function H(n,e){const t=C(n);return e.parameters?.[t]}function $(n,e){return{key:C(n),schema:I(n,e)}}const me=/[-_\s.]+/;function w(n){return n.split(me)}function K(n){return Array.isArray(n)?n.flatMap(e=>W(w(e))):W(w(n))}function W(n){return n.flatMap(e=>{if(e.length===0)return[];const t=[];let o="";for(let r=0;r<e.length;r++){const i=e[r],s=/[A-Z]/.test(i),a=r>0&&/[a-z]/.test(e[r-1]);s&&a&&o?(t.push(o),o=i):o+=i}return o&&t.push(o),t})}function S(n){return n===""||n.length===0?"":K(n).filter(t=>t.length>0).map(t=>{const o=t.charAt(0),r=t.slice(1);return(/[a-zA-Z]/.test(o)?o.toUpperCase():o)+r.toLowerCase()}).join("")}function y(n){const e=S(n);return e.charAt(0).toLowerCase()+e.slice(1)}function fe(n){return n===""||Array.isArray(n)&&n.length===0?"":K(n).filter(t=>t.length>0).map(t=>t.toUpperCase()).join("_")}function u(n){return!!(n&&typeof n=="object"&&"$ref"in n)}function q(n,e){if(e&&!u(e)&&e.content)return e.content[n]?.schema}function Y(n){return q(h.ContentTypeValues.APPLICATION_JSON,n)}function he(n){return q(h.ContentTypeValues.TEXT_EVENT_STREAM,n)}function ye(n){return q("*/*",n)}const xe=["string","number","integer","boolean","null"];function X(n){return Array.isArray(n)?!0:xe.includes(n)}function k(n){return Array.isArray(n.enum)&&n.enum.length>0}function R(n){return n.type==="object"&&!!n.properties}function O(n){return n.type==="array"&&!!n.items}function Ae(n){return Array.isArray(n.anyOf)&&n.anyOf.length>0}function Pe(n){return Array.isArray(n.oneOf)&&n.oneOf.length>0}function D(n){return Array.isArray(n.allOf)&&n.allOf.length>0}function L(n){return Ae(n)||Pe(n)||D(n)}function Ce(n){return n.includes("|")||n.includes("&")?`(${n})[]`:`${n}[]`}function $e(n){return n.type==="object"&&!n.properties&&n.additionalProperties!==void 0}function Te(n){return n.type!=="object"?!1:n.properties?Object.keys(n.properties).length===0:!0}function E(n){if(Array.isArray(n))return n.map(e=>E(e)).join(" | ");switch(n){case"string":return"string";case"number":case"integer":return"number";case"boolean":return"boolean";case"null":return"null";default:return"any"}}function N(n){return[{method:"get",operation:n.get},{method:"put",operation:n.put},{method:"post",operation:n.post},{method:"delete",operation:n.delete},{method:"options",operation:n.options},{method:"head",operation:n.head},{method:"patch",operation:n.patch},{method:"trace",operation:n.trace}].filter(({operation:e})=>e!==void 0)}function F(n){return n.responses[200]}function z(n){const e=F(n);return Y(e)}function Ie(n,e){return n.parameters?n.parameters.map(t=>u(t)?H(t,e):t).filter(t=>t.in==="path"):[]}const ve="string";function Z(n){return!n.schema||u(n.schema)||!n.schema.type||!X(n.schema.type)?ve:E(n.schema.type)}function ee(n){return n.startsWith("http://")||n.startsWith("https://")?Se(n):Ee(n)}async function Se(n){return await(await fetch(n)).text()}function Ee(n){return new Promise((e,t)=>{de.readFile(n,"utf-8",(o,r)=>{o?t(o):e(r)})})}async function Re(n){const e=await ee(n);switch(te(e)){case"json":return JSON.parse(e);case"yaml":return J.parse(e);default:throw new Error(`Unsupported file format: ${n}`)}}async function we(n){const e=await ee(n);switch(te(e)){case"json":return JSON.parse(e);case"yaml":return J.parse(e);default:throw new Error(`Unsupported file format: ${n}`)}}function te(n){const e=n.trimStart();if(e.startsWith("{")||e.startsWith("["))return"json";if(e.startsWith("-")||e.startsWith("%YAML"))return"yaml";try{return JSON.parse(e),"json"}catch{if(e.length>0)return"yaml"}throw new Error("Unable to infer file format")}const ne="types.ts",Oe="@";function De(n){return h.combineURLs(n.path,ne)}function oe(n,e,t){const o=h.combineURLs(e,t),r=n.getSourceFile(o);return r||n.createSourceFile(o,"",{overwrite:!0})}function A(n,e,t){let o=n.getImportDeclaration(r=>r.getModuleSpecifierValue()===e);o||(o=n.addImportDeclaration({moduleSpecifier:e})),t.forEach(r=>{o.getNamedImports().some(s=>s.getName()===r)||o.addNamedImport(r)})}function f(n,e,t){if(t.path.startsWith(Oe)){A(n,t.path,[t.name]);return}const o=n.getDirectoryPath(),r=G.join(e,t.path,ne);let i=G.relative(o,r);i=i.replace(/\.ts$/,""),i.startsWith(".")||(i="./"+i),A(n,i,[t.name])}function Ne(n,e,t,o){n.path!==o.path&&f(e,t,o)}function re(n,e=`
2
+ `){if(!Array.isArray(n))return;const t=n.filter(o=>typeof o=="string"&&o.length>0);return t.length>0?t.join(e):void 0}function v(n,e){const t=re(e);t&&n.addJsDoc(t)}function ie(n,e){const t=[n.title,n.description];return e&&t.push(`- key: ${e}`),n.format&&t.push(`- format: ${n.format}`),U(t,n,"default"),U(t,n,"example"),be(t,n),Me(t,n),qe(t,n),t}function B(n,e,t){const o=ie(e,t);v(n,o)}function U(n,e,t){const o=e[t];if(o){if(typeof o!="object"){n.push(`- ${t}: \`${o}\``);return}n.push(`- ${t}: `),n.push("```json"),n.push(JSON.stringify(o)),n.push("```")}}function be(n,e){const t=["- Numeric Constraints"];e.minimum!==void 0&&t.push(` - minimum: ${e.minimum}`),e.maximum!==void 0&&t.push(` - maximum: ${e.maximum}`),e.exclusiveMinimum!==void 0&&t.push(` - exclusiveMinimum: ${e.exclusiveMinimum}`),e.exclusiveMaximum!==void 0&&t.push(` - exclusiveMaximum: ${e.exclusiveMaximum}`),e.multipleOf!==void 0&&t.push(` - multipleOf: ${e.multipleOf}`),t.length!==1&&n.push(...t)}function Me(n,e){const t=["- String Constraints"];e.minLength!==void 0&&t.push(` - minLength: ${e.minLength}`),e.maxLength!==void 0&&t.push(` - maxLength: ${e.maxLength}`),e.pattern!==void 0&&t.push(` - pattern: ${e.pattern}`),t.length!==1&&n.push(...t)}function qe(n,e){const t=["- Array Constraints"];e.minItems!==void 0&&t.push(` - minItems: ${e.minItems}`),e.maxItems!==void 0&&t.push(` - maxItems: ${e.maxItems}`),e.uniqueItems!==void 0&&t.push(` - uniqueItems: ${e.uniqueItems}`),t.length!==1&&n.push(...t)}function Fe(n){const e=n.split(".");return e.length!=2||e[0].length===0||e[1].length===0?null:e}function je(n){const e=Fe(n.name);return e?{tag:n,contextAlias:e[0],aggregateName:e[1]}:null}function _e(n){const e=n?.map(o=>je(o)).filter(o=>o!==null);if(!e)return new Map;const t=new Map;return e.forEach(o=>{t.set(o.tag.name,{aggregate:o,commands:new Map,events:new Map})}),t}function Ge(n){if(!n)return null;const e=n.split(".");return e.length!=3?null:e[2]}const We="#/components/responses/wow.CommandOk",ke="#/components/parameters/wow.id";class Le{constructor(e){this.openAPI=e,this.aggregates=_e(e.tags),this.build()}aggregates;build(){for(const[e,t]of Object.entries(this.openAPI.paths)){const o=N(t);for(const r of o)this.commands(e,r),this.state(r.operation),this.events(r.operation),this.fields(r.operation)}}resolve(){const e=new Map;for(const t of this.aggregates.values()){if(!t.state||!t.fields)continue;const o=t.aggregate.contextAlias;let r=e.get(o);r||(r=new Set,e.set(o,r)),r.add(t)}return e}commands(e,t){const o=t.operation;if(o.operationId==="wow.command.send")return;const r=Ge(o.operationId);if(!r)return;const i=F(o);if(!i||!u(i)||i.$ref!==We||!o.requestBody)return;const s=o.parameters??[],a=s.filter(d=>u(d)&&d.$ref===ke).at(0),c=s.filter(d=>!u(d)&&d.in==="path");if(a){const d=H(a,this.openAPI.components);c.push(d)}const l=o.requestBody.content[h.ContentTypeValues.APPLICATION_JSON].schema,p=$(l,this.openAPI.components);p.schema.title=p.schema.title||o.summary,p.schema.description=p.schema.description||o.description;const pe={name:r,method:t.method,path:e,pathParameters:c,summary:o.summary,description:o.description,schema:p,operation:o};o.tags?.forEach(d=>{const j=this.aggregates.get(d);j&&j.commands.set(r,pe)})}state(e){if(!e.operationId?.endsWith(".snapshot_state.single"))return;const t=z(e);if(!u(t))return;const o=$(t,this.openAPI.components);e.tags?.forEach(r=>{const i=this.aggregates.get(r);i&&(i.state=o)})}events(e){if(!this.openAPI.components||!e.operationId?.endsWith(".event.list_query"))return;const t=z(e);if(u(t))return;const o=t?.items;if(!u(o))return;const i=I(o,this.openAPI.components).properties.body.items.anyOf.map(s=>{const a=s.title,c=s.properties.name.const,g=s.properties.body,l=$(g,this.openAPI.components);return l.schema.title=l.schema.title||s.title,{title:a,name:c,schema:l}});e.tags?.forEach(s=>{const a=this.aggregates.get(s);a&&i.forEach(c=>{a.events.set(c.name,c)})})}fields(e){if(!this.openAPI.components||!e.operationId?.endsWith(".snapshot.count"))return;const o=V(e.requestBody,this.openAPI.components).content[h.ContentTypeValues.APPLICATION_JSON].schema,i=I(o,this.openAPI.components).properties?.field,s=$(i,this.openAPI.components);e.tags?.forEach(a=>{const c=this.aggregates.get(a);c&&(c.fields=s)})}}const P="@ahoo-wang/fetcher-wow",ze={"wow.command.CommandResult":"CommandResult","wow.command.CommandResultArray":"CommandResultArray","wow.MessageHeaderSqlType":"MessageHeaderSqlType","wow.api.BindingError":"BindingError","wow.api.DefaultErrorInfo":"ErrorInfo","wow.api.RecoverableType":"RecoverableType","wow.api.command.DefaultDeleteAggregate":"DeleteAggregate","wow.api.command.DefaultRecoverAggregate":"RecoverAggregate","wow.api.messaging.FunctionInfoData":"FunctionInfo","wow.api.messaging.FunctionKind":"FunctionKind","wow.api.modeling.AggregateId":"AggregateId","wow.api.query.Condition":"Condition","wow.api.query.ConditionOptions":"ConditionOptions","wow.api.query.ListQuery":"ListQuery","wow.api.query.Operator":"Operator","wow.api.query.PagedQuery":"PagedQuery","wow.api.query.Pagination":"Pagination","wow.api.query.Projection":"Projection","wow.api.query.Sort":"FieldSort","wow.api.query.Sort.Direction":"SortDirection","wow.command.CommandStage":"CommandStage","wow.command.SimpleWaitSignal":"WaitSignal","wow.configuration.Aggregate":"Aggregate","wow.configuration.BoundedContext":"BoundedContext","wow.configuration.WowMetadata":"WowMetadata","wow.modeling.DomainEvent":"DomainEvent","wow.openapi.BatchResult":"BatchResult","wow.messaging.CompensationTarget":"CompensationTarget"};function m(n){if(!n)return{name:"",path:"/"};const e=ze[n];if(e)return{name:e,path:P};const t=n.split(".");let o=-1;for(let c=0;c<t.length;c++)if(t[c]&&/^[A-Z]/.test(t[c])){o=c;break}const r=t.slice(0,o),i=r.length>0?`/${r.join("/")}`:"/",s=t.slice(o);return{name:S(s),path:i}}function T(n){const e=C(n);return m(e)}class Be{constructor(e,t,o,r){this.modelInfo=e,this.sourceFile=t,this.keySchema=o,this.outputDir=r}generate(){const e=this.process();e&&B(e,this.keySchema.schema,this.keySchema.key)}process(){const{schema:e}=this.keySchema;return k(e)?this.processEnum(e):R(e)?this.processInterface(e):O(e)?this.processArray(e):D(e)?this.processIntersection(e):L(e)?this.processComposition(e):this.processTypeAlias(e)}resolveReference(e){const t=T(e);return Ne(this.modelInfo,this.sourceFile,this.outputDir,t),t}resolveAdditionalProperties(e){return e.additionalProperties===void 0||e.additionalProperties===!1?"":e.additionalProperties===!0?"[key: string]: any":`[key: string]: ${this.resolveType(e.additionalProperties)}`}resolvePropertyDefinitions(e){const{properties:t}=e;return Object.entries(t).map(([o,r])=>{const i=this.resolveType(r);if(!u(r)){const s=ie(r),a=re(s,`
3
+ * `);if(a)return`
4
+ /**
5
+ * ${a}
6
+ */
7
+ ${o}: ${i}
8
+ `}return`${o}: ${i}`})}resolveObjectType(e){const t=[];if(R(e)){const r=this.resolvePropertyDefinitions(e);t.push(...r)}const o=this.resolveAdditionalProperties(e);return o&&t.push(o),t.length===0?"Record<string, any>":`{
9
+ ${t.join(`;
10
+ `)};
11
+ }`}resolveMapValueType(e){return e.additionalProperties===void 0||e.additionalProperties===!1||e.additionalProperties===!0?"any":this.resolveType(e.additionalProperties)}resolveType(e){if(u(e))return this.resolveReference(e).name;if($e(e))return`Record<string,${this.resolveMapValueType(e)}>`;if(e.const)return`'${e.const}'`;if(k(e))return e.enum.map(t=>`'${t}'`).join(" | ");if(L(e)){const o=(e.oneOf||e.anyOf||e.allOf||[]).map(i=>this.resolveType(i)),r=D(e)?" & ":" | ";return`(${o.join(r)})`}if(O(e)){const t=this.resolveType(e.items);return Ce(t)}return e.type==="object"?this.resolveObjectType(e):e.type?E(e.type):"any"}processEnum(e){return this.sourceFile.addEnum({name:this.modelInfo.name,isExported:!0,members:e.enum.filter(t=>typeof t=="string"&&t.length>0).map(t=>({name:fe(t),initializer:`'${t}'`}))})}addPropertyToInterface(e,t,o){const r=this.resolveType(o);let i=e.getProperty(t);i?i.setType(r):i=e.addProperty({name:t,type:r}),u(o)||B(i,o)}processInterface(e){const t=this.sourceFile.addInterface({name:this.modelInfo.name,isExported:!0}),o=e.properties||{};return Object.entries(o).forEach(([r,i])=>{this.addPropertyToInterface(t,r,i)}),e.additionalProperties&&t.addIndexSignature({keyName:"key",keyType:"string",returnType:this.resolveType(e.additionalProperties===!0?{}:e.additionalProperties)}).addJsDoc("Additional properties"),t}processArray(e){const t=this.resolveType(e.items);return this.sourceFile.addTypeAlias({name:this.modelInfo.name,type:`Array<${t}>`,isExported:!0})}processComposition(e){return this.sourceFile.addTypeAlias({name:this.modelInfo.name,type:this.resolveType(e),isExported:!0})}processIntersection(e){const t=this.sourceFile.addInterface({name:this.modelInfo.name,isExported:!0});return e.allOf.forEach(o=>{if(u(o)){const r=this.resolveType(o);t.addExtends(r);return}R(o)&&Object.entries(o.properties).forEach(([r,i])=>{this.addPropertyToInterface(t,r,i)})}),t}processTypeAlias(e){return this.sourceFile.addTypeAlias({name:this.modelInfo.name,type:this.resolveType(e),isExported:!0})}}class Ue{constructor(e){this.context=e}getOrCreateSourceFile(e){const t=De(e);return this.context.getOrCreateSourceFile(t)}generate(){const e=this.context.openAPI.components?.schemas;if(!e){this.context.logger.info("No schemas found in OpenAPI specification");return}const t=this.stateAggregatedTypeNames(),o=this.filterSchemas(e,t);this.context.logger.progress(`Generating models for ${o.length} schemas`),o.forEach((r,i)=>{this.context.logger.progressWithCount(i+1,o.length,`Processing schema: ${r.key}`,2),this.generateKeyedSchema(r)}),this.context.logger.success("Model generation completed")}filterSchemas(e,t){return Object.entries(e).map(([o,r])=>({key:o,schema:r})).filter(o=>!this.isWowSchema(o.key,t))}isWowSchema(e,t){if(e!=="wow.api.query.PagedList"&&e.startsWith("wow.api.query.")&&e.endsWith("PagedList"))return!1;if(e.startsWith("wow.")||e.endsWith("AggregatedCondition")||e.endsWith("AggregatedDomainEventStream")||e.endsWith("AggregatedDomainEventStreamPagedList")||e.endsWith("AggregatedDomainEventStreamServerSentEventNonNullData")||e.endsWith("AggregatedListQuery")||e.endsWith("AggregatedPagedQuery")||e.endsWith("AggregatedSingleQuery"))return!0;const o=m(e);return t.has(o.name)}aggregatedSchemaSuffix=["MaterializedSnapshot","MaterializedSnapshotPagedList","MaterializedSnapshotServerSentEventNonNullData","PagedList","ServerSentEventNonNullData","Snapshot","StateEvent"];stateAggregatedTypeNames(){const e=new Set;for(const t of this.context.contextAggregates.values())for(const o of t)this.aggregatedSchemaSuffix.forEach(r=>{const i=m(o.state.key),s=S(i.name)+r;e.add(s)});return e}generateKeyedSchema(e){const t=m(e.key),o=this.getOrCreateSourceFile(t);new Be(t,o,e,this.context.outputDir).generate()}}const Qe="@ahoo-wang/fetcher-decorator",Je=["type ApiMetadata","type ApiMetadataCapable","type ParameterRequest","api","get","post","put","patch","del","request","attribute","path","autoGeneratedError"],Ve={type:"Promise<Response>",metadata:"{resultExtractor: ResultExtractors.Response }"},Q={type:"Promise<string>",metadata:"{resultExtractor: ResultExtractors.Text }"},b=`{
3
12
  headers: { Accept: ContentTypeValues.TEXT_EVENT_STREAM },
4
13
  resultExtractor: JsonEventStreamResultExtractor,
5
- }`;function ie(o){$(o,Ue,ke)}function se(o,e,t=[]){return e.addClass({name:o,isExported:!0,decorators:[{name:"api",arguments:t}]})}function ae(o,e){o.addImplements("ApiMetadataCapable"),o.addConstructor({parameters:[{name:"apiMetadata",type:"ApiMetadata",hasQuestionToken:e===void 0,scope:A.Scope.Public,isReadonly:!0,initializer:e}]})}const Qe="@ahoo-wang/fetcher-eventstream";function ce(o){$(o,Qe,["JsonEventStreamResultExtractor","type JsonServerSentEventStream"])}function Je(o){let e=0,t=0;return o.commands.forEach(n=>{n.path.startsWith(G.ResourceAttributionPathSpec.TENANT)&&(e+=1),n.path.startsWith(G.ResourceAttributionPathSpec.OWNER)&&(t+=1)}),e===0&&t===0?"ResourceAttributionPathSpec.NONE":e>t?"ResourceAttributionPathSpec.TENANT":"ResourceAttributionPathSpec.OWNER"}function ge(o,e,t,n){const r=`${t.contextAlias}/${t.aggregateName}/${n}.ts`;return re(o,e,r)}function Ve(o,e){return`${C(o.aggregateName)}${e}`}function q(o){return o==="delete"?"del":o}const He="x-fetcher-method";function Ke(o,e){const t=o[He];if(t)return t;if(!o.operationId)return;const n=O(o.operationId);for(let r=n.length-1;r>=0;r--){const i=y(n.slice(r));if(!e(i))return i}return y(n)}class Ye{constructor(e){this.context=e,this.apiMetadataCtorInitializer=this.context.currentContextAlias?`{basePath:'${this.context.currentContextAlias}'}`:void 0}defaultParameterRequestType="ParameterRequest";defaultReturnType=Be;apiMetadataCtorInitializer;generate(){this.context.logger.info("Starting API client generation");const e=this.resolveApiTags();this.context.logger.info(`Resolved ${e.size} API client tags: ${Array.from(e.keys()).join(", ")}`);const t=this.groupOperations(e);this.context.logger.info(`Grouped operations into ${t.size} tag groups`),this.generateApiClients(e,t),this.context.logger.success("API client generation completed")}generateApiClients(e,t){this.context.logger.info(`Generating ${t.size} API client classes`);let n=0;for(const[r,i]of t){n++,this.context.logger.progressWithCount(n,t.size,`Generating API client for tag: ${r}`);const s=e.get(r);this.generateApiClient(s,i)}}createApiClientFile(e){let t=e.path;return this.context.currentContextAlias&&(t=h.combineURLs(this.context.currentContextAlias,t)),t=h.combineURLs(t,`${e.name}ApiClient.ts`),this.context.logger.info(`Creating API client file: ${t}`),this.context.getOrCreateSourceFile(t)}generateApiClient(e,t){const n=d(e.name);this.context.logger.info(`Generating API client class: ${n.name}ApiClient with ${t.size} operations`);const r=this.createApiClientFile(n);ie(r),ce(r);const i=se(n.name+"ApiClient",r);R(i,[e.description]),ae(i,this.apiMetadataCtorInitializer),this.context.logger.info(`Processing ${t.size} operations for ${n.name}ApiClient`),t.forEach(s=>{this.processOperation(e,r,i,s)}),this.context.logger.success(`Completed API client: ${n.name}ApiClient`)}getMethodName(e,t){const n=Ke(t,r=>e.getMethod(r)!==void 0);if(!n)throw new Error(`Unable to resolve method name for apiClientClass:${e.getName()}.`);return n}resolveRequestType(e,t){if(!t.requestBody)return this.context.logger.info(`No request body found for operation ${t.operationId}, using default: ${this.defaultParameterRequestType}`),this.defaultParameterRequestType;let n;if(g(t.requestBody)?(this.context.logger.info(`Extracting request body from reference for operation: ${t.operationId}`),n=V(t.requestBody,this.context.openAPI.components)):n=t.requestBody,!n)return this.context.logger.info(`Request body extraction failed for operation ${t.operationId}, using default: ${this.defaultParameterRequestType}`),this.defaultParameterRequestType;if(n.content["multipart/form-data"])return this.context.logger.info(`Detected multipart/form-data content for operation ${t.operationId}, using ParameterRequest<FormData>`),"ParameterRequest<FormData>";if(n.content["application/json"]){const r=n.content["application/json"].schema;if(g(r)){const i=x(r);this.context.logger.info(`Adding import for request body model: ${i.name} from ${i.path}`),f(e,this.context.outputDir,i);const s=`ParameterRequest<${i.name}>`;return this.context.logger.info(`Resolved request type for operation ${t.operationId}: ${s}`),s}}return this.context.logger.info(`Using default request type for operation ${t.operationId}: ${this.defaultParameterRequestType}`),this.defaultParameterRequestType}resolveParameters(e,t,n){const r=$e(n,this.context.openAPI.components).filter(a=>!this.context.isIgnoreApiClientPathParameters(e.name,a.name));this.context.logger.info(`Found ${r.length} path parameters for operation ${n.operationId}`);const i=r.map(a=>{const c=ee(a);return this.context.logger.info(`Adding path parameter: ${a.name} (type: ${c})`),{name:a.name,type:c,hasQuestionToken:!1,decorators:[{name:"path",arguments:[`'${a.name}'`]}]}}),s=this.resolveRequestType(t,n);return this.context.logger.info(`Adding httpRequest parameter: ${s}`),i.push({name:"httpRequest",hasQuestionToken:s===this.defaultParameterRequestType,type:`${s}`,decorators:[{name:"request",arguments:[]}]}),this.context.logger.info("Adding attributes parameter: Record<string, any>"),i.push({name:"attributes",hasQuestionToken:!0,type:"Record<string, any>",decorators:[{name:"attribute",arguments:[]}]}),i}resolveSchemaReturnType(e,t){const n="Promise<any>";if(g(t)){const r=x(t);this.context.logger.info(`Adding import for response model: ${r.name} from ${r.path}`),f(e,this.context.outputDir,r);const i=`Promise<${r.name}>`;return this.context.logger.info(`Resolved reference return type: ${i}`),i}if(!t.type)return this.context.logger.info(`Schema has no type, using default return type: ${n}`),n;if(j(t.type)){const i=`Promise<${P(t.type)}>`;return this.context.logger.info(`Resolved primitive return type: ${i}`),i}return this.context.logger.info(`Using default return type: ${n}`),n}resolveReturnType(e,t){const n=_(t);if(!n)return this.context.logger.info(`No OK response found for operation ${t.operationId}, using default return type: ${this.defaultReturnType.type}`),this.defaultReturnType;const r=Y(n)||he(n);if(r){const s=this.resolveSchemaReturnType(e,r);return this.context.logger.info(`Resolved JSON/wildcard response return type for operation ${t.operationId}: ${s}`),{type:s,metadata:s===Q.type?Q.metadata:void 0}}const i=fe(n);if(i){if(g(i)){const a=v(i,this.context.openAPI.components);if(N(a)&&g(a.items)){const c=x(a.items);this.context.logger.info(`Adding import for event stream model: ${c.name} from ${c.path}`),f(e,this.context.outputDir,c);const l=`Promise<JsonServerSentEventStream<${c.name.includes("ServerSentEvent")?`${c.name}['data']`:c.name}>>`;return this.context.logger.info(`Resolved event stream return type for operation ${t.operationId}: ${l}`),{type:l,metadata:b}}}const s="Promise<JsonServerSentEventStream<any>>";return this.context.logger.info(`Resolved generic event stream return type for operation ${t.operationId}: ${s}`),{type:s,metadata:b}}return this.context.logger.info(`Using default return type for operation ${t.operationId}: ${this.defaultReturnType.type}`),this.defaultReturnType}processOperation(e,t,n,r){this.context.logger.info(`Processing operation: ${r.operation.operationId} (${r.method} ${r.path})`);const i=this.getMethodName(n,r.operation);this.context.logger.info(`Generated method name: ${i}`);const s=this.resolveParameters(e,t,r.operation),a=this.resolveReturnType(t,r.operation),c=a.metadata?{name:q(r.method),arguments:[`'${r.path}'`,a.metadata]}:{name:q(r.method),arguments:[`'${r.path}'`]};this.context.logger.info(`Creating method with ${s.length} parameters, return type: ${a.type}`);const u=n.addMethod({name:i,decorators:[c],parameters:s,returnType:a.type,statements:[`throw autoGeneratedError(${s.map(l=>l.name).join(",")});`]});R(u,[r.operation.summary,r.operation.description,`- operationId: \`${r.operation.operationId}\``,`- path: \`${r.path}\``]),this.context.logger.success(`Operation method generated: ${i}`)}groupOperations(e){this.context.logger.info("Grouping operations by API client tags");const t=new Map;let n=0;for(const[r,i]of Object.entries(this.context.openAPI.paths)){const s=D(i).filter(a=>{if(!a.operation.operationId)return!1;const c=a.operation.tags;return!c||c.length==0?!1:c.every(u=>e.has(u))});this.context.logger.info(`Path ${r}: found ${s.length} valid operations`);for(const a of s)a.operation.tags.forEach(c=>{const u={...a,path:r};t.has(c)||t.set(c,new Set),t.get(c).add(u),n++})}return this.context.logger.info(`Grouped ${n} operations into ${t.size} tag groups`),t}shouldIgnoreTag(e){return e==="wow"||e==="Actuator"||this.isAggregateTag(e)}resolveApiTags(){this.context.logger.info("Resolving API client tags from OpenAPI specification");const e=new Map,t=this.context.openAPI.tags?.length||0;for(const r of Object.values(this.context.openAPI.paths))D(r).forEach(i=>{i.operation.tags?.forEach(s=>{!this.shouldIgnoreTag(s)&&!e.has(s)&&e.set(s,{name:s,description:""})})});let n=0;return this.context.openAPI.tags?.forEach(r=>{this.shouldIgnoreTag(r.name)?this.context.logger.info(`Excluded tag: ${r.name} (wow/Actuator/aggregate)`):(e.set(r.name,r),n++,this.context.logger.info(`Included API client tag: ${r.name}`))}),this.context.logger.info(`Resolved ${n} API client tags from ${t} total tags`),e}isAggregateTag(e){for(const t of this.context.contextAggregates.values())for(const n of t)if(n.aggregate.tag.name===e)return!0;return!1}}class Xe{constructor(e){this.context=e}commandEndpointPathsName="COMMAND_ENDPOINT_PATHS";defaultCommandClientOptionsName="DEFAULT_COMMAND_CLIENT_OPTIONS";generate(){const e=Array.from(this.context.contextAggregates.values()).reduce((n,r)=>n+r.size,0);this.context.logger.info("--- Generating Command Clients ---"),this.context.logger.progress(`Generating command clients for ${e} aggregates`);let t=0;for(const[,n]of this.context.contextAggregates)n.forEach(r=>{t++,this.context.logger.progressWithCount(t,e,`Processing command client for aggregate: ${r.aggregate.aggregateName}`),this.processAggregate(r)});this.context.logger.success("Command client generation completed")}processAggregate(e){this.context.logger.info(`Processing command client for aggregate: ${e.aggregate.aggregateName} in context: ${e.aggregate.contextAlias}`);const t=ge(this.context.project,this.context.outputDir,e.aggregate,"commandClient");this.context.logger.info(`Processing command endpoint paths for ${e.commands.size} commands`),this.processCommandEndpointPaths(t,e),this.context.logger.info(`Creating default command client options: ${this.defaultCommandClientOptionsName}`),t.addVariableStatement({declarationKind:A.VariableDeclarationKind.Const,declarations:[{name:this.defaultCommandClientOptionsName,type:"ApiMetadata",initializer:`{
14
+ }`;function se(n){A(n,Qe,Je)}function ae(n,e,t=[]){return e.addClass({name:n,isExported:!0,decorators:[{name:"api",arguments:t}]})}function ce(n,e){n.addImplements("ApiMetadataCapable"),n.addConstructor({parameters:[{name:"apiMetadata",type:"ApiMetadata",hasQuestionToken:e===void 0,scope:x.Scope.Public,isReadonly:!0,initializer:e}]})}const He="@ahoo-wang/fetcher-eventstream";function ge(n){A(n,He,["JsonEventStreamResultExtractor","type JsonServerSentEventStream"])}function Ke(n){let e=0,t=0;return n.commands.forEach(o=>{o.path.startsWith(_.ResourceAttributionPathSpec.TENANT)&&(e+=1),o.path.startsWith(_.ResourceAttributionPathSpec.OWNER)&&(t+=1)}),e===0&&t===0?"ResourceAttributionPathSpec.NONE":e>t?"ResourceAttributionPathSpec.TENANT":"ResourceAttributionPathSpec.OWNER"}function ue(n,e,t,o){const r=`${t.contextAlias}/${t.aggregateName}/${o}.ts`;return oe(n,e,r)}function Ye(n,e){return`${S(n.aggregateName)}${e}`}function M(n){return n==="delete"?"del":n}const Xe="x-fetcher-method";function Ze(n,e){const t=n[Xe];if(t)return t;if(!n.operationId)return;const o=w(n.operationId);for(let r=o.length-1;r>=0;r--){const i=y(o.slice(r));if(!e(i))return i}return y(o)}class et{constructor(e){this.context=e,this.apiMetadataCtorInitializer=this.context.currentContextAlias?`{basePath:'${this.context.currentContextAlias}'}`:void 0}defaultParameterRequestType="ParameterRequest";defaultReturnType=Ve;apiMetadataCtorInitializer;generate(){this.context.logger.info("Starting API client generation");const e=this.resolveApiTags();this.context.logger.info(`Resolved ${e.size} API client tags: ${Array.from(e.keys()).join(", ")}`);const t=this.groupOperations(e);this.context.logger.info(`Grouped operations into ${t.size} tag groups`),this.generateApiClients(e,t),this.context.logger.success("API client generation completed")}generateApiClients(e,t){this.context.logger.info(`Generating ${t.size} API client classes`);let o=0;for(const[r,i]of t){o++,this.context.logger.progressWithCount(o,t.size,`Generating API client for tag: ${r}`);const s=e.get(r);this.generateApiClient(s,i)}}createApiClientFile(e){let t=e.path;return this.context.currentContextAlias&&(t=h.combineURLs(this.context.currentContextAlias,t)),t=h.combineURLs(t,`${e.name}ApiClient.ts`),this.context.logger.info(`Creating API client file: ${t}`),this.context.getOrCreateSourceFile(t)}generateApiClient(e,t){const o=m(e.name);this.context.logger.info(`Generating API client class: ${o.name}ApiClient with ${t.size} operations`);const r=this.createApiClientFile(o);se(r),ge(r);const i=ae(o.name+"ApiClient",r);v(i,[e.description]),ce(i,this.apiMetadataCtorInitializer),this.context.logger.info(`Processing ${t.size} operations for ${o.name}ApiClient`),t.forEach(s=>{this.processOperation(e,r,i,s)}),this.context.logger.success(`Completed API client: ${o.name}ApiClient`)}getMethodName(e,t){const o=Ze(t,r=>e.getMethod(r)!==void 0);if(!o)throw new Error(`Unable to resolve method name for apiClientClass:${e.getName()}.`);return o}resolveRequestType(e,t){if(!t.requestBody)return this.context.logger.info(`No request body found for operation ${t.operationId}, using default: ${this.defaultParameterRequestType}`),this.defaultParameterRequestType;let o;if(u(t.requestBody)?(this.context.logger.info(`Extracting request body from reference for operation: ${t.operationId}`),o=V(t.requestBody,this.context.openAPI.components)):o=t.requestBody,!o)return this.context.logger.info(`Request body extraction failed for operation ${t.operationId}, using default: ${this.defaultParameterRequestType}`),this.defaultParameterRequestType;if(o.content["multipart/form-data"])return this.context.logger.info(`Detected multipart/form-data content for operation ${t.operationId}, using ParameterRequest<FormData>`),"ParameterRequest<FormData>";if(o.content["application/json"]){const r=o.content["application/json"].schema;if(u(r)){const i=T(r);this.context.logger.info(`Adding import for request body model: ${i.name} from ${i.path}`),f(e,this.context.outputDir,i);const s=`ParameterRequest<${i.name}>`;return this.context.logger.info(`Resolved request type for operation ${t.operationId}: ${s}`),s}}return this.context.logger.info(`Using default request type for operation ${t.operationId}: ${this.defaultParameterRequestType}`),this.defaultParameterRequestType}resolveParameters(e,t,o){const r=Ie(o,this.context.openAPI.components).filter(a=>!this.context.isIgnoreApiClientPathParameters(e.name,a.name));this.context.logger.info(`Found ${r.length} path parameters for operation ${o.operationId}`);const i=r.map(a=>{const c=Z(a);return this.context.logger.info(`Adding path parameter: ${a.name} (type: ${c})`),{name:a.name,type:c,hasQuestionToken:!1,decorators:[{name:"path",arguments:[`'${a.name}'`]}]}}),s=this.resolveRequestType(t,o);return this.context.logger.info(`Adding httpRequest parameter: ${s}`),i.push({name:"httpRequest",hasQuestionToken:s===this.defaultParameterRequestType,type:`${s}`,decorators:[{name:"request",arguments:[]}]}),this.context.logger.info("Adding attributes parameter: Record<string, any>"),i.push({name:"attributes",hasQuestionToken:!0,type:"Record<string, any>",decorators:[{name:"attribute",arguments:[]}]}),i}resolveSchemaReturnType(e,t){const o="Promise<any>";if(u(t)){const r=T(t);this.context.logger.info(`Adding import for response model: ${r.name} from ${r.path}`),f(e,this.context.outputDir,r);const i=`Promise<${r.name}>`;return this.context.logger.info(`Resolved reference return type: ${i}`),i}if(!t.type)return this.context.logger.info(`Schema has no type, using default return type: ${o}`),o;if(X(t.type)){const i=`Promise<${E(t.type)}>`;return this.context.logger.info(`Resolved primitive return type: ${i}`),i}return this.context.logger.info(`Using default return type: ${o}`),o}resolveReturnType(e,t){const o=F(t);if(!o)return this.context.logger.info(`No OK response found for operation ${t.operationId}, using default return type: ${this.defaultReturnType.type}`),this.defaultReturnType;const r=Y(o)||ye(o);if(r){const s=this.resolveSchemaReturnType(e,r);return this.context.logger.info(`Resolved JSON/wildcard response return type for operation ${t.operationId}: ${s}`),{type:s,metadata:s===Q.type?Q.metadata:void 0}}const i=he(o);if(i){if(u(i)){const a=I(i,this.context.openAPI.components);if(O(a)&&u(a.items)){const c=T(a.items);this.context.logger.info(`Adding import for event stream model: ${c.name} from ${c.path}`),f(e,this.context.outputDir,c);const l=`Promise<JsonServerSentEventStream<${c.name.includes("ServerSentEvent")?`${c.name}['data']`:c.name}>>`;return this.context.logger.info(`Resolved event stream return type for operation ${t.operationId}: ${l}`),{type:l,metadata:b}}}const s="Promise<JsonServerSentEventStream<any>>";return this.context.logger.info(`Resolved generic event stream return type for operation ${t.operationId}: ${s}`),{type:s,metadata:b}}return this.context.logger.info(`Using default return type for operation ${t.operationId}: ${this.defaultReturnType.type}`),this.defaultReturnType}processOperation(e,t,o,r){this.context.logger.info(`Processing operation: ${r.operation.operationId} (${r.method} ${r.path})`);const i=this.getMethodName(o,r.operation);this.context.logger.info(`Generated method name: ${i}`);const s=this.resolveParameters(e,t,r.operation),a=this.resolveReturnType(t,r.operation),c=a.metadata?{name:M(r.method),arguments:[`'${r.path}'`,a.metadata]}:{name:M(r.method),arguments:[`'${r.path}'`]};this.context.logger.info(`Creating method with ${s.length} parameters, return type: ${a.type}`);const g=o.addMethod({name:i,decorators:[c],parameters:s,returnType:a.type,statements:[`throw autoGeneratedError(${s.map(l=>l.name).join(",")});`]});v(g,[r.operation.summary,r.operation.description,`- operationId: \`${r.operation.operationId}\``,`- path: \`${r.path}\``]),this.context.logger.success(`Operation method generated: ${i}`)}groupOperations(e){this.context.logger.info("Grouping operations by API client tags");const t=new Map;let o=0;for(const[r,i]of Object.entries(this.context.openAPI.paths)){const s=N(i).filter(a=>{if(!a.operation.operationId)return!1;const c=a.operation.tags;return!c||c.length==0?!1:c.every(g=>e.has(g))});this.context.logger.info(`Path ${r}: found ${s.length} valid operations`);for(const a of s)a.operation.tags.forEach(c=>{const g={...a,path:r};t.has(c)||t.set(c,new Set),t.get(c).add(g),o++})}return this.context.logger.info(`Grouped ${o} operations into ${t.size} tag groups`),t}shouldIgnoreTag(e){return e==="wow"||e==="Actuator"||this.isAggregateTag(e)}resolveApiTags(){this.context.logger.info("Resolving API client tags from OpenAPI specification");const e=new Map,t=this.context.openAPI.tags?.length||0;for(const r of Object.values(this.context.openAPI.paths))N(r).forEach(i=>{i.operation.tags?.forEach(s=>{!this.shouldIgnoreTag(s)&&!e.has(s)&&e.set(s,{name:s,description:""})})});let o=0;return this.context.openAPI.tags?.forEach(r=>{this.shouldIgnoreTag(r.name)?this.context.logger.info(`Excluded tag: ${r.name} (wow/Actuator/aggregate)`):(e.set(r.name,r),o++,this.context.logger.info(`Included API client tag: ${r.name}`))}),this.context.logger.info(`Resolved ${o} API client tags from ${t} total tags`),e}isAggregateTag(e){for(const t of this.context.contextAggregates.values())for(const o of t)if(o.aggregate.tag.name===e)return!0;return!1}}class tt{constructor(e){this.context=e}commandEndpointPathsName="COMMAND_ENDPOINT_PATHS";defaultCommandClientOptionsName="DEFAULT_COMMAND_CLIENT_OPTIONS";generate(){const e=Array.from(this.context.contextAggregates.values()).reduce((o,r)=>o+r.size,0);this.context.logger.info("--- Generating Command Clients ---"),this.context.logger.progress(`Generating command clients for ${e} aggregates`);let t=0;for(const[,o]of this.context.contextAggregates)o.forEach(r=>{t++,this.context.logger.progressWithCount(t,e,`Processing command client for aggregate: ${r.aggregate.aggregateName}`),this.processAggregate(r)});this.context.logger.success("Command client generation completed")}processAggregate(e){this.context.logger.info(`Processing command client for aggregate: ${e.aggregate.aggregateName} in context: ${e.aggregate.contextAlias}`);const t=ue(this.context.project,this.context.outputDir,e.aggregate,"commandClient");this.context.logger.info(`Processing command endpoint paths for ${e.commands.size} commands`),this.processCommandEndpointPaths(t,e),this.context.logger.info(`Creating default command client options: ${this.defaultCommandClientOptionsName}`),t.addVariableStatement({declarationKind:x.VariableDeclarationKind.Const,declarations:[{name:this.defaultCommandClientOptionsName,type:"ApiMetadata",initializer:`{
6
15
  basePath: '${e.aggregate.contextAlias}'
7
- }`}],isExported:!1}),this.context.logger.info(`Adding imports from ${I}: CommandRequest, CommandResult, CommandResultEventStream, DeleteAggregate, RecoverAggregate`),t.addImportDeclaration({moduleSpecifier:I,namedImports:["CommandRequest","CommandResult","CommandResultEventStream","DeleteAggregate","RecoverAggregate"],isTypeOnly:!0}),this.context.logger.info("Adding import from @ahoo-wang/fetcher-eventstream: JsonEventStreamResultExtractor"),ce(t),this.context.logger.info("Adding import from @ahoo-wang/fetcher: ContentTypeValues"),$(t,"@ahoo-wang/fetcher",["ContentTypeValues"]),this.context.logger.info("Adding imports from @ahoo-wang/fetcher-decorator: ApiMetadata types and decorators"),ie(t),this.context.logger.info("Generating standard command client class"),this.processCommandClient(t,e),this.context.logger.info("Generating stream command client class"),this.processCommandClient(t,e,!0),this.context.logger.success(`Command client generation completed for aggregate: ${e.aggregate.aggregateName}`)}processCommandEndpointPaths(e,t){this.context.logger.info(`Creating command endpoint paths enum: ${this.commandEndpointPathsName}`);const n=e.addEnum({name:this.commandEndpointPathsName});t.commands.forEach(r=>{this.context.logger.info(`Adding command endpoint: ${r.name.toUpperCase()} = '${r.path}'`),n.addMember({name:r.name.toUpperCase(),initializer:`'${r.path}'`})}),this.context.logger.success(`Command endpoint paths enum created with ${t.commands.size} entries`)}getEndpointPath(e){return`${this.commandEndpointPathsName}.${e.name.toUpperCase()}`}processCommandClient(e,t,n=!1){let r="CommandClient",i=[],s="Promise<CommandResult>";n&&(r="Stream"+r,i=["''",b],s="Promise<CommandResultEventStream>");const a=Ve(t.aggregate,r),c=se(a,e,i);ae(c,this.defaultCommandClientOptionsName),t.commands.forEach(u=>{this.processCommandMethod(t,e,c,u,s)})}resolveParameters(e,t,n){const r=d(n.schema.key);this.context.logger.info(`Adding import for command model: ${r.name} from path: ${r.path}`),f(t,this.context.outputDir,r);const i=n.pathParameters.filter(s=>!this.context.isIgnoreCommandClientPathParameters(e.name,s.name)).map(s=>{const a=ee(s);return this.context.logger.info(`Adding path parameter: ${s.name} (type: ${a})`),{name:s.name,type:a,hasQuestionToken:!1,decorators:[{name:"path",arguments:[`'${s.name}'`]}]}});return this.context.logger.info(`Adding command request parameter: commandRequest (type: CommandRequest<${r.name}>)`),i.push({name:"commandRequest",hasQuestionToken:Pe(n.schema.schema),type:`CommandRequest<${r.name}>`,decorators:[{name:"request",arguments:[]}]}),this.context.logger.info("Adding attributes parameter: attributes (type: Record<string, any>)"),i.push({name:"attributes",hasQuestionToken:!0,type:"Record<string, any>",decorators:[{name:"attribute",arguments:[]}]}),i}processCommandMethod(e,t,n,r,i){this.context.logger.info(`Generating command method: ${y(r.name)} for command: ${r.name}`),this.context.logger.info(`Command method details: HTTP ${r.method}, path: ${r.path}, return type: ${i}`);const s=this.resolveParameters(e.aggregate.tag,t,r),a=n.addMethod({name:y(r.name),decorators:[{name:q(r.method),arguments:[`${this.getEndpointPath(r)}`]}],parameters:s,returnType:i,statements:[`throw autoGeneratedError(${s.map(c=>c.name).join(",")});`]});this.context.logger.info(`Adding JSDoc documentation for method: ${y(r.name)}`),R(a,[r.summary,r.description,`- operationId: \`${r.operation.operationId}\``,`- path: \`${r.path}\``]),this.context.logger.success(`Command method generated: ${y(r.name)}`)}}class Ze{constructor(e){this.context=e}generate(){const e=Array.from(this.context.contextAggregates.values()).reduce((n,r)=>n+r.size,0);this.context.logger.info("--- Generating Query Clients ---"),this.context.logger.progress(`Generating query clients for ${e} aggregates`);let t=0;for(const[,n]of this.context.contextAggregates)n.forEach(r=>{t++,this.context.logger.progressWithCount(t,e,`Processing query client for aggregate: ${r.aggregate.aggregateName}`),this.processQueryClient(r)});this.context.logger.success("Query client generation completed")}createClientFilePath(e,t){return ge(this.context.project,this.context.outputDir,e,t)}processQueryClient(e){const t=this.createClientFilePath(e.aggregate,"queryClient");this.context.logger.info(`Processing query client for aggregate: ${e.aggregate.aggregateName} in context: ${e.aggregate.contextAlias}`),this.context.logger.info(`Adding imports from ${I}: QueryClientFactory, QueryClientOptions, ResourceAttributionPathSpec`),t.addImportDeclaration({moduleSpecifier:I,namedImports:["QueryClientFactory","QueryClientOptions","ResourceAttributionPathSpec"]});const n="DEFAULT_QUERY_CLIENT_OPTIONS";this.context.logger.info(`Creating default query client options: ${n}`),t.addVariableStatement({declarationKind:A.VariableDeclarationKind.Const,declarations:[{name:n,type:"QueryClientOptions",initializer:`{
16
+ }`}],isExported:!1}),this.context.logger.info(`Adding imports from ${P}: CommandRequest, CommandResult, CommandResultEventStream, DeleteAggregate, RecoverAggregate`),t.addImportDeclaration({moduleSpecifier:P,namedImports:["CommandRequest","CommandResult","CommandResultEventStream","DeleteAggregate","RecoverAggregate"],isTypeOnly:!0}),this.context.logger.info("Adding import from @ahoo-wang/fetcher-eventstream: JsonEventStreamResultExtractor"),ge(t),this.context.logger.info("Adding import from @ahoo-wang/fetcher: ContentTypeValues"),A(t,"@ahoo-wang/fetcher",["ContentTypeValues"]),this.context.logger.info("Adding imports from @ahoo-wang/fetcher-decorator: ApiMetadata types and decorators"),se(t),this.context.logger.info("Generating standard command client class"),this.processCommandClient(t,e),this.context.logger.info("Generating stream command client class"),this.processCommandClient(t,e,!0),this.context.logger.success(`Command client generation completed for aggregate: ${e.aggregate.aggregateName}`)}processCommandEndpointPaths(e,t){this.context.logger.info(`Creating command endpoint paths enum: ${this.commandEndpointPathsName}`);const o=e.addEnum({name:this.commandEndpointPathsName});t.commands.forEach(r=>{this.context.logger.info(`Adding command endpoint: ${r.name.toUpperCase()} = '${r.path}'`),o.addMember({name:r.name.toUpperCase(),initializer:`'${r.path}'`})}),this.context.logger.success(`Command endpoint paths enum created with ${t.commands.size} entries`)}getEndpointPath(e){return`${this.commandEndpointPathsName}.${e.name.toUpperCase()}`}processCommandClient(e,t,o=!1){let r="CommandClient",i=[],s="Promise<CommandResult>";o&&(r="Stream"+r,i=["''",b],s="Promise<CommandResultEventStream>");const a=Ye(t.aggregate,r),c=ae(a,e,i);ce(c,this.defaultCommandClientOptionsName),t.commands.forEach(g=>{this.processCommandMethod(t,e,c,g,s)})}resolveParameters(e,t,o){const r=m(o.schema.key);this.context.logger.info(`Adding import for command model: ${r.name} from path: ${r.path}`),f(t,this.context.outputDir,r);const i=o.pathParameters.filter(s=>!this.context.isIgnoreCommandClientPathParameters(e.name,s.name)).map(s=>{const a=Z(s);return this.context.logger.info(`Adding path parameter: ${s.name} (type: ${a})`),{name:s.name,type:a,hasQuestionToken:!1,decorators:[{name:"path",arguments:[`'${s.name}'`]}]}});return this.context.logger.info(`Adding command request parameter: commandRequest (type: CommandRequest<${r.name}>)`),i.push({name:"commandRequest",hasQuestionToken:Te(o.schema.schema),type:`CommandRequest<${r.name}>`,decorators:[{name:"request",arguments:[]}]}),this.context.logger.info("Adding attributes parameter: attributes (type: Record<string, any>)"),i.push({name:"attributes",hasQuestionToken:!0,type:"Record<string, any>",decorators:[{name:"attribute",arguments:[]}]}),i}processCommandMethod(e,t,o,r,i){this.context.logger.info(`Generating command method: ${y(r.name)} for command: ${r.name}`),this.context.logger.info(`Command method details: HTTP ${r.method}, path: ${r.path}, return type: ${i}`);const s=this.resolveParameters(e.aggregate.tag,t,r),a=o.addMethod({name:y(r.name),decorators:[{name:M(r.method),arguments:[`${this.getEndpointPath(r)}`]}],parameters:s,returnType:i,statements:[`throw autoGeneratedError(${s.map(c=>c.name).join(",")});`]});this.context.logger.info(`Adding JSDoc documentation for method: ${y(r.name)}`),v(a,[r.summary,r.description,`- operationId: \`${r.operation.operationId}\``,`- path: \`${r.path}\``]),this.context.logger.success(`Command method generated: ${y(r.name)}`)}}class nt{constructor(e){this.context=e}generate(){const e=Array.from(this.context.contextAggregates.values()).reduce((o,r)=>o+r.size,0);this.context.logger.info("--- Generating Query Clients ---"),this.context.logger.progress(`Generating query clients for ${e} aggregates`);let t=0;for(const[,o]of this.context.contextAggregates)o.forEach(r=>{t++,this.context.logger.progressWithCount(t,e,`Processing query client for aggregate: ${r.aggregate.aggregateName}`),this.processQueryClient(r)});this.context.logger.success("Query client generation completed")}createClientFilePath(e,t){return ue(this.context.project,this.context.outputDir,e,t)}processQueryClient(e){const t=this.createClientFilePath(e.aggregate,"queryClient");this.context.logger.info(`Processing query client for aggregate: ${e.aggregate.aggregateName} in context: ${e.aggregate.contextAlias}`),this.context.logger.info(`Adding imports from ${P}: QueryClientFactory, QueryClientOptions, ResourceAttributionPathSpec`),t.addImportDeclaration({moduleSpecifier:P,namedImports:["QueryClientFactory","QueryClientOptions","ResourceAttributionPathSpec"]});const o="DEFAULT_QUERY_CLIENT_OPTIONS";this.context.logger.info(`Creating default query client options: ${o}`),t.addVariableStatement({declarationKind:x.VariableDeclarationKind.Const,declarations:[{name:o,type:"QueryClientOptions",initializer:`{
8
17
  contextAlias: '${e.aggregate.contextAlias}',
9
18
  aggregateName: '${e.aggregate.aggregateName}',
10
- resourceAttribution: ${Je(e)},
11
- }`}],isExported:!1});const r=[];this.context.logger.info(`Processing ${e.events.size} domain events for aggregate: ${e.aggregate.aggregateName}`);for(const l of e.events.values()){const p=d(l.schema.key);this.context.logger.info(`Adding import for event model: ${p.name} from path: ${p.path}`),f(t,this.context.outputDir,p),r.push(p)}const i="DOMAIN_EVENT_TYPES",s=r.map(l=>l.name).join(" | ");this.context.logger.info(`Creating domain event types union: ${i} = ${s}`),t.addTypeAlias({name:i,type:s});const a=`${y(e.aggregate.aggregateName)}QueryClientFactory`,c=d(e.state.key),u=d(e.fields.key);this.context.logger.info(`Adding import for state model: ${c.name} from path: ${c.path}`),f(t,this.context.outputDir,c),this.context.logger.info(`Adding import for fields model: ${u.name} from path: ${u.path}`),f(t,this.context.outputDir,u),this.context.logger.info(`Creating query client factory: ${a}`),t.addVariableStatement({declarationKind:A.VariableDeclarationKind.Const,declarations:[{name:a,initializer:`new QueryClientFactory<${c.name}, ${u.name} | string, ${i}>(${n})`}],isExported:!0}),this.context.logger.success(`Query client generation completed for aggregate: ${e.aggregate.aggregateName}`)}}class et{constructor(e){this.context=e,this.queryClientGenerator=new Ze(e),this.commandClientGenerator=new Xe(e),this.apiClientGenerator=new Ye(e)}queryClientGenerator;commandClientGenerator;apiClientGenerator;generate(){this.context.logger.info("--- Generating Clients ---"),this.context.logger.progress(`Generating clients for ${this.context.contextAggregates.size} bounded contexts`);let e=0;for(const[t]of this.context.contextAggregates)e++,this.context.logger.progressWithCount(e,this.context.contextAggregates.size,`Processing bounded context: ${t}`,1),this.processBoundedContext(t);this.queryClientGenerator.generate(),this.commandClientGenerator.generate(),this.apiClientGenerator.generate(),this.context.logger.success("Client generation completed")}processBoundedContext(e){const t=`${e}/boundedContext.ts`;this.context.logger.info(`Creating bounded context file: ${t}`);const n=this.context.getOrCreateSourceFile(t);this.context.logger.info(`Adding bounded context alias constant: BOUNDED_CONTEXT_ALIAS = '${e}'`),n.addStatements(`export const BOUNDED_CONTEXT_ALIAS = '${e}';`),this.context.logger.success(`Bounded context file created successfully: ${t}`)}}class tt{project;openAPI;outputDir;contextAggregates;logger;config;defaultIgnorePathParameters=["tenantId","ownerId"];currentContextAlias;constructor(e){this.project=e.project,this.openAPI=e.openAPI,this.outputDir=e.outputDir,this.contextAggregates=e.contextAggregates,this.logger=e.logger,this.config=e.config??{},this.currentContextAlias=this.openAPI.info["x-wow-context-alias"]}getOrCreateSourceFile(e){return re(this.project,this.outputDir,e)}isIgnoreApiClientPathParameters(e,t){return(this.config.apiClients?.[e]?.ignorePathParameters??this.defaultIgnorePathParameters).includes(t)}isIgnoreCommandClientPathParameters(e,t){return this.defaultIgnorePathParameters.includes(t)}}const ue="./fetcher-generator.config.json";class nt{constructor(e){this.options=e,this.project=new A.Project(e),this.options.logger.info("Project instance created with tsConfigFilePath: ",this.options.tsConfigFilePath)}project;async generate(){this.options.logger.info("Starting code generation from OpenAPI specification"),this.options.logger.info(`Input path: ${this.options.inputPath}`),this.options.logger.info(`Output directory: ${this.options.outputDir}`),this.options.logger.info("Parsing OpenAPI specification");const e=await Se(this.options.inputPath);this.options.logger.info("OpenAPI specification parsed successfully"),this.options.logger.info("Resolving bounded context aggregates");const n=new We(e).resolve();this.options.logger.info(`Resolved ${n.size} bounded context aggregates`);const r=this.options.configPath??ue;let i={};try{this.options.logger.info("Parsing configuration file:",r),i=await ve(r)}catch(u){this.options.logger.info("Configuration file parsing failed ",u)}const s=new tt({openAPI:e,project:this.project,outputDir:this.options.outputDir,contextAggregates:n,logger:this.options.logger,config:i});this.options.logger.info("Generating models"),new ze(s).generate(),this.options.logger.info("Models generated successfully"),this.options.logger.info("Generating clients"),new et(s).generate(),this.options.logger.info("Clients generated successfully"),this.options.logger.info("Generating index files"),this.generateIndex(),this.options.logger.info("Index files generated successfully"),this.options.logger.info("Optimizing source files"),this.optimizeSourceFiles(),this.options.logger.info("Source files optimized successfully"),this.options.logger.info("Saving project to disk"),await this.project.save(),this.options.logger.info("Code generation completed successfully")}generateIndex(){this.options.logger.info(`Generating index files for output directory: ${this.options.outputDir}`);const e=this.project.getDirectory(this.options.outputDir);if(!e){this.options.logger.info("Output directory not found, skipping index generation");return}this.processDirectory(e),this.generateIndexForDirectory(e),this.options.logger.info("Index file generation completed")}processDirectory(e){const t=e.getDirectories();this.options.logger.info(`Processing ${t.length} subdirectories`);for(const n of t)this.options.logger.info(`Processing subdirectory: ${n.getPath()}`),this.generateIndexForDirectory(n),this.processDirectory(n)}generateIndexForDirectory(e){const t=e.getPath();this.options.logger.info(`Generating index for directory: ${t}`);const n=e.getSourceFiles().filter(a=>a.getBaseName().endsWith(".ts")&&a.getBaseName()!=="index.ts"),r=e.getDirectories();if(this.options.logger.info(`Found ${n.length} TypeScript files and ${r.length} subdirectories in ${t}`),n.length===0&&r.length===0){this.options.logger.info(`No files or subdirectories to export in ${t}, skipping index generation`);return}const i=`${t}/index.ts`;this.options.logger.info(`Creating/updating index file: ${i}`);const s=this.project.getSourceFile(i)||this.project.createSourceFile(i,"",{overwrite:!0});s.removeText();for(const a of n){const c=`./${a.getBaseNameWithoutExtension()}`;this.options.logger.info(`Adding export for file: ${c}`),s.addExportDeclaration({moduleSpecifier:c,isTypeOnly:!1,namedExports:[]})}for(const a of r){const c=`./${a.getBaseName()}`;this.options.logger.info(`Adding export for subdirectory: ${c}`),s.addExportDeclaration({moduleSpecifier:c,isTypeOnly:!1,namedExports:[]})}this.options.logger.info(`Index file generated for ${t} with ${n.length+r.length} exports`)}optimizeSourceFiles(){const e=this.project.getSourceFiles();this.options.logger.info(`Optimizing ${e.length} source files`),e.forEach((t,n)=>{this.options.logger.info(`Optimizing file ${n+1}/${e.length}`),t.formatText(),t.organizeImports(),t.fixMissingImports()}),this.options.logger.info("All source files optimized")}}exports.CodeGenerator=nt;exports.DEFAULT_CONFIG_PATH=ue;
19
+ resourceAttribution: ${Ke(e)},
20
+ }`}],isExported:!1});const r=[];this.context.logger.info(`Processing ${e.events.size} domain events for aggregate: ${e.aggregate.aggregateName}`);for(const l of e.events.values()){const p=m(l.schema.key);this.context.logger.info(`Adding import for event model: ${p.name} from path: ${p.path}`),f(t,this.context.outputDir,p),r.push(p)}const i="DOMAIN_EVENT_TYPES",s=r.map(l=>l.name).join(" | ");this.context.logger.info(`Creating domain event types union: ${i} = ${s}`),t.addTypeAlias({name:i,type:s});const a=`${y(e.aggregate.aggregateName)}QueryClientFactory`,c=m(e.state.key),g=m(e.fields.key);this.context.logger.info(`Adding import for state model: ${c.name} from path: ${c.path}`),f(t,this.context.outputDir,c),this.context.logger.info(`Adding import for fields model: ${g.name} from path: ${g.path}`),f(t,this.context.outputDir,g),this.context.logger.info(`Creating query client factory: ${a}`),t.addVariableStatement({declarationKind:x.VariableDeclarationKind.Const,declarations:[{name:a,initializer:`new QueryClientFactory<${c.name}, ${g.name} | string, ${i}>(${o})`}],isExported:!0}),this.context.logger.success(`Query client generation completed for aggregate: ${e.aggregate.aggregateName}`)}}class ot{constructor(e){this.context=e,this.queryClientGenerator=new nt(e),this.commandClientGenerator=new tt(e),this.apiClientGenerator=new et(e)}queryClientGenerator;commandClientGenerator;apiClientGenerator;generate(){this.context.logger.info("--- Generating Clients ---"),this.context.logger.progress(`Generating clients for ${this.context.contextAggregates.size} bounded contexts`);let e=0;for(const[t]of this.context.contextAggregates)e++,this.context.logger.progressWithCount(e,this.context.contextAggregates.size,`Processing bounded context: ${t}`,1),this.processBoundedContext(t);this.queryClientGenerator.generate(),this.commandClientGenerator.generate(),this.apiClientGenerator.generate(),this.context.logger.success("Client generation completed")}processBoundedContext(e){const t=`${e}/boundedContext.ts`;this.context.logger.info(`Creating bounded context file: ${t}`);const o=this.context.getOrCreateSourceFile(t);this.context.logger.info(`Adding bounded context alias constant: BOUNDED_CONTEXT_ALIAS = '${e}'`),o.addStatements(`export const BOUNDED_CONTEXT_ALIAS = '${e}';`),this.context.logger.success(`Bounded context file created successfully: ${t}`)}}class rt{project;openAPI;outputDir;contextAggregates;logger;config;defaultIgnorePathParameters=["tenantId","ownerId"];currentContextAlias;constructor(e){this.project=e.project,this.openAPI=e.openAPI,this.outputDir=e.outputDir,this.contextAggregates=e.contextAggregates,this.logger=e.logger,this.config=e.config??{},this.currentContextAlias=this.openAPI.info["x-wow-context-alias"]}getOrCreateSourceFile(e){return oe(this.project,this.outputDir,e)}isIgnoreApiClientPathParameters(e,t){return(this.config.apiClients?.[e]?.ignorePathParameters??this.defaultIgnorePathParameters).includes(t)}isIgnoreCommandClientPathParameters(e,t){return this.defaultIgnorePathParameters.includes(t)}}const le="./fetcher-generator.config.json";class it{constructor(e){this.options=e,this.project=new x.Project(e),this.options.logger.info("Project instance created with tsConfigFilePath: ",this.options.tsConfigFilePath)}project;async generate(){this.options.logger.info("Starting code generation from OpenAPI specification"),this.options.logger.info(`Input path: ${this.options.inputPath}`),this.options.logger.info(`Output directory: ${this.options.outputDir}`),this.options.logger.info("Parsing OpenAPI specification");const e=await Re(this.options.inputPath);this.options.logger.info("OpenAPI specification parsed successfully"),this.options.logger.info("Resolving bounded context aggregates");const o=new Le(e).resolve();this.options.logger.info(`Resolved ${o.size} bounded context aggregates`);const r=this.options.configPath??le;let i={};try{this.options.logger.info("Parsing configuration file:",r),i=await we(r)}catch(g){this.options.logger.info("Configuration file parsing failed ",g)}const s=new rt({openAPI:e,project:this.project,outputDir:this.options.outputDir,contextAggregates:o,logger:this.options.logger,config:i});this.options.logger.info("Generating models"),new Ue(s).generate(),this.options.logger.info("Models generated successfully"),this.options.logger.info("Generating clients"),new ot(s).generate(),this.options.logger.info("Clients generated successfully"),this.options.logger.info("Generating index files"),this.generateIndex(),this.options.logger.info("Index files generated successfully"),this.options.logger.info("Optimizing source files"),this.optimizeSourceFiles(),this.options.logger.info("Source files optimized successfully"),this.options.logger.info("Saving project to disk"),await this.project.save(),this.options.logger.info("Code generation completed successfully")}generateIndex(){this.options.logger.info(`Generating index files for output directory: ${this.options.outputDir}`);const e=this.project.getDirectory(this.options.outputDir);if(!e){this.options.logger.info("Output directory not found, skipping index generation");return}this.processDirectory(e),this.generateIndexForDirectory(e),this.options.logger.info("Index file generation completed")}processDirectory(e){const t=e.getDirectories();this.options.logger.info(`Processing ${t.length} subdirectories`);for(const o of t)this.options.logger.info(`Processing subdirectory: ${o.getPath()}`),this.generateIndexForDirectory(o),this.processDirectory(o)}generateIndexForDirectory(e){const t=e.getPath();this.options.logger.info(`Generating index for directory: ${t}`);const o=e.getSourceFiles().filter(a=>a.getBaseName().endsWith(".ts")&&a.getBaseName()!=="index.ts"),r=e.getDirectories();if(this.options.logger.info(`Found ${o.length} TypeScript files and ${r.length} subdirectories in ${t}`),o.length===0&&r.length===0){this.options.logger.info(`No files or subdirectories to export in ${t}, skipping index generation`);return}const i=`${t}/index.ts`;this.options.logger.info(`Creating/updating index file: ${i}`);const s=this.project.getSourceFile(i)||this.project.createSourceFile(i,"",{overwrite:!0});s.removeText();for(const a of o){const c=`./${a.getBaseNameWithoutExtension()}`;this.options.logger.info(`Adding export for file: ${c}`),s.addExportDeclaration({moduleSpecifier:c,isTypeOnly:!1,namedExports:[]})}for(const a of r){const c=`./${a.getBaseName()}`;this.options.logger.info(`Adding export for subdirectory: ${c}`),s.addExportDeclaration({moduleSpecifier:c,isTypeOnly:!1,namedExports:[]})}this.options.logger.info(`Index file generated for ${t} with ${o.length+r.length} exports`)}optimizeSourceFiles(){const e=this.project.getSourceFiles();this.options.logger.info(`Optimizing ${e.length} source files`),e.forEach((t,o)=>{this.options.logger.info(`Optimizing file ${o+1}/${e.length}`),t.formatText(),t.organizeImports(),t.fixMissingImports()}),this.options.logger.info("All source files optimized")}}exports.CodeGenerator=it;exports.DEFAULT_CONFIG_PATH=le;
12
21
  //# sourceMappingURL=index.cjs.map