klasik 1.0.19 → 1.0.22

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.
@@ -0,0 +1,18 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(grep:*)",
5
+ "WebSearch",
6
+ "Bash(npx @openapitools/openapi-generator-cli help generate:*)",
7
+ "Bash(node dist/cli.js generate:*)",
8
+ "Bash(npx tsc:*)",
9
+ "Bash(npm install:*)",
10
+ "WebFetch(domain:dev.to)",
11
+ "WebFetch(domain:saintlouvent.com)",
12
+ "WebFetch(domain:zod.dev)",
13
+ "Bash(node test-disc-union.js:*)",
14
+ "Bash(node test-disc-code.js:*)",
15
+ "Bash(node test-new-validators.js:*)"
16
+ ]
17
+ }
18
+ }
package/README.md CHANGED
@@ -9,6 +9,7 @@ Download OpenAPI specifications from remote URLs and generate TypeScript clients
9
9
  - 📄 **JSON and YAML support** - Automatically parse and handle both formats (YAML specs are converted to JSON for code generation)
10
10
  - 🔐 **Authentication support** - Custom headers including Bearer tokens and API keys
11
11
  - 🔗 **External reference resolution** - Automatically download referenced schema files (`$ref`)
12
+ - 📦 **ESM compatibility** - Automatic `.js` extension fixing for Node.js ESM projects
12
13
  - 🔄 **Automatic transformation** - Converts API responses to class instances using class-transformer
13
14
  - 🎯 **Type-safe** - Full TypeScript support with decorators
14
15
  - 🛠️ **Configurable** - Custom headers, timeouts, and templates
@@ -102,6 +103,15 @@ Generate a TypeScript client from an OpenAPI spec (remote URL or local file).
102
103
  - Can be used multiple times for multiple headers
103
104
  - Perfect for authorization: `--header "Authorization: Bearer token"`
104
105
  - `-r, --resolve-refs` - Resolve and download external `$ref` references
106
+ - `--esm` - Add `.js` extensions to imports for ESM compatibility (Node.js modules)
107
+ - `--nestjs-swagger` - Include NestJS Swagger `@ApiProperty` decorators in generated models
108
+ - Automatically adds `@nestjs/swagger` to generated package.json
109
+ - Ideal for NestJS applications with Swagger/OpenAPI documentation
110
+ - Works with both `full` and `models-only` generation modes
111
+ - `--class-validator` - Include class-validator decorators for runtime validation (requires openapi-class-transformer v2.0+)
112
+ - Automatically adds `class-validator` and `class-transformer` to generated package.json
113
+ - Enables runtime validation with decorators like `@IsString`, `@IsEmail`, `@Min`, `@Max`
114
+ - Forward-compatible flag - full decorator generation coming in future version
105
115
  - `-t, --template <dir>` - Custom template directory (klasik includes enhanced TSDoc templates by default)
106
116
  - `-k, --keep-spec` - Keep the downloaded spec file after generation
107
117
  - `--timeout <ms>` - Request timeout in milliseconds for HTTP requests (default: 30000)
@@ -123,6 +133,28 @@ klasik generate \
123
133
  --header "Authorization: Bearer token123" \
124
134
  --resolve-refs
125
135
 
136
+ # NestJS integration with Swagger decorators
137
+ klasik generate \
138
+ --url https://api.example.com/openapi.json \
139
+ --output ./src/generated \
140
+ --mode models-only \
141
+ --nestjs-swagger
142
+
143
+ # With runtime validation decorators
144
+ klasik generate \
145
+ --url https://api.example.com/openapi.json \
146
+ --output ./src/generated \
147
+ --mode models-only \
148
+ --class-validator
149
+
150
+ # Full NestJS setup: Swagger docs + validation
151
+ klasik generate \
152
+ --url https://api.example.com/openapi.json \
153
+ --output ./src/generated \
154
+ --mode models-only \
155
+ --nestjs-swagger \
156
+ --class-validator
157
+
126
158
  # Multiple headers
127
159
  klasik generate \
128
160
  --url https://api.example.com/openapi.json \
@@ -181,11 +213,14 @@ const generator = new K8sClientGenerator();
181
213
  await generator.generate({
182
214
  specUrl: 'https://api.example.com/openapi.json',
183
215
  outputDir: './client',
216
+ mode: 'models-only',
184
217
  headers: {
185
218
  'Authorization': 'Bearer token123',
186
219
  'X-Custom-Header': 'value'
187
220
  },
188
221
  resolveReferences: true, // Download external $ref files
222
+ nestJsSwagger: true, // Include @ApiProperty decorators
223
+ classValidator: true, // Include validation decorators
189
224
  templateDir: './custom-templates', // Optional
190
225
  keepSpec: true, // Keep downloaded spec file
191
226
  timeout: 60000 // Request timeout in ms
@@ -227,6 +262,8 @@ The generated TypeScript client includes:
227
262
  - ✅ **Vendor extensions** - Preserved in JSDoc comments and metadata
228
263
  - ✅ **Error handling** - Configurable transformation error handlers
229
264
  - ✅ **Configuration options** - Enable/disable transformation, custom error handlers
265
+ - ✅ **NestJS Swagger decorators** (optional) - `@ApiProperty` with type, description, example, required, and nullable when `--nestjs-swagger` is enabled
266
+ - ✅ **class-validator decorators** (optional) - Runtime validation decorators when `--class-validator` is enabled (full support in v2.0+)
230
267
 
231
268
  ### Enhanced TSDoc Documentation
232
269
 
@@ -420,6 +457,167 @@ await new K8sClientGenerator().generate({
420
457
  });
421
458
  ```
422
459
 
460
+ ## NestJS Integration
461
+
462
+ ### Using with NestJS Applications
463
+
464
+ Klasik-generated models integrate seamlessly with NestJS applications. Use `--mode models-only` with decorator flags for best results.
465
+
466
+ #### Swagger Documentation Support
467
+
468
+ Generate models with `@ApiProperty` decorators for automatic Swagger documentation:
469
+
470
+ ```bash
471
+ npx klasik generate \
472
+ --url https://api.example.com/openapi.json \
473
+ --output ./src/generated/dto \
474
+ --mode models-only \
475
+ --nestjs-swagger
476
+ ```
477
+
478
+ This generates DTOs like:
479
+
480
+ ```typescript
481
+ import { Expose } from 'class-transformer';
482
+ import { ApiProperty } from '@nestjs/swagger';
483
+
484
+ export class UserDto {
485
+ @ApiProperty({
486
+ type: String,
487
+ description: 'Unique identifier',
488
+ required: true,
489
+ example: '123e4567-e89b-41d3-a456-426614174000',
490
+ })
491
+ @Expose()
492
+ id: string;
493
+
494
+ @ApiProperty({
495
+ type: String,
496
+ description: 'User email address',
497
+ required: true,
498
+ format: 'email',
499
+ })
500
+ @Expose()
501
+ email: string;
502
+ }
503
+ ```
504
+
505
+ Use in your NestJS controllers:
506
+
507
+ ```typescript
508
+ import { Controller, Get, Post, Body } from '@nestjs/common';
509
+ import { ApiTags, ApiResponse } from '@nestjs/swagger';
510
+ import { UserDto } from './generated/dto';
511
+
512
+ @ApiTags('users')
513
+ @Controller('users')
514
+ export class UsersController {
515
+ @Get()
516
+ @ApiResponse({ type: [UserDto], status: 200 })
517
+ async findAll(): Promise<UserDto[]> {
518
+ // Your implementation
519
+ }
520
+
521
+ @Post()
522
+ @ApiResponse({ type: UserDto, status: 201 })
523
+ async create(@Body() createUserDto: UserDto): Promise<UserDto> {
524
+ // Your implementation
525
+ }
526
+ }
527
+ ```
528
+
529
+ Your Swagger UI automatically displays complete documentation from the `@ApiProperty` decorators.
530
+
531
+ #### Runtime Validation Support
532
+
533
+ Add the `--class-validator` flag for runtime validation decorators:
534
+
535
+ ```bash
536
+ npx klasik generate \
537
+ --url https://api.example.com/openapi.json \
538
+ --output ./src/generated/dto \
539
+ --mode models-only \
540
+ --nestjs-swagger \
541
+ --class-validator
542
+ ```
543
+
544
+ **Note**: Full decorator generation requires openapi-class-transformer v2.0+. For now, the dependencies are added to package.json, and you can manually add validation decorators:
545
+
546
+ ```typescript
547
+ import { Expose } from 'class-transformer';
548
+ import { ApiProperty } from '@nestjs/swagger';
549
+ import { IsString, IsEmail } from 'class-validator';
550
+
551
+ export class UserDto {
552
+ @ApiProperty({ type: String, required: true })
553
+ @IsString()
554
+ @Expose()
555
+ id: string;
556
+
557
+ @ApiProperty({ type: String, required: true, format: 'email' })
558
+ @IsEmail()
559
+ @Expose()
560
+ email: string;
561
+ }
562
+ ```
563
+
564
+ Use with NestJS ValidationPipe:
565
+
566
+ ```typescript
567
+ import { ValidationPipe } from '@nestjs/common';
568
+
569
+ // In main.ts
570
+ app.useGlobalPipes(new ValidationPipe({
571
+ transform: true,
572
+ whitelist: true,
573
+ }));
574
+
575
+ // In controller
576
+ @Post()
577
+ async create(@Body() dto: UserDto): Promise<UserDto> {
578
+ // dto is already validated and transformed to UserDto instance!
579
+ }
580
+ ```
581
+
582
+ #### Required Dependencies for NestJS
583
+
584
+ When using `--nestjs-swagger` or `--class-validator`, ensure your project has these peer dependencies:
585
+
586
+ ```bash
587
+ npm install @nestjs/swagger swagger-ui-express
588
+ npm install class-validator class-transformer
589
+ npm install reflect-metadata
590
+ ```
591
+
592
+ Update your `tsconfig.json`:
593
+
594
+ ```json
595
+ {
596
+ "compilerOptions": {
597
+ "experimentalDecorators": true,
598
+ "emitDecoratorMetadata": true
599
+ }
600
+ }
601
+ ```
602
+
603
+ #### Best Practices
604
+
605
+ 1. **Use models-only mode**: Generate only DTOs, keep your NestJS business logic separate
606
+ 2. **Separate directories**: Generate into `src/generated/dto` or similar
607
+ 3. **Extend generated classes**: For complex validation, extend generated DTOs
608
+ 4. **Version control**: Commit generated files or regenerate in CI/CD
609
+
610
+ ```typescript
611
+ // Custom DTO extending generated model
612
+ import { UserDto } from '../generated/dto';
613
+ import { IsStrongPassword } from 'class-validator';
614
+
615
+ export class CreateUserDto extends UserDto {
616
+ @IsStrongPassword()
617
+ password: string;
618
+ }
619
+ ```
620
+
423
621
  ## Best Practices for Existing Projects
424
622
 
425
623
  When integrating klasik into an existing TypeScript project, follow these best practices to avoid conflicts:
@@ -492,6 +690,55 @@ npx klasik generate \
492
690
  --mode full # Generates complete client with APIs
493
691
  ```
494
692
 
693
+ ### ESM (ECMAScript Modules) Support
694
+
695
+ If your project uses ECMAScript Modules (`"type": "module"` in package.json), use the `--esm` flag to automatically add `.js` extensions to all relative imports:
696
+
697
+ ```bash
698
+ # Generate ESM-compatible code
699
+ npx klasik generate \
700
+ --url https://api.example.com/openapi.yaml \
701
+ --output ./src/generated \
702
+ --mode models-only \
703
+ --esm # ✅ Adds .js extensions to imports
704
+ ```
705
+
706
+ **What `--esm` does:**
707
+ - Adds `.js` extensions to all relative imports: `from './user'` → `from './user.js'`
708
+ - Adds `.js` extensions to all relative exports: `export * from './api'` → `export * from './api.js'`
709
+ - Handles directory imports: `from './models'` → `from './models/index.js'`
710
+ - Only affects relative imports (doesn't touch external packages like `axios`, `class-transformer`)
711
+
712
+ **Before `--esm`:**
713
+ ```typescript
714
+ import { User } from './models/user';
715
+ import { Cluster } from '../models/cluster';
716
+ export * from './api/orgs-api';
717
+ ```
718
+
719
+ **After `--esm`:**
720
+ ```typescript
721
+ import { User } from './models/user.js';
722
+ import { Cluster } from '../models/cluster.js';
723
+ export * from './api/orgs-api.js';
724
+ ```
725
+
726
+ **When to use `--esm`:**
727
+ - Your package.json has `"type": "module"`
728
+ - You're using Node.js native ESM
729
+ - You're targeting modern JavaScript environments
730
+ - You want to eliminate post-processing scripts
731
+
732
+ **package.json setup for ESM:**
733
+ ```json
734
+ {
735
+ "type": "module",
736
+ "scripts": {
737
+ "generate-client": "npx klasik generate --url $API_URL --output src/generated --mode models-only --esm"
738
+ }
739
+ }
740
+ ```
741
+
495
742
  ## Advanced Configuration
496
743
 
497
744
  ### Custom Error Handling
package/dist/cli.js CHANGED
@@ -52,6 +52,9 @@ program
52
52
  .option('-t, --template <dir>', 'Custom template directory')
53
53
  .option('-k, --keep-spec', 'Keep the downloaded spec file after generation', false)
54
54
  .option('-r, --resolve-refs', 'Resolve and download external $ref references', false)
55
+ .option('--esm', 'Add .js extensions to imports for ESM compatibility', false)
56
+ .option('--nestjs-swagger', 'Include NestJS Swagger @ApiProperty decorators in generated models', false)
57
+ .option('--class-validator', 'Include class-validator decorators in generated models', false)
55
58
  .option('--timeout <ms>', 'Request timeout in milliseconds', '30000')
56
59
  .action(async (options) => {
57
60
  try {
@@ -82,6 +85,9 @@ program
82
85
  templateDir: options.template,
83
86
  keepSpec: options.keepSpec,
84
87
  resolveReferences: options.resolveRefs,
88
+ fixEsmImports: options.esm,
89
+ nestJsSwagger: options.nestjsSwagger,
90
+ classValidator: options.classValidator,
85
91
  timeout: parseInt(options.timeout, 10),
86
92
  });
87
93
  process.exit(0);
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Fixes relative imports in TypeScript files to include .js extensions for ESM compatibility
3
+ *
4
+ * Node.js ESM requires explicit file extensions for relative imports.
5
+ * This utility adds .js extensions to all relative import/export statements.
6
+ */
7
+ export declare class EsmFixer {
8
+ /**
9
+ * Fix all TypeScript files in a directory recursively
10
+ */
11
+ fixDirectory(directory: string): Promise<void>;
12
+ /**
13
+ * Fix imports in a single file
14
+ * @returns true if file was modified, false otherwise
15
+ */
16
+ private fixFile;
17
+ /**
18
+ * Fix import statements to add .js extensions
19
+ */
20
+ private fixImports;
21
+ /**
22
+ * Fix export statements to add .js extensions
23
+ */
24
+ private fixExports;
25
+ /**
26
+ * Get all TypeScript files in a directory recursively
27
+ */
28
+ private getAllTsFiles;
29
+ }
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.EsmFixer = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Fixes relative imports in TypeScript files to include .js extensions for ESM compatibility
41
+ *
42
+ * Node.js ESM requires explicit file extensions for relative imports.
43
+ * This utility adds .js extensions to all relative import/export statements.
44
+ */
45
+ class EsmFixer {
46
+ /**
47
+ * Fix all TypeScript files in a directory recursively
48
+ */
49
+ async fixDirectory(directory) {
50
+ console.log('Fixing ESM imports to add .js extensions...');
51
+ const files = this.getAllTsFiles(directory);
52
+ let fixedCount = 0;
53
+ for (const file of files) {
54
+ const fixed = await this.fixFile(file);
55
+ if (fixed) {
56
+ fixedCount++;
57
+ }
58
+ }
59
+ console.log(`✅ Fixed ${fixedCount} file(s) for ESM compatibility`);
60
+ }
61
+ /**
62
+ * Fix imports in a single file
63
+ * @returns true if file was modified, false otherwise
64
+ */
65
+ async fixFile(filePath) {
66
+ let content = fs.readFileSync(filePath, 'utf8');
67
+ const originalContent = content;
68
+ // Fix import statements
69
+ content = this.fixImports(content);
70
+ // Fix export statements
71
+ content = this.fixExports(content);
72
+ // Only write if content changed
73
+ if (content !== originalContent) {
74
+ fs.writeFileSync(filePath, content, 'utf8');
75
+ return true;
76
+ }
77
+ return false;
78
+ }
79
+ /**
80
+ * Fix import statements to add .js extensions
81
+ */
82
+ fixImports(content) {
83
+ // Match: import ... from './relative/path'
84
+ // Don't match if already has extension (.js, .ts, .json)
85
+ // Don't match external packages (no . or ..)
86
+ const importRegex = /from\s+(['"])(\.|\.\.)(\/[^'"]*?)(?<!\.js|\.ts|\.json|\.mjs|\.cjs)\1/g;
87
+ return content.replace(importRegex, (match, quote, dots, importPath) => {
88
+ // Handle index imports: './models' -> './models/index.js'
89
+ // But only if the path doesn't already end with a filename
90
+ const hasFilename = /\/[^/]+$/.test(importPath);
91
+ if (!hasFilename && importPath.length > 0) {
92
+ // It's a directory import, add /index.js
93
+ return `from ${quote}${dots}${importPath}/index.js${quote}`;
94
+ }
95
+ // Normal file import, just add .js
96
+ return `from ${quote}${dots}${importPath}.js${quote}`;
97
+ });
98
+ }
99
+ /**
100
+ * Fix export statements to add .js extensions
101
+ */
102
+ fixExports(content) {
103
+ // Match: export ... from './relative/path'
104
+ // Don't match if already has extension
105
+ const exportRegex = /from\s+(['"])(\.|\.\.)(\/[^'"]*?)(?<!\.js|\.ts|\.json|\.mjs|\.cjs)\1/g;
106
+ return content.replace(exportRegex, (match, quote, dots, exportPath) => {
107
+ // Handle index exports
108
+ const hasFilename = /\/[^/]+$/.test(exportPath);
109
+ if (!hasFilename && exportPath.length > 0) {
110
+ return `from ${quote}${dots}${exportPath}/index.js${quote}`;
111
+ }
112
+ return `from ${quote}${dots}${exportPath}.js${quote}`;
113
+ });
114
+ }
115
+ /**
116
+ * Get all TypeScript files in a directory recursively
117
+ */
118
+ getAllTsFiles(directory) {
119
+ const files = [];
120
+ const walk = (dir) => {
121
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
122
+ for (const entry of entries) {
123
+ const fullPath = path.join(dir, entry.name);
124
+ if (entry.isDirectory()) {
125
+ // Skip node_modules and hidden directories
126
+ if (entry.name !== 'node_modules' && !entry.name.startsWith('.')) {
127
+ walk(fullPath);
128
+ }
129
+ }
130
+ else if (entry.isFile() && entry.name.endsWith('.ts')) {
131
+ files.push(fullPath);
132
+ }
133
+ }
134
+ };
135
+ walk(directory);
136
+ return files;
137
+ }
138
+ }
139
+ exports.EsmFixer = EsmFixer;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { K8sClientGenerator, K8sClientGeneratorOptions, GenerationMode } from './k8s-client-generator';
2
2
  export { SpecDownloader, DownloadOptions } from './spec-downloader';
3
+ export { EsmFixer } from './esm-fixer';
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SpecDownloader = exports.K8sClientGenerator = void 0;
3
+ exports.EsmFixer = exports.SpecDownloader = exports.K8sClientGenerator = void 0;
4
4
  var k8s_client_generator_1 = require("./k8s-client-generator");
5
5
  Object.defineProperty(exports, "K8sClientGenerator", { enumerable: true, get: function () { return k8s_client_generator_1.K8sClientGenerator; } });
6
6
  var spec_downloader_1 = require("./spec-downloader");
7
7
  Object.defineProperty(exports, "SpecDownloader", { enumerable: true, get: function () { return spec_downloader_1.SpecDownloader; } });
8
+ var esm_fixer_1 = require("./esm-fixer");
9
+ Object.defineProperty(exports, "EsmFixer", { enumerable: true, get: function () { return esm_fixer_1.EsmFixer; } });
@@ -33,6 +33,32 @@ export interface K8sClientGeneratorOptions {
33
33
  * @default false
34
34
  */
35
35
  resolveReferences?: boolean;
36
+ /**
37
+ * Whether to fix imports by adding .js extensions for ESM compatibility
38
+ * @default false
39
+ */
40
+ fixEsmImports?: boolean;
41
+ /**
42
+ * Include NestJS Swagger @ApiProperty decorators in generated models
43
+ * Adds @nestjs/swagger to generated package.json
44
+ * @default false
45
+ */
46
+ nestJsSwagger?: boolean;
47
+ /**
48
+ * Include class-validator decorators in generated models
49
+ * Adds class-validator to generated package.json
50
+ * Decorators include: @IsString, @IsNumber, @IsOptional, @Min, @Max, @IsEmail, etc.
51
+ * Note: Full decorator generation requires openapi-class-transformer v2.0+
52
+ * @default false
53
+ */
54
+ classValidator?: boolean;
55
+ /**
56
+ * Skip adding .js extensions to imports/exports
57
+ * Useful for bundlers like webpack/Next.js that don't want file extensions
58
+ * When true, imports will be: import { Foo } from './foo' instead of './foo.js'
59
+ * @default false
60
+ */
61
+ skipJsExtensions?: boolean;
36
62
  /**
37
63
  * Request timeout for downloading spec in milliseconds
38
64
  * @default 30000
@@ -59,4 +85,8 @@ export declare class K8sClientGenerator {
59
85
  * Clean up the downloaded spec file
60
86
  */
61
87
  private cleanupSpecFile;
88
+ /**
89
+ * Add decorator dependencies to generated package.json
90
+ */
91
+ private addDecoratorDependencies;
62
92
  }
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.K8sClientGenerator = void 0;
37
37
  const openapi_class_transformer_1 = require("openapi-class-transformer");
38
38
  const spec_downloader_1 = require("./spec-downloader");
39
+ const esm_fixer_1 = require("./esm-fixer");
39
40
  const fs = __importStar(require("fs"));
40
41
  const path = __importStar(require("path"));
41
42
  const yaml = __importStar(require("js-yaml"));
@@ -47,7 +48,7 @@ class K8sClientGenerator {
47
48
  * Generate TypeScript client from a remote OpenAPI spec URL
48
49
  */
49
50
  async generate(options) {
50
- const { specUrl, outputDir, mode = 'full', headers, templateDir, keepSpec = false, resolveReferences = false, timeout, } = options;
51
+ const { specUrl, outputDir, mode = 'full', headers, templateDir, keepSpec = false, resolveReferences = false, fixEsmImports = false, nestJsSwagger = false, classValidator = false, skipJsExtensions = false, timeout, } = options;
51
52
  let specPath;
52
53
  try {
53
54
  // Step 1: Download the OpenAPI spec
@@ -73,6 +74,8 @@ class K8sClientGenerator {
73
74
  inputSpec: jsonSpecPath,
74
75
  outputDir,
75
76
  modelsOnly: mode === 'models-only',
77
+ nestJsSwagger,
78
+ skipJsExtensions,
76
79
  };
77
80
  // Only add templateDir if it's provided
78
81
  if (templateDir) {
@@ -80,6 +83,17 @@ class K8sClientGenerator {
80
83
  }
81
84
  const generator = new openapi_class_transformer_1.Generator(generatorOptions);
82
85
  await generator.generate();
86
+ // Step 3.5: Update generated package.json with decorator dependencies
87
+ if (nestJsSwagger || classValidator) {
88
+ console.log('Step 3.5: Adding decorator dependencies to package.json...');
89
+ this.addDecoratorDependencies(outputDir, nestJsSwagger, classValidator);
90
+ }
91
+ // Step 4: Fix ESM imports if requested
92
+ if (fixEsmImports) {
93
+ console.log('Step 4: Fixing ESM imports...');
94
+ const esmFixer = new esm_fixer_1.EsmFixer();
95
+ await esmFixer.fixDirectory(outputDir);
96
+ }
83
97
  console.log('✅ Client generation completed successfully!');
84
98
  console.log(`📁 Generated files location: ${outputDir}`);
85
99
  }
@@ -165,5 +179,42 @@ class K8sClientGenerator {
165
179
  console.warn('Warning: Failed to cleanup spec file:', error);
166
180
  }
167
181
  }
182
+ /**
183
+ * Add decorator dependencies to generated package.json
184
+ */
185
+ addDecoratorDependencies(outputDir, nestJsSwagger, classValidator) {
186
+ const packageJsonPath = path.join(outputDir, 'package.json');
187
+ if (!fs.existsSync(packageJsonPath)) {
188
+ console.warn('Warning: package.json not found in output directory');
189
+ console.log('Tip: In models-only mode, add these dependencies to your project manually');
190
+ return;
191
+ }
192
+ try {
193
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
194
+ // Initialize dependencies if missing
195
+ if (!packageJson.dependencies) {
196
+ packageJson.dependencies = {};
197
+ }
198
+ // Add @nestjs/swagger if enabled
199
+ if (nestJsSwagger) {
200
+ packageJson.dependencies['@nestjs/swagger'] = '^7.0.0';
201
+ console.log(' ✓ Added @nestjs/swagger@^7.0.0 to dependencies');
202
+ }
203
+ // Add class-validator if enabled
204
+ if (classValidator) {
205
+ packageJson.dependencies['class-validator'] = '^0.14.0';
206
+ packageJson.dependencies['class-transformer'] = '^0.5.1'; // Required peer dependency
207
+ console.log(' ✓ Added class-validator@^0.14.0 to dependencies');
208
+ console.log(' ✓ Added class-transformer@^0.5.1 to dependencies');
209
+ console.log(' Note: Full decorator generation requires openapi-class-transformer v2.0+');
210
+ console.log(' For now, you can manually add validation decorators to the generated models');
211
+ }
212
+ // Write back with formatting
213
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf-8');
214
+ }
215
+ catch (error) {
216
+ console.warn('Warning: Failed to update package.json:', error);
217
+ }
218
+ }
168
219
  }
169
220
  exports.K8sClientGenerator = K8sClientGenerator;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "klasik",
3
- "version": "1.0.19",
3
+ "version": "1.0.22",
4
4
  "description": "Download OpenAPI specs from remote URLs and generate TypeScript clients with class-transformer support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -22,14 +22,18 @@
22
22
  "api-client",
23
23
  "generator"
24
24
  ],
25
- "author": "",
25
+ "author": "hisco",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/hisco/klasik.git"
29
+ },
26
30
  "license": "MIT",
27
31
  "dependencies": {
28
32
  "axios": "^1.6.0",
29
33
  "class-transformer": "^0.5.1",
30
34
  "commander": "^11.0.0",
31
35
  "js-yaml": "^4.1.0",
32
- "openapi-class-transformer": "^1.0.11",
36
+ "openapi-class-transformer": "^1.0.13",
33
37
  "reflect-metadata": "^0.2.2"
34
38
  },
35
39
  "devDependencies": {