klasik 1.0.30 → 1.0.34

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.
@@ -25,7 +25,9 @@
25
25
  "Bash(then echo $f)",
26
26
  "Bash(fi)",
27
27
  "Bash(done)",
28
- "Bash(node -e:*)"
28
+ "Bash(node -e:*)",
29
+ "WebFetch(domain:docs.nestjs.com)",
30
+ "Bash(echo:*)"
29
31
  ]
30
32
  }
31
33
  }
@@ -0,0 +1,536 @@
1
+ # Comprehensive Test Checklist for klasik + openapi-class-transformer Fixes
2
+
3
+ ## Version Information
4
+ - **klasik**: 1.0.31
5
+ - **openapi-class-transformer**: 1.0.17
6
+
7
+ ## Test Environment Setup
8
+ ```bash
9
+ # Clean test directory
10
+ rm -rf /tmp/test-klasik-final
11
+
12
+ # Test with Argo CD CRDs
13
+ npx klasik@latest generate-crd \
14
+ --crd-kind-snake-case \
15
+ --url https://raw.githubusercontent.com/argoproj/argo-cd/master/manifests/crds/application-crd.yaml \
16
+ --output /tmp/test-klasik-final/argocd \
17
+ --nestjs-swagger \
18
+ --class-validator
19
+
20
+ # Test with Kustomize JSON Schema
21
+ npx klasik@latest generate-jsonschema \
22
+ -u https://json.schemastore.org/kustomization.json \
23
+ --output /tmp/test-klasik-final/kustomize \
24
+ --nestjs-swagger \
25
+ --class-validator
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Category 1: NestJS @ApiProperty Decorator Issues
31
+
32
+ ### ✅ Test 1.1: Primitive Type Casing
33
+ **Issue**: Generated `type: 'string'` instead of `type: String`
34
+
35
+ **Files to check**:
36
+ - `/tmp/test-klasik-final/argocd/application/v1alpha1/models/*.ts`
37
+ - `/tmp/test-klasik-final/kustomize/models/*.ts`
38
+
39
+ **What to verify**:
40
+ ```typescript
41
+ // ❌ WRONG (should NOT exist)
42
+ @ApiProperty({ type: 'string' })
43
+ @ApiProperty({ type: 'number' })
44
+ @ApiProperty({ type: 'boolean' })
45
+
46
+ // ✅ CORRECT (should exist)
47
+ @ApiProperty({ type: String })
48
+ @ApiProperty({ type: Number })
49
+ @ApiProperty({ type: Boolean })
50
+ ```
51
+
52
+ **Test command**:
53
+ ```bash
54
+ # Should return 0 results
55
+ grep -r "type: 'string'" /tmp/test-klasik-final/
56
+ grep -r "type: 'number'" /tmp/test-klasik-final/
57
+ grep -r "type: 'boolean'" /tmp/test-klasik-final/
58
+
59
+ # Should have results
60
+ grep -r "type: String," /tmp/test-klasik-final/ | wc -l
61
+ grep -r "type: Number," /tmp/test-klasik-final/ | wc -l
62
+ ```
63
+
64
+ ---
65
+
66
+ ### ✅ Test 1.2: Array Primitive Types
67
+ **Issue**: Generated `type: () => [string]` instead of `type: [String]`
68
+
69
+ **What to verify**:
70
+ ```typescript
71
+ // ❌ WRONG
72
+ @ApiProperty({ type: () => [string] })
73
+
74
+ // ✅ CORRECT
75
+ @ApiProperty({ type: [String] })
76
+ ```
77
+
78
+ **Test command**:
79
+ ```bash
80
+ # Should return 0 results
81
+ grep -r "type: () => \[string\]" /tmp/test-klasik-final/
82
+ grep -r "type: () => \[number\]" /tmp/test-klasik-final/
83
+ ```
84
+
85
+ ---
86
+
87
+ ### ✅ Test 1.3: Complex Object Types (Dictionary)
88
+ **Issue**: Generated `type: 'object'` which is invalid in @nestjs/swagger@8+
89
+
90
+ **Files to check**:
91
+ - `/tmp/test-klasik-final/kustomize/models/helm-chart.ts` (valuesInline property)
92
+
93
+ **What to verify**:
94
+ ```typescript
95
+ // ❌ WRONG
96
+ @ApiProperty({ type: 'object' })
97
+ @ApiProperty({ type: () => [{ [key: string]: any; }] })
98
+
99
+ // ✅ CORRECT
100
+ @ApiProperty({ type: Object })
101
+ ```
102
+
103
+ **Test command**:
104
+ ```bash
105
+ # Should return 0 results
106
+ grep -r "type: 'object'" /tmp/test-klasik-final/
107
+ grep -r "type: () => \[\{" /tmp/test-klasik-final/
108
+
109
+ # Should have results for Object constructor
110
+ grep -r "type: Object," /tmp/test-klasik-final/kustomize/models/helm-chart.ts
111
+ ```
112
+
113
+ ---
114
+
115
+ ### ✅ Test 1.4: Unescaped Backticks in Descriptions
116
+ **Issue**: Descriptions with backticks weren't escaped, causing syntax errors
117
+
118
+ **Files to check**:
119
+ - `/tmp/test-klasik-final/argocd/application/v1alpha1/models/application-spec-source.ts`
120
+
121
+ **What to verify**:
122
+ ```typescript
123
+ // ❌ WRONG
124
+ description: `text `code` here`,
125
+
126
+ // ✅ CORRECT
127
+ description: `text \`code\` here`,
128
+ ```
129
+
130
+ **Test command**:
131
+ ```bash
132
+ # Find files with descriptions containing backticks
133
+ grep -r "description:" /tmp/test-klasik-final/ | grep '`' | head -20
134
+
135
+ # Check specific case mentioned in issues
136
+ grep -A 5 "ref.*source" /tmp/test-klasik-final/argocd/application/v1alpha1/models/application-spec-source.ts
137
+ ```
138
+
139
+ ---
140
+
141
+ ### ✅ Test 1.5: Undefined Descriptions
142
+ **Issue**: `description: undefined` should be `description: ''`
143
+
144
+ **What to verify**:
145
+ ```typescript
146
+ // ❌ WRONG (in @ApiProperty decorators)
147
+ @ApiProperty({
148
+ description: undefined,
149
+ ...
150
+ })
151
+
152
+ // ✅ CORRECT
153
+ @ApiProperty({
154
+ description: '',
155
+ ...
156
+ })
157
+
158
+ // ⚠️ OK (in attributeTypeMap - metadata should stay as-is)
159
+ {
160
+ "description": undefined, // This is fine
161
+ ...
162
+ }
163
+ ```
164
+
165
+ **Test command**:
166
+ ```bash
167
+ # Count description: undefined in decorators (should be 0)
168
+ grep -B 1 "description: undefined," /tmp/test-klasik-final/**/*.ts | grep "@ApiProperty" -c
169
+
170
+ # Count in attributeTypeMap (should be > 0, this is OK)
171
+ grep -A 5 "attributeTypeMap" /tmp/test-klasik-final/**/*.ts | grep '"description": undefined' | wc -l
172
+ ```
173
+
174
+ ---
175
+
176
+ ### ✅ Test 1.6: Missing Class References
177
+ **Issue**: `type: () => NonExistentClass` where class doesn't exist
178
+
179
+ **Files to check**:
180
+ - `/tmp/test-klasik-final/argocd/application/v1alpha1/models/*replicas-item.ts`
181
+
182
+ **What to verify**:
183
+ ```typescript
184
+ // ❌ WRONG
185
+ @ApiProperty({
186
+ type: () => ApplicationSpecSourceKustomizeReplicasItemCount,
187
+ ...
188
+ })
189
+ // But ApplicationSpecSourceKustomizeReplicasItemCount doesn't exist!
190
+
191
+ // ✅ CORRECT - should be removed entirely
192
+ @ApiProperty({
193
+ // no type field for union types like number | string
194
+ ...
195
+ })
196
+ ```
197
+
198
+ **Test command**:
199
+ ```bash
200
+ # Check if any @ApiProperty has type references to non-imported classes
201
+ for file in /tmp/test-klasik-final/**/*-replicas-item.ts; do
202
+ echo "Checking $file..."
203
+ # Extract type references from @ApiProperty
204
+ grep -A 3 "@ApiProperty" "$file" | grep "type: ()" | grep -v "import"
205
+ done
206
+ ```
207
+
208
+ ---
209
+
210
+ ## Category 2: AttributeTypeMap Issues
211
+
212
+ ### ✅ Test 2.1: Missing Closing Braces
213
+ **Issue**: Last object in array missing closing `}` before `];`
214
+
215
+ **What to verify**:
216
+ ```typescript
217
+ // ❌ WRONG
218
+ {
219
+ "vendorExtensions": {}
220
+ ]; // Missing }
221
+
222
+ // ✅ CORRECT
223
+ {
224
+ "vendorExtensions": {}
225
+ }
226
+ ];
227
+ ```
228
+
229
+ **Test command**:
230
+ ```bash
231
+ # Check for malformed attributeTypeMap
232
+ grep -B 2 "^ \];" /tmp/test-klasik-final/**/*.ts | grep -A 1 "vendorExtensions"
233
+
234
+ # Should find properly closed objects
235
+ grep -B 3 "^ \];" /tmp/test-klasik-final/**/*.ts | grep " }" | wc -l
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Category 3: Union Types and @Type() Decorators
241
+
242
+ ### ✅ Test 3.1: Type-Only Imports Should NOT Have @Type()
243
+ **Issue**: Union types (type aliases) had `@Type()` decorators causing runtime errors
244
+
245
+ **Files to check**:
246
+ - `/tmp/test-klasik-final/kustomize/models/kustomization.ts`
247
+ - `/tmp/test-klasik-final/kustomize/models/patch-json6902.ts`
248
+
249
+ **What to verify**:
250
+ ```typescript
251
+ // In patch-json6902.ts - this is a type alias (union)
252
+ import type { PatchJson6902OneOf } from './patch-json6902-one-of.js';
253
+ export type PatchJson6902 = PatchJson6902OneOf | ...;
254
+
255
+ // In kustomization.ts - should NOT have @Type() for this
256
+ @Expose()
257
+ // @Type(() => PatchJson6902) ❌ WRONG - should NOT exist
258
+ 'patchesJson6902'?: Array<PatchJson6902>;
259
+ ```
260
+
261
+ **Test command**:
262
+ ```bash
263
+ # Find all type-only imports
264
+ grep -r "import type {" /tmp/test-klasik-final/ | cut -d':' -f1 | sort -u
265
+
266
+ # For each file with type-only imports, check if @Type() uses them
267
+ for file in $(grep -l "import type {" /tmp/test-klasik-final/**/*.ts); do
268
+ echo "=== Checking $file ==="
269
+ # Extract type-only import names
270
+ TYPE_IMPORTS=$(grep "import type {" "$file" | sed 's/.*{ //; s/ }.*//' | tr ',' '\n' | tr -d ' ')
271
+
272
+ # Check if any @Type() references these
273
+ for type in $TYPE_IMPORTS; do
274
+ if grep -q "@Type(() => $type)" "$file"; then
275
+ echo "❌ ERROR: @Type() decorator found for type-only import: $type"
276
+ fi
277
+ done
278
+ done
279
+ ```
280
+
281
+ ---
282
+
283
+ ### ✅ Test 3.2: Regular Classes SHOULD Have @Type()
284
+ **Issue**: Real classes (not unions) must keep @Type() decorators
285
+
286
+ **Files to check**:
287
+ - `/tmp/test-klasik-final/argocd/application/v1alpha1/models/user.ts` (if exists)
288
+ - Any file with regular class imports
289
+
290
+ **What to verify**:
291
+ ```typescript
292
+ // Regular class import (NOT type-only)
293
+ import { Profile } from './profile.js';
294
+
295
+ // Should have @Type() decorator
296
+ @Expose()
297
+ @Type(() => Profile) // ✅ CORRECT - should exist
298
+ 'profile'?: Profile;
299
+ ```
300
+
301
+ **Test command**:
302
+ ```bash
303
+ # Find files with regular imports (not type imports)
304
+ grep -r "^import { " /tmp/test-klasik-final/ | grep -v "import type" | head -20
305
+
306
+ # Verify @Type() exists for complex types
307
+ grep -B 5 "@Type(() =>" /tmp/test-klasik-final/**/*.ts | head -40
308
+ ```
309
+
310
+ ---
311
+
312
+ ## Category 4: ESM Module System Issues
313
+
314
+ ### ✅ Test 4.1: .js Extensions in Imports (Individual Files)
315
+ **Issue**: Missing `.js` extensions in ES module imports
316
+
317
+ **What to verify**:
318
+ ```typescript
319
+ // ❌ WRONG
320
+ import { Foo } from './foo';
321
+
322
+ // ✅ CORRECT
323
+ import { Foo } from './foo.js';
324
+ ```
325
+
326
+ **Test command**:
327
+ ```bash
328
+ # Count imports without .js (should be minimal, only class-transformer etc.)
329
+ grep -r "^import.*from '\\./" /tmp/test-klasik-final/ | grep -v "\.js'" | wc -l
330
+
331
+ # All local imports should have .js
332
+ grep -r "^import.*from '\\./" /tmp/test-klasik-final/ | grep "\.js'" | wc -l
333
+ ```
334
+
335
+ ---
336
+
337
+ ### ✅ Test 4.2: .js Extensions in Index Files
338
+ **Issue**: JSON schema generator index.ts didn't have .js extensions
339
+
340
+ **Files to check**:
341
+ - `/tmp/test-klasik-final/kustomize/index.ts`
342
+ - `/tmp/test-klasik-final/argocd/application/v1alpha1/index.ts`
343
+
344
+ **What to verify**:
345
+ ```typescript
346
+ // ❌ WRONG
347
+ export * from './models/config-map-args';
348
+
349
+ // ✅ CORRECT
350
+ export * from './models/config-map-args.js';
351
+ ```
352
+
353
+ **Test command**:
354
+ ```bash
355
+ # Check index files
356
+ cat /tmp/test-klasik-final/kustomize/index.ts | head -10
357
+ cat /tmp/test-klasik-final/argocd/application/v1alpha1/index.ts | head -10
358
+
359
+ # All exports should have .js
360
+ grep "export \* from" /tmp/test-klasik-final/kustomize/index.ts | grep -v "\.js'" && echo "❌ FAIL" || echo "✅ PASS"
361
+ ```
362
+
363
+ ---
364
+
365
+ ## Category 5: TypeScript Compilation
366
+
367
+ ### ✅ Test 5.1: No Syntax Errors
368
+ **Issue**: Various syntax errors from all the above issues
369
+
370
+ **Test command**:
371
+ ```bash
372
+ cd /tmp/test-klasik-final/kustomize
373
+ npm init -y
374
+ npm install class-transformer @nestjs/swagger reflect-metadata
375
+
376
+ # Create tsconfig.json
377
+ cat > tsconfig.json << 'EOF'
378
+ {
379
+ "compilerOptions": {
380
+ "target": "ES2020",
381
+ "module": "ES2020",
382
+ "moduleResolution": "node16",
383
+ "esModuleInterop": true,
384
+ "skipLibCheck": true,
385
+ "strict": true,
386
+ "isolatedModules": true,
387
+ "emitDecoratorMetadata": true,
388
+ "experimentalDecorators": true,
389
+ "declaration": true,
390
+ "outDir": "./dist"
391
+ },
392
+ "include": ["models/**/*", "index.ts"]
393
+ }
394
+ EOF
395
+
396
+ # Compile - should have NO errors
397
+ npx tsc --noEmit
398
+ ```
399
+
400
+ ---
401
+
402
+ ### ✅ Test 5.2: Specific TypeScript Errors Fixed
403
+
404
+ **Test each error type**:
405
+
406
+ ```bash
407
+ cd /tmp/test-klasik-final/kustomize
408
+
409
+ # Test 1: No "type used as value" errors
410
+ npx tsc --noEmit 2>&1 | grep "only refers to a type, but is being used as a value" && echo "❌ FAIL" || echo "✅ PASS"
411
+
412
+ # Test 2: No "missing file extension" errors
413
+ npx tsc --noEmit 2>&1 | grep "need explicit file extensions" && echo "❌ FAIL" || echo "✅ PASS"
414
+
415
+ # Test 3: No "not assignable to type" errors for @ApiProperty
416
+ npx tsc --noEmit 2>&1 | grep "not assignable.*ApiProperty" && echo "❌ FAIL" || echo "✅ PASS"
417
+
418
+ # Test 4: No "Cannot find name" errors
419
+ npx tsc --noEmit 2>&1 | grep "Cannot find name" && echo "❌ FAIL" || echo "✅ PASS"
420
+ ```
421
+
422
+ ---
423
+
424
+ ## Category 6: Runtime Testing
425
+
426
+ ### ✅ Test 6.1: class-transformer Deserialization
427
+ **Issue**: Verify classes can be properly transformed
428
+
429
+ **Test file**: Create `/tmp/test-klasik-final/test-runtime.ts`
430
+
431
+ ```typescript
432
+ import 'reflect-metadata';
433
+ import { plainToInstance } from 'class-transformer';
434
+ import { Kustomization } from './kustomize/models/kustomization.js';
435
+
436
+ const data = {
437
+ apiVersion: 'kustomize.config.k8s.io/v1beta1',
438
+ kind: 'Kustomization',
439
+ resources: ['deployment.yaml', 'service.yaml']
440
+ };
441
+
442
+ const instance = plainToInstance(Kustomization, data);
443
+ console.log('✅ Successfully created instance:', instance);
444
+ console.log('Has proper class methods:', instance instanceof Kustomization);
445
+ ```
446
+
447
+ **Run test**:
448
+ ```bash
449
+ npx ts-node --esm /tmp/test-klasik-final/test-runtime.ts
450
+ ```
451
+
452
+ ---
453
+
454
+ ## Summary Checklist
455
+
456
+ Run all tests and check:
457
+
458
+ - [ ] **Test 1.1**: No lowercase primitive types (`'string'`, `'number'`, `'boolean'`)
459
+ - [ ] **Test 1.2**: No array primitive syntax `() => [string]`
460
+ - [ ] **Test 1.3**: No `type: 'object'`, uses `type: Object`
461
+ - [ ] **Test 1.4**: All backticks in descriptions are escaped
462
+ - [ ] **Test 1.5**: No `description: undefined` in decorators
463
+ - [ ] **Test 1.6**: No type references to non-existent classes
464
+ - [ ] **Test 2.1**: All attributeTypeMap arrays properly closed
465
+ - [ ] **Test 3.1**: No `@Type()` for type-only imports (unions)
466
+ - [ ] **Test 3.2**: `@Type()` exists for regular class references
467
+ - [ ] **Test 4.1**: All local imports have `.js` extensions
468
+ - [ ] **Test 4.2**: Index files have `.js` extensions in exports
469
+ - [ ] **Test 5.1**: `tsc --noEmit` passes with no errors
470
+ - [ ] **Test 5.2**: No specific TypeScript compilation errors
471
+ - [ ] **Test 6.1**: Runtime deserialization works
472
+
473
+ ---
474
+
475
+ ## Quick Test Script
476
+
477
+ ```bash
478
+ #!/bin/bash
479
+ set -e
480
+
481
+ echo "🧪 Running comprehensive klasik tests..."
482
+
483
+ # Setup
484
+ rm -rf /tmp/test-klasik-final
485
+ mkdir -p /tmp/test-klasik-final
486
+
487
+ # Generate Argo CD
488
+ echo "📦 Generating Argo CD models..."
489
+ npx klasik@latest generate-crd \
490
+ --crd-kind-snake-case \
491
+ --url https://raw.githubusercontent.com/argoproj/argo-cd/master/manifests/crds/application-crd.yaml \
492
+ --output /tmp/test-klasik-final/argocd \
493
+ --nestjs-swagger \
494
+ --class-validator
495
+
496
+ # Generate Kustomize
497
+ echo "📦 Generating Kustomize models..."
498
+ npx klasik@latest generate-jsonschema \
499
+ -u https://json.schemastore.org/kustomization.json \
500
+ --output /tmp/test-klasik-final/kustomize \
501
+ --nestjs-swagger \
502
+ --class-validator
503
+
504
+ # Run checks
505
+ echo "✅ Test 1.1: Primitive type casing..."
506
+ ! grep -r "type: 'string'" /tmp/test-klasik-final/ || exit 1
507
+
508
+ echo "✅ Test 1.3: Complex object types..."
509
+ ! grep -r "type: 'object'" /tmp/test-klasik-final/ || exit 1
510
+
511
+ echo "✅ Test 4.2: Index.ts has .js extensions..."
512
+ grep "export \* from" /tmp/test-klasik-final/kustomize/index.ts | grep -q "\.js'" || exit 1
513
+
514
+ echo "✅ Test 5.1: TypeScript compilation..."
515
+ cd /tmp/test-klasik-final/kustomize
516
+ npm init -y > /dev/null 2>&1
517
+ npm install class-transformer @nestjs/swagger reflect-metadata > /dev/null 2>&1
518
+ cat > tsconfig.json << 'EOF'
519
+ {
520
+ "compilerOptions": {
521
+ "target": "ES2020",
522
+ "module": "ES2020",
523
+ "moduleResolution": "node16",
524
+ "skipLibCheck": true,
525
+ "isolatedModules": true,
526
+ "emitDecoratorMetadata": true,
527
+ "experimentalDecorators": true
528
+ }
529
+ }
530
+ EOF
531
+ npx tsc --noEmit || exit 1
532
+
533
+ echo "🎉 All tests passed!"
534
+ ```
535
+
536
+ Save as `/tmp/test-klasik.sh` and run with `bash /tmp/test-klasik.sh`
@@ -83,6 +83,7 @@ export declare class JSONSchemaGenerator {
83
83
  * Generate index file for all definitions
84
84
  * @param outputDir Output directory
85
85
  * @param definitions List of definition names
86
+ * @param skipJsExtensions Whether to skip adding .js extensions to exports
86
87
  */
87
88
  private generateIndex;
88
89
  /**
@@ -157,7 +157,7 @@ class JSONSchemaGenerator {
157
157
  }
158
158
  // Step 3: Generate index file
159
159
  console.log('\nStep 3: Generating index files...');
160
- this.generateIndex(outputDir, allDefinitions);
160
+ this.generateIndex(outputDir, allDefinitions, skipJsExtensions);
161
161
  console.log('\n✅ JSON Schema client generation completed successfully!');
162
162
  console.log(`📁 Generated files location: ${outputDir}`);
163
163
  }
@@ -244,16 +244,18 @@ class JSONSchemaGenerator {
244
244
  * Generate index file for all definitions
245
245
  * @param outputDir Output directory
246
246
  * @param definitions List of definition names
247
+ * @param skipJsExtensions Whether to skip adding .js extensions to exports
247
248
  */
248
- generateIndex(outputDir, definitions) {
249
+ generateIndex(outputDir, definitions, skipJsExtensions) {
249
250
  // Remove duplicates
250
251
  const uniqueDefinitions = Array.from(new Set(definitions));
251
- // Generate exports
252
+ // Generate exports with .js extensions if not skipped
253
+ const extension = skipJsExtensions ? '' : '.js';
252
254
  const exports = uniqueDefinitions
253
255
  .map(name => {
254
256
  // Convert definition name to file name (ConfigMapArgs → config-map-args)
255
257
  const fileName = this.toFileName(name);
256
- return `export * from './models/${fileName}';`;
258
+ return `export * from './models/${fileName}${extension}';`;
257
259
  })
258
260
  .join('\n');
259
261
  const indexContent = `// Auto-generated index for JSON Schema models\n${exports}\n`;
@@ -12,6 +12,8 @@
12
12
  * instead of empty strings
13
13
  * 4. Invalid complex object types: Uses invalid arrow function syntax for
14
14
  * dictionary types (type: () => [{ [key: string]: any; }])
15
+ * 5. Invalid string literal 'object': @nestjs/swagger@8+ only accepts
16
+ * constructors (Type<unknown> | Function), not string literals
15
17
  *
16
18
  * This utility transforms:
17
19
  * - type: 'string' -> type: String
@@ -20,7 +22,8 @@
20
22
  * - type: () => [string] -> type: [String]
21
23
  * - type: () => [number] -> type: [Number]
22
24
  * - type: () => [boolean] -> type: [Boolean]
23
- * - type: () => [{ [key: string]: any; }] -> type: 'object'
25
+ * - type: () => [{ [key: string]: any; }], -> type: Object,
26
+ * - type: 'object', -> type: Object,
24
27
  * - description: `text `code` here` -> description: `text \`code\` here`
25
28
  * - description: undefined -> description: ''
26
29
  *
@@ -54,6 +57,19 @@ export declare class NestJsTypeFixer {
54
57
  * Replace undefined descriptions with empty strings
55
58
  */
56
59
  private fixUndefinedDescriptions;
60
+ /**
61
+ * Fix references to non-existent classes in type fields
62
+ *
63
+ * When the generator creates types for union types like number | string,
64
+ * it sometimes references classes that don't exist (e.g., for x-kubernetes-int-or-string).
65
+ * This method detects and removes those invalid type references by checking if the
66
+ * referenced class is actually imported in the file.
67
+ */
68
+ private fixMissingClassReferences;
69
+ /**
70
+ * Extract all imported class names from import statements
71
+ */
72
+ private extractImportedClasses;
57
73
  /**
58
74
  * Get all TypeScript files in a directory recursively
59
75
  */
@@ -50,6 +50,8 @@ const path = __importStar(require("path"));
50
50
  * instead of empty strings
51
51
  * 4. Invalid complex object types: Uses invalid arrow function syntax for
52
52
  * dictionary types (type: () => [{ [key: string]: any; }])
53
+ * 5. Invalid string literal 'object': @nestjs/swagger@8+ only accepts
54
+ * constructors (Type<unknown> | Function), not string literals
53
55
  *
54
56
  * This utility transforms:
55
57
  * - type: 'string' -> type: String
@@ -58,7 +60,8 @@ const path = __importStar(require("path"));
58
60
  * - type: () => [string] -> type: [String]
59
61
  * - type: () => [number] -> type: [Number]
60
62
  * - type: () => [boolean] -> type: [Boolean]
61
- * - type: () => [{ [key: string]: any; }] -> type: 'object'
63
+ * - type: () => [{ [key: string]: any; }], -> type: Object,
64
+ * - type: 'object', -> type: Object,
62
65
  * - description: `text `code` here` -> description: `text \`code\` here`
63
66
  * - description: undefined -> description: ''
64
67
  *
@@ -141,8 +144,16 @@ class NestJsTypeFixer {
141
144
  return `type: [${capitalized}]`;
142
145
  });
143
146
  // Fix invalid complex object types with index signatures
144
- // type: () => [{ [key: string]: any; }] -> type: 'object'
145
- content = content.replace(/type:\s*\(\)\s*=>\s*\[\{[^\]]*\[key:\s*string\][^\]]*\}\]/g, "type: 'object'");
147
+ // type: () => [{ [key: string]: any; }], -> type: Object,
148
+ content = content.replace(/type:\s*\(\)\s*=>\s*\[\{[^\]]*\[key:\s*string\][^\]]*\}\],/g, "type: Object,");
149
+ // Fix string literal 'object' which is invalid in @nestjs/swagger@8+
150
+ // @nestjs/swagger@8 only accepts constructors, not string literals
151
+ // type: 'object', -> type: Object,
152
+ content = content.replace(/type:\s*'object',/g, "type: Object,");
153
+ // Fix missing class references (classes that don't exist)
154
+ // For x-kubernetes-int-or-string types, remove the invalid type reference
155
+ // type: () => SomeNonExistentClass, -> (removed)
156
+ content = this.fixMissingClassReferences(content);
146
157
  // Fix unescaped backticks in description strings
147
158
  content = this.escapeBackticksInDescriptions(content);
148
159
  // Fix undefined descriptions
@@ -171,6 +182,59 @@ class NestJsTypeFixer {
171
182
  // Only affects @ApiProperty decorators (split-point protects attributeTypeMap)
172
183
  return content.replace(/description:\s*undefined/g, "description: ''");
173
184
  }
185
+ /**
186
+ * Fix references to non-existent classes in type fields
187
+ *
188
+ * When the generator creates types for union types like number | string,
189
+ * it sometimes references classes that don't exist (e.g., for x-kubernetes-int-or-string).
190
+ * This method detects and removes those invalid type references by checking if the
191
+ * referenced class is actually imported in the file.
192
+ */
193
+ fixMissingClassReferences(content) {
194
+ // Extract all imported class names from the file
195
+ const importedClasses = this.extractImportedClasses(content);
196
+ // Find all type: () => ClassName references in @ApiProperty decorators
197
+ const typeReferenceRegex = /type:\s*\(\)\s*=>\s*([A-Z][a-zA-Z0-9]*),/g;
198
+ return content.replace(typeReferenceRegex, (match, className) => {
199
+ // If the class is not imported, remove the entire type line
200
+ if (!importedClasses.has(className)) {
201
+ // Remove the entire line including newline
202
+ return '';
203
+ }
204
+ // Keep it if the class is imported
205
+ return match;
206
+ });
207
+ }
208
+ /**
209
+ * Extract all imported class names from import statements
210
+ */
211
+ extractImportedClasses(content) {
212
+ const importedClasses = new Set();
213
+ // Match various import patterns:
214
+ // import { ClassName } from '...'
215
+ // import { ClassName as Alias } from '...'
216
+ // import ClassName from '...'
217
+ const importRegex = /import\s+(?:type\s+)?(?:\{([^}]+)\}|([A-Z][a-zA-Z0-9]*))\s+from/g;
218
+ let match;
219
+ while ((match = importRegex.exec(content)) !== null) {
220
+ if (match[1]) {
221
+ // Named imports: { Class1, Class2 as Alias, Class3 }
222
+ const namedImports = match[1].split(',').map(s => s.trim());
223
+ namedImports.forEach(imp => {
224
+ // Handle "ClassName" or "ClassName as Alias"
225
+ const className = imp.split(/\s+as\s+/)[0].trim();
226
+ if (className && /^[A-Z]/.test(className)) {
227
+ importedClasses.add(className);
228
+ }
229
+ });
230
+ }
231
+ else if (match[2]) {
232
+ // Default import: import ClassName from '...'
233
+ importedClasses.add(match[2]);
234
+ }
235
+ }
236
+ return importedClasses;
237
+ }
174
238
  /**
175
239
  * Get all TypeScript files in a directory recursively
176
240
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "klasik",
3
- "version": "1.0.30",
3
+ "version": "1.0.34",
4
4
  "description": "Download OpenAPI specs from remote URLs and generate TypeScript clients with class-transformer support - support yaml, json, CustomResourceDefinition formats",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -33,7 +33,7 @@
33
33
  "class-transformer": "^0.5.1",
34
34
  "commander": "^11.0.0",
35
35
  "js-yaml": "^4.1.0",
36
- "openapi-class-transformer": "^1.0.15",
36
+ "openapi-class-transformer": "^1.0.21",
37
37
  "reflect-metadata": "^0.2.2"
38
38
  },
39
39
  "devDependencies": {