ng-openapi 0.2.22 → 0.3.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.
Files changed (5) hide show
  1. package/README.md +41 -17
  2. package/cli.cjs +1199 -857
  3. package/index.d.ts +529 -83
  4. package/index.js +1265 -906
  5. package/package.json +1 -1
package/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
8
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
9
  var __getProtoOf = Object.getPrototypeOf;
@@ -22,6 +24,7 @@ var __spreadValues = (a, b) => {
22
24
  }
23
25
  return a;
24
26
  };
27
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
28
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
26
29
  var __export = (target, all) => {
27
30
  for (var name in all)
@@ -75,17 +78,29 @@ var index_exports = {};
75
78
  __export(index_exports, {
76
79
  BASE_INTERCEPTOR_HEADER_COMMENT: () => BASE_INTERCEPTOR_HEADER_COMMENT,
77
80
  CONTENT_TYPES: () => CONTENT_TYPES,
81
+ ConfigValidationError: () => ConfigValidationError,
78
82
  HTTP_RESOURCE_GENERATOR_HEADER_COMMENT: () => HTTP_RESOURCE_GENERATOR_HEADER_COMMENT,
79
83
  MAIN_INDEX_GENERATOR_HEADER_COMMENT: () => MAIN_INDEX_GENERATOR_HEADER_COMMENT,
84
+ NgOpenApiError: () => NgOpenApiError,
80
85
  PROVIDER_GENERATOR_HEADER_COMMENT: () => PROVIDER_GENERATOR_HEADER_COMMENT,
81
86
  REQUEST_PARAMS_GENERATOR_HEADER_COMMENT: () => REQUEST_PARAMS_GENERATOR_HEADER_COMMENT,
82
87
  SERVICE_GENERATOR_HEADER_COMMENT: () => SERVICE_GENERATOR_HEADER_COMMENT,
83
88
  SERVICE_INDEX_GENERATOR_HEADER_COMMENT: () => SERVICE_INDEX_GENERATOR_HEADER_COMMENT,
89
+ SpecLoadError: () => SpecLoadError,
90
+ SpecParseError: () => SpecParseError,
84
91
  SwaggerParser: () => SwaggerParser,
85
92
  TYPE_GENERATOR_HEADER_COMMENT: () => TYPE_GENERATOR_HEADER_COMMENT,
86
93
  ZOD_PLUGIN_GENERATOR_HEADER_COMMENT: () => ZOD_PLUGIN_GENERATOR_HEADER_COMMENT,
87
94
  ZOD_PLUGIN_INDEX_GENERATOR_HEADER_COMMENT: () => ZOD_PLUGIN_INDEX_GENERATOR_HEADER_COMMENT,
88
95
  camelCase: () => camelCase,
96
+ defineConfig: () => defineConfig,
97
+ emitDefaultHeadersMerge: () => emitDefaultHeadersMerge,
98
+ emitHeaders: () => emitHeaders,
99
+ emitQueryParams: () => emitQueryParams,
100
+ emitResponseTypeOption: () => emitResponseTypeOption,
101
+ emitSignalAwareQueryParams: () => emitSignalAwareQueryParams,
102
+ emitUrlConstruction: () => emitUrlConstruction,
103
+ emitUrlExpression: () => emitUrlExpression,
89
104
  escapeString: () => escapeString,
90
105
  extractPaths: () => extractPaths,
91
106
  generateFromConfig: () => generateFromConfig,
@@ -101,17 +116,234 @@ __export(index_exports, {
101
116
  inferResponseTypeFromContentType: () => inferResponseTypeFromContentType,
102
117
  isDataTypeInterface: () => isDataTypeInterface,
103
118
  isPrimitiveType: () => isPrimitiveType,
119
+ isUrl: () => isUrl,
120
+ joinRequestOptionEntries: () => joinRequestOptionEntries,
104
121
  kebabCase: () => kebabCase,
122
+ normalizeSchema: () => normalizeSchema,
123
+ normalizeSpec: () => normalizeSpec,
105
124
  nullableType: () => nullableType,
106
125
  pascalCase: () => pascalCase,
107
126
  pascalCaseForEnums: () => pascalCaseForEnums,
127
+ plainParamValue: () => plainParamValue,
108
128
  screamingSnakeCase: () => screamingSnakeCase,
129
+ signalAwareParamValue: () => signalAwareParamValue,
130
+ validateGeneratorConfig: () => validateGeneratorConfig,
109
131
  validateInput: () => validateInput
110
132
  });
111
133
  module.exports = __toCommonJS(index_exports);
112
134
 
113
135
  // src/lib/core/generator.ts
114
- var import_ts_morph7 = require("ts-morph");
136
+ var import_ts_morph10 = require("ts-morph");
137
+
138
+ // ../shared/src/core/spec-loader.ts
139
+ var fs = __toESM(require("fs"));
140
+
141
+ // ../shared/src/utils/functions/is-url.ts
142
+ function isUrl(input) {
143
+ try {
144
+ const url = new URL(input);
145
+ return [
146
+ "http:",
147
+ "https:"
148
+ ].includes(url.protocol);
149
+ } catch (e) {
150
+ return false;
151
+ }
152
+ }
153
+ __name(isUrl, "isUrl");
154
+
155
+ // ../shared/src/errors.ts
156
+ var _NgOpenApiError = class _NgOpenApiError extends Error {
157
+ constructor(message, cause) {
158
+ super(message);
159
+ /** The underlying error that caused this one, when there is one. */
160
+ __publicField(this, "cause");
161
+ this.name = new.target.name;
162
+ this.cause = cause;
163
+ }
164
+ };
165
+ __name(_NgOpenApiError, "NgOpenApiError");
166
+ var NgOpenApiError = _NgOpenApiError;
167
+ var _SpecLoadError = class _SpecLoadError extends NgOpenApiError {
168
+ constructor(message, source, cause) {
169
+ super(message, cause);
170
+ /** The file path or URL that failed to load. */
171
+ __publicField(this, "source");
172
+ this.source = source;
173
+ }
174
+ };
175
+ __name(_SpecLoadError, "SpecLoadError");
176
+ var SpecLoadError = _SpecLoadError;
177
+ var _SpecParseError = class _SpecParseError extends NgOpenApiError {
178
+ constructor(message, source, cause) {
179
+ super(message, cause);
180
+ /** The file path or URL the content came from, when known. */
181
+ __publicField(this, "source");
182
+ this.source = source;
183
+ }
184
+ };
185
+ __name(_SpecParseError, "SpecParseError");
186
+ var SpecParseError = _SpecParseError;
187
+
188
+ // ../shared/src/core/spec-loader.ts
189
+ function loadSpecContent(pathOrUrl) {
190
+ return __async(this, null, function* () {
191
+ if (isUrl(pathOrUrl)) {
192
+ return yield fetchUrlContent(pathOrUrl);
193
+ }
194
+ try {
195
+ return fs.readFileSync(pathOrUrl, "utf8");
196
+ } catch (error) {
197
+ throw new SpecLoadError(`Failed to read spec file: ${pathOrUrl}${error instanceof Error ? ` - ${error.message}` : ""}`, pathOrUrl, error);
198
+ }
199
+ });
200
+ }
201
+ __name(loadSpecContent, "loadSpecContent");
202
+ function fetchUrlContent(url) {
203
+ return __async(this, null, function* () {
204
+ try {
205
+ const response = yield fetch(url, {
206
+ method: "GET",
207
+ headers: {
208
+ Accept: "application/json, application/yaml, text/yaml, text/plain, */*",
209
+ "User-Agent": "ng-openapi"
210
+ },
211
+ // 30 second timeout
212
+ signal: AbortSignal.timeout(3e4)
213
+ });
214
+ if (!response.ok) {
215
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
216
+ }
217
+ const content = yield response.text();
218
+ if (!content || content.trim() === "") {
219
+ throw new Error(`Empty response from URL: ${url}`);
220
+ }
221
+ return content;
222
+ } catch (error) {
223
+ let errorMessage = `Failed to fetch content from URL: ${url}`;
224
+ if (error instanceof Error && (error.name === "TimeoutError" || error.name === "AbortError")) {
225
+ errorMessage += " - Request timeout (30s)";
226
+ } else if (error instanceof Error && error.message) {
227
+ errorMessage += ` - ${error.message}`;
228
+ }
229
+ throw new SpecLoadError(errorMessage, url, error);
230
+ }
231
+ });
232
+ }
233
+ __name(fetchUrlContent, "fetchUrlContent");
234
+
235
+ // ../shared/src/core/spec-format.ts
236
+ var path = __toESM(require("path"));
237
+ var yaml = __toESM(require("js-yaml"));
238
+ function parseSpecContent(content, pathOrUrl) {
239
+ let format;
240
+ if (isUrl(pathOrUrl)) {
241
+ const urlPath = new URL(pathOrUrl).pathname.toLowerCase();
242
+ if (urlPath.endsWith(".json")) {
243
+ format = "json";
244
+ } else if (urlPath.endsWith(".yaml") || urlPath.endsWith(".yml")) {
245
+ format = "yaml";
246
+ } else {
247
+ format = detectFormat(content);
248
+ }
249
+ } else {
250
+ const extension = path.extname(pathOrUrl).toLowerCase();
251
+ switch (extension) {
252
+ case ".json":
253
+ format = "json";
254
+ break;
255
+ case ".yaml":
256
+ format = "yaml";
257
+ break;
258
+ case ".yml":
259
+ format = "yml";
260
+ break;
261
+ default:
262
+ format = detectFormat(content);
263
+ }
264
+ }
265
+ try {
266
+ switch (format) {
267
+ case "json":
268
+ return JSON.parse(content);
269
+ case "yaml":
270
+ case "yml":
271
+ return yaml.load(content);
272
+ default:
273
+ throw new Error(`Unable to determine format for: ${pathOrUrl}`);
274
+ }
275
+ } catch (error) {
276
+ throw new SpecParseError(`Failed to parse ${format.toUpperCase()} content from: ${pathOrUrl}. Error: ${error instanceof Error ? error.message : error}`, pathOrUrl, error);
277
+ }
278
+ }
279
+ __name(parseSpecContent, "parseSpecContent");
280
+ function detectFormat(content) {
281
+ const trimmed = content.trim();
282
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
283
+ return "json";
284
+ }
285
+ if (trimmed.includes("openapi:") || trimmed.includes("swagger:") || trimmed.includes("---") || /^[a-zA-Z][a-zA-Z0-9_]*\s*:/.test(trimmed)) {
286
+ return "yaml";
287
+ }
288
+ return "json";
289
+ }
290
+ __name(detectFormat, "detectFormat");
291
+
292
+ // ../shared/src/utils/content-types.constants.ts
293
+ var CONTENT_TYPES = {
294
+ MULTIPART: "multipart/form-data",
295
+ FORM_URLENCODED: "application/x-www-form-urlencoded",
296
+ JSON: "application/json"
297
+ };
298
+
299
+ // ../shared/src/utils/functions/extract-paths.ts
300
+ function extractPaths(swaggerPaths = {}, methods = [
301
+ "get",
302
+ "post",
303
+ "put",
304
+ "patch",
305
+ "delete",
306
+ "options",
307
+ "head"
308
+ ]) {
309
+ const paths = [];
310
+ Object.entries(swaggerPaths).forEach(([path13, pathItem]) => {
311
+ methods.forEach((method) => {
312
+ const operation = pathItem[method];
313
+ if (operation) {
314
+ paths.push({
315
+ path: path13,
316
+ method: method.toUpperCase(),
317
+ operationId: operation.operationId,
318
+ summary: operation.summary,
319
+ description: operation.description,
320
+ tags: operation.tags || [],
321
+ parameters: parseParameters(operation.parameters || [], pathItem.parameters || []),
322
+ requestBody: operation.requestBody,
323
+ responses: operation.responses || {}
324
+ });
325
+ }
326
+ });
327
+ });
328
+ return paths;
329
+ }
330
+ __name(extractPaths, "extractPaths");
331
+ function parseParameters(operationParams, pathParams) {
332
+ const allParams = [
333
+ ...pathParams,
334
+ ...operationParams
335
+ ];
336
+ return allParams.map((param) => ({
337
+ name: param.name,
338
+ in: param.in,
339
+ required: param.required || param.in === "path",
340
+ schema: param.schema,
341
+ type: param.type,
342
+ format: param.format,
343
+ description: param.description
344
+ }));
345
+ }
346
+ __name(parseParameters, "parseParameters");
115
347
 
116
348
  // ../shared/src/utils/string.utils.ts
117
349
  function camelCase(str) {
@@ -157,7 +389,7 @@ function getTypeScriptType(schemaOrType, config, formatOrNullable, isNullable, c
157
389
  return nullableType(pascalCaseForEnums(refName), nullable);
158
390
  }
159
391
  if (schema.type === "array") {
160
- const itemType = schema.items ? getTypeScriptType(schema.items, config, void 0, void 0, context) : "unknown";
392
+ const itemType = schema.items ? Array.isArray(schema.items) ? "any" : getTypeScriptType(schema.items, config, void 0, void 0, context) : "unknown";
161
393
  return nullable ? `(Array<${itemType}> | null)` : `Array<${itemType}>`;
162
394
  }
163
395
  switch (schema.type) {
@@ -204,78 +436,6 @@ function escapeString(str) {
204
436
  }
205
437
  __name(escapeString, "escapeString");
206
438
 
207
- // ../shared/src/utils/functions/token-names.ts
208
- function getClientContextTokenName(clientName = "default") {
209
- const clientSuffix = clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
210
- return `CLIENT_CONTEXT_TOKEN_${clientSuffix}`;
211
- }
212
- __name(getClientContextTokenName, "getClientContextTokenName");
213
- function getBasePathTokenName(clientName = "default") {
214
- const clientSuffix = clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
215
- return `BASE_PATH_${clientSuffix}`;
216
- }
217
- __name(getBasePathTokenName, "getBasePathTokenName");
218
- function getInterceptorsTokenName(clientName = "default") {
219
- const clientSuffix = clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
220
- return `HTTP_INTERCEPTORS_${clientSuffix}`;
221
- }
222
- __name(getInterceptorsTokenName, "getInterceptorsTokenName");
223
-
224
- // ../shared/src/utils/functions/duplicate-function-name.ts
225
- function hasDuplicateFunctionNames(arr) {
226
- return new Set(arr.map((fn) => fn.getName())).size !== arr.length;
227
- }
228
- __name(hasDuplicateFunctionNames, "hasDuplicateFunctionNames");
229
-
230
- // ../shared/src/utils/functions/extract-paths.ts
231
- function extractPaths(swaggerPaths = {}, methods = [
232
- "get",
233
- "post",
234
- "put",
235
- "patch",
236
- "delete",
237
- "options",
238
- "head"
239
- ]) {
240
- const paths = [];
241
- Object.entries(swaggerPaths).forEach(([path13, pathItem]) => {
242
- methods.forEach((method) => {
243
- if (pathItem[method]) {
244
- const operation = pathItem[method];
245
- paths.push({
246
- path: path13,
247
- method: method.toUpperCase(),
248
- operationId: operation.operationId,
249
- summary: operation.summary,
250
- description: operation.description,
251
- tags: operation.tags || [],
252
- parameters: parseParameters(operation.parameters || [], pathItem.parameters || []),
253
- requestBody: operation.requestBody,
254
- responses: operation.responses || {}
255
- });
256
- }
257
- });
258
- });
259
- return paths;
260
- }
261
- __name(extractPaths, "extractPaths");
262
- function parseParameters(operationParams, pathParams) {
263
- const allParams = [
264
- ...pathParams,
265
- ...operationParams
266
- ];
267
- return allParams.map((param) => ({
268
- name: param.name,
269
- in: param.in,
270
- required: param.required || param.in === "path",
271
- schema: param.schema,
272
- type: param.type,
273
- format: param.format,
274
- description: param.description
275
- }));
276
- }
277
- __name(parseParameters, "parseParameters");
278
-
279
439
  // ../shared/src/utils/functions/extract-swagger-response-type.ts
280
440
  function getResponseTypeFromResponse(response, responseTypeMapping) {
281
441
  var _a;
@@ -340,7 +500,7 @@ function isPrimitiveType(schema) {
340
500
  "integer",
341
501
  "boolean"
342
502
  ];
343
- if (primitiveTypes.includes(schema.type)) {
503
+ if (schema.type && primitiveTypes.includes(schema.type)) {
344
504
  return true;
345
505
  }
346
506
  if (schema.type === "array") {
@@ -411,60 +571,434 @@ function getResponseType(response, config) {
411
571
  }
412
572
  __name(getResponseType, "getResponseType");
413
573
 
414
- // ../shared/src/utils/content-types.constants.ts
415
- var CONTENT_TYPES = {
416
- MULTIPART: "multipart/form-data",
417
- FORM_URLENCODED: "application/x-www-form-urlencoded",
418
- JSON: "application/json"
419
- };
420
-
421
- // ../shared/src/utils/functions/get-request-body-type.ts
422
- function getRequestBodyType(requestBody, config) {
423
- const content = requestBody.content || {};
424
- const jsonContent = content[CONTENT_TYPES.JSON];
425
- if (jsonContent == null ? void 0 : jsonContent.schema) {
426
- return getTypeScriptType(jsonContent.schema, config, jsonContent.schema.nullable);
574
+ // ../shared/src/core/normalize.ts
575
+ function normalizeSpec(spec) {
576
+ var _a;
577
+ const rawDefinitions = spec.definitions || ((_a = spec.components) == null ? void 0 : _a.schemas) || {};
578
+ const definitions = Object.fromEntries(Object.entries(rawDefinitions).map(([name, definition]) => [
579
+ name,
580
+ normalizeSchema(definition)
581
+ ]));
582
+ const resolveReference = /* @__PURE__ */ __name((ref) => {
583
+ const parts = ref.split("/");
584
+ return definitions[parts[parts.length - 1]];
585
+ }, "resolveReference");
586
+ return {
587
+ version: spec.swagger ? {
588
+ type: "swagger",
589
+ version: spec.swagger
590
+ } : spec.openapi ? {
591
+ type: "openapi",
592
+ version: spec.openapi
593
+ } : null,
594
+ definitions,
595
+ operations: extractPaths(spec.paths).map((operation) => normalizeOperation(normalizeOperationSchemas(operation), resolveReference)),
596
+ resolveReference
597
+ };
598
+ }
599
+ __name(normalizeSpec, "normalizeSpec");
600
+ function normalizeSchema(schema) {
601
+ const normalized = __spreadValues({}, schema);
602
+ const rawType = normalized.type;
603
+ if (Array.isArray(rawType)) {
604
+ const types = rawType.filter((t) => t !== "null");
605
+ if (types.length < rawType.length) {
606
+ normalized.nullable = true;
607
+ }
608
+ normalized.type = types.length === 1 ? types[0] : types.length === 0 ? "null" : types;
609
+ }
610
+ if (normalized.const !== void 0 && !normalized.enum) {
611
+ const constType = typeof normalized.const;
612
+ if (constType === "string" || constType === "number") {
613
+ normalized.enum = [
614
+ normalized.const
615
+ ];
616
+ if (normalized.type === void 0) {
617
+ normalized.type = constType;
618
+ }
619
+ delete normalized.const;
620
+ } else if (constType === "boolean") {
621
+ if (normalized.type === void 0) {
622
+ normalized.type = "boolean";
623
+ }
624
+ delete normalized.const;
625
+ }
427
626
  }
428
- return "any";
627
+ if (normalized.properties) {
628
+ normalized.properties = Object.fromEntries(Object.entries(normalized.properties).map(([name, property]) => [
629
+ name,
630
+ normalizeSchema(property)
631
+ ]));
632
+ }
633
+ if (normalized.items) {
634
+ normalized.items = Array.isArray(normalized.items) ? normalized.items.map(normalizeSchema) : normalizeSchema(normalized.items);
635
+ }
636
+ if (typeof normalized.additionalProperties === "object") {
637
+ normalized.additionalProperties = normalizeSchema(normalized.additionalProperties);
638
+ }
639
+ if (normalized.allOf) {
640
+ normalized.allOf = normalized.allOf.map(normalizeSchema);
641
+ }
642
+ if (normalized.oneOf) {
643
+ normalized.oneOf = normalized.oneOf.map(normalizeSchema);
644
+ }
645
+ if (normalized.anyOf) {
646
+ normalized.anyOf = normalized.anyOf.map(normalizeSchema);
647
+ }
648
+ return normalized;
429
649
  }
430
- __name(getRequestBodyType, "getRequestBodyType");
431
-
432
- // ../shared/src/utils/functions/is-data-type-interface.ts
433
- function isDataTypeInterface(type) {
434
- const invalidTypes = [
435
- "any",
436
- "File",
437
- "string",
438
- "number",
439
- "boolean",
440
- "object",
441
- "unknown",
442
- "[]",
443
- "Array"
444
- ];
445
- return !invalidTypes.some((invalidType) => type.includes(invalidType));
650
+ __name(normalizeSchema, "normalizeSchema");
651
+ function normalizeOperationSchemas(operation) {
652
+ var _a;
653
+ return __spreadProps(__spreadValues({}, operation), {
654
+ parameters: (_a = operation.parameters) == null ? void 0 : _a.map((parameter) => parameter.schema ? __spreadProps(__spreadValues({}, parameter), {
655
+ schema: normalizeSchema(parameter.schema)
656
+ }) : parameter),
657
+ requestBody: operation.requestBody ? __spreadProps(__spreadValues({}, operation.requestBody), {
658
+ content: normalizeContentSchemas(operation.requestBody.content)
659
+ }) : operation.requestBody,
660
+ responses: operation.responses ? Object.fromEntries(Object.entries(operation.responses).map(([status, response]) => [
661
+ status,
662
+ __spreadProps(__spreadValues({}, response), {
663
+ content: normalizeContentSchemas(response.content)
664
+ })
665
+ ])) : operation.responses
666
+ });
446
667
  }
447
- __name(isDataTypeInterface, "isDataTypeInterface");
448
-
449
- // ../shared/src/utils/functions/generate-parse-request-type-params.ts
450
- function generateParseRequestTypeParams(params) {
451
- const bodyParam = params.find((param) => {
452
- return typeof param.type === "string" && isDataTypeInterface(param.type);
668
+ __name(normalizeOperationSchemas, "normalizeOperationSchemas");
669
+ function normalizeContentSchemas(content) {
670
+ if (!content) return content;
671
+ return Object.fromEntries(Object.entries(content).map(([contentType, mediaType]) => [
672
+ contentType,
673
+ (mediaType == null ? void 0 : mediaType.schema) ? __spreadProps(__spreadValues({}, mediaType), {
674
+ schema: normalizeSchema(mediaType.schema)
675
+ }) : mediaType
676
+ ]));
677
+ }
678
+ __name(normalizeContentSchemas, "normalizeContentSchemas");
679
+ function normalizeOperation(operation, resolveRef) {
680
+ var _a, _b, _c;
681
+ const content = (_a = operation.requestBody) == null ? void 0 : _a.content;
682
+ const isMultipart = !!(content == null ? void 0 : content[CONTENT_TYPES.MULTIPART]);
683
+ const isUrlEncoded = !!(content == null ? void 0 : content[CONTENT_TYPES.FORM_URLENCODED]) && !(content == null ? void 0 : content[CONTENT_TYPES.JSON]);
684
+ const formDataSchema = isMultipart ? resolveBodySchema(operation.requestBody, CONTENT_TYPES.MULTIPART, resolveRef) : void 0;
685
+ const urlEncodedSchema = isUrlEncoded ? resolveBodySchema(operation.requestBody, CONTENT_TYPES.FORM_URLENCODED, resolveRef) : void 0;
686
+ return __spreadProps(__spreadValues({}, operation), {
687
+ pathParams: ((_b = operation.parameters) == null ? void 0 : _b.filter((p) => p.in === "path")) || [],
688
+ queryParams: ((_c = operation.parameters) == null ? void 0 : _c.filter((p) => p.in === "query")) || [],
689
+ hasBody: !!operation.requestBody,
690
+ isMultipart,
691
+ isUrlEncoded,
692
+ formDataSchema,
693
+ formDataFields: Object.keys((formDataSchema == null ? void 0 : formDataSchema.properties) || {}),
694
+ urlEncodedSchema,
695
+ urlEncodedFields: Object.keys((urlEncodedSchema == null ? void 0 : urlEncodedSchema.properties) || {}),
696
+ responseType: determineResponseType(operation)
453
697
  });
454
- if (bodyParam) {
455
- const optional = bodyParam.hasQuestionToken ? " | undefined" : "";
456
- return `${bodyParam.type}${optional}`;
698
+ }
699
+ __name(normalizeOperation, "normalizeOperation");
700
+ function resolveBodySchema(requestBody, contentType, resolveRef) {
701
+ var _a, _b;
702
+ const schema = (_b = (_a = requestBody == null ? void 0 : requestBody.content) == null ? void 0 : _a[contentType]) == null ? void 0 : _b.schema;
703
+ return (schema == null ? void 0 : schema.$ref) ? resolveRef(schema.$ref) : schema;
704
+ }
705
+ __name(resolveBodySchema, "resolveBodySchema");
706
+ function determineResponseType(operation) {
707
+ var _a;
708
+ const successResponses = [
709
+ "200",
710
+ "201",
711
+ "202",
712
+ "204",
713
+ "206"
714
+ ];
715
+ for (const statusCode of successResponses) {
716
+ const response = (_a = operation.responses) == null ? void 0 : _a[statusCode];
717
+ if (!response) continue;
718
+ return getResponseTypeFromResponse(response);
457
719
  }
458
- return "";
720
+ return "json";
459
721
  }
460
- __name(generateParseRequestTypeParams, "generateParseRequestTypeParams");
722
+ __name(determineResponseType, "determineResponseType");
461
723
 
462
- // ../shared/src/config/constants.ts
463
- var disableLinting = `/* @ts-nocheck */
464
- /* eslint-disable */
465
- /* @noformat */
466
- /* @formatter:off */
467
- `;
724
+ // ../shared/src/core/swagger-parser.ts
725
+ var _SwaggerParser = class _SwaggerParser {
726
+ constructor(spec, config) {
727
+ __publicField(this, "spec");
728
+ __publicField(this, "normalized");
729
+ var _a, _b;
730
+ const isInputValid = (_b = (_a = config.validateInput) == null ? void 0 : _a.call(config, spec)) != null ? _b : true;
731
+ if (!isInputValid) {
732
+ throw new SpecParseError("Swagger spec is not valid. Check your `validateInput` condition.");
733
+ }
734
+ this.spec = spec;
735
+ }
736
+ /**
737
+ * Loads, parses and wraps a spec.
738
+ *
739
+ * @throws SpecLoadError when the file/URL cannot be read.
740
+ * @throws SpecParseError when the content cannot be parsed or the
741
+ * config's `validateInput` hook rejects the spec.
742
+ */
743
+ static create(swaggerPathOrUrl, config) {
744
+ return __async(this, null, function* () {
745
+ const swaggerContent = yield loadSpecContent(swaggerPathOrUrl);
746
+ const spec = parseSpecContent(swaggerContent, swaggerPathOrUrl);
747
+ return new _SwaggerParser(spec, config);
748
+ });
749
+ }
750
+ /**
751
+ * The version-free model generators consume. Computed once and cached —
752
+ * all generators share the same NormalizedOperation instances, so they
753
+ * can be used as Map keys across generators.
754
+ */
755
+ getNormalizedSpec() {
756
+ var _a;
757
+ (_a = this.normalized) != null ? _a : this.normalized = normalizeSpec(this.spec);
758
+ return this.normalized;
759
+ }
760
+ /** Definition map regardless of version: 2.0 `definitions` or 3.x `components.schemas`. */
761
+ getDefinitions() {
762
+ var _a;
763
+ return this.spec.definitions || ((_a = this.spec.components) == null ? void 0 : _a.schemas) || {};
764
+ }
765
+ /** One definition by bare name, or undefined when the spec has none by that name. */
766
+ getDefinition(name) {
767
+ const definitions = this.getDefinitions();
768
+ return definitions[name];
769
+ }
770
+ /** Resolves "#/definitions/X" / "#/components/schemas/X" style refs by their last segment. */
771
+ resolveReference(ref) {
772
+ const parts = ref.split("/");
773
+ const definitionName = parts[parts.length - 1];
774
+ return this.getDefinition(definitionName);
775
+ }
776
+ getAllDefinitionNames() {
777
+ return Object.keys(this.getDefinitions());
778
+ }
779
+ /** The raw parsed spec — prefer getNormalizedSpec() unless raw access is the point. */
780
+ getSpec() {
781
+ return this.spec;
782
+ }
783
+ getPaths() {
784
+ return this.spec.paths || {};
785
+ }
786
+ /** Whether the spec declares a supported version (Swagger 2.x or OpenAPI 3.x). */
787
+ isValidSpec() {
788
+ return !!(this.spec.swagger && this.spec.swagger.startsWith("2.") || this.spec.openapi && this.spec.openapi.startsWith("3."));
789
+ }
790
+ /** Detected flavor + literal version string, or null when neither field is present. */
791
+ getSpecVersion() {
792
+ if (this.spec.swagger) {
793
+ return {
794
+ type: "swagger",
795
+ version: this.spec.swagger
796
+ };
797
+ }
798
+ if (this.spec.openapi) {
799
+ return {
800
+ type: "openapi",
801
+ version: this.spec.openapi
802
+ };
803
+ }
804
+ return null;
805
+ }
806
+ };
807
+ __name(_SwaggerParser, "SwaggerParser");
808
+ var SwaggerParser = _SwaggerParser;
809
+
810
+ // ../shared/src/emit/headers.emit.ts
811
+ function emitHeaders(options) {
812
+ const { optionsExpression, customHeaders, contentType } = options;
813
+ let headerCode = `
814
+ let headers: HttpHeaders;
815
+ if (${optionsExpression}?.headers instanceof HttpHeaders) {
816
+ headers = ${optionsExpression}.headers;
817
+ } else {
818
+ headers = new HttpHeaders(${optionsExpression}?.headers);
819
+ }`;
820
+ if (customHeaders) {
821
+ headerCode += `
822
+ // Add default headers if not already present
823
+ ${emitDefaultHeaderGuards(customHeaders)}`;
824
+ }
825
+ if (contentType == null ? void 0 : contentType.isMultipart) {
826
+ headerCode += `
827
+ // Remove Content-Type for multipart (browser will set it with boundary)
828
+ headers = headers.delete('Content-Type');`;
829
+ } else if (contentType == null ? void 0 : contentType.isUrlEncoded) {
830
+ headerCode += `
831
+ // Set Content-Type for URL-encoded form data
832
+ if (!headers.has('Content-Type')) {
833
+ headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
834
+ }`;
835
+ } else if (contentType == null ? void 0 : contentType.hasBody) {
836
+ headerCode += `
837
+ // Set Content-Type for JSON requests if not already set
838
+ if (!headers.has('Content-Type')) {
839
+ headers = headers.set('Content-Type', 'application/json');
840
+ }`;
841
+ }
842
+ return headerCode;
843
+ }
844
+ __name(emitHeaders, "emitHeaders");
845
+ function emitDefaultHeadersMerge(optionsExpression, customHeaders) {
846
+ const defaultsLiteral = Object.entries(customHeaders).map(([key, value]) => `'${key}': '${value}'`).join(", ");
847
+ return `
848
+ // Add default headers if not already present
849
+ let headers = ${optionsExpression}?.headers;
850
+ if (headers instanceof HttpHeaders) {
851
+ ${emitDefaultHeaderGuards(customHeaders)}
852
+ } else {
853
+ headers = { ${defaultsLiteral}, ...headers };
854
+ }`;
855
+ }
856
+ __name(emitDefaultHeadersMerge, "emitDefaultHeadersMerge");
857
+ function emitDefaultHeaderGuards(customHeaders) {
858
+ return Object.entries(customHeaders).map(([key, value]) => `if (!headers.has('${key}')) {
859
+ headers = headers.set('${key}', '${value}');
860
+ }`).join("\n");
861
+ }
862
+ __name(emitDefaultHeaderGuards, "emitDefaultHeaderGuards");
863
+
864
+ // ../shared/src/emit/url.emit.ts
865
+ function plainParamValue(identifier) {
866
+ return identifier;
867
+ }
868
+ __name(plainParamValue, "plainParamValue");
869
+ function signalAwareParamValue(identifier) {
870
+ return `typeof ${identifier} === 'function' ? ${identifier}() : ${identifier}`;
871
+ }
872
+ __name(signalAwareParamValue, "signalAwareParamValue");
873
+ function emitUrlExpression(path13, pathParams, paramValue = plainParamValue) {
874
+ let urlExpression = `\`\${this.basePath}${path13}\``;
875
+ pathParams.forEach((param) => {
876
+ urlExpression = urlExpression.replace(`{${param.name}}`, `\${${paramValue(camelCase(param.name))}}`);
877
+ });
878
+ return urlExpression;
879
+ }
880
+ __name(emitUrlExpression, "emitUrlExpression");
881
+ function emitUrlConstruction(path13, pathParams) {
882
+ return `const url = ${emitUrlExpression(path13, pathParams)};`;
883
+ }
884
+ __name(emitUrlConstruction, "emitUrlConstruction");
885
+
886
+ // ../shared/src/emit/query-params.emit.ts
887
+ function emitQueryParams(queryParams) {
888
+ if (queryParams.length === 0) {
889
+ return "";
890
+ }
891
+ const paramMappings = queryParams.map((param) => `if (${camelCase(param.name)} != null) {
892
+ params = HttpParamsBuilder.addToHttpParams(params, ${camelCase(param.name)}, '${param.name}');
893
+ }`).join("\n");
894
+ return `
895
+ let params = new HttpParams();
896
+ ${paramMappings}`;
897
+ }
898
+ __name(emitQueryParams, "emitQueryParams");
899
+ function emitSignalAwareQueryParams(queryParams) {
900
+ if (queryParams.length === 0) {
901
+ return "";
902
+ }
903
+ const paramMappings = queryParams.map((param) => `const ${camelCase(param.name)}Value = ${signalAwareParamValue(camelCase(param.name))};
904
+ if (${camelCase(param.name)}Value != null) {
905
+ params = HttpParamsBuilder.addToHttpParams(params, ${camelCase(param.name)}Value, '${param.name}');
906
+ }`).join("\n");
907
+ return `
908
+ let params = new HttpParams();
909
+ ${paramMappings}`;
910
+ }
911
+ __name(emitSignalAwareQueryParams, "emitSignalAwareQueryParams");
912
+
913
+ // ../shared/src/emit/response-type.emit.ts
914
+ function emitResponseTypeOption(responseType) {
915
+ if (responseType === "json") {
916
+ return "";
917
+ }
918
+ return `responseType: '${responseType}'`;
919
+ }
920
+ __name(emitResponseTypeOption, "emitResponseTypeOption");
921
+ function joinRequestOptionEntries(entries) {
922
+ return entries.filter((entry) => entry && !entry.includes("undefined")).join(",\n ");
923
+ }
924
+ __name(joinRequestOptionEntries, "joinRequestOptionEntries");
925
+
926
+ // ../shared/src/utils/functions/token-names.ts
927
+ function getClientContextTokenName(clientName = "default") {
928
+ const clientSuffix = clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
929
+ return `CLIENT_CONTEXT_TOKEN_${clientSuffix}`;
930
+ }
931
+ __name(getClientContextTokenName, "getClientContextTokenName");
932
+ function getBasePathTokenName(clientName = "default") {
933
+ const clientSuffix = clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
934
+ return `BASE_PATH_${clientSuffix}`;
935
+ }
936
+ __name(getBasePathTokenName, "getBasePathTokenName");
937
+ function getInterceptorsTokenName(clientName = "default") {
938
+ const clientSuffix = clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
939
+ return `HTTP_INTERCEPTORS_${clientSuffix}`;
940
+ }
941
+ __name(getInterceptorsTokenName, "getInterceptorsTokenName");
942
+
943
+ // ../shared/src/utils/functions/duplicate-function-name.ts
944
+ function hasDuplicateFunctionNames(arr) {
945
+ return new Set(arr.map((fn) => fn.getName())).size !== arr.length;
946
+ }
947
+ __name(hasDuplicateFunctionNames, "hasDuplicateFunctionNames");
948
+
949
+ // ../shared/src/utils/functions/get-request-body-type.ts
950
+ function getRequestBodyType(requestBody, config) {
951
+ const content = requestBody.content || {};
952
+ const jsonContent = content[CONTENT_TYPES.JSON];
953
+ if (jsonContent == null ? void 0 : jsonContent.schema) {
954
+ return getTypeScriptType(jsonContent.schema, config, jsonContent.schema.nullable);
955
+ }
956
+ return "any";
957
+ }
958
+ __name(getRequestBodyType, "getRequestBodyType");
959
+
960
+ // ../shared/src/utils/functions/is-data-type-interface.ts
961
+ function isDataTypeInterface(type) {
962
+ const invalidTypes = [
963
+ "any",
964
+ "File",
965
+ "string",
966
+ "number",
967
+ "boolean",
968
+ "object",
969
+ "unknown",
970
+ "[]",
971
+ "Array"
972
+ ];
973
+ return !invalidTypes.some((invalidType) => type.includes(invalidType));
974
+ }
975
+ __name(isDataTypeInterface, "isDataTypeInterface");
976
+
977
+ // ../shared/src/utils/functions/generate-parse-request-type-params.ts
978
+ function generateParseRequestTypeParams(params) {
979
+ const bodyParam = params.find((param) => {
980
+ return typeof param.type === "string" && isDataTypeInterface(param.type);
981
+ });
982
+ if (bodyParam) {
983
+ const optional = bodyParam.hasQuestionToken ? " | undefined" : "";
984
+ return `${bodyParam.type}${optional}`;
985
+ }
986
+ return "";
987
+ }
988
+ __name(generateParseRequestTypeParams, "generateParseRequestTypeParams");
989
+
990
+ // ../shared/src/config/define-config.ts
991
+ function defineConfig(config) {
992
+ return config;
993
+ }
994
+ __name(defineConfig, "defineConfig");
995
+
996
+ // ../shared/src/config/constants.ts
997
+ var disableLinting = `/* @ts-nocheck */
998
+ /* eslint-disable */
999
+ /* @noformat */
1000
+ /* @formatter:off */
1001
+ `;
468
1002
  var authorComment = `/**
469
1003
  * Generated by ng-openapi
470
1004
  `;
@@ -497,8 +1031,7 @@ var BASE_INTERCEPTOR_HEADER_COMMENT = /* @__PURE__ */ __name((clientName) => def
497
1031
  * Do not edit this file manually
498
1032
  */
499
1033
  `, "BASE_INTERCEPTOR_HEADER_COMMENT");
500
- var HTTP_RESOURCE_GENERATOR_HEADER_COMMENT = /* @__PURE__ */ __name((resourceName) => defaultHeaderComment + `* \`httpResource\` is still an experimental feature - NOT PRODUCTION READY
501
- * Generated Angular service for ${resourceName}
1034
+ var HTTP_RESOURCE_GENERATOR_HEADER_COMMENT = /* @__PURE__ */ __name((resourceName) => defaultHeaderComment + `* Generated Angular \`httpResource\` service for ${resourceName}
502
1035
  * Do not edit this file manually
503
1036
  */
504
1037
  `, "HTTP_RESOURCE_GENERATOR_HEADER_COMMENT");
@@ -511,267 +1044,181 @@ var ZOD_PLUGIN_INDEX_GENERATOR_HEADER_COMMENT = defaultHeaderComment + `* Genera
511
1044
  */
512
1045
  `;
513
1046
 
514
- // ../shared/src/core/swagger-parser.ts
515
- var fs = __toESM(require("fs"));
516
- var path = __toESM(require("path"));
517
- var yaml = __toESM(require("js-yaml"));
1047
+ // src/lib/generators/type/enum-builder.ts
1048
+ var import_ts_morph = require("ts-morph");
518
1049
 
519
- // ../shared/src/utils/functions/is-url.ts
520
- function isUrl(input) {
521
- try {
522
- const url = new URL(input);
523
- return [
524
- "http:",
525
- "https:"
526
- ].includes(url.protocol);
527
- } catch (e) {
528
- return false;
1050
+ // src/lib/generators/type/type-resolver.ts
1051
+ function escapeString2(str) {
1052
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1053
+ }
1054
+ __name(escapeString2, "escapeString");
1055
+ function sanitizePropertyName(name) {
1056
+ if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)) {
1057
+ return `"${name}"`;
529
1058
  }
1059
+ return name;
530
1060
  }
531
- __name(isUrl, "isUrl");
532
-
533
- // ../shared/src/core/swagger-parser.ts
534
- var _SwaggerParser = class _SwaggerParser {
535
- constructor(spec, config) {
536
- __publicField(this, "spec");
537
- var _a, _b;
538
- const isInputValid = (_b = (_a = config.validateInput) == null ? void 0 : _a.call(config, spec)) != null ? _b : true;
539
- if (!isInputValid) {
540
- throw new Error("Swagger spec is not valid. Check your `validateInput` condition.");
541
- }
542
- this.spec = spec;
1061
+ __name(sanitizePropertyName, "sanitizePropertyName");
1062
+ var _TypeResolver = class _TypeResolver {
1063
+ constructor(config, onWarning) {
1064
+ __publicField(this, "config");
1065
+ __publicField(this, "onWarning");
1066
+ __publicField(this, "resolutionCache", /* @__PURE__ */ new WeakMap());
1067
+ __publicField(this, "pascalCaseCache", /* @__PURE__ */ new Map());
1068
+ __publicField(this, "sanitizedNameCache", /* @__PURE__ */ new Map());
1069
+ this.config = config;
1070
+ this.onWarning = onWarning;
543
1071
  }
544
- static create(swaggerPathOrUrl, config) {
545
- return __async(this, null, function* () {
546
- const swaggerContent = yield _SwaggerParser.loadContent(swaggerPathOrUrl);
547
- const spec = _SwaggerParser.parseSpecContent(swaggerContent, swaggerPathOrUrl);
548
- return new _SwaggerParser(spec, config);
549
- });
1072
+ resolve(schema) {
1073
+ const cached = this.resolutionCache.get(schema);
1074
+ if (cached !== void 0) {
1075
+ return cached;
1076
+ }
1077
+ const result = this.resolveUncached(schema);
1078
+ this.resolutionCache.set(schema, result);
1079
+ return result;
550
1080
  }
551
- static loadContent(pathOrUrl) {
552
- return __async(this, null, function* () {
553
- if (isUrl(pathOrUrl)) {
554
- return yield _SwaggerParser.fetchUrlContent(pathOrUrl);
555
- } else {
556
- return fs.readFileSync(pathOrUrl, "utf8");
557
- }
558
- });
1081
+ pascalName(str) {
1082
+ if (!this.pascalCaseCache.has(str)) {
1083
+ this.pascalCaseCache.set(str, pascalCaseForEnums(str));
1084
+ }
1085
+ return this.pascalCaseCache.get(str);
559
1086
  }
560
- static fetchUrlContent(url) {
561
- return __async(this, null, function* () {
562
- try {
563
- const response = yield fetch(url, {
564
- method: "GET",
565
- headers: {
566
- Accept: "application/json, application/yaml, text/yaml, text/plain, */*",
567
- "User-Agent": "ng-openapi"
568
- },
569
- // 30 second timeout
570
- signal: AbortSignal.timeout(3e4)
571
- });
572
- if (!response.ok) {
573
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
574
- }
575
- const content = yield response.text();
576
- if (!content || content.trim() === "") {
577
- throw new Error(`Empty response from URL: ${url}`);
578
- }
579
- return content;
580
- } catch (error) {
581
- let errorMessage = `Failed to fetch content from URL: ${url}`;
582
- if (error.name === "AbortError") {
583
- errorMessage += " - Request timeout (30s)";
584
- } else if (error.message) {
585
- errorMessage += ` - ${error.message}`;
586
- }
587
- throw new Error(errorMessage);
588
- }
589
- });
1087
+ sanitizeName(name) {
1088
+ if (!this.sanitizedNameCache.has(name)) {
1089
+ this.sanitizedNameCache.set(name, sanitizePropertyName(name));
1090
+ }
1091
+ return this.sanitizedNameCache.get(name);
590
1092
  }
591
- static parseSpecContent(content, pathOrUrl) {
592
- let format;
593
- if (isUrl(pathOrUrl)) {
594
- const urlPath = new URL(pathOrUrl).pathname.toLowerCase();
595
- if (urlPath.endsWith(".json")) {
596
- format = "json";
597
- } else if (urlPath.endsWith(".yaml") || urlPath.endsWith(".yml")) {
598
- format = "yaml";
599
- } else {
600
- format = _SwaggerParser.detectFormat(content);
601
- }
1093
+ getArrayItemType(items) {
1094
+ if (Array.isArray(items)) {
1095
+ const types = items.map((item) => this.resolve(item));
1096
+ return `[${types.join(", ")}]`;
602
1097
  } else {
603
- const extension = path.extname(pathOrUrl).toLowerCase();
604
- switch (extension) {
605
- case ".json":
606
- format = "json";
607
- break;
608
- case ".yaml":
609
- format = "yaml";
610
- break;
611
- case ".yml":
612
- format = "yml";
613
- break;
614
- default:
615
- format = _SwaggerParser.detectFormat(content);
616
- }
617
- }
618
- try {
619
- switch (format) {
620
- case "json":
621
- return JSON.parse(content);
622
- case "yaml":
623
- case "yml":
624
- return yaml.load(content);
625
- default:
626
- throw new Error(`Unable to determine format for: ${pathOrUrl}`);
627
- }
628
- } catch (error) {
629
- throw new Error(`Failed to parse ${format.toUpperCase()} content from: ${pathOrUrl}. Error: ${error instanceof Error ? error.message : error}`);
1098
+ return this.resolve(items);
630
1099
  }
631
1100
  }
632
- static detectFormat(content) {
633
- const trimmed = content.trim();
634
- if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
635
- return "json";
1101
+ resolveUncached(schema) {
1102
+ if (schema.$ref) {
1103
+ return this.resolveReference(schema.$ref);
1104
+ }
1105
+ if (schema.enum) {
1106
+ return schema.enum.map((value) => typeof value === "string" ? `'${escapeString2(value)}'` : String(value)).join(" | ");
1107
+ }
1108
+ if (schema.allOf) {
1109
+ return schema.allOf.map((def) => this.resolve(def)).filter((type) => type !== "any" && type !== "unknown").join(" & ") || "Record<string, unknown>";
1110
+ }
1111
+ if (schema.oneOf) {
1112
+ return schema.oneOf.map((def) => this.resolve(def)).filter((type, index, array) => type !== "any" && type !== "unknown" && array.indexOf(type) === index).join(" | ") || "unknown";
1113
+ }
1114
+ if (schema.anyOf) {
1115
+ return schema.anyOf.map((def) => this.resolve(def)).filter((type) => type !== "any" && type !== "unknown").join(" | ") || "unknown";
1116
+ }
1117
+ if (schema.type === "array") {
1118
+ const itemType = schema.items ? this.getArrayItemType(schema.items) : "unknown";
1119
+ return `Array<${itemType}>`;
636
1120
  }
637
- if (trimmed.includes("openapi:") || trimmed.includes("swagger:") || trimmed.includes("---") || /^[a-zA-Z][a-zA-Z0-9_]*\s*:/.test(trimmed)) {
638
- return "yaml";
1121
+ if (schema.type === "object") {
1122
+ if (schema.properties) {
1123
+ return this.generateInlineObjectType(schema);
1124
+ }
1125
+ if (schema.additionalProperties) {
1126
+ const valueType = typeof schema.additionalProperties === "object" ? this.resolve(schema.additionalProperties) : "unknown";
1127
+ return `Record<string, ${valueType}>`;
1128
+ }
1129
+ return "Record<string, unknown>";
639
1130
  }
640
- return "json";
641
- }
642
- getDefinitions() {
643
- var _a;
644
- return this.spec.definitions || ((_a = this.spec.components) == null ? void 0 : _a.schemas) || {};
1131
+ return this.mapSwaggerTypeToTypeScript(schema.type, schema.format, schema.nullable);
645
1132
  }
646
- getDefinition(name) {
647
- const definitions = this.getDefinitions();
648
- return definitions[name];
1133
+ generateInlineObjectType(definition) {
1134
+ if (!definition.properties) {
1135
+ if (definition.additionalProperties) {
1136
+ const additionalType = typeof definition.additionalProperties === "object" ? this.resolve(definition.additionalProperties) : "unknown";
1137
+ return `Record<string, ${additionalType}>`;
1138
+ }
1139
+ return "Record<string, unknown>";
1140
+ }
1141
+ const properties = Object.entries(definition.properties).map(([key, prop]) => {
1142
+ var _a, _b;
1143
+ const isRequired = (_b = (_a = definition.required) == null ? void 0 : _a.includes(key)) != null ? _b : false;
1144
+ const questionMark = isRequired ? "" : "?";
1145
+ const sanitizedKey = this.sanitizeName(key);
1146
+ return `${sanitizedKey}${questionMark}: ${this.resolve(prop)}`;
1147
+ }).join("; ");
1148
+ return `{ ${properties} }`;
649
1149
  }
650
1150
  resolveReference(ref) {
651
- const parts = ref.split("/");
652
- const definitionName = parts[parts.length - 1];
653
- return this.getDefinition(definitionName);
654
- }
655
- getAllDefinitionNames() {
656
- return Object.keys(this.getDefinitions());
657
- }
658
- getSpec() {
659
- return this.spec;
660
- }
661
- getPaths() {
662
- return this.spec.paths || {};
663
- }
664
- isValidSpec() {
665
- return !!(this.spec.swagger && this.spec.swagger.startsWith("2.") || this.spec.openapi && this.spec.openapi.startsWith("3."));
666
- }
667
- getSpecVersion() {
668
- if (this.spec.swagger) {
669
- return {
670
- type: "swagger",
671
- version: this.spec.swagger
672
- };
1151
+ var _a;
1152
+ const refName = ref.split("/").pop();
1153
+ if (!refName) {
1154
+ (_a = this.onWarning) == null ? void 0 : _a.call(this, `Invalid reference format: ${ref}`);
1155
+ return "unknown";
673
1156
  }
674
- if (this.spec.openapi) {
675
- return {
676
- type: "openapi",
677
- version: this.spec.openapi
678
- };
1157
+ return this.pascalName(refName);
1158
+ }
1159
+ mapSwaggerTypeToTypeScript(type, format, isNullable) {
1160
+ switch (type) {
1161
+ case "string":
1162
+ if (format === "date" || format === "date-time") {
1163
+ const dateType = this.config.options.dateType === "Date" ? "Date" : "string";
1164
+ return this.nullableType(dateType, isNullable);
1165
+ }
1166
+ if (format === "binary") return "Blob";
1167
+ if (format === "uuid") return "string";
1168
+ if (format === "email") return "string";
1169
+ if (format === "uri") return "string";
1170
+ return this.nullableType("string", isNullable);
1171
+ case "number":
1172
+ case "integer":
1173
+ return this.nullableType("number", isNullable);
1174
+ case "boolean":
1175
+ return this.nullableType("boolean", isNullable);
1176
+ case "array":
1177
+ return this.nullableType("any[]", isNullable);
1178
+ case "object":
1179
+ return this.nullableType("Record<string, unknown>", isNullable);
1180
+ case "null":
1181
+ return this.nullableType("null", isNullable);
1182
+ default:
1183
+ if (Array.isArray(type)) {
1184
+ const types = type.map((t) => this.mapSwaggerTypeToTypeScript(t, void 0, isNullable));
1185
+ return this.nullableType(types.join(" | "), isNullable);
1186
+ }
1187
+ return this.nullableType("any", isNullable);
679
1188
  }
680
- return null;
1189
+ }
1190
+ nullableType(type, isNullable) {
1191
+ return type + (isNullable ? " | null" : "");
681
1192
  }
682
1193
  };
683
- __name(_SwaggerParser, "SwaggerParser");
684
- var SwaggerParser = _SwaggerParser;
1194
+ __name(_TypeResolver, "TypeResolver");
1195
+ var TypeResolver = _TypeResolver;
685
1196
 
686
- // src/lib/generators/type/type.generator.ts
687
- var import_ts_morph = require("ts-morph");
688
- var _TypeGenerator = class _TypeGenerator {
689
- constructor(parser, project, config, outputRoot) {
690
- __publicField(this, "project");
691
- __publicField(this, "parser");
692
- __publicField(this, "sourceFile");
693
- __publicField(this, "generatedTypes", /* @__PURE__ */ new Set());
1197
+ // src/lib/generators/type/enum-builder.ts
1198
+ function toEnumKey(value) {
1199
+ const str = value.toString();
1200
+ const hasLeadingMinus = str.startsWith("-");
1201
+ const pascalCased = pascalCase(str);
1202
+ return hasLeadingMinus ? pascalCased.replace(/^([0-9])/, "_n$1") : pascalCased.replace(/^([0-9])/, "_$1");
1203
+ }
1204
+ __name(toEnumKey, "toEnumKey");
1205
+ var _EnumBuilder = class _EnumBuilder {
1206
+ constructor(config, onWarning) {
694
1207
  __publicField(this, "config");
695
- // Performance caches
696
- __publicField(this, "pascalCaseCache", /* @__PURE__ */ new Map());
697
- __publicField(this, "sanitizedNameCache", /* @__PURE__ */ new Map());
698
- __publicField(this, "typeResolutionCache", /* @__PURE__ */ new Map());
699
- // Batch collection for AST operations
700
- __publicField(this, "statements", []);
701
- __publicField(this, "deferredTypes", /* @__PURE__ */ new Map());
1208
+ __publicField(this, "onWarning");
702
1209
  this.config = config;
703
- this.project = project;
704
- this.parser = parser;
705
- const outputPath = outputRoot + "/models/index.ts";
706
- this.sourceFile = this.project.createSourceFile(outputPath, "", {
707
- overwrite: true
708
- });
709
- }
710
- generate() {
711
- return __async(this, null, function* () {
712
- try {
713
- const definitions = this.parser.getDefinitions();
714
- if (!definitions || Object.keys(definitions).length === 0) {
715
- console.warn("No definitions found in swagger file");
716
- }
717
- this.collectAllTypeStructures(definitions);
718
- this.collectSdkTypes();
719
- this.applyBatchUpdates();
720
- yield this.finalize();
721
- } catch (error) {
722
- console.error("Error in generate():", error);
723
- throw new Error(`Failed to generate types: ${error instanceof Error ? error.message : "Unknown error"}`);
724
- }
725
- });
726
- }
727
- collectAllTypeStructures(definitions) {
728
- Object.keys(definitions).forEach((name) => {
729
- const interfaceName = this.getCachedPascalCase(name);
730
- this.generatedTypes.add(interfaceName);
731
- });
732
- Object.entries(definitions).forEach(([name, definition]) => {
733
- this.collectTypeStructure(name, definition);
734
- });
735
- this.deferredTypes.forEach((definition, name) => {
736
- this.collectTypeStructure(name, definition);
737
- });
738
- }
739
- collectTypeStructure(name, definition) {
740
- var _a;
741
- const interfaceName = (_a = this.getCachedPascalCase(name)) != null ? _a : "";
742
- if (definition.enum) {
743
- this.collectEnumStructure(interfaceName, definition);
744
- } else if (definition.allOf) {
745
- this.collectCompositeTypeStructure(interfaceName, definition);
746
- } else if (definition.items) {
747
- this.collectArrayTypeStructure(interfaceName, definition);
748
- } else if (definition.properties) {
749
- this.collectInterfaceStructure(interfaceName, definition);
750
- } else {
751
- const propertyType = this.resolveSwaggerTypeCached(definition);
752
- this.statements.push({
753
- kind: import_ts_morph.StructureKind.TypeAlias,
754
- name: interfaceName,
755
- isExported: true,
756
- docs: definition.description ? [
757
- definition.description
758
- ] : void 0,
759
- type: propertyType
760
- });
761
- }
1210
+ this.onWarning = onWarning;
762
1211
  }
763
- collectEnumStructure(name, definition) {
1212
+ build(name, definition) {
764
1213
  var _a;
765
- if (!((_a = definition.enum) == null ? void 0 : _a.length)) return;
1214
+ if (!((_a = definition.enum) == null ? void 0 : _a.length)) return [];
766
1215
  const docs = !this.config.options.generateEnumBasedOnDescription && definition.description ? [
767
1216
  definition.description
768
1217
  ] : void 0;
769
1218
  if (this.config.options.enumStyle === "enum") {
770
- const statement = this.buildEnumAsEnum(name, definition, docs);
771
- this.statements.push(...statement);
1219
+ return this.buildEnumAsEnum(name, definition, docs);
772
1220
  } else {
773
- const statement = this.buildEnumAsUnion(name, definition, docs);
774
- this.statements.push(...statement);
1221
+ return this.buildEnumAsUnion(name, definition, docs);
775
1222
  }
776
1223
  }
777
1224
  buildEnumAsEnum(name, definition, docs) {
@@ -781,7 +1228,7 @@ var _TypeGenerator = class _TypeGenerator {
781
1228
  const isStringEnum = definition.enum.some((value) => typeof value === "string");
782
1229
  if (isStringEnum) {
783
1230
  const members = definition.enum.map((value) => ({
784
- name: this.toEnumKey(value),
1231
+ name: toEnumKey(value),
785
1232
  value: `${String(value)}`
786
1233
  }));
787
1234
  statements.push({
@@ -792,7 +1239,7 @@ var _TypeGenerator = class _TypeGenerator {
792
1239
  members
793
1240
  });
794
1241
  } else {
795
- const members = this.buildEnumMembers(definition);
1242
+ const members = this.buildEnumMembers(name, definition);
796
1243
  statements.push({
797
1244
  kind: import_ts_morph.StructureKind.Enum,
798
1245
  name,
@@ -809,8 +1256,8 @@ var _TypeGenerator = class _TypeGenerator {
809
1256
  const statements = [];
810
1257
  const objectProperties = [];
811
1258
  const unionType = definition.enum.map((value) => {
812
- const key = this.toEnumKey(value);
813
- const val = typeof value === "string" ? `'${this.escapeString(value)}'` : isNaN(value) ? `'${value}'` : `${value}`;
1259
+ const key = toEnumKey(value);
1260
+ const val = typeof value === "string" ? `'${escapeString2(value)}'` : isNaN(value) ? `'${value}'` : `${value}`;
814
1261
  objectProperties.push(`${key}: ${val} as ${name}`);
815
1262
  return val;
816
1263
  }).join(" | ");
@@ -834,8 +1281,8 @@ var _TypeGenerator = class _TypeGenerator {
834
1281
  });
835
1282
  return statements;
836
1283
  }
837
- buildEnumMembers(definition) {
838
- var _a;
1284
+ buildEnumMembers(name, definition) {
1285
+ var _a, _b;
839
1286
  if (definition.description && this.config.options.generateEnumBasedOnDescription) {
840
1287
  try {
841
1288
  const enumValueObjects = JSON.parse(definition.description);
@@ -844,55 +1291,40 @@ var _TypeGenerator = class _TypeGenerator {
844
1291
  value: obj.Value
845
1292
  }));
846
1293
  } catch (e) {
1294
+ if (/^\s*[[{]/.test(definition.description)) {
1295
+ (_a = this.onWarning) == null ? void 0 : _a.call(this, `Enum "${name}": description looks like JSON (generateEnumBasedOnDescription) but could not be used \u2014 falling back to raw enum values`);
1296
+ }
847
1297
  }
848
1298
  }
849
- return (_a = definition.enum) == null ? void 0 : _a.map((value) => ({
850
- name: this.toEnumKey(value),
1299
+ return (_b = definition.enum) == null ? void 0 : _b.map((value) => ({
1300
+ name: toEnumKey(value),
851
1301
  value
852
1302
  }));
853
1303
  }
854
- collectCompositeTypeStructure(name, definition) {
855
- let typeExpression = "";
856
- if (definition.allOf) {
857
- const types = definition.allOf.map((def) => this.resolveSwaggerTypeCached(def)).filter((type) => type !== "any" && type !== "unknown");
858
- typeExpression = types.length > 0 ? types.join(" & ") : "Record<string, unknown>";
859
- }
860
- this.statements.push({
861
- kind: import_ts_morph.StructureKind.TypeAlias,
862
- name,
863
- type: typeExpression,
864
- isExported: true,
865
- docs: definition.description ? [
866
- definition.description
867
- ] : void 0
868
- });
869
- }
870
- collectArrayTypeStructure(name, definition) {
871
- const itemType = definition.items ? this.getArrayItemType(definition.items) : "unknown";
872
- this.statements.push({
873
- kind: import_ts_morph.StructureKind.TypeAlias,
874
- name,
875
- isExported: true,
876
- docs: definition.description ? [
877
- definition.description
878
- ] : void 0,
879
- type: `Array<${itemType}>`
880
- });
1304
+ };
1305
+ __name(_EnumBuilder, "EnumBuilder");
1306
+ var EnumBuilder = _EnumBuilder;
1307
+
1308
+ // src/lib/generators/type/interface-builder.ts
1309
+ var import_ts_morph2 = require("ts-morph");
1310
+ var _InterfaceBuilder = class _InterfaceBuilder {
1311
+ constructor(resolver) {
1312
+ __publicField(this, "resolver");
1313
+ this.resolver = resolver;
881
1314
  }
882
- collectInterfaceStructure(name, definition) {
883
- const properties = this.buildInterfaceProperties(definition);
884
- this.statements.push({
885
- kind: import_ts_morph.StructureKind.Interface,
1315
+ build(name, definition) {
1316
+ return {
1317
+ kind: import_ts_morph2.StructureKind.Interface,
886
1318
  name,
887
1319
  isExported: true,
888
1320
  docs: definition.description ? [
889
1321
  definition.description
890
1322
  ] : void 0,
891
- properties,
1323
+ properties: this.buildProperties(definition),
892
1324
  indexSignatures: this.buildIndexSignatures(definition)
893
- });
1325
+ };
894
1326
  }
895
- buildInterfaceProperties(definition) {
1327
+ buildProperties(definition) {
896
1328
  if (!definition.properties) {
897
1329
  return [];
898
1330
  }
@@ -900,8 +1332,8 @@ var _TypeGenerator = class _TypeGenerator {
900
1332
  var _a, _b;
901
1333
  const isRequired = (_b = (_a = definition.required) == null ? void 0 : _a.includes(propertyName)) != null ? _b : false;
902
1334
  const isReadOnly = property.readOnly;
903
- const propertyType = this.resolveSwaggerTypeCached(property);
904
- const sanitizedName = this.getCachedSanitizedName(propertyName);
1335
+ const propertyType = this.resolver.resolve(property);
1336
+ const sanitizedName = this.resolver.sanitizeName(propertyName);
905
1337
  return {
906
1338
  name: sanitizedName,
907
1339
  type: propertyType,
@@ -943,123 +1375,159 @@ var _TypeGenerator = class _TypeGenerator {
943
1375
  }
944
1376
  return [];
945
1377
  }
946
- resolveSwaggerTypeCached(schema) {
947
- const cacheKey = JSON.stringify(schema);
948
- if (this.typeResolutionCache.has(cacheKey)) {
949
- return this.typeResolutionCache.get(cacheKey);
1378
+ };
1379
+ __name(_InterfaceBuilder, "InterfaceBuilder");
1380
+ var InterfaceBuilder = _InterfaceBuilder;
1381
+
1382
+ // src/lib/generators/type/sdk-types.ts
1383
+ var import_ts_morph3 = require("ts-morph");
1384
+ function buildSdkTypes(config) {
1385
+ var _a;
1386
+ const { response } = (_a = config.options.validation) != null ? _a : {};
1387
+ const typeParameters = [
1388
+ "TResponseType extends 'arraybuffer' | 'blob' | 'json' | 'text'"
1389
+ ];
1390
+ const properties = [
1391
+ {
1392
+ name: "headers",
1393
+ type: "HttpHeaders",
1394
+ hasQuestionToken: true
1395
+ },
1396
+ {
1397
+ name: "reportProgress",
1398
+ type: "boolean",
1399
+ hasQuestionToken: true
1400
+ },
1401
+ {
1402
+ name: "responseType",
1403
+ type: "TResponseType",
1404
+ hasQuestionToken: true
1405
+ },
1406
+ {
1407
+ name: "withCredentials",
1408
+ type: "boolean",
1409
+ hasQuestionToken: true
1410
+ },
1411
+ {
1412
+ name: "context",
1413
+ type: "HttpContext",
1414
+ hasQuestionToken: true
950
1415
  }
951
- const result = this.resolveSwaggerType(schema);
952
- this.typeResolutionCache.set(cacheKey, result);
953
- return result;
1416
+ ];
1417
+ if (response) {
1418
+ properties.push({
1419
+ name: "parse",
1420
+ type: "(response: unknown) => TReturnType",
1421
+ hasQuestionToken: true
1422
+ });
1423
+ typeParameters.push("TReturnType");
954
1424
  }
955
- resolveSwaggerType(schema) {
956
- if (schema.$ref) {
957
- return this.resolveReference(schema.$ref);
958
- }
959
- if (schema.enum) {
960
- return schema.enum.map((value) => typeof value === "string" ? `'${this.escapeString(value)}'` : String(value)).join(" | ");
961
- }
962
- if (schema.allOf) {
963
- return schema.allOf.map((def) => this.resolveSwaggerTypeCached(def)).filter((type) => type !== "any" && type !== "unknown").join(" & ") || "Record<string, unknown>";
964
- }
965
- if (schema.oneOf) {
966
- return schema.oneOf.map((def) => this.resolveSwaggerTypeCached(def)).filter((type, index, array) => type !== "any" && type !== "unknown" && array.indexOf(type) === index).join(" | ") || "unknown";
967
- }
968
- if (schema.anyOf) {
969
- return schema.anyOf.map((def) => this.resolveSwaggerTypeCached(def)).filter((type) => type !== "any" && type !== "unknown").join(" | ") || "unknown";
970
- }
971
- if (schema.type === "array") {
972
- const itemType = schema.items ? this.getArrayItemType(schema.items) : "unknown";
973
- return `Array<${itemType}>`;
974
- }
975
- if (schema.type === "object") {
976
- if (schema.properties) {
977
- return this.generateInlineObjectType(schema);
978
- }
979
- if (schema.additionalProperties) {
980
- const valueType = typeof schema.additionalProperties === "object" ? this.resolveSwaggerTypeCached(schema.additionalProperties) : "unknown";
981
- return `Record<string, ${valueType}>`;
982
- }
983
- return "Record<string, unknown>";
1425
+ return [
1426
+ {
1427
+ kind: import_ts_morph3.StructureKind.Interface,
1428
+ name: "RequestOptions",
1429
+ isExported: true,
1430
+ typeParameters,
1431
+ properties,
1432
+ docs: [
1433
+ "Request Options for Angular HttpClient requests"
1434
+ ]
984
1435
  }
985
- return this.mapSwaggerTypeToTypeScript(schema.type, schema.format, schema.nullable);
1436
+ ];
1437
+ }
1438
+ __name(buildSdkTypes, "buildSdkTypes");
1439
+
1440
+ // src/lib/generators/type/type.generator.ts
1441
+ var import_ts_morph4 = require("ts-morph");
1442
+ var _TypeGenerator = class _TypeGenerator {
1443
+ constructor(parser, project, config, outputRoot, onWarning) {
1444
+ __publicField(this, "parser");
1445
+ __publicField(this, "config");
1446
+ __publicField(this, "sourceFile");
1447
+ __publicField(this, "resolver");
1448
+ __publicField(this, "enumBuilder");
1449
+ __publicField(this, "interfaceBuilder");
1450
+ __publicField(this, "statements", []);
1451
+ __publicField(this, "onWarning");
1452
+ this.config = config;
1453
+ this.parser = parser;
1454
+ this.onWarning = onWarning;
1455
+ const outputPath = outputRoot + "/models/index.ts";
1456
+ this.sourceFile = project.createSourceFile(outputPath, "", {
1457
+ overwrite: true
1458
+ });
1459
+ this.resolver = new TypeResolver(config, onWarning);
1460
+ this.enumBuilder = new EnumBuilder(config, onWarning);
1461
+ this.interfaceBuilder = new InterfaceBuilder(this.resolver);
986
1462
  }
987
- generateInlineObjectType(definition) {
988
- if (!definition.properties) {
989
- if (definition.additionalProperties) {
990
- const additionalType = typeof definition.additionalProperties === "object" ? this.resolveSwaggerTypeCached(definition.additionalProperties) : "unknown";
991
- return `Record<string, ${additionalType}>`;
1463
+ generate() {
1464
+ return __async(this, null, function* () {
1465
+ var _a;
1466
+ try {
1467
+ const definitions = this.parser.getNormalizedSpec().definitions;
1468
+ if (!definitions || Object.keys(definitions).length === 0) {
1469
+ (_a = this.onWarning) == null ? void 0 : _a.call(this, "No definitions found in swagger file");
1470
+ }
1471
+ Object.entries(definitions).forEach(([name, definition]) => {
1472
+ this.collectTypeStructure(name, definition);
1473
+ });
1474
+ this.statements.push(...buildSdkTypes(this.config));
1475
+ this.applyBatchUpdates();
1476
+ yield this.finalize();
1477
+ } catch (error) {
1478
+ throw new Error(`Failed to generate types: ${error instanceof Error ? error.message : "Unknown error"}`);
992
1479
  }
993
- return "Record<string, unknown>";
1480
+ });
1481
+ }
1482
+ collectTypeStructure(name, definition) {
1483
+ const typeName = this.resolver.pascalName(name);
1484
+ if (definition.enum) {
1485
+ this.statements.push(...this.enumBuilder.build(typeName, definition));
1486
+ } else if (definition.allOf) {
1487
+ this.statements.push(this.buildCompositeTypeAlias(typeName, definition));
1488
+ } else if (definition.items) {
1489
+ this.statements.push(this.buildArrayTypeAlias(typeName, definition));
1490
+ } else if (definition.properties) {
1491
+ this.statements.push(this.interfaceBuilder.build(typeName, definition));
1492
+ } else {
1493
+ this.statements.push({
1494
+ kind: import_ts_morph4.StructureKind.TypeAlias,
1495
+ name: typeName,
1496
+ isExported: true,
1497
+ docs: definition.description ? [
1498
+ definition.description
1499
+ ] : void 0,
1500
+ type: this.resolver.resolve(definition)
1501
+ });
994
1502
  }
995
- const properties = Object.entries(definition.properties).map(([key, prop]) => {
996
- var _a, _b;
997
- const isRequired = (_b = (_a = definition.required) == null ? void 0 : _a.includes(key)) != null ? _b : false;
998
- const questionMark = isRequired ? "" : "?";
999
- const sanitizedKey = this.getCachedSanitizedName(key);
1000
- return `${sanitizedKey}${questionMark}: ${this.resolveSwaggerTypeCached(prop)}`;
1001
- }).join("; ");
1002
- return `{ ${properties} }`;
1003
1503
  }
1004
- resolveReference(ref) {
1005
- const refName = ref.split("/").pop();
1006
- if (!refName) {
1007
- console.warn(`Invalid reference format: ${ref}`);
1008
- return "unknown";
1504
+ buildCompositeTypeAlias(name, definition) {
1505
+ let typeExpression = "";
1506
+ if (definition.allOf) {
1507
+ const types = definition.allOf.map((def) => this.resolver.resolve(def)).filter((type) => type !== "any" && type !== "unknown");
1508
+ typeExpression = types.length > 0 ? types.join(" & ") : "Record<string, unknown>";
1009
1509
  }
1010
- return this.getCachedPascalCase(refName);
1510
+ return {
1511
+ kind: import_ts_morph4.StructureKind.TypeAlias,
1512
+ name,
1513
+ type: typeExpression,
1514
+ isExported: true,
1515
+ docs: definition.description ? [
1516
+ definition.description
1517
+ ] : void 0
1518
+ };
1011
1519
  }
1012
- collectSdkTypes() {
1013
- var _a;
1014
- const { response } = (_a = this.config.options.validation) != null ? _a : {};
1015
- const typeParameters = [
1016
- "TResponseType extends 'arraybuffer' | 'blob' | 'json' | 'text'"
1017
- ];
1018
- const properties = [
1019
- {
1020
- name: "headers",
1021
- type: "HttpHeaders",
1022
- hasQuestionToken: true
1023
- },
1024
- {
1025
- name: "reportProgress",
1026
- type: "boolean",
1027
- hasQuestionToken: true
1028
- },
1029
- {
1030
- name: "responseType",
1031
- type: "TResponseType",
1032
- hasQuestionToken: true
1033
- },
1034
- {
1035
- name: "withCredentials",
1036
- type: "boolean",
1037
- hasQuestionToken: true
1038
- },
1039
- {
1040
- name: "context",
1041
- type: "HttpContext",
1042
- hasQuestionToken: true
1043
- }
1044
- ];
1045
- if (response) {
1046
- properties.push({
1047
- name: "parse",
1048
- type: "(response: unknown) => TReturnType",
1049
- hasQuestionToken: true
1050
- });
1051
- typeParameters.push("TReturnType");
1052
- }
1053
- this.statements.push({
1054
- kind: import_ts_morph.StructureKind.Interface,
1055
- name: "RequestOptions",
1520
+ buildArrayTypeAlias(name, definition) {
1521
+ const itemType = definition.items ? this.resolver.getArrayItemType(definition.items) : "unknown";
1522
+ return {
1523
+ kind: import_ts_morph4.StructureKind.TypeAlias,
1524
+ name,
1056
1525
  isExported: true,
1057
- typeParameters,
1058
- properties,
1059
- docs: [
1060
- "Request Options for Angular HttpClient requests"
1061
- ]
1062
- });
1526
+ docs: definition.description ? [
1527
+ definition.description
1528
+ ] : void 0,
1529
+ type: `Array<${itemType}>`
1530
+ };
1063
1531
  }
1064
1532
  applyBatchUpdates() {
1065
1533
  this.sourceFile.insertText(0, TYPE_GENERATOR_HEADER_COMMENT);
@@ -1080,83 +1548,12 @@ var _TypeGenerator = class _TypeGenerator {
1080
1548
  yield this.sourceFile.save();
1081
1549
  });
1082
1550
  }
1083
- // Cached helper methods
1084
- getCachedPascalCase(str) {
1085
- if (!this.pascalCaseCache.has(str)) {
1086
- this.pascalCaseCache.set(str, pascalCaseForEnums(str));
1087
- }
1088
- return this.pascalCaseCache.get(str);
1089
- }
1090
- getCachedSanitizedName(name) {
1091
- if (!this.sanitizedNameCache.has(name)) {
1092
- this.sanitizedNameCache.set(name, this.sanitizePropertyName(name));
1093
- }
1094
- return this.sanitizedNameCache.get(name);
1095
- }
1096
- // Original helper methods
1097
- mapSwaggerTypeToTypeScript(type, format, isNullable) {
1098
- switch (type) {
1099
- case "string":
1100
- if (format === "date" || format === "date-time") {
1101
- const dateType = this.config.options.dateType === "Date" ? "Date" : "string";
1102
- return this.nullableType(dateType, isNullable);
1103
- }
1104
- if (format === "binary") return "Blob";
1105
- if (format === "uuid") return "string";
1106
- if (format === "email") return "string";
1107
- if (format === "uri") return "string";
1108
- return this.nullableType("string", isNullable);
1109
- case "number":
1110
- case "integer":
1111
- return this.nullableType("number", isNullable);
1112
- case "boolean":
1113
- return this.nullableType("boolean", isNullable);
1114
- case "array":
1115
- return this.nullableType("any[]", isNullable);
1116
- case "object":
1117
- return this.nullableType("Record<string, unknown>", isNullable);
1118
- case "null":
1119
- return this.nullableType("null", isNullable);
1120
- default:
1121
- if (Array.isArray(type)) {
1122
- const types = type.map((t) => this.mapSwaggerTypeToTypeScript(t, void 0, isNullable));
1123
- return this.nullableType(types.join(" | "), isNullable);
1124
- }
1125
- return this.nullableType("any", isNullable);
1126
- }
1127
- }
1128
- nullableType(type, isNullable) {
1129
- return type + (isNullable ? " | null" : "");
1130
- }
1131
- sanitizePropertyName(name) {
1132
- if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)) {
1133
- return `"${name}"`;
1134
- }
1135
- return name;
1136
- }
1137
- toEnumKey(value) {
1138
- const str = value.toString();
1139
- const hasLeadingMinus = str.startsWith("-");
1140
- const pascalCased = pascalCase(str);
1141
- return hasLeadingMinus ? pascalCased.replace(/^([0-9])/, "_n$1") : pascalCased.replace(/^([0-9])/, "_$1");
1142
- }
1143
- getArrayItemType(items) {
1144
- if (Array.isArray(items)) {
1145
- const types = items.map((item) => this.resolveSwaggerTypeCached(item));
1146
- return `[${types.join(", ")}]`;
1147
- } else {
1148
- return this.resolveSwaggerTypeCached(items);
1149
- }
1150
- }
1151
- escapeString(str) {
1152
- return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1153
- }
1154
1551
  };
1155
1552
  __name(_TypeGenerator, "TypeGenerator");
1156
1553
  var TypeGenerator = _TypeGenerator;
1157
1554
 
1158
1555
  // src/lib/generators/utility/token.generator.ts
1159
- var import_ts_morph2 = require("ts-morph");
1556
+ var import_ts_morph5 = require("ts-morph");
1160
1557
  var path2 = __toESM(require("path"));
1161
1558
  var _TokenGenerator = class _TokenGenerator {
1162
1559
  constructor(project, clientName = "default") {
@@ -1191,7 +1588,7 @@ var _TokenGenerator = class _TokenGenerator {
1191
1588
  const clientContextTokenName = this.getClientContextTokenName();
1192
1589
  sourceFile.addVariableStatement({
1193
1590
  isExported: true,
1194
- declarationKind: import_ts_morph2.VariableDeclarationKind.Const,
1591
+ declarationKind: import_ts_morph5.VariableDeclarationKind.Const,
1195
1592
  declarations: [
1196
1593
  {
1197
1594
  name: basePathTokenName,
@@ -1208,7 +1605,7 @@ var _TokenGenerator = class _TokenGenerator {
1208
1605
  });
1209
1606
  sourceFile.addVariableStatement({
1210
1607
  isExported: true,
1211
- declarationKind: import_ts_morph2.VariableDeclarationKind.Const,
1608
+ declarationKind: import_ts_morph5.VariableDeclarationKind.Const,
1212
1609
  declarations: [
1213
1610
  {
1214
1611
  name: interceptorsTokenName,
@@ -1225,7 +1622,7 @@ var _TokenGenerator = class _TokenGenerator {
1225
1622
  });
1226
1623
  sourceFile.addVariableStatement({
1227
1624
  isExported: true,
1228
- declarationKind: import_ts_morph2.VariableDeclarationKind.Const,
1625
+ declarationKind: import_ts_morph5.VariableDeclarationKind.Const,
1229
1626
  declarations: [
1230
1627
  {
1231
1628
  name: clientContextTokenName,
@@ -1240,7 +1637,7 @@ var _TokenGenerator = class _TokenGenerator {
1240
1637
  if (this.clientName === "default") {
1241
1638
  sourceFile.addVariableStatement({
1242
1639
  isExported: true,
1243
- declarationKind: import_ts_morph2.VariableDeclarationKind.Const,
1640
+ declarationKind: import_ts_morph5.VariableDeclarationKind.Const,
1244
1641
  declarations: [
1245
1642
  {
1246
1643
  name: "BASE_PATH",
@@ -1254,7 +1651,7 @@ var _TokenGenerator = class _TokenGenerator {
1254
1651
  });
1255
1652
  sourceFile.addVariableStatement({
1256
1653
  isExported: true,
1257
- declarationKind: import_ts_morph2.VariableDeclarationKind.Const,
1654
+ declarationKind: import_ts_morph5.VariableDeclarationKind.Const,
1258
1655
  declarations: [
1259
1656
  {
1260
1657
  name: "CLIENT_CONTEXT_TOKEN",
@@ -1426,7 +1823,7 @@ __name(_FileDownloadGenerator, "FileDownloadGenerator");
1426
1823
  var FileDownloadGenerator = _FileDownloadGenerator;
1427
1824
 
1428
1825
  // src/lib/generators/utility/date-transformer.generator.ts
1429
- var import_ts_morph3 = require("ts-morph");
1826
+ var import_ts_morph6 = require("ts-morph");
1430
1827
  var path4 = __toESM(require("path"));
1431
1828
  var _DateTransformerGenerator = class _DateTransformerGenerator {
1432
1829
  constructor(project) {
@@ -1466,7 +1863,7 @@ var _DateTransformerGenerator = class _DateTransformerGenerator {
1466
1863
  ]);
1467
1864
  sourceFile.addVariableStatement({
1468
1865
  isExported: true,
1469
- declarationKind: import_ts_morph3.VariableDeclarationKind.Const,
1866
+ declarationKind: import_ts_morph6.VariableDeclarationKind.Const,
1470
1867
  declarations: [
1471
1868
  {
1472
1869
  name: "ISO_DATE_REGEX",
@@ -1538,7 +1935,7 @@ var _DateTransformerGenerator = class _DateTransformerGenerator {
1538
1935
  {
1539
1936
  name: "dateRegex",
1540
1937
  type: "RegExp",
1541
- scope: import_ts_morph3.Scope.Private,
1938
+ scope: import_ts_morph6.Scope.Private,
1542
1939
  isReadonly: true,
1543
1940
  initializer: "ISO_DATE_REGEX"
1544
1941
  }
@@ -1836,7 +2233,7 @@ __name(_ProviderGenerator, "ProviderGenerator");
1836
2233
  var ProviderGenerator = _ProviderGenerator;
1837
2234
 
1838
2235
  // src/lib/generators/utility/base-interceptor.generator.ts
1839
- var import_ts_morph4 = require("ts-morph");
2236
+ var import_ts_morph7 = require("ts-morph");
1840
2237
  var path7 = __toESM(require("path"));
1841
2238
  var _project, _clientName;
1842
2239
  var _BaseInterceptorGenerator = class _BaseInterceptorGenerator {
@@ -1903,14 +2300,14 @@ var _BaseInterceptorGenerator = class _BaseInterceptorGenerator {
1903
2300
  {
1904
2301
  name: "httpInterceptors",
1905
2302
  type: "HttpInterceptor[]",
1906
- scope: import_ts_morph4.Scope.Private,
2303
+ scope: import_ts_morph7.Scope.Private,
1907
2304
  isReadonly: true,
1908
2305
  initializer: `inject(${interceptorsTokenName})`
1909
2306
  },
1910
2307
  {
1911
2308
  name: "clientContextToken",
1912
2309
  type: "HttpContextToken<string>",
1913
- scope: import_ts_morph4.Scope.Private,
2310
+ scope: import_ts_morph7.Scope.Private,
1914
2311
  isReadonly: true,
1915
2312
  initializer: clientContextTokenName
1916
2313
  }
@@ -1964,7 +2361,7 @@ var BaseInterceptorGenerator = _BaseInterceptorGenerator;
1964
2361
 
1965
2362
  // src/lib/generators/utility/http-params-builder.generator.ts
1966
2363
  var path8 = __toESM(require("path"));
1967
- var import_ts_morph5 = require("ts-morph");
2364
+ var import_ts_morph8 = require("ts-morph");
1968
2365
  var _HttpParamsBuilderGenerator = class _HttpParamsBuilderGenerator {
1969
2366
  constructor(project) {
1970
2367
  __publicField(this, "project");
@@ -1995,7 +2392,7 @@ var _HttpParamsBuilderGenerator = class _HttpParamsBuilderGenerator {
1995
2392
  {
1996
2393
  name: "addToHttpParams",
1997
2394
  isStatic: true,
1998
- scope: import_ts_morph5.Scope.Public,
2395
+ scope: import_ts_morph8.Scope.Public,
1999
2396
  parameters: [
2000
2397
  {
2001
2398
  name: "httpParams",
@@ -2028,7 +2425,7 @@ return this.addToHttpParamsRecursive(httpParams, value, key);`
2028
2425
  {
2029
2426
  name: "addToHttpParamsRecursive",
2030
2427
  isStatic: true,
2031
- scope: import_ts_morph5.Scope.Private,
2428
+ scope: import_ts_morph8.Scope.Private,
2032
2429
  parameters: [
2033
2430
  {
2034
2431
  name: "httpParams",
@@ -2067,7 +2464,7 @@ return this.handlePrimitive(httpParams, value, key);`
2067
2464
  {
2068
2465
  name: "handleArray",
2069
2466
  isStatic: true,
2070
- scope: import_ts_morph5.Scope.Private,
2467
+ scope: import_ts_morph8.Scope.Private,
2071
2468
  parameters: [
2072
2469
  {
2073
2470
  name: "httpParams",
@@ -2092,7 +2489,7 @@ return httpParams;`
2092
2489
  {
2093
2490
  name: "handleDate",
2094
2491
  isStatic: true,
2095
- scope: import_ts_morph5.Scope.Private,
2492
+ scope: import_ts_morph8.Scope.Private,
2096
2493
  parameters: [
2097
2494
  {
2098
2495
  name: "httpParams",
@@ -2117,7 +2514,7 @@ return httpParams.append(key, date.toISOString());`
2117
2514
  {
2118
2515
  name: "handleObject",
2119
2516
  isStatic: true,
2120
- scope: import_ts_morph5.Scope.Private,
2517
+ scope: import_ts_morph8.Scope.Private,
2121
2518
  parameters: [
2122
2519
  {
2123
2520
  name: "httpParams",
@@ -2143,7 +2540,7 @@ return httpParams;`
2143
2540
  {
2144
2541
  name: "handlePrimitive",
2145
2542
  isStatic: true,
2146
- scope: import_ts_morph5.Scope.Private,
2543
+ scope: import_ts_morph8.Scope.Private,
2147
2544
  parameters: [
2148
2545
  {
2149
2546
  name: "httpParams",
@@ -2173,144 +2570,37 @@ __name(_HttpParamsBuilderGenerator, "HttpParamsBuilderGenerator");
2173
2570
  var HttpParamsBuilderGenerator = _HttpParamsBuilderGenerator;
2174
2571
 
2175
2572
  // src/lib/generators/service/service.generator.ts
2176
- var import_ts_morph6 = require("ts-morph");
2573
+ var import_ts_morph9 = require("ts-morph");
2177
2574
  var path10 = __toESM(require("path"));
2178
2575
 
2179
2576
  // src/lib/generators/service/service-method/service-method-body.generator.ts
2180
2577
  var _ServiceMethodBodyGenerator = class _ServiceMethodBodyGenerator {
2181
- constructor(config, parser) {
2578
+ constructor(config) {
2182
2579
  __publicField(this, "config");
2183
- __publicField(this, "parser");
2184
2580
  this.config = config;
2185
- this.parser = parser;
2186
2581
  }
2187
2582
  generateMethodBody(operation) {
2188
- const context = this.createGenerationContext(operation);
2189
2583
  const bodyParts = [
2190
- this.generateUrlConstruction(operation, context),
2191
- this.generateQueryParams(context),
2192
- this.generateHeaders(context),
2193
- this.generateMultipartFormData(operation, context),
2194
- this.generateUrlEncodedFormData(operation, context),
2195
- this.generateRequestOptions(context),
2196
- this.generateHttpRequest(operation, context)
2584
+ emitUrlConstruction(operation.path, operation.pathParams),
2585
+ emitQueryParams(operation.queryParams),
2586
+ emitHeaders({
2587
+ optionsExpression: "options",
2588
+ customHeaders: this.config.options.customHeaders,
2589
+ contentType: operation
2590
+ }),
2591
+ this.generateMultipartFormData(operation),
2592
+ this.generateUrlEncodedFormData(operation),
2593
+ this.generateHttpRequest(operation)
2197
2594
  ];
2198
2595
  return bodyParts.filter(Boolean).join("\n");
2199
2596
  }
2200
- isMultipartFormData(operation) {
2201
- var _a, _b;
2202
- return !!((_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b[CONTENT_TYPES.MULTIPART]);
2203
- }
2204
- isUrlEncodedFormData(operation) {
2205
- var _a, _b, _c, _d;
2206
- return !!((_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b[CONTENT_TYPES.FORM_URLENCODED]) && !((_d = (_c = operation.requestBody) == null ? void 0 : _c.content) == null ? void 0 : _d[CONTENT_TYPES.JSON]);
2207
- }
2208
- getFormDataFields(operation) {
2209
- var _a, _b;
2210
- if (!this.isMultipartFormData(operation)) {
2211
- return [];
2212
- }
2213
- const schema = (_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b[CONTENT_TYPES.MULTIPART].schema;
2214
- let resolvedSchema = schema;
2215
- if (schema == null ? void 0 : schema.$ref) {
2216
- resolvedSchema = this.parser.resolveReference(schema.$ref);
2217
- }
2218
- const properties = (resolvedSchema == null ? void 0 : resolvedSchema.properties) || {};
2219
- return Object.keys(properties);
2220
- }
2221
- getUrlEncodedFields(operation) {
2222
- var _a, _b;
2223
- if (!this.isUrlEncodedFormData(operation)) {
2224
- return [];
2225
- }
2226
- const schema = (_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b[CONTENT_TYPES.FORM_URLENCODED].schema;
2227
- let resolvedSchema = schema;
2228
- if (schema == null ? void 0 : schema.$ref) {
2229
- resolvedSchema = this.parser.resolveReference(schema.$ref);
2230
- }
2231
- const properties = (resolvedSchema == null ? void 0 : resolvedSchema.properties) || {};
2232
- return Object.keys(properties);
2233
- }
2234
- createGenerationContext(operation) {
2235
- var _a, _b;
2236
- return {
2237
- pathParams: ((_a = operation.parameters) == null ? void 0 : _a.filter((p) => p.in === "path")) || [],
2238
- queryParams: ((_b = operation.parameters) == null ? void 0 : _b.filter((p) => p.in === "query")) || [],
2239
- hasBody: !!operation.requestBody,
2240
- isMultipart: this.isMultipartFormData(operation),
2241
- isUrlEncoded: this.isUrlEncodedFormData(operation),
2242
- formDataFields: this.getFormDataFields(operation),
2243
- urlEncodedFields: this.getUrlEncodedFields(operation),
2244
- responseType: this.determineResponseType(operation)
2245
- };
2246
- }
2247
- generateUrlConstruction(operation, context) {
2248
- let urlExpression = `\`\${this.basePath}${operation.path}\``;
2249
- if (context.pathParams.length > 0) {
2250
- context.pathParams.forEach((param) => {
2251
- urlExpression = urlExpression.replace(`{${param.name}}`, `\${${camelCase(param.name)}}`);
2252
- });
2253
- }
2254
- return `const url = ${urlExpression};`;
2255
- }
2256
- generateQueryParams(context) {
2257
- if (context.queryParams.length === 0) {
2258
- return "";
2259
- }
2260
- const paramMappings = context.queryParams.map((param) => `if (${camelCase(param.name)} != null) {
2261
- params = HttpParamsBuilder.addToHttpParams(params, ${camelCase(param.name)}, '${param.name}');
2262
- }`).join("\n");
2263
- return `
2264
- let params = new HttpParams();
2265
- ${paramMappings}`;
2266
- }
2267
- generateHeaders(context) {
2268
- const hasCustomHeaders = this.config.options.customHeaders;
2269
- let headerCode = `
2270
- let headers: HttpHeaders;
2271
- if (options?.headers instanceof HttpHeaders) {
2272
- headers = options.headers;
2273
- } else {
2274
- headers = new HttpHeaders(options?.headers);
2275
- }`;
2276
- if (hasCustomHeaders) {
2277
- headerCode += `
2278
- // Add default headers if not already present
2279
- ${Object.entries(this.config.options.customHeaders || {}).map(([key, value]) => `if (!headers.has('${key}')) {
2280
- headers = headers.set('${key}', '${value}');
2281
- }`).join("\n")}`;
2282
- }
2283
- if (context.isMultipart) {
2284
- headerCode += `
2285
- // Remove Content-Type for multipart (browser will set it with boundary)
2286
- headers = headers.delete('Content-Type');`;
2287
- } else if (context.isUrlEncoded) {
2288
- headerCode += `
2289
- // Set Content-Type for URL-encoded form data
2290
- if (!headers.has('Content-Type')) {
2291
- headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
2292
- }`;
2293
- } else if (context.hasBody) {
2294
- headerCode += `
2295
- // Set Content-Type for JSON requests if not already set
2296
- if (!headers.has('Content-Type')) {
2297
- headers = headers.set('Content-Type', 'application/json');
2298
- }`;
2299
- }
2300
- return headerCode;
2301
- }
2302
- generateMultipartFormData(operation, context) {
2303
- var _a, _b;
2304
- if (!context.isMultipart || context.formDataFields.length === 0) {
2597
+ generateMultipartFormData(operation) {
2598
+ var _a;
2599
+ if (!operation.isMultipart || operation.formDataFields.length === 0) {
2305
2600
  return "";
2306
2601
  }
2307
- const schema = (_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b[CONTENT_TYPES.MULTIPART].schema;
2308
- let resolvedSchema = schema;
2309
- if (schema == null ? void 0 : schema.$ref) {
2310
- resolvedSchema = this.parser.resolveReference(schema.$ref);
2311
- }
2312
- const properties = (resolvedSchema == null ? void 0 : resolvedSchema.properties) || {};
2313
- const formDataAppends = context.formDataFields.map((field) => {
2602
+ const properties = ((_a = operation.formDataSchema) == null ? void 0 : _a.properties) || {};
2603
+ const formDataAppends = operation.formDataFields.map((field) => {
2314
2604
  const fieldSchema = properties[field];
2315
2605
  const isFile = (fieldSchema == null ? void 0 : fieldSchema.type) === "string" && (fieldSchema == null ? void 0 : fieldSchema.format) === "binary";
2316
2606
  const isArray = (fieldSchema == null ? void 0 : fieldSchema.type) === "array";
@@ -2336,18 +2626,13 @@ if (!headers.has('Content-Type')) {
2336
2626
  const formData = new FormData();
2337
2627
  ${formDataAppends}`;
2338
2628
  }
2339
- generateUrlEncodedFormData(operation, context) {
2340
- var _a, _b;
2341
- if (!context.isUrlEncoded || context.urlEncodedFields.length === 0) {
2629
+ generateUrlEncodedFormData(operation) {
2630
+ var _a;
2631
+ if (!operation.isUrlEncoded || operation.urlEncodedFields.length === 0) {
2342
2632
  return "";
2343
2633
  }
2344
- const schema = (_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b[CONTENT_TYPES.FORM_URLENCODED].schema;
2345
- let resolvedSchema = schema;
2346
- if (schema == null ? void 0 : schema.$ref) {
2347
- resolvedSchema = this.parser.resolveReference(schema.$ref);
2348
- }
2349
- const properties = (resolvedSchema == null ? void 0 : resolvedSchema.properties) || {};
2350
- const formBodyAppends = context.urlEncodedFields.map((field) => {
2634
+ const properties = ((_a = operation.urlEncodedSchema) == null ? void 0 : _a.properties) || {};
2635
+ const formBodyAppends = operation.urlEncodedFields.map((field) => {
2351
2636
  const fieldSchema = properties[field];
2352
2637
  const isArray = (fieldSchema == null ? void 0 : fieldSchema.type) === "array";
2353
2638
  if (isArray) {
@@ -2368,33 +2653,14 @@ ${formDataAppends}`;
2368
2653
  const formBody = new URLSearchParams();
2369
2654
  ${formBodyAppends}`;
2370
2655
  }
2371
- generateRequestOptions(context) {
2372
- const options = [];
2373
- options.push("observe: observe as any");
2374
- options.push("headers");
2375
- if (context.queryParams.length > 0) {
2376
- options.push("params");
2377
- }
2378
- if (context.responseType !== "json") {
2379
- options.push(`responseType: '${context.responseType}' as '${context.responseType}'`);
2380
- }
2381
- options.push("reportProgress: options?.reportProgress");
2382
- options.push("withCredentials: options?.withCredentials");
2383
- options.push("context: this.createContextWithClientId(options?.context)");
2384
- const formattedOptions = options.filter((opt) => opt && !opt.includes("undefined")).join(",\n ");
2385
- return `
2386
- const requestOptions: any = {
2387
- ${formattedOptions}
2388
- };`;
2389
- }
2390
- generateHttpRequest(operation, context) {
2656
+ generateHttpRequest(operation) {
2391
2657
  var _a, _b, _c;
2392
2658
  const httpMethod = operation.method.toLowerCase();
2393
2659
  let bodyParam = "";
2394
- if (context.hasBody) {
2395
- if (context.isMultipart) {
2660
+ if (operation.hasBody) {
2661
+ if (operation.isMultipart) {
2396
2662
  bodyParam = "formData";
2397
- } else if (context.isUrlEncoded) {
2663
+ } else if (operation.isUrlEncoded) {
2398
2664
  bodyParam = "formBody.toString()";
2399
2665
  } else if ((_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b[CONTENT_TYPES.JSON]) {
2400
2666
  const bodyType = getRequestBodyType(operation.requestBody, this.config);
@@ -2408,29 +2674,23 @@ const requestOptions: any = {
2408
2674
  "patch"
2409
2675
  ];
2410
2676
  const parseResponse = ((_c = this.config.options.validation) == null ? void 0 : _c.response) ? `.pipe(map(response => options?.parse?.(response) ?? response))` : "";
2677
+ const entries = [];
2411
2678
  if (methodsWithBody.includes(httpMethod)) {
2412
- return `
2413
- return this.httpClient.${httpMethod}(url, ${bodyParam || "null"}, requestOptions)${parseResponse};`;
2414
- } else {
2415
- return `
2416
- return this.httpClient.${httpMethod}(url, requestOptions)${parseResponse};`;
2679
+ entries.push(`body: ${bodyParam || "null"}`);
2417
2680
  }
2418
- }
2419
- determineResponseType(operation) {
2420
- var _a;
2421
- const successResponses = [
2422
- "200",
2423
- "201",
2424
- "202",
2425
- "204",
2426
- "206"
2427
- ];
2428
- for (const statusCode of successResponses) {
2429
- const response = (_a = operation.responses) == null ? void 0 : _a[statusCode];
2430
- if (!response) continue;
2431
- return getResponseTypeFromResponse(response);
2681
+ entries.push("observe");
2682
+ entries.push("headers");
2683
+ if (operation.queryParams.length > 0) {
2684
+ entries.push("params");
2432
2685
  }
2433
- return "json";
2686
+ entries.push(emitResponseTypeOption(operation.responseType));
2687
+ entries.push("reportProgress: options?.reportProgress");
2688
+ entries.push("withCredentials: options?.withCredentials");
2689
+ entries.push("context: this.createContextWithClientId(options?.context)");
2690
+ return `
2691
+ return this.httpClient.request('${httpMethod}', url, {
2692
+ ${joinRequestOptionEntries(entries)}
2693
+ })${parseResponse};`;
2434
2694
  }
2435
2695
  };
2436
2696
  __name(_ServiceMethodBodyGenerator, "ServiceMethodBodyGenerator");
@@ -2504,11 +2764,9 @@ var ServiceMethodRequestObjectGenerator = _ServiceMethodRequestObjectGenerator;
2504
2764
 
2505
2765
  // src/lib/generators/service/service-method/service-method-params.generator.ts
2506
2766
  var _ServiceMethodParamsGenerator = class _ServiceMethodParamsGenerator {
2507
- constructor(config, parser) {
2767
+ constructor(config) {
2508
2768
  __publicField(this, "config");
2509
- __publicField(this, "parser");
2510
2769
  this.config = config;
2511
- this.parser = parser;
2512
2770
  }
2513
2771
  generateMethodParameters(operation) {
2514
2772
  const params = this.generateApiParameters(operation);
@@ -2519,30 +2777,28 @@ var _ServiceMethodParamsGenerator = class _ServiceMethodParamsGenerator {
2519
2777
  ]);
2520
2778
  }
2521
2779
  generateApiParameters(operation) {
2522
- var _a, _b, _c, _d, _e;
2780
+ var _a;
2523
2781
  const params = [];
2524
- const pathParams = ((_a = operation.parameters) == null ? void 0 : _a.filter((p) => p.in === "path")) || [];
2525
- pathParams.forEach((param) => {
2782
+ operation.pathParams.forEach((param) => {
2526
2783
  params.push({
2527
2784
  name: camelCase(param.name),
2528
- type: getTypeScriptType(param.schema || param, this.config),
2785
+ // Swagger 2.0 puts type/format/enum on the parameter itself; the
2786
+ // spread (vs passing param directly) is needed because Parameter
2787
+ // lacks TypeSchema's index signature — a fresh literal satisfies it.
2788
+ type: getTypeScriptType(param.schema || __spreadValues({}, param), this.config),
2529
2789
  hasQuestionToken: !param.required
2530
2790
  });
2531
2791
  });
2532
2792
  const requestBody = operation.requestBody;
2533
2793
  if (requestBody) {
2534
- const formDataContent = (_b = requestBody.content) == null ? void 0 : _b[CONTENT_TYPES.MULTIPART];
2535
- const urlEncodedContent = (_c = requestBody.content) == null ? void 0 : _c[CONTENT_TYPES.FORM_URLENCODED];
2536
- const jsonContent = (_d = requestBody.content) == null ? void 0 : _d[CONTENT_TYPES.JSON];
2537
- if (formDataContent) {
2538
- const formParams = this.convertObjectToSingleParams(formDataContent.schema);
2539
- params.push(...formParams);
2794
+ const jsonContent = (_a = requestBody.content) == null ? void 0 : _a[CONTENT_TYPES.JSON];
2795
+ if (operation.isMultipart) {
2796
+ params.push(...this.convertObjectToSingleParams(operation.formDataSchema));
2540
2797
  }
2541
- if (!jsonContent && urlEncodedContent) {
2542
- const formParams = this.convertObjectToSingleParams(urlEncodedContent.schema);
2543
- params.push(...formParams);
2798
+ if (operation.isUrlEncoded) {
2799
+ params.push(...this.convertObjectToSingleParams(operation.urlEncodedSchema));
2544
2800
  }
2545
- if (jsonContent && !formDataContent) {
2801
+ if (jsonContent && !operation.isMultipart) {
2546
2802
  const bodyType = this.getRequestBodyType(requestBody);
2547
2803
  const isInterface = isDataTypeInterface(bodyType);
2548
2804
  params.push({
@@ -2552,11 +2808,10 @@ var _ServiceMethodParamsGenerator = class _ServiceMethodParamsGenerator {
2552
2808
  });
2553
2809
  }
2554
2810
  }
2555
- const queryParams = ((_e = operation.parameters) == null ? void 0 : _e.filter((p) => p.in === "query")) || [];
2556
- queryParams.forEach((param) => {
2811
+ operation.queryParams.forEach((param) => {
2557
2812
  params.push({
2558
2813
  name: camelCase(param.name),
2559
- type: getTypeScriptType(param.schema || param, this.config),
2814
+ type: getTypeScriptType(param.schema || __spreadValues({}, param), this.config),
2560
2815
  hasQuestionToken: !param.required
2561
2816
  });
2562
2817
  });
@@ -2596,19 +2851,16 @@ var _ServiceMethodParamsGenerator = class _ServiceMethodParamsGenerator {
2596
2851
  }
2597
2852
  return "any";
2598
2853
  }
2854
+ /** `schema` arrives ref-resolved from the normalizer (formData/urlEncoded schema). */
2599
2855
  convertObjectToSingleParams(schema) {
2600
2856
  var _a;
2601
2857
  const params = [];
2602
- let resolvedSchema = schema;
2603
- if (schema == null ? void 0 : schema.$ref) {
2604
- resolvedSchema = this.parser.resolveReference(schema.$ref);
2605
- }
2606
- Object.entries((_a = resolvedSchema == null ? void 0 : resolvedSchema.properties) != null ? _a : {}).forEach(([key, value]) => {
2858
+ Object.entries((_a = schema == null ? void 0 : schema.properties) != null ? _a : {}).forEach(([key, value]) => {
2607
2859
  var _a2;
2608
2860
  params.push({
2609
2861
  name: key,
2610
2862
  type: getTypeScriptType(value, this.config, value.nullable),
2611
- hasQuestionToken: !((_a2 = resolvedSchema == null ? void 0 : resolvedSchema.required) == null ? void 0 : _a2.includes(key))
2863
+ hasQuestionToken: !((_a2 = schema == null ? void 0 : schema.required) == null ? void 0 : _a2.includes(key))
2612
2864
  });
2613
2865
  });
2614
2866
  return params;
@@ -2619,12 +2871,12 @@ var ServiceMethodParamsGenerator = _ServiceMethodParamsGenerator;
2619
2871
 
2620
2872
  // src/lib/generators/service/service-method/service-method-overloads.generator.ts
2621
2873
  var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2622
- constructor(config, parser) {
2874
+ constructor(config) {
2623
2875
  __publicField(this, "config");
2624
2876
  __publicField(this, "paramsGenerator");
2625
2877
  __publicField(this, "responseDataType", "any");
2626
2878
  this.config = config;
2627
- this.paramsGenerator = new ServiceMethodParamsGenerator(config, parser);
2879
+ this.paramsGenerator = new ServiceMethodParamsGenerator(config);
2628
2880
  }
2629
2881
  generateMethodOverloads(operation, requestObject) {
2630
2882
  const observeTypes = [
@@ -2633,7 +2885,7 @@ var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2633
2885
  "events"
2634
2886
  ];
2635
2887
  const overloads = [];
2636
- const responseType = this.determineResponseTypeForOperation(operation);
2888
+ const responseType = operation.responseType;
2637
2889
  observeTypes.forEach((observe) => {
2638
2890
  const overload = this.generateMethodOverload(operation, observe, responseType, requestObject);
2639
2891
  if (overload) {
@@ -2711,37 +2963,21 @@ var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2711
2963
  }
2712
2964
  return `RequestOptions<'${responseType}', ${additionalTypeParameters.join(", ")}>`;
2713
2965
  }
2714
- determineResponseTypeForOperation(operation) {
2715
- var _a;
2716
- const successResponses = [
2717
- "200",
2718
- "201",
2719
- "202",
2720
- "204",
2721
- "206"
2722
- ];
2723
- for (const statusCode of successResponses) {
2724
- const response = (_a = operation.responses) == null ? void 0 : _a[statusCode];
2725
- if (!response) continue;
2726
- return getResponseTypeFromResponse(response);
2727
- }
2728
- return "json";
2729
- }
2730
2966
  };
2731
2967
  __name(_ServiceMethodOverloadsGenerator, "ServiceMethodOverloadsGenerator");
2732
2968
  var ServiceMethodOverloadsGenerator = _ServiceMethodOverloadsGenerator;
2733
2969
 
2734
2970
  // src/lib/generators/service/service-method.generator.ts
2735
2971
  var _ServiceMethodGenerator = class _ServiceMethodGenerator {
2736
- constructor(config, parser) {
2972
+ constructor(config) {
2737
2973
  __publicField(this, "config");
2738
2974
  __publicField(this, "bodyGenerator");
2739
2975
  __publicField(this, "overloadsGenerator");
2740
2976
  __publicField(this, "paramsGenerator");
2741
2977
  this.config = config;
2742
- this.bodyGenerator = new ServiceMethodBodyGenerator(config, parser);
2743
- this.overloadsGenerator = new ServiceMethodOverloadsGenerator(config, parser);
2744
- this.paramsGenerator = new ServiceMethodParamsGenerator(config, parser);
2978
+ this.bodyGenerator = new ServiceMethodBodyGenerator(config);
2979
+ this.overloadsGenerator = new ServiceMethodOverloadsGenerator(config);
2980
+ this.paramsGenerator = new ServiceMethodParamsGenerator(config);
2745
2981
  }
2746
2982
  addServiceMethod(serviceClass, operation, requestObject) {
2747
2983
  const methodName = this.generateMethodName(operation);
@@ -2801,13 +3037,13 @@ var ServiceMethodGenerator = _ServiceMethodGenerator;
2801
3037
  // src/lib/generators/service/request-params.generator.ts
2802
3038
  var path9 = __toESM(require("path"));
2803
3039
  var _RequestParamsGenerator = class _RequestParamsGenerator {
2804
- constructor(parser, project, config) {
3040
+ constructor(project, config) {
2805
3041
  __publicField(this, "project");
2806
3042
  __publicField(this, "paramsGenerator");
2807
3043
  __publicField(this, "registry", /* @__PURE__ */ new Map());
2808
3044
  __publicField(this, "usedInterfaceNames", /* @__PURE__ */ new Set());
2809
3045
  this.project = project;
2810
- this.paramsGenerator = new ServiceMethodParamsGenerator(config, parser);
3046
+ this.paramsGenerator = new ServiceMethodParamsGenerator(config);
2811
3047
  }
2812
3048
  buildRegistry(controllerGroups, getMethodName) {
2813
3049
  Object.entries(controllerGroups).forEach(([controllerName, operations]) => {
@@ -2908,34 +3144,31 @@ var RequestParamsGenerator = _RequestParamsGenerator;
2908
3144
 
2909
3145
  // src/lib/generators/service/service.generator.ts
2910
3146
  var _ServiceGenerator = class _ServiceGenerator {
2911
- constructor(parser, project, config) {
3147
+ constructor(parser, project, config, onWarning) {
2912
3148
  __publicField(this, "project");
2913
3149
  __publicField(this, "parser");
2914
- __publicField(this, "spec");
2915
3150
  __publicField(this, "config");
2916
3151
  __publicField(this, "methodGenerator");
2917
3152
  __publicField(this, "requestObjects");
3153
+ __publicField(this, "onWarning");
2918
3154
  this.config = config;
2919
3155
  this.project = project;
2920
3156
  this.parser = parser;
2921
- this.spec = this.parser.getSpec();
2922
- if (!this.parser.isValidSpec()) {
2923
- const versionInfo = this.parser.getSpecVersion();
2924
- throw new Error(`Invalid or unsupported specification format. Expected OpenAPI 3.x or Swagger 2.x. ${versionInfo ? `Found: ${versionInfo.type} ${versionInfo.version}` : "No version info found"}`);
2925
- }
2926
- this.methodGenerator = new ServiceMethodGenerator(config, parser);
3157
+ this.onWarning = onWarning;
3158
+ this.methodGenerator = new ServiceMethodGenerator(config);
2927
3159
  }
2928
3160
  generate(outputRoot) {
2929
3161
  return __async(this, null, function* () {
3162
+ var _a;
2930
3163
  const outputDir = path10.join(outputRoot, "services");
2931
- const paths = extractPaths(this.spec.paths);
3164
+ const paths = this.parser.getNormalizedSpec().operations;
2932
3165
  if (paths.length === 0) {
2933
- console.warn("No API paths found in the specification");
3166
+ (_a = this.onWarning) == null ? void 0 : _a.call(this, "No API paths found in the specification");
2934
3167
  return;
2935
3168
  }
2936
3169
  const controllerGroups = this.groupPathsByController(paths);
2937
3170
  if (this.config.options.useSingleRequestParameter) {
2938
- const requestParamsGenerator = new RequestParamsGenerator(this.parser, this.project, this.config);
3171
+ const requestParamsGenerator = new RequestParamsGenerator(this.project, this.config);
2939
3172
  this.requestObjects = requestParamsGenerator.buildRegistry(controllerGroups, (operation) => this.methodGenerator.generateMethodName(operation));
2940
3173
  requestParamsGenerator.generate(outputRoot);
2941
3174
  }
@@ -3034,27 +3267,27 @@ var _ServiceGenerator = class _ServiceGenerator {
3034
3267
  serviceClass.addProperty({
3035
3268
  name: "httpClient",
3036
3269
  type: "HttpClient",
3037
- scope: import_ts_morph6.Scope.Private,
3270
+ scope: import_ts_morph9.Scope.Private,
3038
3271
  isReadonly: true,
3039
3272
  initializer: "inject(HttpClient)"
3040
3273
  });
3041
3274
  serviceClass.addProperty({
3042
3275
  name: "basePath",
3043
3276
  type: "string",
3044
- scope: import_ts_morph6.Scope.Private,
3277
+ scope: import_ts_morph9.Scope.Private,
3045
3278
  isReadonly: true,
3046
3279
  initializer: `inject(${basePathTokenName})`
3047
3280
  });
3048
3281
  serviceClass.addProperty({
3049
3282
  name: "clientContextToken",
3050
3283
  type: "HttpContextToken<string>",
3051
- scope: import_ts_morph6.Scope.Private,
3284
+ scope: import_ts_morph9.Scope.Private,
3052
3285
  isReadonly: true,
3053
3286
  initializer: clientContextTokenName
3054
3287
  });
3055
3288
  serviceClass.addMethod({
3056
3289
  name: "createContextWithClientId",
3057
- scope: import_ts_morph6.Scope.Private,
3290
+ scope: import_ts_morph9.Scope.Private,
3058
3291
  parameters: [
3059
3292
  {
3060
3293
  name: "existingContext",
@@ -3109,6 +3342,110 @@ var _ServiceIndexGenerator = class _ServiceIndexGenerator {
3109
3342
  __name(_ServiceIndexGenerator, "ServiceIndexGenerator");
3110
3343
  var ServiceIndexGenerator = _ServiceIndexGenerator;
3111
3344
 
3345
+ // src/lib/core/config-validation.ts
3346
+ var RESPONSE_TYPES = [
3347
+ "json",
3348
+ "blob",
3349
+ "arraybuffer",
3350
+ "text"
3351
+ ];
3352
+ var _ConfigValidationError = class _ConfigValidationError extends Error {
3353
+ constructor(issues) {
3354
+ super(`Invalid ng-openapi configuration:
3355
+ ${issues.map((issue) => ` - ${issue}`).join("\n")}`);
3356
+ __publicField(this, "issues");
3357
+ this.name = "ConfigValidationError";
3358
+ this.issues = issues;
3359
+ }
3360
+ };
3361
+ __name(_ConfigValidationError, "ConfigValidationError");
3362
+ var ConfigValidationError = _ConfigValidationError;
3363
+ function validateGeneratorConfig(config) {
3364
+ if (!config || typeof config !== "object") {
3365
+ throw new ConfigValidationError([
3366
+ "config must be an object \u2014 see https://ng-openapi.dev for the shape"
3367
+ ]);
3368
+ }
3369
+ const issues = [];
3370
+ const c = config;
3371
+ if (typeof c.input !== "string" || c.input.trim() === "") {
3372
+ issues.push("`input` must be a non-empty string (path or URL of the OpenAPI/Swagger spec)");
3373
+ }
3374
+ if (typeof c.output !== "string" || c.output.trim() === "") {
3375
+ issues.push("`output` must be a non-empty string (output directory)");
3376
+ }
3377
+ if (c.clientName !== void 0 && typeof c.clientName !== "string") {
3378
+ issues.push("`clientName` must be a string");
3379
+ }
3380
+ if (c.validateInput !== void 0 && typeof c.validateInput !== "function") {
3381
+ issues.push("`validateInput` must be a function (spec) => boolean");
3382
+ }
3383
+ if (!c.options || typeof c.options !== "object") {
3384
+ issues.push("`options` must be an object with at least `dateType` and `enumStyle`");
3385
+ } else {
3386
+ const options = c.options;
3387
+ if (options.dateType !== "string" && options.dateType !== "Date") {
3388
+ issues.push(`\`options.dateType\` must be "string" or "Date", got ${JSON.stringify(options.dateType)}`);
3389
+ }
3390
+ if (options.enumStyle !== "enum" && options.enumStyle !== "union") {
3391
+ issues.push(`\`options.enumStyle\` must be "enum" or "union", got ${JSON.stringify(options.enumStyle)}`);
3392
+ }
3393
+ const booleanKeys = [
3394
+ "generateServices",
3395
+ "generateEnumBasedOnDescription",
3396
+ "useSingleRequestParameter"
3397
+ ];
3398
+ for (const key of booleanKeys) {
3399
+ if (options[key] !== void 0 && typeof options[key] !== "boolean") {
3400
+ issues.push(`\`options.${key}\` must be a boolean`);
3401
+ }
3402
+ }
3403
+ if (options.customizeMethodName !== void 0 && typeof options.customizeMethodName !== "function") {
3404
+ issues.push("`options.customizeMethodName` must be a function (operationId) => string");
3405
+ }
3406
+ if (options.validation !== void 0 && (typeof options.validation !== "object" || options.validation === null)) {
3407
+ issues.push("`options.validation` must be an object like { response?: boolean }");
3408
+ }
3409
+ if (options.customHeaders !== void 0) {
3410
+ if (typeof options.customHeaders !== "object" || options.customHeaders === null) {
3411
+ issues.push("`options.customHeaders` must be an object of header name \u2192 value strings");
3412
+ } else {
3413
+ for (const [header, value] of Object.entries(options.customHeaders)) {
3414
+ if (typeof value !== "string") {
3415
+ issues.push(`\`options.customHeaders["${header}"]\` must be a string`);
3416
+ }
3417
+ }
3418
+ }
3419
+ }
3420
+ if (options.responseTypeMapping !== void 0) {
3421
+ if (typeof options.responseTypeMapping !== "object" || options.responseTypeMapping === null) {
3422
+ issues.push("`options.responseTypeMapping` must be an object of content type \u2192 response type");
3423
+ } else {
3424
+ for (const [contentType, value] of Object.entries(options.responseTypeMapping)) {
3425
+ if (!RESPONSE_TYPES.includes(value)) {
3426
+ issues.push(`\`options.responseTypeMapping["${contentType}"]\` must be one of ${RESPONSE_TYPES.join(", ")}, got ${JSON.stringify(value)}`);
3427
+ }
3428
+ }
3429
+ }
3430
+ }
3431
+ }
3432
+ if (c.plugins !== void 0) {
3433
+ if (!Array.isArray(c.plugins)) {
3434
+ issues.push("`plugins` must be an array of plugin classes (e.g. HttpResourcePlugin, ZodPlugin)");
3435
+ } else {
3436
+ c.plugins.forEach((plugin, index) => {
3437
+ if (typeof plugin !== "function") {
3438
+ issues.push(`\`plugins[${index}]\` must be a plugin class, got ${typeof plugin}`);
3439
+ }
3440
+ });
3441
+ }
3442
+ }
3443
+ if (issues.length > 0) {
3444
+ throw new ConfigValidationError(issues);
3445
+ }
3446
+ }
3447
+ __name(validateGeneratorConfig, "validateGeneratorConfig");
3448
+
3112
3449
  // src/lib/core/generator.ts
3113
3450
  var fs3 = __toESM(require("fs"));
3114
3451
  var path12 = __toESM(require("path"));
@@ -3117,7 +3454,7 @@ function validateInput(inputPath) {
3117
3454
  return;
3118
3455
  }
3119
3456
  if (!fs3.existsSync(inputPath)) {
3120
- throw new Error(`Input file not found: ${inputPath}`);
3457
+ throw new SpecLoadError(`Input file not found: ${inputPath}`, inputPath);
3121
3458
  }
3122
3459
  const extension = path12.extname(inputPath).toLowerCase();
3123
3460
  const supportedExtensions = [
@@ -3126,85 +3463,88 @@ function validateInput(inputPath) {
3126
3463
  ".yml"
3127
3464
  ];
3128
3465
  if (!supportedExtensions.includes(extension)) {
3129
- throw new Error(`Failed to parse ${extension || "specification"}. Supported formats are .json, .yaml, and .yml.`);
3466
+ throw new SpecLoadError(`Failed to parse ${extension || "specification"}. Supported formats are .json, .yaml, and .yml.`, inputPath);
3130
3467
  }
3131
3468
  }
3132
3469
  __name(validateInput, "validateInput");
3133
- function generateFromConfig(config) {
3134
- return __async(this, null, function* () {
3135
- var _a, _b;
3470
+ function generateFromConfig(_0) {
3471
+ return __async(this, arguments, function* (config, reporter = {}) {
3472
+ var _a, _b, _c, _d, _e, _f;
3473
+ const startedAt = Date.now();
3474
+ validateGeneratorConfig(config);
3136
3475
  validateInput(config.input);
3137
3476
  const outputPath = config.output;
3138
3477
  const generateServices = (_a = config.options.generateServices) != null ? _a : true;
3139
- const inputType = isUrl(config.input) ? "URL" : "file";
3478
+ const warnings = [];
3479
+ const onWarning = /* @__PURE__ */ __name((message) => {
3480
+ var _a2;
3481
+ warnings.push(message);
3482
+ (_a2 = reporter.onWarning) == null ? void 0 : _a2.call(reporter, message);
3483
+ }, "onWarning");
3140
3484
  if (!fs3.existsSync(outputPath)) {
3141
3485
  fs3.mkdirSync(outputPath, {
3142
3486
  recursive: true
3143
3487
  });
3144
3488
  }
3145
- try {
3146
- const project = new import_ts_morph7.Project({
3147
- compilerOptions: __spreadValues({
3148
- declaration: true,
3149
- target: import_ts_morph7.ScriptTarget.ES2022,
3150
- module: import_ts_morph7.ModuleKind.Preserve,
3151
- strict: true
3152
- }, config.compilerOptions)
3153
- });
3154
- console.log(`\u{1F4E1} Processing OpenAPI specification from ${inputType}: ${config.input}`);
3155
- const swaggerParser = yield SwaggerParser.create(config.input, config);
3156
- const typeGenerator = new TypeGenerator(swaggerParser, project, config, outputPath);
3157
- yield typeGenerator.generate();
3158
- console.log(`\u2705 TypeScript interfaces generated`);
3159
- if (generateServices) {
3160
- const tokenGenerator = new TokenGenerator(project, config.clientName);
3161
- tokenGenerator.generate(outputPath);
3162
- if (config.options.dateType === "Date") {
3163
- const dateTransformer = new DateTransformerGenerator(project);
3164
- dateTransformer.generate(outputPath);
3165
- }
3166
- const fileDownloadHelper = new FileDownloadGenerator(project);
3167
- fileDownloadHelper.generate(outputPath);
3168
- const httpParamsBuilderGenerator = new HttpParamsBuilderGenerator(project);
3169
- httpParamsBuilderGenerator.generate(outputPath);
3170
- const providerGenerator = new ProviderGenerator(project, config);
3171
- providerGenerator.generate(outputPath);
3172
- const baseInterceptorGenerator = new BaseInterceptorGenerator(project, config.clientName);
3173
- baseInterceptorGenerator.generate(outputPath);
3174
- const serviceGenerator = new ServiceGenerator(swaggerParser, project, config);
3175
- yield serviceGenerator.generate(outputPath);
3176
- const indexGenerator = new ServiceIndexGenerator(project);
3177
- indexGenerator.generateIndex(outputPath);
3178
- console.log(`\u2705 Angular services generated`);
3179
- }
3180
- if ((_b = config.plugins) == null ? void 0 : _b.length) {
3181
- for (const plugin of config.plugins) {
3182
- const generatorClass = plugin;
3183
- const pluginGenerator = new generatorClass(swaggerParser, project, config);
3184
- yield pluginGenerator.generate(outputPath);
3185
- }
3186
- console.log(`\u2705 Plugins are generated`);
3489
+ const project = new import_ts_morph10.Project({
3490
+ compilerOptions: __spreadValues({
3491
+ declaration: true,
3492
+ target: import_ts_morph10.ScriptTarget.ES2022,
3493
+ module: import_ts_morph10.ModuleKind.Preserve,
3494
+ strict: true
3495
+ }, config.compilerOptions)
3496
+ });
3497
+ (_b = reporter.onPhase) == null ? void 0 : _b.call(reporter, "processing-spec");
3498
+ const swaggerParser = yield SwaggerParser.create(config.input, config);
3499
+ if (!swaggerParser.isValidSpec()) {
3500
+ const versionInfo = swaggerParser.getSpecVersion();
3501
+ throw new SpecParseError(`Invalid or unsupported specification format. Expected OpenAPI 3.x or Swagger 2.x. ${versionInfo ? `Found: ${versionInfo.type} ${versionInfo.version}` : "No version info found"}`, config.input);
3502
+ }
3503
+ const normalizedSpec = swaggerParser.getNormalizedSpec();
3504
+ const typeGenerator = new TypeGenerator(swaggerParser, project, config, outputPath, onWarning);
3505
+ yield typeGenerator.generate();
3506
+ (_c = reporter.onPhase) == null ? void 0 : _c.call(reporter, "types-generated");
3507
+ if (generateServices) {
3508
+ const tokenGenerator = new TokenGenerator(project, config.clientName);
3509
+ tokenGenerator.generate(outputPath);
3510
+ if (config.options.dateType === "Date") {
3511
+ const dateTransformer = new DateTransformerGenerator(project);
3512
+ dateTransformer.generate(outputPath);
3187
3513
  }
3188
- const mainIndexGenerator = new MainIndexGenerator(project, config);
3189
- mainIndexGenerator.generateMainIndex(outputPath);
3190
- const sourceInfo = `from ${inputType}: ${config.input}`;
3191
- if (config.clientName) {
3192
- console.log(`\u{1F389} ${config.clientName} Generation completed successfully ${sourceInfo} -> ${outputPath}`);
3193
- } else {
3194
- console.log(`\u{1F389} Generation completed successfully ${sourceInfo} -> ${outputPath}`);
3195
- }
3196
- } catch (error) {
3197
- if (error instanceof Error) {
3198
- console.error("\u274C Error during generation:", error.message);
3199
- if (error.message.includes("fetch") || error.message.includes("Failed to fetch")) {
3200
- console.error("\u{1F4A1} Tip: Make sure the URL is accessible and returns a valid OpenAPI/Swagger specification");
3201
- console.error("\u{1F4A1} Alternative: Download the specification file locally and use the file path instead");
3202
- }
3203
- } else {
3204
- console.error("\u274C Unknown error during generation:", error);
3514
+ const fileDownloadHelper = new FileDownloadGenerator(project);
3515
+ fileDownloadHelper.generate(outputPath);
3516
+ const httpParamsBuilderGenerator = new HttpParamsBuilderGenerator(project);
3517
+ httpParamsBuilderGenerator.generate(outputPath);
3518
+ const providerGenerator = new ProviderGenerator(project, config);
3519
+ providerGenerator.generate(outputPath);
3520
+ const baseInterceptorGenerator = new BaseInterceptorGenerator(project, config.clientName);
3521
+ baseInterceptorGenerator.generate(outputPath);
3522
+ const serviceGenerator = new ServiceGenerator(swaggerParser, project, config, onWarning);
3523
+ yield serviceGenerator.generate(outputPath);
3524
+ const indexGenerator = new ServiceIndexGenerator(project);
3525
+ indexGenerator.generateIndex(outputPath);
3526
+ (_d = reporter.onPhase) == null ? void 0 : _d.call(reporter, "services-generated");
3527
+ }
3528
+ if ((_e = config.plugins) == null ? void 0 : _e.length) {
3529
+ for (const plugin of config.plugins) {
3530
+ const pluginGenerator = new plugin({
3531
+ spec: normalizedSpec,
3532
+ project,
3533
+ config,
3534
+ onWarning
3535
+ });
3536
+ yield pluginGenerator.generate(outputPath);
3205
3537
  }
3206
- throw error;
3538
+ (_f = reporter.onPhase) == null ? void 0 : _f.call(reporter, "plugins-generated");
3207
3539
  }
3540
+ const mainIndexGenerator = new MainIndexGenerator(project, config);
3541
+ mainIndexGenerator.generateMainIndex(outputPath);
3542
+ return {
3543
+ client: config.clientName,
3544
+ filesWritten: project.getSourceFiles().map((sourceFile) => sourceFile.getFilePath()),
3545
+ warnings,
3546
+ durationMs: Date.now() - startedAt
3547
+ };
3208
3548
  });
3209
3549
  }
3210
3550
  __name(generateFromConfig, "generateFromConfig");
@@ -3212,17 +3552,29 @@ __name(generateFromConfig, "generateFromConfig");
3212
3552
  0 && (module.exports = {
3213
3553
  BASE_INTERCEPTOR_HEADER_COMMENT,
3214
3554
  CONTENT_TYPES,
3555
+ ConfigValidationError,
3215
3556
  HTTP_RESOURCE_GENERATOR_HEADER_COMMENT,
3216
3557
  MAIN_INDEX_GENERATOR_HEADER_COMMENT,
3558
+ NgOpenApiError,
3217
3559
  PROVIDER_GENERATOR_HEADER_COMMENT,
3218
3560
  REQUEST_PARAMS_GENERATOR_HEADER_COMMENT,
3219
3561
  SERVICE_GENERATOR_HEADER_COMMENT,
3220
3562
  SERVICE_INDEX_GENERATOR_HEADER_COMMENT,
3563
+ SpecLoadError,
3564
+ SpecParseError,
3221
3565
  SwaggerParser,
3222
3566
  TYPE_GENERATOR_HEADER_COMMENT,
3223
3567
  ZOD_PLUGIN_GENERATOR_HEADER_COMMENT,
3224
3568
  ZOD_PLUGIN_INDEX_GENERATOR_HEADER_COMMENT,
3225
3569
  camelCase,
3570
+ defineConfig,
3571
+ emitDefaultHeadersMerge,
3572
+ emitHeaders,
3573
+ emitQueryParams,
3574
+ emitResponseTypeOption,
3575
+ emitSignalAwareQueryParams,
3576
+ emitUrlConstruction,
3577
+ emitUrlExpression,
3226
3578
  escapeString,
3227
3579
  extractPaths,
3228
3580
  generateFromConfig,
@@ -3238,11 +3590,18 @@ __name(generateFromConfig, "generateFromConfig");
3238
3590
  inferResponseTypeFromContentType,
3239
3591
  isDataTypeInterface,
3240
3592
  isPrimitiveType,
3593
+ isUrl,
3594
+ joinRequestOptionEntries,
3241
3595
  kebabCase,
3596
+ normalizeSchema,
3597
+ normalizeSpec,
3242
3598
  nullableType,
3243
3599
  pascalCase,
3244
3600
  pascalCaseForEnums,
3601
+ plainParamValue,
3245
3602
  screamingSnakeCase,
3603
+ signalAwareParamValue,
3604
+ validateGeneratorConfig,
3246
3605
  validateInput
3247
3606
  });
3248
3607
  //# sourceMappingURL=index.js.map