zod-codegen 1.6.3 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/.github/workflows/ci.yml +50 -48
  2. package/.github/workflows/release.yml +13 -3
  3. package/.husky/commit-msg +1 -1
  4. package/.husky/pre-commit +1 -1
  5. package/.lintstagedrc.json +5 -1
  6. package/.nvmrc +1 -1
  7. package/.prettierrc.json +12 -5
  8. package/CHANGELOG.md +17 -0
  9. package/CONTRIBUTING.md +12 -12
  10. package/EXAMPLES.md +135 -57
  11. package/PERFORMANCE.md +4 -4
  12. package/README.md +87 -64
  13. package/SECURITY.md +1 -1
  14. package/dist/src/cli.js +11 -18
  15. package/dist/src/generator.d.ts +2 -2
  16. package/dist/src/generator.d.ts.map +1 -1
  17. package/dist/src/generator.js +5 -3
  18. package/dist/src/interfaces/code-generator.d.ts.map +1 -1
  19. package/dist/src/services/code-generator.service.d.ts +3 -1
  20. package/dist/src/services/code-generator.service.d.ts.map +1 -1
  21. package/dist/src/services/code-generator.service.js +236 -219
  22. package/dist/src/services/file-reader.service.d.ts +2 -0
  23. package/dist/src/services/file-reader.service.d.ts.map +1 -1
  24. package/dist/src/services/file-reader.service.js +25 -11
  25. package/dist/src/services/file-writer.service.d.ts.map +1 -1
  26. package/dist/src/services/file-writer.service.js +2 -2
  27. package/dist/src/services/import-builder.service.d.ts.map +1 -1
  28. package/dist/src/services/import-builder.service.js +3 -3
  29. package/dist/src/services/type-builder.service.d.ts.map +1 -1
  30. package/dist/src/types/generator-options.d.ts.map +1 -1
  31. package/dist/src/types/openapi.d.ts.map +1 -1
  32. package/dist/src/types/openapi.js +20 -20
  33. package/dist/src/utils/error-handler.d.ts.map +1 -1
  34. package/dist/src/utils/naming-convention.d.ts.map +1 -1
  35. package/dist/src/utils/naming-convention.js +6 -3
  36. package/dist/src/utils/signal-handler.d.ts.map +1 -1
  37. package/dist/tests/integration/cli-comprehensive.test.d.ts +2 -0
  38. package/dist/tests/integration/cli-comprehensive.test.d.ts.map +1 -0
  39. package/dist/tests/integration/cli-comprehensive.test.js +123 -0
  40. package/dist/tests/integration/cli.test.d.ts +2 -0
  41. package/dist/tests/integration/cli.test.d.ts.map +1 -0
  42. package/dist/tests/integration/cli.test.js +25 -0
  43. package/dist/tests/integration/error-scenarios.test.d.ts +2 -0
  44. package/dist/tests/integration/error-scenarios.test.d.ts.map +1 -0
  45. package/dist/tests/integration/error-scenarios.test.js +169 -0
  46. package/dist/tests/integration/snapshots.test.d.ts +2 -0
  47. package/dist/tests/integration/snapshots.test.d.ts.map +1 -0
  48. package/dist/tests/integration/snapshots.test.js +100 -0
  49. package/dist/tests/unit/code-generator-edge-cases.test.d.ts +2 -0
  50. package/dist/tests/unit/code-generator-edge-cases.test.d.ts.map +1 -0
  51. package/dist/tests/unit/code-generator-edge-cases.test.js +506 -0
  52. package/dist/tests/unit/code-generator.test.d.ts +2 -0
  53. package/dist/tests/unit/code-generator.test.d.ts.map +1 -0
  54. package/dist/tests/unit/code-generator.test.js +1364 -0
  55. package/dist/tests/unit/file-reader.test.d.ts +2 -0
  56. package/dist/tests/unit/file-reader.test.d.ts.map +1 -0
  57. package/dist/tests/unit/file-reader.test.js +153 -0
  58. package/dist/tests/unit/generator.test.d.ts +2 -0
  59. package/dist/tests/unit/generator.test.d.ts.map +1 -0
  60. package/dist/tests/unit/generator.test.js +119 -0
  61. package/dist/tests/unit/naming-convention.test.d.ts +2 -0
  62. package/dist/tests/unit/naming-convention.test.d.ts.map +1 -0
  63. package/dist/tests/unit/naming-convention.test.js +256 -0
  64. package/dist/tests/unit/reporter.test.d.ts +2 -0
  65. package/dist/tests/unit/reporter.test.d.ts.map +1 -0
  66. package/dist/tests/unit/reporter.test.js +44 -0
  67. package/dist/tests/unit/type-builder.test.d.ts +2 -0
  68. package/dist/tests/unit/type-builder.test.d.ts.map +1 -0
  69. package/dist/tests/unit/type-builder.test.js +108 -0
  70. package/dist/vitest.config.d.ts.map +1 -1
  71. package/dist/vitest.config.js +10 -20
  72. package/eslint.config.mjs +38 -28
  73. package/examples/.gitkeep +1 -1
  74. package/examples/README.md +4 -2
  75. package/examples/petstore/README.md +18 -17
  76. package/examples/petstore/{type.ts → api.ts} +158 -74
  77. package/examples/petstore/authenticated-usage.ts +6 -4
  78. package/examples/petstore/basic-usage.ts +4 -3
  79. package/examples/petstore/error-handling-usage.ts +84 -0
  80. package/examples/petstore/retry-handler-usage.ts +11 -18
  81. package/examples/petstore/server-variables-usage.ts +10 -10
  82. package/examples/pokeapi/README.md +8 -8
  83. package/examples/pokeapi/api.ts +218 -0
  84. package/examples/pokeapi/basic-usage.ts +3 -2
  85. package/examples/pokeapi/custom-client.ts +5 -4
  86. package/package.json +17 -21
  87. package/src/cli.ts +20 -25
  88. package/src/generator.ts +13 -11
  89. package/src/interfaces/code-generator.ts +1 -1
  90. package/src/services/code-generator.service.ts +799 -1120
  91. package/src/services/file-reader.service.ts +35 -15
  92. package/src/services/file-writer.service.ts +7 -7
  93. package/src/services/import-builder.service.ts +9 -13
  94. package/src/services/type-builder.service.ts +8 -19
  95. package/src/types/generator-options.ts +1 -1
  96. package/src/types/openapi.ts +22 -22
  97. package/src/utils/error-handler.ts +2 -2
  98. package/src/utils/naming-convention.ts +13 -10
  99. package/src/utils/reporter.ts +2 -2
  100. package/src/utils/signal-handler.ts +7 -8
  101. package/tests/integration/cli-comprehensive.test.ts +53 -31
  102. package/tests/integration/cli.test.ts +5 -5
  103. package/tests/integration/error-scenarios.test.ts +20 -26
  104. package/tests/integration/snapshots.test.ts +19 -23
  105. package/tests/unit/code-generator-edge-cases.test.ts +133 -133
  106. package/tests/unit/code-generator.test.ts +431 -330
  107. package/tests/unit/file-reader.test.ts +58 -18
  108. package/tests/unit/generator.test.ts +30 -18
  109. package/tests/unit/naming-convention.test.ts +27 -27
  110. package/tests/unit/type-builder.test.ts +2 -2
  111. package/tsconfig.json +5 -3
  112. package/vitest.config.ts +11 -21
  113. package/dist/scripts/update-manifest.d.ts +0 -14
  114. package/dist/scripts/update-manifest.d.ts.map +0 -1
  115. package/dist/scripts/update-manifest.js +0 -33
  116. package/dist/src/assets/manifest.json +0 -5
  117. package/examples/pokeapi/type.ts +0 -109
  118. package/generated/type.ts +0 -371
  119. package/scripts/update-manifest.ts +0 -49
  120. package/src/assets/manifest.json +0 -5
@@ -1,7 +1,9 @@
1
1
  import type { OpenApiFileParser, OpenApiFileReader } from '../interfaces/file-reader';
2
2
  import type { OpenApiSpecType } from '../types/openapi';
3
3
  export declare class SyncFileReaderService implements OpenApiFileReader {
4
+ private isUrl;
4
5
  readFile(path: string): Promise<string>;
6
+ private fetchUrl;
5
7
  }
6
8
  export declare class OpenApiFileParserService implements OpenApiFileParser<OpenApiSpecType> {
7
9
  parse(input: unknown): OpenApiSpecType;
@@ -1 +1 @@
1
- {"version":3,"file":"file-reader.service.d.ts","sourceRoot":"","sources":["../../../src/services/file-reader.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,iBAAiB,EAAE,iBAAiB,EAAC,MAAM,2BAA2B,CAAC;AACpF,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAGtD,qBAAa,qBAAsB,YAAW,iBAAiB;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAe9C;AAED,qBAAa,wBAAyB,YAAW,iBAAiB,CAAC,eAAe,CAAC;IACjF,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe;CAgBvC"}
1
+ {"version":3,"file":"file-reader.service.d.ts","sourceRoot":"","sources":["../../../src/services/file-reader.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD,qBAAa,qBAAsB,YAAW,iBAAiB;IAC7D,OAAO,CAAC,KAAK;IASP,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAQ/B,QAAQ;CAkBvB;AAED,qBAAa,wBAAyB,YAAW,iBAAiB,CAAC,eAAe,CAAC;IACjF,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe;CAgBvC"}
@@ -1,22 +1,36 @@
1
- import { readFileSync } from 'node:fs';
2
1
  import { load } from 'js-yaml';
2
+ import { readFileSync } from 'node:fs';
3
3
  import { OpenApiSpec } from '../types/openapi.js';
4
4
  export class SyncFileReaderService {
5
- async readFile(path) {
6
- // Check if path is a URL
5
+ isUrl(path) {
7
6
  try {
8
7
  const url = new URL(path);
9
- // If it's a valid URL, fetch it
10
- const response = await fetch(url.toString());
11
- if (!response.ok) {
12
- throw new Error(`Failed to fetch ${path}: ${String(response.status)} ${response.statusText}`);
13
- }
14
- return await response.text();
8
+ return url.protocol === 'http:' || url.protocol === 'https:';
15
9
  }
16
10
  catch {
17
- // If URL parsing fails, treat it as a local file path
18
- return readFileSync(path, 'utf8');
11
+ return false;
12
+ }
13
+ }
14
+ async readFile(path) {
15
+ if (this.isUrl(path)) {
16
+ return await this.fetchUrl(path);
17
+ }
18
+ return readFileSync(path, 'utf8');
19
+ }
20
+ async fetchUrl(path) {
21
+ const url = new URL(path);
22
+ const headers = {};
23
+ if (url.username || url.password) {
24
+ const credentials = `${decodeURIComponent(url.username)}:${decodeURIComponent(url.password)}`;
25
+ headers['Authorization'] = `Basic ${btoa(credentials)}`;
26
+ url.username = '';
27
+ url.password = '';
28
+ }
29
+ const response = await fetch(url.toString(), { headers });
30
+ if (!response.ok) {
31
+ throw new Error(`Failed to fetch ${path}: ${String(response.status)} ${response.statusText}`);
19
32
  }
33
+ return await response.text();
20
34
  }
21
35
  }
22
36
  export class OpenApiFileParserService {
@@ -1 +1 @@
1
- {"version":3,"file":"file-writer.service.d.ts","sourceRoot":"","sources":["../../../src/services/file-writer.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,8BAA8B,CAAC;AAE7D,qBAAa,qBAAsB,YAAW,UAAU;IAEpD,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAFT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM;IAGpC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAqBlD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,MAAM;CAGnE"}
1
+ {"version":3,"file":"file-writer.service.d.ts","sourceRoot":"","sources":["../../../src/services/file-writer.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,qBAAa,qBAAsB,YAAW,UAAU;IAEpD,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAFT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM;IAGpC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAqBlD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAW,GAAG,MAAM;CAGlE"}
@@ -18,7 +18,7 @@ export class SyncFileWriterService {
18
18
  '/* eslint-disable */',
19
19
  '// @ts-nocheck',
20
20
  '',
21
- content,
21
+ content
22
22
  ].join('\n');
23
23
  const dirPath = dirname(filePath);
24
24
  if (!existsSync(dirPath)) {
@@ -26,7 +26,7 @@ export class SyncFileWriterService {
26
26
  }
27
27
  writeFileSync(filePath, generatedContent);
28
28
  }
29
- resolveOutputPath(outputDir, fileName = 'type.ts') {
29
+ resolveOutputPath(outputDir, fileName = 'api.ts') {
30
30
  return resolve(outputDir, fileName);
31
31
  }
32
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"import-builder.service.d.ts","sourceRoot":"","sources":["../../../src/services/import-builder.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAKhE,QAAA,MAAM,aAAa;;;iBAGjB,CAAC;AAEH,KAAK,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEvD,qBAAa,8BAA+B,YAAW,aAAa;IAClE,YAAY,IAAI,EAAE,CAAC,iBAAiB,EAAE;IAQtC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,EAAE,CAAC,iBAAiB;CAqC/E"}
1
+ {"version":3,"file":"import-builder.service.d.ts","sourceRoot":"","sources":["../../../src/services/import-builder.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAKlE,QAAA,MAAM,aAAa;;;iBAGjB,CAAC;AAEH,KAAK,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEvD,qBAAa,8BAA+B,YAAW,aAAa;IAClE,YAAY,IAAI,EAAE,CAAC,iBAAiB,EAAE;IAQtC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,EAAE,CAAC,iBAAiB;CAiC/E"}
@@ -4,14 +4,14 @@ const IsTypeImport = z.boolean();
4
4
  const ImportedElement = z.record(z.string(), IsTypeImport);
5
5
  const ImportOptions = z.object({
6
6
  defaultImport: ImportedElement.optional(),
7
- namedImports: ImportedElement.optional(),
7
+ namedImports: ImportedElement.optional()
8
8
  });
9
9
  export class TypeScriptImportBuilderService {
10
10
  buildImports() {
11
11
  return [
12
12
  this.createImport('zod', {
13
- namedImports: { z: false },
14
- }),
13
+ namedImports: { z: false }
14
+ })
15
15
  ];
16
16
  }
17
17
  createImport(target, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"type-builder.service.d.ts","sourceRoot":"","sources":["../../../src/services/type-builder.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAE9D,qBAAa,4BAA6B,YAAW,WAAW;IAC9D,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ;IA6BpC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,EAAE,CAAC,mBAAmB;IAYtF,eAAe,CACb,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,EAC3B,YAAY,CAAC,EAAE,EAAE,CAAC,UAAU,EAC5B,UAAU,UAAQ,GACjB,EAAE,CAAC,oBAAoB;IAW1B,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,wBAAwB;IAS5D,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAMxC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIjC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAGnC"}
1
+ {"version":3,"file":"type-builder.service.d.ts","sourceRoot":"","sources":["../../../src/services/type-builder.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEhE,qBAAa,4BAA6B,YAAW,WAAW;IAC9D,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ;IA4BpC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,EAAE,CAAC,mBAAmB;IAYtF,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,UAAU,UAAQ,GAAG,EAAE,CAAC,oBAAoB;IAWrI,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,wBAAwB;IAI5D,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAMxC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIjC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAGnC"}
@@ -1 +1 @@
1
- {"version":3,"file":"generator-options.d.ts","sourceRoot":"","sources":["../../../src/types/generator-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAE,wBAAwB,EAAC,MAAM,4BAA4B,CAAC;AAE3F;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAEpC;;;;;;;;;;;;;;;;;;OAkBG;IACH,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;CACrD"}
1
+ {"version":3,"file":"generator-options.d.ts","sourceRoot":"","sources":["../../../src/types/generator-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE7F;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAEpC;;;;;;;;;;;;;;;;;;OAkBG;IACH,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;CACrD"}
@@ -1 +1 @@
1
- {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../../src/types/openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,eAAO,MAAM,SAAS;;iBAEpB,CAAC;AA6CH,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAKxD,CAAC;AAcF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;iBAYpB,CAAC;AAkBH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;iBAKnB,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;iBAKtB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASvB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAanB,CAAC;AA+CH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAStB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAC1D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AACpE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AACpD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAC1D,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AACpD,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../../src/types/openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,SAAS;;iBAEpB,CAAC;AA6CH,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAKxD,CAAC;AAcF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;iBAYpB,CAAC;AAkBH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;iBAKnB,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;iBAKtB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASvB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAanB,CAAC;AA+CH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAStB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAC1D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AACpE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AACpD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAC1D,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AACpD,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  export const Reference = z.object({
3
- $ref: z.string().optional(),
3
+ $ref: z.string().optional()
4
4
  });
5
5
  const BaseSchemaProperties = z.object({
6
6
  $ref: z.string().optional(),
@@ -36,27 +36,27 @@ const BaseSchemaProperties = z.object({
36
36
  xml: z
37
37
  .object({
38
38
  name: z.string().optional(),
39
- wrapped: z.boolean().optional(),
39
+ wrapped: z.boolean().optional()
40
40
  })
41
41
  .optional(),
42
42
  externalDocs: Reference.optional(),
43
43
  example: z.unknown().optional(),
44
- deprecated: z.boolean().optional(),
44
+ deprecated: z.boolean().optional()
45
45
  });
46
46
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
47
  export const SchemaProperties = z.lazy(() => BaseSchemaProperties.extend({
48
48
  properties: z.record(z.string(), SchemaProperties).optional(),
49
- items: SchemaProperties.optional(),
49
+ items: SchemaProperties.optional()
50
50
  }));
51
51
  const ServerVariable = z.object({
52
52
  default: z.string(),
53
53
  description: z.string().optional(),
54
- enum: z.array(z.string()).optional(),
54
+ enum: z.array(z.string()).optional()
55
55
  });
56
56
  const Server = z.object({
57
57
  url: z.string(), // Allow templated URLs with {variables}
58
58
  description: z.string().optional(),
59
- variables: z.record(z.string(), ServerVariable).optional(),
59
+ variables: z.record(z.string(), ServerVariable).optional()
60
60
  });
61
61
  export const Parameter = z.object({
62
62
  $ref: z.string().optional(),
@@ -69,7 +69,7 @@ export const Parameter = z.object({
69
69
  style: z.string().optional(),
70
70
  explode: z.boolean().optional(),
71
71
  allowReserved: z.boolean().optional(),
72
- schema: SchemaProperties.optional(),
72
+ schema: SchemaProperties.optional()
73
73
  });
74
74
  const ResponseHeader = z.object({
75
75
  $ref: z.string().optional(),
@@ -80,22 +80,22 @@ const ResponseHeader = z.object({
80
80
  style: z.string().optional(),
81
81
  explode: z.boolean().optional(),
82
82
  allowReserved: z.boolean().optional(),
83
- schema: Reference.optional(),
83
+ schema: Reference.optional()
84
84
  });
85
85
  const MediaType = z.object({
86
- schema: z.unknown().optional(),
86
+ schema: z.unknown().optional()
87
87
  });
88
88
  export const Response = z.object({
89
89
  $ref: z.string().optional(),
90
90
  description: z.string(),
91
91
  headers: z.record(z.string(), ResponseHeader).optional(),
92
- content: z.record(z.string(), MediaType).optional(),
92
+ content: z.record(z.string(), MediaType).optional()
93
93
  });
94
94
  export const RequestBody = z.object({
95
95
  $ref: z.string().optional(),
96
96
  description: z.string().optional(),
97
97
  required: z.boolean().optional(),
98
- content: z.record(z.string(), MediaType).optional(),
98
+ content: z.record(z.string(), MediaType).optional()
99
99
  });
100
100
  export const MethodSchema = z.object({
101
101
  summary: z.string().optional(),
@@ -105,7 +105,7 @@ export const MethodSchema = z.object({
105
105
  requestBody: RequestBody.optional(),
106
106
  responses: z.record(z.string(), Response).optional(),
107
107
  tags: z.array(z.string()).optional(),
108
- deprecated: z.boolean().optional(),
108
+ deprecated: z.boolean().optional()
109
109
  });
110
110
  export const PathItem = z.object({
111
111
  $ref: z.string().optional(),
@@ -119,7 +119,7 @@ export const PathItem = z.object({
119
119
  head: MethodSchema.optional(),
120
120
  options: MethodSchema.optional(),
121
121
  trace: MethodSchema.optional(),
122
- parameters: z.array(Parameter).optional(),
122
+ parameters: z.array(Parameter).optional()
123
123
  });
124
124
  const Info = z.object({
125
125
  title: z.string().min(1),
@@ -130,25 +130,25 @@ const Info = z.object({
130
130
  .object({
131
131
  name: z.string().optional(),
132
132
  email: z.email().optional(),
133
- url: z.url().optional(),
133
+ url: z.url().optional()
134
134
  })
135
135
  .optional(),
136
136
  license: z
137
137
  .object({
138
138
  name: z.string().min(1),
139
- url: z.url().optional(),
139
+ url: z.url().optional()
140
140
  })
141
- .optional(),
141
+ .optional()
142
142
  });
143
143
  const SecurityRequirement = z.record(z.string(), z.array(z.string()));
144
144
  const Tag = z.object({
145
145
  name: z.string().min(1),
146
146
  description: z.string().optional(),
147
- externalDocs: Reference.optional(),
147
+ externalDocs: Reference.optional()
148
148
  });
149
149
  const ExternalDocumentation = z.object({
150
150
  description: z.string().optional(),
151
- url: z.url(),
151
+ url: z.url()
152
152
  });
153
153
  const Components = z.object({
154
154
  schemas: z.record(z.string(), SchemaProperties).optional(),
@@ -159,7 +159,7 @@ const Components = z.object({
159
159
  headers: z.record(z.string(), ResponseHeader).optional(),
160
160
  securitySchemes: z.record(z.string(), Reference).optional(),
161
161
  links: z.record(z.string(), Reference).optional(),
162
- callbacks: z.record(z.string(), Reference).optional(),
162
+ callbacks: z.record(z.string(), Reference).optional()
163
163
  });
164
164
  export const OpenApiSpec = z.object({
165
165
  openapi: z.string().regex(/^3\.\d+\.\d+$/, 'OpenAPI version must be in format 3.x.x'),
@@ -169,5 +169,5 @@ export const OpenApiSpec = z.object({
169
169
  components: Components.optional(),
170
170
  security: z.array(SecurityRequirement).optional(),
171
171
  tags: z.array(Tag).optional(),
172
- externalDocs: ExternalDocumentation.optional(),
172
+ externalDocs: ExternalDocumentation.optional()
173
173
  });
@@ -1 +1 @@
1
- {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../../src/utils/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEzC,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,CAAC,OAAO,EAAE,WAAW,MAAM,EAAE,UAAU,QAAQ,WAAS,IAGpG,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,CAAC,OAAO,EAAE,WAAW,MAAM,EAAE,UAAU,QAAQ,KAAG,IAK7F,CAAC"}
1
+ {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../../src/utils/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,CAAC,OAAO,EAAE,WAAW,MAAM,EAAE,UAAU,QAAQ,WAAS,IAGpG,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,CAAC,OAAO,EAAE,WAAW,MAAM,EAAE,UAAU,QAAQ,KAAG,IAK7F,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"naming-convention.d.ts","sourceRoot":"","sources":["../../../src/utils/naming-convention.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,sBAAsB,GACtB,sBAAsB,CAAC;AAE3B;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,CAAC;AA0G7E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,MAAM,CAsB7F"}
1
+ {"version":3,"file":"naming-convention.d.ts","sourceRoot":"","sources":["../../../src/utils/naming-convention.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,sBAAsB,GAAG,sBAAsB,CAAC;AAE1I;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,CAAC;AAmH7E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,MAAM,CAsB7F"}
@@ -2,8 +2,9 @@
2
2
  * Capitalizes the first letter of a word
3
3
  */
4
4
  function capitalize(word) {
5
- if (word.length === 0)
5
+ if (word.length === 0) {
6
6
  return word;
7
+ }
7
8
  return word.charAt(0).toUpperCase() + word.slice(1);
8
9
  }
9
10
  /**
@@ -52,11 +53,13 @@ function normalizeToWords(input) {
52
53
  * Converts words array to camelCase
53
54
  */
54
55
  function toCamelCase(words) {
55
- if (words.length === 0)
56
+ if (words.length === 0) {
56
57
  return '';
58
+ }
57
59
  const [first, ...rest] = words;
58
- if (!first)
60
+ if (!first) {
59
61
  return '';
62
+ }
60
63
  return first + rest.map((w) => capitalize(w)).join('');
61
64
  }
62
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"signal-handler.d.ts","sourceRoot":"","sources":["../../../src/utils/signal-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEzC,eAAO,MAAM,cAAc,GACxB,SAAS,MAAM,CAAC,OAAO,EAAE,WAAW,MAAM,EAAE,OAAO,MAAM,CAAC,OAAO,EAAE,UAAU,QAAQ,WAAS,IAI9F,CAAC;AAEJ,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,CAAC,OAAO,EAAE,WAAW,MAAM,EAAE,UAAU,QAAQ,KAAG,IAK9F,CAAC"}
1
+ {"version":3,"file":"signal-handler.d.ts","sourceRoot":"","sources":["../../../src/utils/signal-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,CAAC,OAAO,EAAE,WAAW,MAAM,EAAE,OAAO,MAAM,CAAC,OAAO,EAAE,UAAU,QAAQ,WAAS,IAI5H,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,CAAC,OAAO,EAAE,WAAW,MAAM,EAAE,UAAU,QAAQ,KAAG,IAK9F,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli-comprehensive.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-comprehensive.test.d.ts","sourceRoot":"","sources":["../../../tests/integration/cli-comprehensive.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,123 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { existsSync, readFileSync, rmSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { describe, expect, it } from 'vitest';
5
+ describe('CLI Comprehensive Integration', () => {
6
+ const cwd = resolve(__dirname, '../..');
7
+ const testOutputDir = resolve(cwd, 'test-output-cli');
8
+ beforeEach(() => {
9
+ if (existsSync(testOutputDir)) {
10
+ rmSync(testOutputDir, { recursive: true, force: true });
11
+ }
12
+ });
13
+ afterEach(() => {
14
+ if (existsSync(testOutputDir)) {
15
+ rmSync(testOutputDir, { recursive: true, force: true });
16
+ }
17
+ });
18
+ describe('Basic CLI Usage', () => {
19
+ it('should generate code with default output directory', () => {
20
+ execSync('node ./dist/src/cli.js --input ./samples/swagger-petstore.yaml --output generated', {
21
+ encoding: 'utf-8',
22
+ cwd
23
+ });
24
+ const outputFile = resolve(cwd, 'generated/api.ts');
25
+ expect(existsSync(outputFile)).toBe(true);
26
+ const content = readFileSync(outputFile, 'utf-8');
27
+ expect(content).toContain('SwaggerPetstoreOpenAPI30');
28
+ });
29
+ it('should generate code with custom output directory', () => {
30
+ execSync(`node ./dist/src/cli.js --input ./samples/swagger-petstore.yaml --output ${testOutputDir}`, {
31
+ encoding: 'utf-8',
32
+ cwd
33
+ });
34
+ const outputFile = resolve(testOutputDir, 'api.ts');
35
+ expect(existsSync(outputFile)).toBe(true);
36
+ });
37
+ it('should accept naming convention option', () => {
38
+ execSync(`node ./dist/src/cli.js --input ./samples/swagger-petstore.yaml --output ${testOutputDir} --naming-convention camelCase`, {
39
+ encoding: 'utf-8',
40
+ cwd
41
+ });
42
+ const outputFile = resolve(testOutputDir, 'api.ts');
43
+ const content = readFileSync(outputFile, 'utf-8');
44
+ // Verify camelCase is applied (operation IDs should be camelCase)
45
+ expect(content).toMatch(/async \w+\(/);
46
+ });
47
+ it('should reject invalid naming convention', () => {
48
+ expect(() => {
49
+ execSync(`node ./dist/src/cli.js --input ./samples/swagger-petstore.yaml --output ${testOutputDir} --naming-convention invalid`, {
50
+ encoding: 'utf-8',
51
+ cwd,
52
+ stdio: 'pipe'
53
+ });
54
+ }).toThrow();
55
+ });
56
+ it('should write to custom file when output is a .ts path', () => {
57
+ const outputFile = resolve(testOutputDir, 'client.ts');
58
+ execSync(`node ./dist/src/cli.js --input ./samples/swagger-petstore.yaml --output "${outputFile}"`, {
59
+ encoding: 'utf-8',
60
+ cwd
61
+ });
62
+ expect(existsSync(outputFile)).toBe(true);
63
+ const content = readFileSync(outputFile, 'utf-8');
64
+ expect(content).toContain('SwaggerPetstoreOpenAPI30');
65
+ });
66
+ });
67
+ describe('CLI Error Handling', () => {
68
+ it('should exit with code 1 on invalid input file', () => {
69
+ try {
70
+ execSync('node ./dist/src/cli.js --input ./nonexistent.yaml --output generated', {
71
+ encoding: 'utf-8',
72
+ cwd,
73
+ stdio: 'pipe'
74
+ });
75
+ expect.fail('Should have thrown an error');
76
+ }
77
+ catch (error) {
78
+ // Command should fail
79
+ expect(error).toBeDefined();
80
+ }
81
+ });
82
+ it('should require input option', () => {
83
+ expect(() => {
84
+ execSync('node ./dist/src/cli.js --output generated', {
85
+ encoding: 'utf-8',
86
+ cwd,
87
+ stdio: 'pipe'
88
+ });
89
+ }).toThrow();
90
+ });
91
+ });
92
+ describe('CLI with Different Spec Formats', () => {
93
+ it('should handle JSON format', () => {
94
+ execSync(`node ./dist/src/cli.js --input ./samples/pokeapi-openapi.json --output ${testOutputDir}`, {
95
+ encoding: 'utf-8',
96
+ cwd
97
+ });
98
+ const outputFile = resolve(testOutputDir, 'api.ts');
99
+ expect(existsSync(outputFile)).toBe(true);
100
+ });
101
+ it('should handle YAML format', () => {
102
+ execSync(`node ./dist/src/cli.js --input ./samples/swagger-petstore.yaml --output ${testOutputDir}`, {
103
+ encoding: 'utf-8',
104
+ cwd
105
+ });
106
+ const outputFile = resolve(testOutputDir, 'api.ts');
107
+ expect(existsSync(outputFile)).toBe(true);
108
+ });
109
+ it('should generate code from a remote URL', () => {
110
+ execSync(`node ./dist/src/cli.js --input https://petstore3.swagger.io/api/v3/openapi.json --output ${testOutputDir}`, {
111
+ encoding: 'utf-8',
112
+ cwd,
113
+ timeout: 30000
114
+ });
115
+ const outputFile = resolve(testOutputDir, 'api.ts');
116
+ expect(existsSync(outputFile)).toBe(true);
117
+ const content = readFileSync(outputFile, 'utf-8');
118
+ expect(content).toContain('export default class');
119
+ expect(content).toContain('class ResponseValidationError<T> extends Error');
120
+ expect(content).toContain('import { z }');
121
+ });
122
+ });
123
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.d.ts","sourceRoot":"","sources":["../../../tests/integration/cli.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { resolve } from 'node:path';
3
+ import { describe, expect, it } from 'vitest';
4
+ describe('CLI Integration', () => {
5
+ describe('--help', () => {
6
+ it('should display help information', () => {
7
+ const result = execSync('node ./dist/src/cli.js --help', {
8
+ encoding: 'utf-8',
9
+ cwd: resolve(__dirname, '../..')
10
+ });
11
+ expect(result).toContain('Usage:');
12
+ expect(result).toContain('--input');
13
+ expect(result).toContain('--output');
14
+ });
15
+ });
16
+ describe('--version', () => {
17
+ it('should display version information', () => {
18
+ const result = execSync('node ./dist/src/cli.js --version', {
19
+ encoding: 'utf-8',
20
+ cwd: resolve(__dirname, '../..')
21
+ });
22
+ expect(result).toMatch(/\d+\.\d+\.\d+/);
23
+ });
24
+ });
25
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=error-scenarios.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-scenarios.test.d.ts","sourceRoot":"","sources":["../../../tests/integration/error-scenarios.test.ts"],"names":[],"mappings":""}