@ahoo-wang/fetcher-generator 2.1.1 → 2.2.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/dist/index.js CHANGED
@@ -1,70 +1,73 @@
1
- import { VariableDeclarationKind as S, Scope as k } from "ts-morph";
1
+ import { VariableDeclarationKind as O, Scope as L } from "ts-morph";
2
2
  import { parse as Q } from "yaml";
3
- import { readFile as K } from "fs";
4
- import { ContentTypeValues as T, combineURLs as C } from "@ahoo-wang/fetcher";
5
- import { ResourceAttributionPathSpec as b } from "@ahoo-wang/fetcher-wow";
6
- function d(t) {
7
- return t.$ref.split("/").pop();
3
+ import * as v from "fs";
4
+ import { readFile as k } from "fs";
5
+ import { ContentTypeValues as I, combineURLs as q } from "@ahoo-wang/fetcher";
6
+ import * as K from "path";
7
+ import { join as U, relative as J } from "path";
8
+ import { ResourceAttributionPathSpec as R } from "@ahoo-wang/fetcher-wow";
9
+ function f(n) {
10
+ return n.$ref.split("/").pop();
8
11
  }
9
- function R(t, e) {
10
- const n = d(t);
11
- return e.schemas?.[n];
12
+ function S(n, e) {
13
+ const t = f(n);
14
+ return e.schemas?.[t];
12
15
  }
13
- function J(t, e) {
14
- const n = d(t);
15
- return e.requestBodies?.[n];
16
+ function V(n, e) {
17
+ const t = f(n);
18
+ return e.requestBodies?.[t];
16
19
  }
17
- function U(t, e) {
18
- const n = d(t);
19
- return e.parameters?.[n];
20
+ function H(n, e) {
21
+ const t = f(n);
22
+ return e.parameters?.[t];
20
23
  }
21
- function y(t, e) {
24
+ function C(n, e) {
22
25
  return {
23
- key: d(t),
24
- schema: R(t, e)
26
+ key: f(n),
27
+ schema: S(n, e)
25
28
  };
26
29
  }
27
- const $ = /[-_\s.]+|(?=[A-Z])/;
28
- function P(t) {
29
- if (t === "" || t.length === 0)
30
+ const b = /[-_\s.]+|(?=[A-Z])/;
31
+ function w(n) {
32
+ if (n === "" || n.length === 0)
30
33
  return "";
31
34
  let e;
32
- return Array.isArray(t) ? e = t.flatMap((n) => n.split($)) : e = t.split($), e.filter((n) => n.length > 0).map((n) => {
33
- if (n.length === 0) return "";
34
- const r = n.charAt(0), o = n.slice(1);
35
- return (/[a-zA-Z]/.test(r) ? r.toUpperCase() : r) + o.toLowerCase();
35
+ return Array.isArray(n) ? e = n.flatMap((t) => t.split(b)) : e = n.split(b), e.filter((t) => t.length > 0).map((t) => {
36
+ if (t.length === 0) return "";
37
+ const o = t.charAt(0), r = t.slice(1);
38
+ return (/[a-zA-Z]/.test(o) ? o.toUpperCase() : o) + r.toLowerCase();
36
39
  }).join("");
37
40
  }
38
- function q(t) {
39
- const e = P(t);
41
+ function h(n) {
42
+ const e = w(n);
40
43
  return e.charAt(0).toLowerCase() + e.slice(1);
41
44
  }
42
- function V(t) {
43
- return t.startsWith("http://") || t.startsWith("https://") ? z(t) : H(t);
45
+ function Y(n) {
46
+ return n.startsWith("http://") || n.startsWith("https://") ? X(n) : Z(n);
44
47
  }
45
- async function z(t) {
46
- return await (await fetch(t)).text();
48
+ async function X(n) {
49
+ return await (await fetch(n)).text();
47
50
  }
48
- function H(t) {
49
- return new Promise((e, n) => {
50
- K(t, "utf-8", (r, o) => {
51
- r ? n(r) : e(o);
51
+ function Z(n) {
52
+ return new Promise((e, t) => {
53
+ k(n, "utf-8", (o, r) => {
54
+ o ? t(o) : e(r);
52
55
  });
53
56
  });
54
57
  }
55
- async function Y(t) {
56
- const e = await V(t);
57
- switch (Z(e)) {
58
+ async function ee(n) {
59
+ const e = await Y(n);
60
+ switch (te(e)) {
58
61
  case "json":
59
62
  return JSON.parse(e);
60
63
  case "yaml":
61
64
  return Q(e);
62
65
  default:
63
- throw new Error(`Unsupported file format: ${t}`);
66
+ throw new Error(`Unsupported file format: ${n}`);
64
67
  }
65
68
  }
66
- function Z(t) {
67
- const e = t.trimStart();
69
+ function te(n) {
70
+ const e = n.trimStart();
68
71
  if (e.startsWith("{") || e.startsWith("["))
69
72
  return "json";
70
73
  if (e.startsWith("-") || e.startsWith("%YAML"))
@@ -77,69 +80,69 @@ function Z(t) {
77
80
  }
78
81
  throw new Error("Unable to infer file format");
79
82
  }
80
- function u(t) {
81
- return !!(t && typeof t == "object" && "$ref" in t);
83
+ function g(n) {
84
+ return !!(n && typeof n == "object" && "$ref" in n);
82
85
  }
83
- function X(t) {
84
- return !t || u(t) || !t.content ? void 0 : t.content[T.APPLICATION_JSON]?.schema;
86
+ function oe(n) {
87
+ return !n || g(n) || !n.content ? void 0 : n.content[I.APPLICATION_JSON]?.schema;
85
88
  }
86
- function ee(t) {
89
+ function ne(n) {
87
90
  return [
88
- { method: "get", operation: t.get },
89
- { method: "put", operation: t.put },
90
- { method: "post", operation: t.post },
91
- { method: "delete", operation: t.delete },
92
- { method: "options", operation: t.options },
93
- { method: "head", operation: t.head },
94
- { method: "patch", operation: t.patch },
95
- { method: "trace", operation: t.trace }
91
+ { method: "get", operation: n.get },
92
+ { method: "put", operation: n.put },
93
+ { method: "post", operation: n.post },
94
+ { method: "delete", operation: n.delete },
95
+ { method: "options", operation: n.options },
96
+ { method: "head", operation: n.head },
97
+ { method: "patch", operation: n.patch },
98
+ { method: "trace", operation: n.trace }
96
99
  ].filter(({ operation: e }) => e !== void 0);
97
100
  }
98
- function _(t) {
99
- return t.responses[200];
101
+ function G(n) {
102
+ return n.responses[200];
100
103
  }
101
- function M(t) {
102
- const e = _(t);
103
- return X(e);
104
+ function M(n) {
105
+ const e = G(n);
106
+ return oe(e);
104
107
  }
105
- const te = [
108
+ const re = [
106
109
  "string",
107
110
  "number",
108
111
  "integer",
109
112
  "boolean",
110
113
  "null"
111
114
  ];
112
- function ne(t) {
113
- return Array.isArray(t) ? !0 : te.includes(t);
115
+ function se(n) {
116
+ return Array.isArray(n) ? !0 : re.includes(n);
114
117
  }
115
- function re(t) {
116
- return t.type === "array";
118
+ function ie(n) {
119
+ return n.type === "array";
117
120
  }
118
- function oe(t) {
119
- return Array.isArray(t.enum) && t.enum.length > 0;
121
+ function ae(n) {
122
+ return Array.isArray(n.enum) && n.enum.length > 0;
120
123
  }
121
- function G(t) {
122
- return Array.isArray(t.anyOf) && t.anyOf.length > 0;
124
+ function F(n) {
125
+ return Array.isArray(n.anyOf) && n.anyOf.length > 0;
123
126
  }
124
- function W(t) {
125
- return Array.isArray(t.oneOf) && t.oneOf.length > 0;
127
+ function _(n) {
128
+ return Array.isArray(n.oneOf) && n.oneOf.length > 0;
126
129
  }
127
- function ae(t) {
128
- return G(t) || W(t);
130
+ function ce(n) {
131
+ return F(n) || _(n);
129
132
  }
130
- function se(t) {
131
- return Array.isArray(t.allOf) && t.allOf.length > 0;
133
+ function ge(n) {
134
+ return Array.isArray(n.allOf) && n.allOf.length > 0;
132
135
  }
133
- function j(t) {
134
- return G(t) || W(t) || se(t);
136
+ function j(n) {
137
+ return F(n) || _(n) || ge(n);
135
138
  }
136
- function ie(t) {
137
- return t.includes("|") || t.includes("&") ? `(${t})[]` : `${t}[]`;
139
+ function le(n) {
140
+ return n.includes("|") || n.includes("&") ? `(${n})[]` : `${n}[]`;
138
141
  }
139
- function x(t) {
140
- if (Array.isArray(t))
141
- return t.map((e) => x(e)).join(" | ");
142
- switch (t) {
142
+ function N(n) {
143
+ if (Array.isArray(n))
144
+ return n.map((e) => N(e)).join(" | ");
145
+ switch (n) {
143
146
  case "string":
144
147
  return "string";
145
148
  case "number":
@@ -153,291 +156,92 @@ function x(t) {
153
156
  return "any";
154
157
  }
155
158
  }
156
- const E = "@ahoo-wang/fetcher-wow", ce = {
157
- "wow.command.CommandResult": "CommandResult",
158
- "wow.MessageHeaderSqlType": "MessageHeaderSqlType",
159
- "wow.api.BindingError": "BindingError",
160
- "wow.api.DefaultErrorInfo": "ErrorInfo",
161
- "wow.api.RecoverableType": "RecoverableType",
162
- "wow.api.command.DefaultDeleteAggregate": "DeleteAggregate",
163
- "wow.api.command.DefaultRecoverAggregate": "RecoverAggregate",
164
- "wow.api.messaging.FunctionInfoData": "FunctionInfo",
165
- "wow.api.messaging.FunctionKind": "FunctionKind",
166
- "wow.api.modeling.AggregateId": "AggregateId",
167
- "wow.api.query.Condition": "Condition",
168
- "wow.api.query.ConditionOptions": "ConditionOptions",
169
- "wow.api.query.ListQuery": "ListQuery",
170
- "wow.api.query.Operator": "Operator",
171
- "wow.api.query.PagedQuery": "PagedQuery",
172
- "wow.api.query.Pagination": "Pagination",
173
- "wow.api.query.Projection": "Projection",
174
- "wow.api.query.Sort": "FieldSort",
175
- "wow.api.query.Sort.Direction": "SortDirection",
176
- "wow.command.CommandStage": "CommandStage",
177
- "wow.command.SimpleWaitSignal": "WaitSignal",
178
- "wow.configuration.Aggregate": "Aggregate",
179
- "wow.configuration.BoundedContext": "BoundedContext",
180
- "wow.configuration.WowMetadata": "WowMetadata",
181
- "wow.modeling.DomainEvent": "DomainEvent",
182
- "wow.openapi.BatchResult": "BatchResult",
183
- "wow.messaging.CompensationTarget": "CompensationTarget"
184
- };
185
- function l(t) {
186
- if (!t)
187
- return { name: "", path: "/" };
188
- const e = ce[t];
189
- if (e)
190
- return { name: e, path: E };
191
- const n = t.split(".");
192
- let r = -1;
193
- for (let i = 0; i < n.length; i++)
194
- if (n[i] && /^[A-Z]/.test(n[i])) {
195
- r = i;
196
- break;
197
- }
198
- if (r === -1)
199
- return { name: t, path: "/" };
200
- const o = n.slice(0, r), a = o.length > 0 ? `/${o.join("/")}` : "/", s = n.slice(r);
201
- return { name: P(s), path: a };
159
+ const W = "types.ts", pe = "@";
160
+ function me(n) {
161
+ return q(n.path, W);
202
162
  }
203
- class O {
204
- /** The ts-morph project instance used for code generation */
205
- project;
206
- /** The OpenAPI specification object */
207
- openAPI;
208
- /** The output directory path for generated files */
209
- outputDir;
210
- /** Map of bounded context aggregates for domain modeling */
211
- contextAggregates;
212
- /** Optional logger for generation progress and errors */
213
- logger;
214
- /**
215
- * Creates a new ClientGenerator instance.
216
- * @param context - The generation context containing OpenAPI spec and project details
217
- */
218
- constructor(e) {
219
- this.project = e.project, this.openAPI = e.openAPI, this.outputDir = e.outputDir, this.contextAggregates = e.contextAggregates, this.logger = e.logger;
220
- }
221
- }
222
- class ue extends O {
223
- constructor(e) {
224
- super(e);
225
- }
226
- getOrCreateSourceFile(e) {
227
- const n = B(e);
228
- return v(this.project, this.outputDir, n);
229
- }
230
- /**
231
- * Generates models for all schemas in the OpenAPI specification.
232
- * Skips schemas with keys starting with 'wow.'.
233
- *
234
- * @remarks
235
- * This method iterates through all schemas in the OpenAPI specification
236
- * and generates corresponding TypeScript models for each one.
237
- */
238
- generate() {
239
- const e = this.openAPI.components?.schemas;
240
- if (!e) {
241
- this.logger.info("No schemas found in OpenAPI specification");
242
- return;
243
- }
244
- this.logger.progress(
245
- `Generating models for ${Object.keys(e).length} schemas`
246
- ), Object.entries(e).forEach(([n, r]) => {
247
- if (n.startsWith("wow."))
248
- return;
249
- this.logger.progress(`Processing schema: ${n}`);
250
- const o = {
251
- key: n,
252
- schema: r
253
- };
254
- this.generateKeyedSchema(o);
255
- }), this.logger.success("Model generation completed");
256
- }
257
- /**
258
- * Generates a model for a specific schema key.
259
- * Processes enums, objects, unions, and type aliases in order.
260
- *
261
- * @param schemaKey - The key of the schema to generate
262
- * @param schema - The schema definition
263
- *
264
- * @remarks
265
- * The generation process follows this order:
266
- * 1. Enum processing
267
- * 2. Object processing
268
- * 3. Union processing
269
- * 4. Type alias processing
270
- */
271
- generateKeyedSchema({ key: e, schema: n }) {
272
- const r = l(e), o = this.getOrCreateSourceFile(r), a = this.process(r, o, n);
273
- a && A(a, n.title, n.description);
274
- }
275
- process(e, n, r) {
276
- if (oe(r))
277
- return n.addEnum({
278
- name: e.name,
279
- isExported: !0,
280
- members: r.enum.filter((a) => typeof a == "string" && a.length > 0).map((a) => ({
281
- name: a,
282
- initializer: `'${a}'`
283
- }))
284
- });
285
- const o = n.addInterface({
286
- name: e.name,
287
- isExported: !0
288
- });
289
- return r.type === "object" && r.properties ? this.processInterface(n, e, r, o) : (j(r) && (r.anyOf || r.oneOf || r.allOf).forEach((s) => {
290
- if (u(s)) {
291
- const c = l(d(s));
292
- N(e, n, this.outputDir, c), o.addExtends(c.name);
293
- return;
294
- }
295
- this.processInterface(n, e, s, o);
296
- }), o);
297
- }
298
- processObject(e, n, r) {
299
- const o = e.addInterface({
300
- name: n.name,
301
- isExported: !0
302
- });
303
- return this.processInterface(e, n, r, o);
304
- }
305
- processInterface(e, n, r, o) {
306
- for (const [a, s] of Object.entries(r.properties)) {
307
- const c = this.resolvePropertyType(n, e, a, s);
308
- let i = o.getProperty(a);
309
- i ? i.setType(c) : i = o.addProperty({
310
- name: a,
311
- type: c
312
- }), u(s) || A(i, s.title, s.description);
313
- }
314
- return o;
315
- }
316
- resolvePropertyType(e, n, r, o) {
317
- if (u(o)) {
318
- const a = l(d(o));
319
- return N(e, n, this.outputDir, a), a.name;
320
- }
321
- if (o.const)
322
- return `'${o.const}'`;
323
- if (re(o)) {
324
- const a = this.resolvePropertyType(e, n, r, o.items);
325
- return ie(a);
326
- }
327
- if (o.type && ne(o.type))
328
- return x(o.type);
329
- if (j(o))
330
- return this.resolvePropertyCompositionType(e, n, o);
331
- if (o.type === "object" && o.properties) {
332
- const a = {
333
- path: e.path,
334
- name: `${e.name}${P(r)}`
335
- }, s = this.processObject(n, a, o);
336
- return A(s, o.title, o.description), a.name;
337
- }
338
- return "any";
339
- }
340
- resolvePropertyCompositionType(e, n, r) {
341
- const o = r.anyOf || r.oneOf || r.allOf, a = /* @__PURE__ */ new Set();
342
- o.forEach((c) => {
343
- if (u(c)) {
344
- const i = l(d(c));
345
- N(e, n, this.outputDir, i), a.add(i.name);
346
- return;
347
- }
348
- a.add(x(c.type ?? "string"));
349
- });
350
- const s = ae(r) ? "|" : "&";
351
- return Array.from(a).join(s);
352
- }
353
- }
354
- const pe = "types.ts", I = "@";
355
- function B(t) {
356
- return C(t.path, pe);
357
- }
358
- function v(t, e, n) {
359
- const r = C(e, n), o = t.getSourceFile(r);
360
- return o || t.createSourceFile(r, "", {
163
+ function D(n, e, t) {
164
+ const o = q(e, t), r = n.getSourceFile(o);
165
+ return r || n.createSourceFile(o, "", {
361
166
  overwrite: !0
362
167
  });
363
168
  }
364
- function w(t, e, n) {
365
- let r = t.getImportDeclaration(
366
- (o) => o.getModuleSpecifierValue() === e
169
+ function $(n, e, t) {
170
+ let o = n.getImportDeclaration(
171
+ (r) => r.getModuleSpecifierValue() === e
367
172
  );
368
- r || (r = t.addImportDeclaration({
173
+ o || (o = n.addImportDeclaration({
369
174
  moduleSpecifier: e
370
- })), n.forEach((o) => {
371
- r.getNamedImports().some(
372
- (s) => s.getName() === o
373
- ) || r.addNamedImport(o);
175
+ })), t.forEach((r) => {
176
+ o.getNamedImports().some(
177
+ (i) => i.getName() === r
178
+ ) || o.addNamedImport(r);
374
179
  });
375
180
  }
376
- function h(t, e, n) {
377
- if (n.path === E) {
378
- w(t, n.path, [n.name]);
181
+ function y(n, e, t) {
182
+ if (t.path.startsWith(pe)) {
183
+ $(n, t.path, [t.name]);
379
184
  return;
380
185
  }
381
- let r = B(n);
382
- n.path.startsWith(I) || (r = C(e, r));
383
- let o = r;
384
- r.startsWith(I) || (o = C(I, r)), w(t, o, [n.name]);
186
+ const o = n.getDirectoryPath(), r = U(e, t.path, W);
187
+ let s = J(o, r);
188
+ s = s.replace(/\.ts$/, ""), s.startsWith(".") || (s = "./" + s), $(n, s, [t.name]);
385
189
  }
386
- function N(t, e, n, r) {
387
- t.path !== r.path && h(e, n, r);
190
+ function E(n, e, t, o) {
191
+ n.path !== o.path && y(e, t, o);
388
192
  }
389
- function me(t, e) {
390
- const n = [t, e].filter(
391
- (r) => r !== void 0 && r.length > 0
193
+ function de(n, e) {
194
+ const t = [n, e].filter(
195
+ (o) => o !== void 0 && o.length > 0
392
196
  );
393
- return n.length > 0 ? n.join(`
197
+ return t.length > 0 ? t.join(`
394
198
  `) : void 0;
395
199
  }
396
- function A(t, e, n) {
397
- const r = me(e, n);
398
- r && t.addJsDoc({
399
- description: r
200
+ function P(n, e, t) {
201
+ const o = de(e, t);
202
+ o && n.addJsDoc({
203
+ description: o
400
204
  });
401
205
  }
402
- function ge(t) {
403
- const e = t.split(".");
206
+ function ue(n) {
207
+ const e = n.split(".");
404
208
  return e.length != 2 || e[0].length === 0 || e[1].length === 0 ? null : e;
405
209
  }
406
- function le(t) {
407
- const e = ge(t.name);
210
+ function fe(n) {
211
+ const e = ue(n.name);
408
212
  return e ? {
409
- tag: t,
213
+ tag: n,
410
214
  contextAlias: e[0],
411
215
  aggregateName: e[1]
412
216
  } : null;
413
217
  }
414
- function de(t) {
415
- const e = t?.map((r) => le(r)).filter((r) => r !== null);
218
+ function he(n) {
219
+ const e = n?.map((o) => fe(o)).filter((o) => o !== null);
416
220
  if (!e)
417
221
  return /* @__PURE__ */ new Map();
418
- const n = /* @__PURE__ */ new Map();
419
- return e.forEach((r) => {
420
- n.set(r.tag.name, {
421
- aggregate: r,
222
+ const t = /* @__PURE__ */ new Map();
223
+ return e.forEach((o) => {
224
+ t.set(o.tag.name, {
225
+ aggregate: o,
422
226
  commands: /* @__PURE__ */ new Map(),
423
227
  events: /* @__PURE__ */ new Map()
424
228
  });
425
- }), n;
229
+ }), t;
426
230
  }
427
- function fe(t) {
428
- if (!t)
231
+ function ye(n) {
232
+ if (!n)
429
233
  return null;
430
- const e = t.split(".");
234
+ const e = n.split(".");
431
235
  return e.length != 3 ? null : e[2];
432
236
  }
433
- const he = "#/components/responses/wow.CommandOk", ye = "#/components/parameters/wow.id";
434
- class Ae {
237
+ const Ae = "#/components/responses/wow.CommandOk", Ce = "#/components/parameters/wow.id";
238
+ class Pe {
435
239
  /**
436
240
  * Creates a new AggregateResolver instance.
437
241
  * @param openAPI - The OpenAPI specification to resolve aggregates from
438
242
  */
439
243
  constructor(e) {
440
- this.openAPI = e, this.aggregates = de(e.tags), this.build();
244
+ this.openAPI = e, this.aggregates = he(e.tags), this.build();
441
245
  }
442
246
  aggregates;
443
247
  /**
@@ -445,10 +249,10 @@ class Ae {
445
249
  * @private
446
250
  */
447
251
  build() {
448
- for (const [e, n] of Object.entries(this.openAPI.paths)) {
449
- const r = ee(n);
450
- for (const o of r)
451
- this.commands(e, o), this.state(o.operation), this.events(o.operation), this.fields(o.operation);
252
+ for (const [e, t] of Object.entries(this.openAPI.paths)) {
253
+ const o = ne(t);
254
+ for (const r of o)
255
+ this.commands(e, r), this.state(r.operation), this.events(r.operation), this.fields(r.operation);
452
256
  }
453
257
  }
454
258
  /**
@@ -457,12 +261,12 @@ class Ae {
457
261
  */
458
262
  resolve() {
459
263
  const e = /* @__PURE__ */ new Map();
460
- for (const n of this.aggregates.values()) {
461
- if (!n.state || !n.fields)
264
+ for (const t of this.aggregates.values()) {
265
+ if (!t.state || !t.fields)
462
266
  continue;
463
- const r = n.aggregate.contextAlias;
464
- let o = e.get(r);
465
- o || (o = /* @__PURE__ */ new Set(), e.set(r, o)), o.add(n);
267
+ const o = t.aggregate.contextAlias;
268
+ let r = e.get(o);
269
+ r || (r = /* @__PURE__ */ new Set(), e.set(o, r)), r.add(t);
466
270
  }
467
271
  return e;
468
272
  }
@@ -471,44 +275,44 @@ class Ae {
471
275
  * @param path - The API path
472
276
  * @param methodOperation - The HTTP method and operation details
473
277
  */
474
- commands(e, n) {
475
- const r = n.operation;
476
- if (r.operationId === "wow.command.send")
278
+ commands(e, t) {
279
+ const o = t.operation;
280
+ if (o.operationId === "wow.command.send")
477
281
  return;
478
- const o = fe(r.operationId);
479
- if (!o)
282
+ const r = ye(o.operationId);
283
+ if (!r)
480
284
  return;
481
- const a = _(r);
482
- if (!a || !u(a) || a.$ref !== he || !r.requestBody)
285
+ const s = G(o);
286
+ if (!s || !g(s) || s.$ref !== Ae || !o.requestBody)
483
287
  return;
484
- const s = r.parameters ?? [], c = s.filter((p) => u(p) && p.$ref === ye).at(0), i = s.filter(
485
- (p) => !u(p) && p.in === "path"
288
+ const i = o.parameters ?? [], c = i.filter((d) => g(d) && d.$ref === Ce).at(0), a = i.filter(
289
+ (d) => !g(d) && d.in === "path"
486
290
  );
487
291
  if (c) {
488
- const p = U(
292
+ const d = H(
489
293
  c,
490
294
  this.openAPI.components
491
295
  );
492
- i.push(p);
296
+ a.push(d);
493
297
  }
494
- const g = r.requestBody.content[T.APPLICATION_JSON].schema, f = y(
495
- g,
298
+ const m = o.requestBody.content[I.APPLICATION_JSON].schema, l = C(
299
+ m,
496
300
  this.openAPI.components
497
301
  );
498
- f.schema.title = f.schema.title || r.summary, f.schema.description = f.schema.description || r.description;
499
- const L = {
500
- name: o,
501
- method: n.method,
302
+ l.schema.title = l.schema.title || o.summary, l.schema.description = l.schema.description || o.description;
303
+ const z = {
304
+ name: r,
305
+ method: t.method,
502
306
  path: e,
503
- pathParameters: i,
504
- summary: r.summary,
505
- description: r.description,
506
- schema: f,
507
- operation: r
307
+ pathParameters: a,
308
+ summary: o.summary,
309
+ description: o.description,
310
+ schema: l,
311
+ operation: o
508
312
  };
509
- r.tags?.forEach((p) => {
510
- const D = this.aggregates.get(p);
511
- D && D.commands.set(o, L);
313
+ o.tags?.forEach((d) => {
314
+ const T = this.aggregates.get(d);
315
+ T && T.commands.set(r, z);
512
316
  });
513
317
  }
514
318
  /**
@@ -518,16 +322,16 @@ class Ae {
518
322
  state(e) {
519
323
  if (!e.operationId?.endsWith(".snapshot_state.single"))
520
324
  return;
521
- const n = M(e);
522
- if (!u(n))
325
+ const t = M(e);
326
+ if (!g(t))
523
327
  return;
524
- const r = y(
525
- n,
328
+ const o = C(
329
+ t,
526
330
  this.openAPI.components
527
331
  );
528
- e.tags?.forEach((o) => {
529
- const a = this.aggregates.get(o);
530
- a && (a.state = r);
332
+ e.tags?.forEach((r) => {
333
+ const s = this.aggregates.get(r);
334
+ s && (s.state = o);
531
335
  });
532
336
  }
533
337
  /**
@@ -537,30 +341,30 @@ class Ae {
537
341
  events(e) {
538
342
  if (!this.openAPI.components || !e.operationId?.endsWith(".event.list_query"))
539
343
  return;
540
- const n = M(e);
541
- if (u(n))
344
+ const t = M(e);
345
+ if (g(t))
542
346
  return;
543
- const r = n?.items;
544
- if (!u(r))
347
+ const o = t?.items;
348
+ if (!g(o))
545
349
  return;
546
- const a = R(
547
- r,
350
+ const s = S(
351
+ o,
548
352
  this.openAPI.components
549
- ).properties.body.items.anyOf.map((s) => {
550
- const c = s.title, i = s.properties.name.const, m = s.properties.body, g = y(
551
- m,
353
+ ).properties.body.items.anyOf.map((i) => {
354
+ const c = i.title, a = i.properties.name.const, p = i.properties.body, m = C(
355
+ p,
552
356
  this.openAPI.components
553
357
  );
554
- return g.schema.title = g.schema.title || s.title, {
358
+ return m.schema.title = m.schema.title || i.title, {
555
359
  title: c,
556
- name: i,
557
- schema: g
360
+ name: a,
361
+ schema: m
558
362
  };
559
363
  });
560
- e.tags?.forEach((s) => {
561
- const c = this.aggregates.get(s);
562
- c && a.forEach((i) => {
563
- c.events.set(i.name, i);
364
+ e.tags?.forEach((i) => {
365
+ const c = this.aggregates.get(i);
366
+ c && s.forEach((a) => {
367
+ c.events.set(a.name, a);
564
368
  });
565
369
  });
566
370
  }
@@ -571,33 +375,289 @@ class Ae {
571
375
  fields(e) {
572
376
  if (!this.openAPI.components || !e.operationId?.endsWith(".snapshot.count"))
573
377
  return;
574
- const r = J(
378
+ const o = V(
575
379
  e.requestBody,
576
380
  this.openAPI.components
577
- ).content[T.APPLICATION_JSON].schema, a = R(
578
- r,
381
+ ).content[I.APPLICATION_JSON].schema, s = S(
382
+ o,
579
383
  this.openAPI.components
580
- ).properties?.field, s = y(a, this.openAPI.components);
384
+ ).properties?.field, i = C(s, this.openAPI.components);
581
385
  e.tags?.forEach((c) => {
582
- const i = this.aggregates.get(c);
583
- i && (i.fields = s);
386
+ const a = this.aggregates.get(c);
387
+ a && (a.fields = i);
388
+ });
389
+ }
390
+ }
391
+ const A = "@ahoo-wang/fetcher-wow", $e = {
392
+ "wow.command.CommandResult": "CommandResult",
393
+ "wow.MessageHeaderSqlType": "MessageHeaderSqlType",
394
+ "wow.api.BindingError": "BindingError",
395
+ "wow.api.DefaultErrorInfo": "ErrorInfo",
396
+ "wow.api.RecoverableType": "RecoverableType",
397
+ "wow.api.command.DefaultDeleteAggregate": "DeleteAggregate",
398
+ "wow.api.command.DefaultRecoverAggregate": "RecoverAggregate",
399
+ "wow.api.messaging.FunctionInfoData": "FunctionInfo",
400
+ "wow.api.messaging.FunctionKind": "FunctionKind",
401
+ "wow.api.modeling.AggregateId": "AggregateId",
402
+ "wow.api.query.Condition": "Condition",
403
+ "wow.api.query.ConditionOptions": "ConditionOptions",
404
+ "wow.api.query.ListQuery": "ListQuery",
405
+ "wow.api.query.Operator": "Operator",
406
+ "wow.api.query.PagedQuery": "PagedQuery",
407
+ "wow.api.query.Pagination": "Pagination",
408
+ "wow.api.query.Projection": "Projection",
409
+ "wow.api.query.Sort": "FieldSort",
410
+ "wow.api.query.Sort.Direction": "SortDirection",
411
+ "wow.command.CommandStage": "CommandStage",
412
+ "wow.command.SimpleWaitSignal": "WaitSignal",
413
+ "wow.configuration.Aggregate": "Aggregate",
414
+ "wow.configuration.BoundedContext": "BoundedContext",
415
+ "wow.configuration.WowMetadata": "WowMetadata",
416
+ "wow.modeling.DomainEvent": "DomainEvent",
417
+ "wow.openapi.BatchResult": "BatchResult",
418
+ "wow.messaging.CompensationTarget": "CompensationTarget"
419
+ };
420
+ function u(n) {
421
+ if (!n)
422
+ return { name: "", path: "/" };
423
+ const e = $e[n];
424
+ if (e)
425
+ return { name: e, path: A };
426
+ const t = n.split(".");
427
+ let o = -1;
428
+ for (let a = 0; a < t.length; a++)
429
+ if (t[a] && /^[A-Z]/.test(t[a])) {
430
+ o = a;
431
+ break;
432
+ }
433
+ if (o === -1)
434
+ return { name: n, path: "/" };
435
+ const r = t.slice(0, o), s = r.length > 0 ? `/${r.join("/")}` : "/", i = t.slice(o);
436
+ return { name: w(i), path: s };
437
+ }
438
+ class x {
439
+ /** The ts-morph project instance used for code generation */
440
+ project;
441
+ /** The OpenAPI specification object */
442
+ openAPI;
443
+ /** The output directory path for generated files */
444
+ outputDir;
445
+ /** Map of bounded context aggregates for domain modeling */
446
+ contextAggregates;
447
+ /** Optional logger for generation progress and errors */
448
+ logger;
449
+ /**
450
+ * Creates a new ClientGenerator instance.
451
+ * @param context - The generation context containing OpenAPI spec and project details
452
+ */
453
+ constructor(e) {
454
+ this.project = e.project, this.openAPI = e.openAPI, this.outputDir = e.outputDir, this.contextAggregates = e.contextAggregates, this.logger = e.logger;
455
+ }
456
+ }
457
+ class we extends x {
458
+ constructor(e) {
459
+ super(e);
460
+ }
461
+ getOrCreateSourceFile(e) {
462
+ const t = me(e);
463
+ return D(this.project, this.outputDir, t);
464
+ }
465
+ /**
466
+ * Generates models for all schemas in the OpenAPI specification.
467
+ * Skips schemas with keys starting with 'wow.'.
468
+ *
469
+ * @remarks
470
+ * This method iterates through all schemas in the OpenAPI specification
471
+ * and generates corresponding TypeScript models for each one.
472
+ */
473
+ generate() {
474
+ const e = this.openAPI.components?.schemas;
475
+ if (!e) {
476
+ this.logger.info("No schemas found in OpenAPI specification");
477
+ return;
478
+ }
479
+ const t = Object.entries(e).filter(
480
+ ([o]) => !o.startsWith("wow.")
481
+ );
482
+ this.logger.progress(
483
+ `Generating models for ${t.length} schemas`
484
+ ), t.forEach(([o, r], s) => {
485
+ this.logger.progressWithCount(
486
+ s + 1,
487
+ t.length,
488
+ `Processing schema: ${o}`,
489
+ 2
490
+ );
491
+ const i = {
492
+ key: o,
493
+ schema: r
494
+ };
495
+ this.generateKeyedSchema(i);
496
+ }), this.logger.success("Model generation completed");
497
+ }
498
+ /**
499
+ * Generates a model for a specific schema key.
500
+ * Processes enums, objects, unions, and type aliases in order.
501
+ *
502
+ * @param schemaKey - The key of the schema to generate
503
+ * @param schema - The schema definition
504
+ *
505
+ * @remarks
506
+ * The generation process follows this order:
507
+ * 1. Enum processing
508
+ * 2. Object processing
509
+ * 3. Union processing
510
+ * 4. Type alias processing
511
+ */
512
+ generateKeyedSchema({ key: e, schema: t }) {
513
+ const o = u(e), r = this.getOrCreateSourceFile(o), s = this.process(o, r, t);
514
+ s && P(s, t.title, t.description);
515
+ }
516
+ process(e, t, o) {
517
+ if (ae(o))
518
+ return t.addEnum({
519
+ name: e.name,
520
+ isExported: !0,
521
+ members: o.enum.filter((s) => typeof s == "string" && s.length > 0).map((s) => ({
522
+ name: s,
523
+ initializer: `'${s}'`
524
+ }))
525
+ });
526
+ const r = t.addInterface({
527
+ name: e.name,
528
+ isExported: !0
529
+ });
530
+ return o.type === "object" && o.properties ? this.processInterface(
531
+ t,
532
+ e,
533
+ o,
534
+ r
535
+ ) : (j(o) && (o.anyOf || o.oneOf || o.allOf).forEach((i) => {
536
+ if (g(i)) {
537
+ const c = u(
538
+ f(i)
539
+ );
540
+ E(
541
+ e,
542
+ t,
543
+ this.outputDir,
544
+ c
545
+ ), r.addExtends(c.name);
546
+ return;
547
+ }
548
+ this.processInterface(
549
+ t,
550
+ e,
551
+ i,
552
+ r
553
+ );
554
+ }), r);
555
+ }
556
+ processObject(e, t, o) {
557
+ const r = e.addInterface({
558
+ name: t.name,
559
+ isExported: !0
560
+ });
561
+ return this.processInterface(
562
+ e,
563
+ t,
564
+ o,
565
+ r
566
+ );
567
+ }
568
+ processInterface(e, t, o, r) {
569
+ for (const [s, i] of Object.entries(o.properties)) {
570
+ const c = this.resolvePropertyType(
571
+ t,
572
+ e,
573
+ s,
574
+ i
575
+ );
576
+ let a = r.getProperty(s);
577
+ a ? a.setType(c) : a = r.addProperty({
578
+ name: s,
579
+ type: c
580
+ }), g(i) || P(a, i.title, i.description);
581
+ }
582
+ return r;
583
+ }
584
+ resolvePropertyType(e, t, o, r) {
585
+ if (g(r)) {
586
+ const s = u(f(r));
587
+ return E(
588
+ e,
589
+ t,
590
+ this.outputDir,
591
+ s
592
+ ), s.name;
593
+ }
594
+ if (r.const)
595
+ return `'${r.const}'`;
596
+ if (ie(r)) {
597
+ const s = this.resolvePropertyType(
598
+ e,
599
+ t,
600
+ o,
601
+ r.items
602
+ );
603
+ return le(s);
604
+ }
605
+ if (r.type && se(r.type))
606
+ return N(r.type);
607
+ if (j(r))
608
+ return this.resolvePropertyCompositionType(
609
+ e,
610
+ t,
611
+ r
612
+ );
613
+ if (r.type === "object" && r.properties) {
614
+ const s = {
615
+ path: e.path,
616
+ name: `${e.name}${w(o)}`
617
+ }, i = this.processObject(
618
+ t,
619
+ s,
620
+ r
621
+ );
622
+ return P(i, r.title, r.description), s.name;
623
+ }
624
+ return "any";
625
+ }
626
+ resolvePropertyCompositionType(e, t, o) {
627
+ const r = o.anyOf || o.oneOf || o.allOf, s = /* @__PURE__ */ new Set();
628
+ r.forEach((c) => {
629
+ if (g(c)) {
630
+ const a = u(
631
+ f(c)
632
+ );
633
+ E(
634
+ e,
635
+ t,
636
+ this.outputDir,
637
+ a
638
+ ), s.add(a.name);
639
+ return;
640
+ }
641
+ s.add(N(c.type ?? "string"));
584
642
  });
643
+ const i = ce(o) ? "|" : "&";
644
+ return Array.from(s).join(i);
585
645
  }
586
646
  }
587
- function Ce(t) {
588
- let e = 0, n = 0;
589
- return t.commands.forEach((r) => {
590
- r.path.startsWith(b.TENANT) && (e += 1), r.path.startsWith(b.OWNER) && (n += 1);
591
- }), e === 0 && n === 0 ? "ResourceAttributionPathSpec.NONE" : e > n ? "ResourceAttributionPathSpec.TENANT" : "ResourceAttributionPathSpec.OWNER";
647
+ function xe(n) {
648
+ let e = 0, t = 0;
649
+ return n.commands.forEach((o) => {
650
+ o.path.startsWith(R.TENANT) && (e += 1), o.path.startsWith(R.OWNER) && (t += 1);
651
+ }), e === 0 && t === 0 ? "ResourceAttributionPathSpec.NONE" : e > t ? "ResourceAttributionPathSpec.TENANT" : "ResourceAttributionPathSpec.OWNER";
592
652
  }
593
- function F(t, e, n, r) {
594
- const o = `${n.contextAlias}/${n.aggregateName}/${r}.ts`;
595
- return v(t, e, o);
653
+ function B(n, e, t, o) {
654
+ const r = `${t.contextAlias}/${t.aggregateName}/${o}.ts`;
655
+ return D(n, e, r);
596
656
  }
597
- function we(t, e) {
598
- return `${P(t.aggregateName)}${e}`;
657
+ function Ee(n, e) {
658
+ return `${w(n.aggregateName)}${e}`;
599
659
  }
600
- class Pe extends O {
660
+ class Oe extends x {
601
661
  /**
602
662
  * Creates a new QueryClientGenerator instance.
603
663
  * @param context - The generation context containing OpenAPI spec and project details
@@ -609,13 +669,19 @@ class Pe extends O {
609
669
  * Generates query client classes for all aggregates.
610
670
  */
611
671
  generate() {
612
- const e = Array.from(this.contextAggregates.values()).flat().length;
613
- this.logger.progress(
672
+ const e = Array.from(this.contextAggregates.values()).reduce(
673
+ (o, r) => o + r.size,
674
+ 0
675
+ );
676
+ this.logger.info("--- Generating Query Clients ---"), this.logger.progress(
614
677
  `Generating query clients for ${e} aggregates`
615
678
  );
616
- for (const [, n] of this.contextAggregates)
617
- n.forEach((r) => {
618
- this.logger.progress(
679
+ let t = 0;
680
+ for (const [, o] of this.contextAggregates)
681
+ o.forEach((r) => {
682
+ t++, this.logger.progressWithCount(
683
+ t,
684
+ e,
619
685
  `Processing query client for aggregate: ${r.aggregate.aggregateName}`
620
686
  ), this.processQueryClient(r);
621
687
  });
@@ -627,12 +693,12 @@ class Pe extends O {
627
693
  * @param fileName - The name of the client file
628
694
  * @returns The source file for the client
629
695
  */
630
- createClientFilePath(e, n) {
631
- return F(
696
+ createClientFilePath(e, t) {
697
+ return B(
632
698
  this.project,
633
699
  this.outputDir,
634
700
  e,
635
- n
701
+ t
636
702
  );
637
703
  }
638
704
  /**
@@ -640,58 +706,77 @@ class Pe extends O {
640
706
  * @param aggregate - The aggregate definition
641
707
  */
642
708
  processQueryClient(e) {
643
- const n = this.createClientFilePath(
709
+ const t = this.createClientFilePath(
644
710
  e.aggregate,
645
711
  "queryClient"
646
712
  );
647
- n.addImportDeclaration({
648
- moduleSpecifier: E,
713
+ this.logger.info(
714
+ `Processing query client for aggregate: ${e.aggregate.aggregateName} in context: ${e.aggregate.contextAlias}`
715
+ ), this.logger.info(
716
+ `Adding imports from ${A}: QueryClientFactory, QueryClientOptions, ResourceAttributionPathSpec`
717
+ ), t.addImportDeclaration({
718
+ moduleSpecifier: A,
649
719
  namedImports: [
650
720
  "QueryClientFactory",
651
721
  "QueryClientOptions",
652
722
  "ResourceAttributionPathSpec"
653
723
  ]
654
724
  });
655
- const r = "DEFAULT_QUERY_CLIENT_OPTIONS";
656
- n.addVariableStatement({
657
- declarationKind: S.Const,
725
+ const o = "DEFAULT_QUERY_CLIENT_OPTIONS";
726
+ this.logger.info(
727
+ `Creating default query client options: ${o}`
728
+ ), t.addVariableStatement({
729
+ declarationKind: O.Const,
658
730
  declarations: [
659
731
  {
660
- name: r,
732
+ name: o,
661
733
  type: "QueryClientOptions",
662
734
  initializer: `{
663
735
  contextAlias: '${e.aggregate.contextAlias}',
664
736
  aggregateName: '${e.aggregate.aggregateName}',
665
- resourceAttribution: ${Ce(e)},
737
+ resourceAttribution: ${xe(e)},
666
738
  }`
667
739
  }
668
740
  ],
669
741
  isExported: !1
670
742
  });
671
- const o = [];
743
+ const r = [];
744
+ this.logger.info(
745
+ `Processing ${e.events.size} domain events for aggregate: ${e.aggregate.aggregateName}`
746
+ );
672
747
  for (const m of e.events.values()) {
673
- const g = l(m.schema.key);
674
- h(n, this.outputDir, g), o.push(g);
748
+ const l = u(m.schema.key);
749
+ this.logger.info(
750
+ `Adding import for event model: ${l.name} from path: ${l.path}`
751
+ ), y(t, this.outputDir, l), r.push(l);
675
752
  }
676
- const a = "DOMAIN_EVENT_TYPES";
677
- n.addTypeAlias({
678
- name: a,
679
- type: o.map((m) => m.name).join(" | ")
753
+ const s = "DOMAIN_EVENT_TYPES", i = r.map((m) => m.name).join(" | ");
754
+ this.logger.info(
755
+ `Creating domain event types union: ${s} = ${i}`
756
+ ), t.addTypeAlias({
757
+ name: s,
758
+ type: i
680
759
  });
681
- const s = `${q(e.aggregate.aggregateName)}QueryClientFactory`, c = l(e.state.key), i = l(e.fields.key);
682
- h(n, this.outputDir, c), h(n, this.outputDir, i), n.addVariableStatement({
683
- declarationKind: S.Const,
760
+ const c = `${h(e.aggregate.aggregateName)}QueryClientFactory`, a = u(e.state.key), p = u(e.fields.key);
761
+ this.logger.info(
762
+ `Adding import for state model: ${a.name} from path: ${a.path}`
763
+ ), y(t, this.outputDir, a), this.logger.info(
764
+ `Adding import for fields model: ${p.name} from path: ${p.path}`
765
+ ), y(t, this.outputDir, p), this.logger.info(`Creating query client factory: ${c}`), t.addVariableStatement({
766
+ declarationKind: O.Const,
684
767
  declarations: [
685
768
  {
686
- name: s,
687
- initializer: `new QueryClientFactory<${c.name}, ${i.name} | string, ${a}>(${r})`
769
+ name: c,
770
+ initializer: `new QueryClientFactory<${a.name}, ${p.name} | string, ${s}>(${o})`
688
771
  }
689
772
  ],
690
773
  isExported: !0
691
- });
774
+ }), this.logger.success(
775
+ `Query client generation completed for aggregate: ${e.aggregate.aggregateName}`
776
+ );
692
777
  }
693
778
  }
694
- class Ee extends O {
779
+ class Ie extends x {
695
780
  commandEndpointPathsName = "COMMAND_ENDPOINT_PATHS";
696
781
  defaultCommandClientOptionsName = "DEFAULT_COMMAND_CLIENT_OPTIONS";
697
782
  /**
@@ -705,13 +790,19 @@ class Ee extends O {
705
790
  * Generates command client classes for all aggregates.
706
791
  */
707
792
  generate() {
708
- const e = Array.from(this.contextAggregates.values()).flat().length;
709
- this.logger.progress(
793
+ const e = Array.from(this.contextAggregates.values()).reduce(
794
+ (o, r) => o + r.size,
795
+ 0
796
+ );
797
+ this.logger.info("--- Generating Command Clients ---"), this.logger.progress(
710
798
  `Generating command clients for ${e} aggregates`
711
799
  );
712
- for (const [, n] of this.contextAggregates)
713
- n.forEach((r) => {
714
- this.logger.progress(
800
+ let t = 0;
801
+ for (const [, o] of this.contextAggregates)
802
+ o.forEach((r) => {
803
+ t++, this.logger.progressWithCount(
804
+ t,
805
+ e,
715
806
  `Processing command client for aggregate: ${r.aggregate.aggregateName}`
716
807
  ), this.processAggregate(r);
717
808
  });
@@ -722,14 +813,21 @@ class Ee extends O {
722
813
  * @param aggregate - The aggregate definition
723
814
  */
724
815
  processAggregate(e) {
725
- const n = F(
816
+ this.logger.info(
817
+ `Processing command client for aggregate: ${e.aggregate.aggregateName} in context: ${e.aggregate.contextAlias}`
818
+ );
819
+ const t = B(
726
820
  this.project,
727
821
  this.outputDir,
728
822
  e.aggregate,
729
823
  "commandClient"
730
824
  );
731
- this.processCommandEndpointPaths(n, e), n.addVariableStatement({
732
- declarationKind: S.Const,
825
+ this.logger.info(
826
+ `Processing command endpoint paths for ${e.commands.size} commands`
827
+ ), this.processCommandEndpointPaths(t, e), this.logger.info(
828
+ `Creating default command client options: ${this.defaultCommandClientOptionsName}`
829
+ ), t.addVariableStatement({
830
+ declarationKind: O.Const,
733
831
  declarations: [
734
832
  {
735
833
  name: this.defaultCommandClientOptionsName,
@@ -740,8 +838,10 @@ class Ee extends O {
740
838
  }
741
839
  ],
742
840
  isExported: !1
743
- }), n.addImportDeclaration({
744
- moduleSpecifier: E,
841
+ }), this.logger.info(
842
+ `Adding imports from ${A}: CommandRequest, CommandResult, CommandResultEventStream, DeleteAggregate, RecoverAggregate`
843
+ ), t.addImportDeclaration({
844
+ moduleSpecifier: A,
745
845
  namedImports: [
746
846
  "CommandRequest",
747
847
  "CommandResult",
@@ -750,10 +850,16 @@ class Ee extends O {
750
850
  "RecoverAggregate"
751
851
  ],
752
852
  isTypeOnly: !0
753
- }), n.addImportDeclaration({
853
+ }), this.logger.info(
854
+ "Adding import from @ahoo-wang/fetcher-eventstream: JsonEventStreamResultExtractor"
855
+ ), t.addImportDeclaration({
754
856
  moduleSpecifier: "@ahoo-wang/fetcher-eventstream",
755
857
  namedImports: ["JsonEventStreamResultExtractor"]
756
- }), w(n, "@ahoo-wang/fetcher", ["ContentTypeValues"]), w(n, "@ahoo-wang/fetcher-decorator", [
858
+ }), this.logger.info(
859
+ "Adding import from @ahoo-wang/fetcher: ContentTypeValues"
860
+ ), $(t, "@ahoo-wang/fetcher", ["ContentTypeValues"]), this.logger.info(
861
+ "Adding imports from @ahoo-wang/fetcher-decorator: ApiMetadata types and decorators"
862
+ ), $(t, "@ahoo-wang/fetcher-decorator", [
757
863
  "type ApiMetadata",
758
864
  "type ApiMetadataCapable",
759
865
  "api",
@@ -765,28 +871,37 @@ class Ee extends O {
765
871
  "attribute",
766
872
  "path",
767
873
  "autoGeneratedError"
768
- ]), this.processCommandClient(n, e), this.processCommandClient(n, e, !0);
874
+ ]), this.logger.info("Generating standard command client class"), this.processCommandClient(t, e), this.logger.info("Generating stream command client class"), this.processCommandClient(t, e, !0), this.logger.success(
875
+ `Command client generation completed for aggregate: ${e.aggregate.aggregateName}`
876
+ );
769
877
  }
770
- processCommandEndpointPaths(e, n) {
771
- const r = e.addEnum({
878
+ processCommandEndpointPaths(e, t) {
879
+ this.logger.info(
880
+ `Creating command endpoint paths enum: ${this.commandEndpointPathsName}`
881
+ );
882
+ const o = e.addEnum({
772
883
  name: this.commandEndpointPathsName
773
884
  });
774
- n.commands.forEach((o) => {
775
- r.addMember({
776
- name: o.name.toUpperCase(),
777
- initializer: `'${o.path}'`
885
+ t.commands.forEach((r) => {
886
+ this.logger.info(
887
+ `Adding command endpoint: ${r.name.toUpperCase()} = '${r.path}'`
888
+ ), o.addMember({
889
+ name: r.name.toUpperCase(),
890
+ initializer: `'${r.path}'`
778
891
  });
779
- });
892
+ }), this.logger.success(
893
+ `Command endpoint paths enum created with ${t.commands.size} entries`
894
+ );
780
895
  }
781
896
  getEndpointPath(e) {
782
897
  return `${this.commandEndpointPathsName}.${e.name.toUpperCase()}`;
783
898
  }
784
- processCommandClient(e, n, r = !1) {
785
- let o = "CommandClient", a = {
899
+ processCommandClient(e, t, o = !1) {
900
+ let r = "CommandClient", s = {
786
901
  name: "api",
787
902
  arguments: []
788
- }, s = "Promise<CommandResult>";
789
- r && (o = "Stream" + o, a = {
903
+ }, i = "Promise<CommandResult>";
904
+ o && (r = "Stream" + r, s = {
790
905
  name: "api",
791
906
  arguments: [
792
907
  "''",
@@ -795,28 +910,28 @@ class Ee extends O {
795
910
  resultExtractor: JsonEventStreamResultExtractor,
796
911
  }`
797
912
  ]
798
- }, s = "Promise<CommandResultEventStream>");
799
- const c = we(
800
- n.aggregate,
801
- o
802
- ), i = e.addClass({
913
+ }, i = "Promise<CommandResultEventStream>");
914
+ const c = Ee(
915
+ t.aggregate,
916
+ r
917
+ ), a = e.addClass({
803
918
  name: c,
804
919
  isExported: !0,
805
- decorators: [a],
920
+ decorators: [s],
806
921
  implements: ["ApiMetadataCapable"]
807
922
  });
808
- i.addConstructor({
923
+ a.addConstructor({
809
924
  parameters: [
810
925
  {
811
926
  name: "apiMetadata",
812
927
  type: "ApiMetadata",
813
- scope: k.Public,
928
+ scope: L.Public,
814
929
  isReadonly: !0,
815
930
  initializer: `${this.defaultCommandClientOptionsName}`
816
931
  }
817
932
  ]
818
- }), n.commands.forEach((m) => {
819
- this.processCommandMethod(e, i, m, s);
933
+ }), t.commands.forEach((p) => {
934
+ this.processCommandMethod(e, a, p, i);
820
935
  });
821
936
  }
822
937
  methodToDecorator(e) {
@@ -828,29 +943,41 @@ class Ee extends O {
828
943
  * @param client - The client class declaration
829
944
  * @param definition - The command definition
830
945
  */
831
- processCommandMethod(e, n, r, o) {
832
- const a = l(r.schema.key);
833
- h(e, this.outputDir, a);
834
- const s = r.pathParameters.map((i) => ({
835
- name: i.name,
946
+ processCommandMethod(e, t, o, r) {
947
+ const s = u(o.schema.key);
948
+ this.logger.info(
949
+ `Adding import for command model: ${s.name} from path: ${s.path}`
950
+ ), y(e, this.outputDir, s), this.logger.info(
951
+ `Generating command method: ${h(o.name)} for command: ${o.name}`
952
+ ), this.logger.info(
953
+ `Command method details: HTTP ${o.method}, path: ${o.path}, return type: ${r}`
954
+ );
955
+ const i = o.pathParameters.map((a) => (this.logger.info(
956
+ `Adding path parameter: ${a.name} (type: string)`
957
+ ), {
958
+ name: a.name,
836
959
  type: "string",
837
960
  decorators: [
838
961
  {
839
962
  name: "path",
840
- arguments: [`'${i.name}'`]
963
+ arguments: [`'${a.name}'`]
841
964
  }
842
965
  ]
843
966
  }));
844
- s.push({
967
+ this.logger.info(
968
+ `Adding command request parameter: commandRequest (type: CommandRequest<${s.name}>)`
969
+ ), i.push({
845
970
  name: "commandRequest",
846
- type: `CommandRequest<${a.name}>`,
971
+ type: `CommandRequest<${s.name}>`,
847
972
  decorators: [
848
973
  {
849
974
  name: "request",
850
975
  arguments: []
851
976
  }
852
977
  ]
853
- }), s.push({
978
+ }), this.logger.info(
979
+ "Adding attributes parameter: attributes (type: Record<string, any>)"
980
+ ), i.push({
854
981
  name: "attributes",
855
982
  type: "Record<string, any>",
856
983
  decorators: [
@@ -860,24 +987,28 @@ class Ee extends O {
860
987
  }
861
988
  ]
862
989
  });
863
- const c = n.addMethod({
864
- name: q(r.name),
990
+ const c = t.addMethod({
991
+ name: h(o.name),
865
992
  decorators: [
866
993
  {
867
- name: this.methodToDecorator(r.method),
868
- arguments: [`${this.getEndpointPath(r)}`]
994
+ name: this.methodToDecorator(o.method),
995
+ arguments: [`${this.getEndpointPath(o)}`]
869
996
  }
870
997
  ],
871
- parameters: s,
872
- returnType: o,
998
+ parameters: i,
999
+ returnType: r,
873
1000
  statements: [
874
- `throw autoGeneratedError(${s.map((i) => i.name).join(",")});`
1001
+ `throw autoGeneratedError(${i.map((a) => a.name).join(",")});`
875
1002
  ]
876
1003
  });
877
- A(c, r.summary, r.description);
1004
+ (o.summary || o.description) && this.logger.info(
1005
+ `Adding JSDoc documentation for method: ${h(o.name)}`
1006
+ ), P(c, o.summary, o.description), this.logger.success(
1007
+ `Command method generated: ${h(o.name)}`
1008
+ );
878
1009
  }
879
1010
  }
880
- class Oe extends O {
1011
+ class Se extends x {
881
1012
  queryClientGenerator;
882
1013
  commandClientGenerator;
883
1014
  /**
@@ -885,17 +1016,23 @@ class Oe extends O {
885
1016
  * @param context - The generation context containing OpenAPI spec and project details
886
1017
  */
887
1018
  constructor(e) {
888
- super(e), this.queryClientGenerator = new Pe(e), this.commandClientGenerator = new Ee(e);
1019
+ super(e), this.queryClientGenerator = new Oe(e), this.commandClientGenerator = new Ie(e);
889
1020
  }
890
1021
  /**
891
1022
  * Generates client classes for all aggregates.
892
1023
  */
893
1024
  generate() {
894
- this.logger.progress(
1025
+ this.logger.info("--- Generating Clients ---"), this.logger.progress(
895
1026
  `Generating clients for ${this.contextAggregates.size} bounded contexts`
896
1027
  );
897
- for (const [e] of this.contextAggregates)
898
- this.logger.progress(`Processing bounded context: ${e}`), this.processBoundedContext(e);
1028
+ let e = 0;
1029
+ for (const [t] of this.contextAggregates)
1030
+ e++, this.logger.progressWithCount(
1031
+ e,
1032
+ this.contextAggregates.size,
1033
+ `Processing bounded context: ${t}`,
1034
+ 1
1035
+ ), this.processBoundedContext(t);
899
1036
  this.queryClientGenerator.generate(), this.commandClientGenerator.generate(), this.logger.success("Client generation completed");
900
1037
  }
901
1038
  /**
@@ -903,19 +1040,25 @@ class Oe extends O {
903
1040
  * @param contextAlias - The alias of the bounded context to process
904
1041
  */
905
1042
  processBoundedContext(e) {
906
- const n = `${e}/boundedContext.ts`;
907
- v(this.project, this.outputDir, n).addStatements(
1043
+ const t = `${e}/boundedContext.ts`;
1044
+ this.logger.info(`Creating bounded context file: ${t}`);
1045
+ const o = D(this.project, this.outputDir, t);
1046
+ this.logger.info(
1047
+ `Adding bounded context alias constant: BOUNDED_CONTEXT_ALIAS = '${e}'`
1048
+ ), o.addStatements(
908
1049
  `export const BOUNDED_CONTEXT_ALIAS = '${e}';`
1050
+ ), this.logger.success(
1051
+ `Bounded context file created successfully: ${t}`
909
1052
  );
910
1053
  }
911
1054
  }
912
- class xe {
1055
+ class Me {
913
1056
  /**
914
1057
  * Creates a new CodeGenerator instance.
915
1058
  * @param options - Configuration options for code generation
916
1059
  */
917
1060
  constructor(e) {
918
- this.options = e, this.project = e.project;
1061
+ this.options = e, this.project = e.project, this.options.logger.info("CodeGenerator instance created");
919
1062
  }
920
1063
  project;
921
1064
  /**
@@ -924,19 +1067,113 @@ class xe {
924
1067
  * and formats the output files.
925
1068
  */
926
1069
  async generate() {
927
- const e = await Y(this.options.inputPath), r = new Ae(e).resolve(), o = {
1070
+ this.options.logger.info(
1071
+ "Starting code generation from OpenAPI specification"
1072
+ ), 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");
1073
+ const e = await ee(this.options.inputPath);
1074
+ this.options.logger.info("OpenAPI specification parsed successfully"), this.options.logger.info("Resolving bounded context aggregates");
1075
+ const o = new Pe(e).resolve();
1076
+ this.options.logger.info(
1077
+ `Resolved ${o.size} bounded context aggregates`
1078
+ );
1079
+ const r = {
928
1080
  openAPI: e,
929
1081
  project: this.project,
930
1082
  outputDir: this.options.outputDir,
931
- contextAggregates: r,
1083
+ contextAggregates: o,
932
1084
  logger: this.options.logger
933
1085
  };
934
- new ue(o).generate(), new Oe(o).generate(), this.project.getSourceFiles().forEach((c) => {
935
- c.formatText(), c.organizeImports(), c.fixMissingImports();
936
- }), await this.project.save();
1086
+ this.options.logger.info("Generating models"), new we(r).generate(), this.options.logger.info("Models generated successfully"), this.options.logger.info("Generating clients"), new Se(r).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");
1087
+ }
1088
+ /**
1089
+ * Generates index.ts files for all subdirectories in the output directory.
1090
+ * Scans all directories, gets all .ts files in each directory,
1091
+ * and creates index.ts files with export * from './xxx' statements.
1092
+ */
1093
+ generateIndex() {
1094
+ this.options.logger.info(
1095
+ `Generating index files for output directory: ${this.options.outputDir}`
1096
+ );
1097
+ const e = this.project.getDirectory(this.options.outputDir);
1098
+ if (!e) {
1099
+ this.options.logger.info(
1100
+ "Output directory not found, skipping index generation"
1101
+ );
1102
+ return;
1103
+ }
1104
+ this.processDirectory(e), this.options.logger.info("Index file generation completed");
1105
+ }
1106
+ processDirectory(e) {
1107
+ const t = e.getDirectories();
1108
+ this.options.logger.info(`Processing ${t.length} subdirectories`);
1109
+ for (const o of t)
1110
+ this.options.logger.info(`Processing subdirectory: ${o.getPath()}`), this.generateIndexForDirectory(o), this.processDirectory(o);
1111
+ }
1112
+ /**
1113
+ * Generates an index.ts file for a specific directory.
1114
+ * @param dir - The directory to generate index.ts for
1115
+ */
1116
+ generateIndexForDirectory(e) {
1117
+ const t = e.getPath();
1118
+ this.options.logger.info(`Generating index for directory: ${t}`);
1119
+ const o = e.getSourceFiles().filter(
1120
+ (c) => c.getBaseName().endsWith(".ts") && c.getBaseName() !== "index.ts"
1121
+ );
1122
+ let r = [];
1123
+ try {
1124
+ r = v.readdirSync(t).filter((c) => {
1125
+ const a = K.join(t, c);
1126
+ return v.statSync(a).isDirectory();
1127
+ });
1128
+ } catch (c) {
1129
+ this.options.logger.error(
1130
+ `Failed to read subdirectories for ${t}: ${c}`
1131
+ );
1132
+ }
1133
+ if (this.options.logger.info(
1134
+ `Found ${o.length} TypeScript files and ${r.length} subdirectories in ${t}`
1135
+ ), o.length === 0 && r.length === 0) {
1136
+ this.options.logger.info(
1137
+ `No files or subdirectories to export in ${t}, skipping index generation`
1138
+ );
1139
+ return;
1140
+ }
1141
+ const s = `${t}/index.ts`;
1142
+ this.options.logger.info(`Creating/updating index file: ${s}`);
1143
+ const i = this.project.getSourceFile(s) || this.project.createSourceFile(s, "", { overwrite: !0 });
1144
+ i.removeText();
1145
+ for (const c of o) {
1146
+ const a = `./${c.getBaseNameWithoutExtension()}`;
1147
+ this.options.logger.info(`Adding export for file: ${a}`), i.addExportDeclaration({
1148
+ moduleSpecifier: a,
1149
+ isTypeOnly: !1,
1150
+ namedExports: []
1151
+ });
1152
+ }
1153
+ for (const c of r) {
1154
+ const a = `./${c}`;
1155
+ this.options.logger.info(
1156
+ `Adding export for subdirectory: ${a}`
1157
+ ), i.addExportDeclaration({
1158
+ moduleSpecifier: a,
1159
+ isTypeOnly: !1,
1160
+ namedExports: []
1161
+ });
1162
+ }
1163
+ this.options.logger.info(
1164
+ `Index file generated for ${t} with ${o.length + r.length} exports`
1165
+ );
1166
+ }
1167
+ optimizeSourceFiles() {
1168
+ const e = this.project.getSourceFiles();
1169
+ this.options.logger.info(`Optimizing ${e.length} source files`), e.forEach((t, o) => {
1170
+ this.options.logger.info(
1171
+ `Optimizing file ${o + 1}/${e.length}`
1172
+ ), t.formatText(), t.organizeImports(), t.fixMissingImports();
1173
+ }), this.options.logger.info("All source files optimized");
937
1174
  }
938
1175
  }
939
1176
  export {
940
- xe as CodeGenerator
1177
+ Me as CodeGenerator
941
1178
  };
942
1179
  //# sourceMappingURL=index.js.map